Configure uma malha de vários clusters no Cloud Service Mesh gerido
Este guia explica como juntar dois clusters num único Cloud Service Mesh através da AC da malha ou do serviço de autoridade de certificação e ativar o equilíbrio de carga entre clusters. Pode expandir facilmente este processo para incorporar qualquer número de clusters na sua malha.
Uma configuração de Cloud Service Mesh com vários clusters pode resolver vários cenários empresariais cruciais, como a escala, a localização e o isolamento. Para mais informações, consulte o artigo Exemplos de utilização com vários clusters.
Pré-requisitos
Este guia pressupõe que tem dois ou mais Google Cloud clusters do GKE que cumprem os seguintes requisitos:
- Cloud Service Mesh instalado nos clusters. Precisa do
asmcli
, da ferramentaistioctl
e de exemplos que oasmcli
transfere para o diretório que especificou em--output_dir
. - Os clusters na sua malha têm de ter conetividade entre todos os pods antes de configurar o Cloud Service Mesh. Além disso, se juntar clusters que não estejam no mesmo projeto, têm de estar registados no mesmo projeto anfitrião da frota e os clusters têm de estar numa configuração de VPC partilhada em conjunto na mesma rede. Também recomendamos que tenha um projeto para alojar a VPC partilhada e dois projetos de serviço para criar clusters. Para mais informações, consulte o artigo Configurar clusters com a VPC partilhada.
- Se usar o serviço de autoridade de certificação, todos os clusters têm de ter a respetiva cadeia de pools de AC subordinadas no mesmo pool de AC de raiz. Caso contrário, todos têm de usar o mesmo conjunto de ACs.
Definir variáveis de projeto e cluster
Crie as seguintes variáveis de ambiente para o ID do projeto, a zona ou a região do cluster, o nome do cluster e o contexto.
export PROJECT_1=PROJECT_ID_1 export LOCATION_1=CLUSTER_LOCATION_1 export CLUSTER_1=CLUSTER_NAME_1 export CTX_1="gke_${PROJECT_1}_${LOCATION_1}_${CLUSTER_1}" export PROJECT_2=PROJECT_ID_2 export LOCATION_2=CLUSTER_LOCATION_2 export CLUSTER_2=CLUSTER_NAME_2 export CTX_2="gke_${PROJECT_2}_${LOCATION_2}_${CLUSTER_2}"
Se estes forem clusters criados recentemente, certifique-se de que obtém credenciais para cada cluster com os seguintes comandos
gcloud
. Caso contrário, oscontext
associados não vão estar disponíveis para utilização nos passos seguintes deste guia.Os comandos dependem do tipo de cluster, regional ou zonal:
Regional
gcloud container clusters get-credentials ${CLUSTER_1} --region ${LOCATION_1} gcloud container clusters get-credentials ${CLUSTER_2} --region ${LOCATION_2}
Zonal
gcloud container clusters get-credentials ${CLUSTER_1} --zone ${LOCATION_1} gcloud container clusters get-credentials ${CLUSTER_2} --zone ${LOCATION_2}
Crie uma regra de firewall
Em alguns casos, tem de criar uma regra de firewall para permitir o tráfego entre clusters. Por exemplo, tem de criar uma regra de firewall se:
- Usar sub-redes diferentes para os clusters na sua malha.
- Os seus pods abrem portas que não sejam 443 e 15002.
O GKE adiciona automaticamente regras de firewall a cada nó para permitir o tráfego na mesma sub-rede. Se a sua malha contiver várias sub-redes, tem de configurar explicitamente as regras de firewall para permitir o tráfego entre sub-redes. Tem de adicionar uma nova regra de firewall para cada sub-rede para permitir os blocos CIDR de IP de origem e as portas de destino de todo o tráfego recebido.
As instruções seguintes permitem a comunicação entre todos os clusters no seu projeto ou apenas entre $CLUSTER_1
e $CLUSTER_2
.
Recolha informações sobre a rede dos seus clusters.
Todos os clusters de projetos
Se os clusters estiverem no mesmo projeto, pode usar o seguinte comando para permitir a comunicação entre todos os clusters no seu projeto. Se existirem clusters no seu projeto que não quer expor, use o comando no separador Clusters específicos.
function join_by { local IFS="$1"; shift; echo "$*"; } ALL_CLUSTER_CIDRS=$(gcloud container clusters list --project $PROJECT_1 --format='value(clusterIpv4Cidr)' | sort | uniq) ALL_CLUSTER_CIDRS=$(join_by , $(echo "${ALL_CLUSTER_CIDRS}")) ALL_CLUSTER_NETTAGS=$(gcloud compute instances list --project $PROJECT_1 --format='value(tags.items.[0])' | sort | uniq) ALL_CLUSTER_NETTAGS=$(join_by , $(echo "${ALL_CLUSTER_NETTAGS}"))
Clusters específicos
O comando seguinte permite a comunicação entre
$CLUSTER_1
e$CLUSTER_2
e não expõe outros clusters no seu projeto.function join_by { local IFS="$1"; shift; echo "$*"; } ALL_CLUSTER_CIDRS=$(for P in $PROJECT_1 $PROJECT_2; do gcloud --project $P container clusters list --filter="name:($CLUSTER_1,$CLUSTER_2)" --format='value(clusterIpv4Cidr)'; done | sort | uniq) ALL_CLUSTER_CIDRS=$(join_by , $(echo "${ALL_CLUSTER_CIDRS}")) ALL_CLUSTER_NETTAGS=$(for P in $PROJECT_1 $PROJECT_2; do gcloud --project $P compute instances list --filter="name:($CLUSTER_1,$CLUSTER_2)" --format='value(tags.items.[0])' ; done | sort | uniq) ALL_CLUSTER_NETTAGS=$(join_by , $(echo "${ALL_CLUSTER_NETTAGS}"))
Crie a regra de firewall.
GKE
gcloud compute firewall-rules create istio-multicluster-pods \ --allow=tcp,udp,icmp,esp,ah,sctp \ --direction=INGRESS \ --priority=900 \ --source-ranges="${ALL_CLUSTER_CIDRS}" \ --target-tags="${ALL_CLUSTER_NETTAGS}" --quiet \ --network=YOUR_NETWORK
Piloto automático
TAGS="" for CLUSTER in ${CLUSTER_1} ${CLUSTER_2} do TAGS+=$(gcloud compute firewall-rules list --filter="Name:$CLUSTER*" --format="value(targetTags)" | uniq) && TAGS+="," done TAGS=${TAGS::-1} echo "Network tags for pod ranges are $TAGS" gcloud compute firewall-rules create asm-multicluster-pods \ --allow=tcp,udp,icmp,esp,ah,sctp \ --network=gke-cluster-vpc \ --direction=INGRESS \ --priority=900 --network=VPC_NAME \ --source-ranges="${ALL_CLUSTER_CIDRS}" \ --target-tags=$TAGS
Configure a descoberta de pontos finais
Ative a deteção de pontos finais entre clusters públicos ou privados com a API declarativa
A ativação da malha de serviços na nuvem gerida com a API Fleet permite a deteção de pontos finais
para este cluster. Se aprovisionou o Cloud Service Mesh gerido com uma ferramenta diferente, pode ativar manualmente a deteção de pontos finais em clusters públicos ou
privados numa frota aplicando a configuração "multicluster_mode":"connected"
no
configmap asm-options
. Os clusters com esta configuração ativada na mesma frota têm a deteção de serviços entre clusters ativada automaticamente entre si.
Esta é a única forma de configurar a deteção de pontos finais de vários clusters se tiver a implementação do plano de controlo (TD) gerida e a forma recomendada de a configurar se tiver a implementação gerida (Istiod).
Antes de continuar, tem de criar uma regra de firewall.
Ativar
Se o asm-options
configmap já existir no seu cluster, ative a deteção de pontos finais para o cluster:
kubectl patch configmap/asm-options -n istio-system --type merge -p '{"data":{"multicluster_mode":"connected"}}'
Se o asm-options
configmap ainda não existir no seu cluster, então
crie-o com os dados associados e ative a deteção de pontos finais para o
cluster:
kubectl --context ${CTX_1} create configmap asm-options -n istio-system --from-file <(echo '{"data":{"multicluster_mode":"connected"}}')
Desativar
Desative a descoberta de pontos finais para um cluster:
kubectl patch configmap/asm-options -n istio-system --type merge -p '{"data":{"multicluster_mode":"manual"}}'
Se anular o registo de um cluster na frota sem desativar a deteção de pontos finais, os segredos podem permanecer no cluster. Tem de limpar manualmente todos os segredos restantes.
Execute o seguinte comando para encontrar segredos que requerem limpeza:
kubectl get secrets -n istio-system -l istio.io/owned-by=mesh.googleapis.com,istio/multiCluster=true
Elimine cada segredo:
kubectl delete secret SECRET_NAME
Repita este passo para cada segredo restante.
Valide a conetividade de vários clusters
Esta secção explica como implementar os serviços de exemplo HelloWorld
e Sleep
no seu ambiente de vários clusters para verificar se o equilíbrio de carga entre clusters funciona.
Defina a variável para o diretório de exemplos
Navegue para onde
asmcli
foi transferido e execute o seguinte comando para definirASM_VERSION
export ASM_VERSION="$(./asmcli --version)"
Defina uma pasta de trabalho para os exemplos que usa para verificar se o equilíbrio de carga entre clusters funciona. Os exemplos estão localizados num subdiretório no diretório
--output_dir
que especificou no comandoasmcli install
. No comando seguinte, altereOUTPUT_DIR
para o diretório que especificou em--output_dir
.export SAMPLES_DIR=OUTPUT_DIR/istio-${ASM_VERSION%+*}
Ative a injeção de sidecar
Crie o namespace de exemplo em cada cluster.
for CTX in ${CTX_1} ${CTX_2} do kubectl create --context=${CTX} namespace sample done
Ative o espaço de nomes para injeção. Os passos dependem da sua implementação do plano de controlo.
Gerido (TD)
- Aplique a etiqueta de injeção predefinida ao espaço de nomes:
for CTX in ${CTX_1} ${CTX_2} do kubectl label --context=${CTX} namespace sample \ istio.io/rev- istio-injection=enabled --overwrite done
Gerido (Istiod)
Recomendado: execute o seguinte comando para aplicar a etiqueta de injeção predefinida ao espaço de nomes:
for CTX in ${CTX_1} ${CTX_2} do kubectl label --context=${CTX} namespace sample \ istio.io/rev- istio-injection=enabled --overwrite done
Se for um utilizador existente com o plano de controlo do Istiod gerido: recomendamos que use a injeção predefinida, mas a injeção baseada em revisões é suportada. Siga as instruções abaixo:
Execute o seguinte comando para localizar os canais de lançamento disponíveis:
kubectl -n istio-system get controlplanerevision
O resultado é semelhante ao seguinte:
NAME AGE asm-managed-rapid 6d7h
Na saída, o valor na coluna
NAME
é a etiqueta de revisão que corresponde ao canal de lançamento disponível para a versão do Cloud Service Mesh.Aplique a etiqueta de revisão ao espaço de nomes:
for CTX in ${CTX_1} ${CTX_2} do kubectl label --context=${CTX} namespace sample \ istio-injection- istio.io/rev=REVISION_LABEL --overwrite done
Instale o serviço HelloWorld
Crie o serviço HelloWorld em ambos os clusters:
kubectl create --context=${CTX_1} \ -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \ -l service=helloworld -n sample
kubectl create --context=${CTX_2} \ -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \ -l service=helloworld -n sample
Implemente o HelloWorld v1 e v2 em cada cluster
Implemente
HelloWorld v1
emCLUSTER_1
ev2
emCLUSTER_2
, o que ajuda mais tarde a validar o balanceamento de carga entre clusters:kubectl create --context=${CTX_1} \ -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \ -l version=v1 -n sample
kubectl create --context=${CTX_2} \ -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \ -l version=v2 -n sample
Confirme se o
HelloWorld v1
e ov2
estão a ser executados através dos seguintes comandos. Verifique se o resultado é semelhante ao apresentado:kubectl get pod --context=${CTX_1} -n sample
NAME READY STATUS RESTARTS AGE helloworld-v1-86f77cd7bd-cpxhv 2/2 Running 0 40s
kubectl get pod --context=${CTX_2} -n sample
NAME READY STATUS RESTARTS AGE helloworld-v2-758dd55874-6x4t8 2/2 Running 0 40s
Implemente o serviço de sono
Implemente o serviço
Sleep
em ambos os clusters. Este pod gera tráfego de rede artificial para fins de demonstração:for CTX in ${CTX_1} ${CTX_2} do kubectl apply --context=${CTX} \ -f ${SAMPLES_DIR}/samples/sleep/sleep.yaml -n sample done
Aguarde que o serviço
Sleep
seja iniciado em cada cluster. Verifique se o resultado é semelhante ao apresentado:kubectl get pod --context=${CTX_1} -n sample -l app=sleep
NAME READY STATUS RESTARTS AGE sleep-754684654f-n6bzf 2/2 Running 0 5s
kubectl get pod --context=${CTX_2} -n sample -l app=sleep
NAME READY STATUS RESTARTS AGE sleep-754684654f-dzl9j 2/2 Running 0 5s
Valide o balanceamento de carga entre clusters
Chame o serviço HelloWorld
várias vezes e verifique o resultado para validar
respostas alternadas da v1 e v2:
Ligue para o serviço
HelloWorld
:kubectl exec --context="${CTX_1}" -n sample -c sleep \ "$(kubectl get pod --context="${CTX_1}" -n sample -l \ app=sleep -o jsonpath='{.items[0].metadata.name}')" \ -- /bin/sh -c 'for i in $(seq 1 20); do curl -sS helloworld.sample:5000/hello; done'
O resultado é semelhante ao apresentado:
Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8 Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv ...
Ligue novamente para o serviço
HelloWorld
:kubectl exec --context="${CTX_2}" -n sample -c sleep \ "$(kubectl get pod --context="${CTX_2}" -n sample -l \ app=sleep -o jsonpath='{.items[0].metadata.name}')" \ -- /bin/sh -c 'for i in $(seq 1 20); do curl -sS helloworld.sample:5000/hello; done'
O resultado é semelhante ao apresentado:
Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8 Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv ...
Parabéns, validou a sua malha de serviços na nuvem com vários clusters e equilíbrio de carga!
Limpe o serviço HelloWorld
Quando terminar a validação do equilíbrio de carga, remova o serviço HelloWorld
e Sleep
do cluster.
kubectl delete ns sample --context ${CTX_1} kubectl delete ns sample --context ${CTX_2}