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 ferramenta istioctl e de exemplos que o asmcli 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

  1. 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}"
    
  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, os context 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.

  1. 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}"))
    
  2. 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.

  1. 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
    
  2. 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

  1. Navegue para onde asmcli foi transferido e execute o seguinte comando para definir ASM_VERSION

    export ASM_VERSION="$(./asmcli --version)"
    
  2. 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 comando asmcli install. No comando seguinte, altere OUTPUT_DIR para o diretório que especificou em --output_dir.

    export SAMPLES_DIR=OUTPUT_DIR/istio-${ASM_VERSION%+*}
    

Ative a injeção de sidecar

  1. Crie o namespace de exemplo em cada cluster.

    for CTX in ${CTX_1} ${CTX_2}
    do
        kubectl create --context=${CTX} namespace sample
    done
    
  2. Ative o espaço de nomes para injeção. Os passos dependem da sua implementação do plano de controlo.

    Gerido (TD)

    1. 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:

    1. 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.

    2. 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

  1. Implemente HelloWorld v1 em CLUSTER_1 e v2 em CLUSTER_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
  2. Confirme se o HelloWorld v1 e o v2 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

  1. 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
    
  2. 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:

  1. 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
    ...
  2. 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}