Configure uma malha de vários clusters no GKE
Este guia explica como juntar dois clusters num único Cloud Service Mesh usando a AC de malha ou a AC do Istio, 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:
O Cloud Service Mesh versão 1.11 ou posterior instalado nos clusters que usam o
asmcli install
. Precisa deasmcli
, da ferramentaistioctl
e de exemplos queasmcli
transfere para o diretório que especificou em--output_dir
quando executouasmcli install
. Se precisar de configurar, siga os passos em Instale ferramentas dependentes e valide o cluster para: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 a AC do Istio, use o mesmo certificado de raiz personalizado para ambos os clusters.
Se a sua malha de serviços na nuvem for criada em clusters privados, recomendamos que crie uma única sub-rede na mesma VPC. Caso contrário, tem de garantir que:
- Os planos de controlo podem alcançar os planos de controlo de clusters privados remotos através dos IPs privados do cluster.
- Pode adicionar os intervalos de IP dos planos de controlo de chamadas às redes autorizadas dos clusters privados remotos. Para mais informações, consulte o artigo Configure a deteção de pontos finais entre clusters privados.
O servidor da API tem de estar acessível às outras instâncias do plano de controlo do Cloud Service Mesh na malha de vários clusters.
- Certifique-se de que os clusters têm o acesso global ativado.
- Certifique-se de que o IP do plano de controlo da malha de serviços na nuvem foi devidamente permitido através da lista de permissões com a rede autorizada principal.
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
Os passos necessários para configurar a deteção de pontos finais dependem de preferir usar a API declarativa em clusters numa frota ou ativá-la manualmente em clusters públicos ou clusters privados.
Ative a deteção de pontos finais entre clusters públicos ou privados com a API declarativa (pré-visualização)
Pode ativar a deteção de pontos finais em clusters públicos ou privados numa frota
aplicando a configuração "multicluster_mode":"connected"
no mapa de configuração
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.
Este método está disponível para instalações geridas do Cloud Service Mesh em todos os canais de lançamento. Esta é também a forma preferencial de configurar a deteção de pontos finais de vários clusters se tiver aprovisionado a malha de serviços na nuvem gerida através da funcionalidade Ativar malha de serviços na nuvem quando criar um novo cluster do GKE na Google Cloud consola.
Antes de continuar, tem de criar uma regra de firewall.
Para vários projetos, tem de adicionar manualmente FLEET_PROJECT_ID.svc.id.goog
a trustDomainAliases
na meshConfig
da revisão, se ainda não estiver presente.
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, 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.
Configure a deteção de pontos finais entre clusters públicos
Para configurar a deteção de pontos finais entre clusters do GKE, execute o comando
asmcli create-mesh
. Este comando:
- Regista todos os clusters na mesma frota.
- Configura a malha para confiar na identidade da carga de trabalho da frota.
- Cria segredos remotos.
Pode especificar o URI para cada cluster ou o caminho do ficheiro kubeconfig.
URI do cluster
No comando seguinte, substitua FLEET_PROJECT_ID
pelo ID do projeto anfitrião da frota e o URI do cluster pelo nome do cluster, a zona ou a região e o ID do projeto para cada cluster.
Este exemplo mostra apenas dois clusters, mas pode executar o comando para ativar a deteção de pontos finais em clusters adicionais, sujeito ao número máximo permitido de clusters que pode adicionar à sua frota.
./asmcli create-mesh \
FLEET_PROJECT_ID \
${PROJECT_1}/${LOCATION_1}/${CLUSTER_1} \
${PROJECT_2}/${LOCATION_2}/${CLUSTER_2}
ficheiro kubeconfig
No comando seguinte, substitua FLEET_PROJECT_ID
pelo ID do projeto do projeto anfitrião da frota e PATH_TO_KUBECONFIG
pelo caminho para cada ficheiro kubeconfig
. Este exemplo mostra apenas dois clusters, mas pode executar o comando para ativar a deteção de pontos finais em clusters adicionais, sujeito ao número máximo permitido de clusters que pode adicionar à sua frota.
./asmcli create-mesh \
FLEET_PROJECT_ID \
PATH_TO_KUBECONFIG_1 \
PATH_TO_KUBECONFIG_2
Configure a descoberta de pontos finais entre clusters privados
Configure segredos remotos para permitir o acesso do servidor da API ao cluster para o plano de controlo da Cloud Service Mesh do outro cluster. Os comandos dependem do tipo de Cloud Service Mesh (no cluster ou gerido):
A. Para a malha de serviços na nuvem no cluster, tem de configurar os IPs privados em vez dos IPs públicos, porque os IPs públicos não são acessíveis:
PRIV_IP=`gcloud container clusters describe "${CLUSTER_1}" --project "${PROJECT_1}" \ --zone "${LOCATION_1}" --format "value(privateClusterConfig.privateEndpoint)"` ./istioctl x create-remote-secret --context=${CTX_1} --name=${CLUSTER_1} --server=https://${PRIV_IP} > ${CTX_1}.secret
PRIV_IP=`gcloud container clusters describe "${CLUSTER_2}" --project "${PROJECT_2}" \ --zone "${LOCATION_2}" --format "value(privateClusterConfig.privateEndpoint)"` ./istioctl x create-remote-secret --context=${CTX_2} --name=${CLUSTER_2} --server=https://${PRIV_IP} > ${CTX_2}.secret
B. Para o Managed Cloud Service Mesh:
PUBLIC_IP=`gcloud container clusters describe "${CLUSTER_1}" --project "${PROJECT_1}" \ --zone "${LOCATION_1}" --format "value(privateClusterConfig.publicEndpoint)"` ./istioctl x create-remote-secret --context=${CTX_1} --name=${CLUSTER_1} --server=https://${PUBLIC_IP} > ${CTX_1}.secret
PUBLIC_IP=`gcloud container clusters describe "${CLUSTER_2}" --project "${PROJECT_2}" \ --zone "${LOCATION_2}" --format "value(privateClusterConfig.publicEndpoint)"` ./istioctl x create-remote-secret --context=${CTX_2} --name=${CLUSTER_2} --server=https://${PUBLIC_IP} > ${CTX_2}.secret
Aplique os novos segredos nos clusters:
kubectl apply -f ${CTX_1}.secret --context=${CTX_2}
kubectl apply -f ${CTX_2}.secret --context=${CTX_1}
Configure redes autorizadas para clusters privados
Siga esta secção apenas se todas as condições seguintes se aplicarem à sua malha:
- Está a usar clusters privados.
- Os clusters não pertencem à mesma sub-rede.
- Os clusters têm redes autorizadas ativadas.
Quando implementa vários clusters privados, o plano de controlo da malha de serviços na nuvem em cada cluster tem de chamar o plano de controlo do GKE dos clusters remotos. Para permitir o tráfego, tem de adicionar o intervalo de endereços do pod no cluster de chamada às redes autorizadas dos clusters remotos.
Obtenha o bloco CIDR de IP do agrupamento para cada cluster:
POD_IP_CIDR_1=`gcloud container clusters describe ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \ --format "value(ipAllocationPolicy.clusterIpv4CidrBlock)"`
POD_IP_CIDR_2=`gcloud container clusters describe ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \ --format "value(ipAllocationPolicy.clusterIpv4CidrBlock)"`
Adicione os blocos CIDR de IP de pods do cluster do Kubernetes aos clusters remotos:
EXISTING_CIDR_1=`gcloud container clusters describe ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \ --format "value(masterAuthorizedNetworksConfig.cidrBlocks.cidrBlock)"` gcloud container clusters update ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \ --enable-master-authorized-networks \ --master-authorized-networks ${POD_IP_CIDR_2},${EXISTING_CIDR_1//;/,}
EXISTING_CIDR_2=`gcloud container clusters describe ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \ --format "value(masterAuthorizedNetworksConfig.cidrBlocks.cidrBlock)"` gcloud container clusters update ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \ --enable-master-authorized-networks \ --master-authorized-networks ${POD_IP_CIDR_1},${EXISTING_CIDR_2//;/,}
Para mais informações, consulte o artigo Criar um cluster com redes autorizadas.
Confirme se as redes autorizadas estão atualizadas:
gcloud container clusters describe ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \ --format "value(masterAuthorizedNetworksConfig.cidrBlocks.cidrBlock)"
gcloud container clusters describe ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \ --format "value(masterAuthorizedNetworksConfig.cidrBlocks.cidrBlock)"
Ative o acesso global ao plano de controlo
Siga esta secção apenas se todas as condições seguintes se aplicarem à sua malha:
- Está a usar clusters privados.
- Usar regiões diferentes para os clusters na sua rede de malha.
Tem de ativar o acesso global do plano de controlo para permitir que o plano de controlo da Cloud Service Mesh em cada cluster chame o plano de controlo do GKE dos clusters remotos.
Ative o acesso global do plano de controlo:
gcloud container clusters update ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \ --enable-master-global-access
gcloud container clusters update ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \ --enable-master-global-access
Verifique se o acesso global do plano de controlo está ativado:
gcloud container clusters describe ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1}
gcloud container clusters describe ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2}
A secção
privateClusterConfig
na saída apresenta o estado demasterGlobalAccessConfig
.
Valide a conetividade multicluster
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.
OUTPUT_DIR/istio-${ASM_VERSION%+*}/samples
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
Localize o valor da etiqueta de revisão, que usa em passos posteriores. O passo depende do tipo de Cloud Service Mesh (gerido ou no cluster).
Gerido
Use o comando seguinte para localizar a etiqueta de revisão, que vai usar nos passos posteriores.
kubectl get controlplanerevision -n istio-system
O resultado tem um aspeto semelhante ao seguinte:
NAME RECONCILED STALLED AGE asm-managed-rapid True False 89d
No resultado, na coluna
NAME
, tome nota do valor da etiqueta de revisão. Neste exemplo, o valor éasm-managed-rapid
. Use o valor da revisão nos passos da secção seguinte.No cluster
Use o comando seguinte para localizar a etiqueta de revisão, que vai usar nos passos posteriores.
kubectl -n istio-system get pods -l app=istiod --show-labels
O resultado tem um aspeto semelhante ao seguinte:
NAME READY STATUS RESTARTS AGE LABELS istiod-asm-173-3-5788d57586-bljj4 1/1 Running 0 23h app=istiod,istio.io/rev=asm-173-3,istio=istiod,pod-template-hash=5788d57586 istiod-asm-173-3-5788d57586-vsklm 1/1 Running 1 23h app=istiod,istio.io/rev=asm-173-3,istio=istiod,pod-template-hash=5788d57586
Na saída, na coluna
LABELS
, repare no valor da etiqueta de revisãoistiod
, que segue o prefixoistio.io/rev=
. Neste exemplo, o valor éasm-173-3
. Use o valor da revisão nos passos da secção seguinte.
Instale o serviço HelloWorld
Crie o namespace de exemplo e a definição de serviço em cada cluster. No comando seguinte, substitua REVISION pela
istiod
etiqueta de revisão que anotou no passo anterior.for CTX in ${CTX_1} ${CTX_2} do kubectl create --context=${CTX} namespace sample kubectl label --context=${CTX} namespace sample \ istio-injection- istio.io/rev=REVISION --overwrite done
onde REVISION é a etiqueta de revisão
istiod
que anotou anteriormente.O resultado é:
label "istio-injection" not found. namespace/sample labeled
Pode ignorar com segurança
label "istio-injection" not found.
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}