Executando serviços distribuídos em clusters privados do GKE usando o Cloud Service Mesh

Este documento mostra como executar serviços distribuídos em vários clusters do Google Kubernetes Engine (GKE) em Google Cloud usando o Cloud Service Mesh. Este documento também mostra como expor um serviço distribuído usando o Multi Cluster Ingress e o Cloud Service Mesh. Você pode usar este documento para configurar clusters do GKE não privados; o documento destaca a configuração destinada estritamente a clusters privados.

Este documento destina-se a administradores de plataforma e operadores de serviço com conhecimento básico do Kubernetes. Conhecimentos de Service Mesh são benéficos, embora não sejam obrigatórios. O Cloud Service Mesh é baseado na tecnologia Istio de código aberto. Para obter mais informações sobre Service Mesh e Istio, consulte istio.io .

Um serviço distribuído é um serviço do Kubernetes que atua como um único serviço lógico. Serviços distribuídos são mais resilientes do que serviços do Kubernetes porque são executados em vários clusters do Kubernetes no mesmo namespace. Um serviço distribuído permanece ativo mesmo que um ou mais clusters do GKE estejam inativos, desde que os clusters íntegros consigam atender à carga desejada.

Os serviços do Kubernetes são conhecidos apenas pelo servidor da API do Kubernetes do cluster em que são executados. Se o cluster do Kubernetes estiver inativo (por exemplo, durante uma manutenção programada), todos os serviços do Kubernetes em execução nesse cluster também estarão inativos. A execução de serviços distribuídos facilita o gerenciamento do ciclo de vida do cluster, pois você pode desativar clusters para manutenção ou atualizações enquanto outros clusters atendem ao tráfego. Para criar um serviço distribuído, a funcionalidade de malha de serviços fornecida pelo Cloud Service Mesh é usada para vincular serviços em execução em vários clusters para atuarem como um único serviço lógico.

Os clusters privados do GKE permitem configurar os nós e o servidor de API como recursos privados disponíveis apenas na rede de Nuvem Privada Virtual (VPC). A execução de serviços distribuídos em clusters privados do GKE oferece às empresas serviços seguros e confiáveis.

Arquitetura

Este tutorial usa a arquitetura mostrada no diagrama a seguir:

Arquitetura de serviços distribuídos em clusters privados do GKE usando o Cloud Service Mesh

No diagrama anterior, a arquitetura inclui os seguintes clusters:

  • Dois clusters ( gke-central-priv e gke-west-priv ) atuam como clusters privados idênticos do GKE em duas regiões diferentes.
  • Um cluster separado ( ingress-config ) atua como o cluster do plano de controle que configura o Multi Cluster Ingress.

Neste tutorial, você implantará o aplicativo de exemplo do Bank of Anthos em dois clusters privados do GKE ( gke-central-priv e gke-west-priv ). O Bank of Anthos é um aplicativo de microsserviços de exemplo que consiste em vários microsserviços e bancos de dados SQL que simulam um aplicativo de banco online. O aplicativo consiste em um front-end web que os clientes podem acessar e vários serviços de back-end, como serviços de saldo, razão e conta, que simulam um banco.

O aplicativo inclui dois bancos de dados PostgreSQL instalados no Kubernetes como StatefulSets. Um banco de dados é usado para transações, enquanto o outro é usado para contas de usuário. Todos os serviços, exceto os dois bancos de dados, são executados como serviços distribuídos. Isso significa que os Pods para todos os serviços são executados em ambos os clusters de aplicativos (no mesmo namespace), e o Cloud Service Mesh é configurado para que cada serviço apareça como um único serviço lógico.

Objetivos

  • Crie três clusters do GKE.
  • Configure dois dos clusters do GKE como clusters privados ( gke-central-priv e gke-west-priv ).
  • Configure um cluster do GKE ( ingress-config ) como o cluster de configuração central. Este cluster atua como um cluster de configuração para o Multi Cluster Ingress.
  • Configure a rede (gateways NAT, roteador de nuvem e regras de firewall) para permitir tráfego entre clusters e de saída dos dois clusters privados do GKE.
  • Configure redes autorizadas para permitir acesso ao serviço de API do Cloud Shell aos dois clusters privados do GKE.
  • Implante e configure o Cloud Service Mesh multicluster nos dois clusters privados no modo multiprimário. O modo multiprimário implanta um plano de controle do Cloud Service Mesh em ambos os clusters.
  • Implante o aplicativo Bank of Anthos nos dois clusters privados. Todos os serviços, exceto os bancos de dados, são implantados como serviços distribuídos (pods em execução nos dois clusters privados).
  • Monitore serviços usando o Cloud Service Mesh.
  • Configure o Multi Cluster Ingress nos serviços frontend do Bank of Anthos. Isso permite que clientes externos (por exemplo, seu navegador da Web) acessem um serviço distribuído em execução em uma frota de clusters privados do GKE.

Custos

Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços. Novos usuários do Google Cloud podem estar qualificados para uma avaliação gratuita.

Antes de começar

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Make sure that billing is enabled for your Google Cloud project.

  3. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

    Você executa todos os comandos neste tutorial no Cloud Shell.

  4. Defina as variáveis ​​de ambiente usadas neste tutorial. As variáveis ​​definem nomes de cluster, regiões, zonas, endereçamento IP e versões do Cloud Service Mesh usadas neste tutorial.

    1. Substitua YOUR_PROJECT_ID pelo ID do seu projeto:

      export PROJECT_ID=YOUR_PROJECT_ID
      gcloud config set project ${PROJECT_ID}
      
    2. Defina as variáveis ​​de ambiente restantes:

      export CLUSTER_1=gke-west-priv
      export CLUSTER_2=gke-central-priv
      export CLUSTER_1_ZONE=us-west2-a
      export CLUSTER_1_REGION=us-west2
      export CLUSTER_1_MASTER_IPV4_CIDR=172.16.0.0/28
      export CLUSTER_2_ZONE=us-central1-a
      export CLUSTER_2_REGION=us-central1
      export CLUSTER_2_MASTER_IPV4_CIDR=172.16.1.0/28
      export CLUSTER_INGRESS=gke-ingress
      export CLUSTER_INGRESS_ZONE=us-west1-a
      export CLUSTER_INGRESS_REGION=us-west1
      export CLUSTER_INGRESS_MASTER_IPV4_CIDR=172.16.2.0/28
      export WORKLOAD_POOL=${PROJECT_ID}.svc.id.goog
      export ASM_VERSION=1.10
      export CLOUDSHELL_IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
      

Prepare seu ambiente

  1. No Cloud Shell, habilite as APIs:

    gcloud services enable \
      --project=${PROJECT_ID} \
      container.googleapis.com \
      mesh.googleapis.com \
      gkehub.googleapis.com
    
  2. Habilite o Cloud Service Mesh Fleet para seu projeto:

    gcloud container fleet mesh enable --project=${PROJECT_ID}
    

Preparar a rede para clusters privados do GKE

Nesta seção, você prepara a rede para os clusters privados do GKE que você usa para executar serviços distribuídos.

Os nós de cluster privados do GKE não recebem um endereço IP público. Todos os nós em um cluster privado do GKE recebem um endereço IP privado da VPC (no espaço de endereço RFC 1918). Isso significa que os pods que precisam acessar recursos externos (fora da rede da VPC) precisam de um gateway NAT do Cloud . Os gateways NAT do Cloud são gateways NAT regionais que permitem que pods com endereços IP internos se comuniquem com a Internet. Neste tutorial, você configurará um gateway NAT do Cloud em cada uma de duas regiões. Vários clusters em uma região podem usar o mesmo gateway NAT.

  1. No Cloud Shell, crie e reserve dois endereços IP externos para os dois gateways NAT:

    gcloud compute addresses create ${CLUSTER_1_REGION}-nat-ip \
      --project=${PROJECT_ID} \
      --region=${CLUSTER_1_REGION}
    
    gcloud compute addresses create ${CLUSTER_2_REGION}-nat-ip \
      --project=${PROJECT_ID} \
      --region=${CLUSTER_2_REGION}
    
  2. Armazene o endereço IP e o nome dos endereços IP em variáveis:

    export NAT_REGION_1_IP_ADDR=$(gcloud compute addresses describe ${CLUSTER_1_REGION}-nat-ip \
      --project=${PROJECT_ID} \
      --region=${CLUSTER_1_REGION} \
      --format='value(address)')
    
    export NAT_REGION_1_IP_NAME=$(gcloud compute addresses describe ${CLUSTER_1_REGION}-nat-ip \
      --project=${PROJECT_ID} \
      --region=${CLUSTER_1_REGION} \
      --format='value(name)')
    
    export NAT_REGION_2_IP_ADDR=$(gcloud compute addresses describe ${CLUSTER_2_REGION}-nat-ip \
      --project=${PROJECT_ID} \
      --region=${CLUSTER_2_REGION} \
      --format='value(address)')
    
    export NAT_REGION_2_IP_NAME=$(gcloud compute addresses describe ${CLUSTER_2_REGION}-nat-ip \
      --project=${PROJECT_ID} \
      --region=${CLUSTER_2_REGION} \
      --format='value(name)')
    
  3. Crie gateways do Cloud NAT nas duas regiões dos clusters privados do GKE:

    gcloud compute routers create rtr-${CLUSTER_1_REGION} \
      --network=default \
      --region ${CLUSTER_1_REGION}
    
    gcloud compute routers nats create nat-gw-${CLUSTER_1_REGION} \
      --router=rtr-${CLUSTER_1_REGION} \
      --region ${CLUSTER_1_REGION} \
      --nat-external-ip-pool=${NAT_REGION_1_IP_NAME} \
      --nat-all-subnet-ip-ranges \
      --enable-logging
    
    gcloud compute routers create rtr-${CLUSTER_2_REGION} \
      --network=default \
      --region ${CLUSTER_2_REGION}
    
    gcloud compute routers nats create nat-gw-${CLUSTER_2_REGION} \
      --router=rtr-${CLUSTER_2_REGION} \
      --region ${CLUSTER_2_REGION} \
      --nat-external-ip-pool=${NAT_REGION_2_IP_NAME} \
      --nat-all-subnet-ip-ranges \
      --enable-logging
    
  4. Crie uma regra de firewall que permita a comunicação entre pods e entre pods e servidores de API. A comunicação entre pods permite que os serviços distribuídos se comuniquem entre si nos clusters do GKE. A comunicação entre pods e servidores de API permite que o plano de controle do Cloud Service Mesh consulte os clusters do GKE para descoberta de serviços.

    gcloud compute firewall-rules create all-pods-and-master-ipv4-cidrs \
      --project ${PROJECT_ID} \
      --network default \
      --allow all \
      --direction INGRESS \
      --source-ranges 10.0.0.0/8,${CLUSTER_1_MASTER_IPV4_CIDR},${CLUSTER_2_MASTER_IPV4_CIDR},${CLUSTER_INGRESS_MASTER_IPV4_CIDR}
    

A rede agora está preparada. Neste tutorial, você usará todo o intervalo de endereços IP 10.0.0.0/8 , que inclui todos os intervalos de Pods. Recomendamos que você crie uma regra de firewall mais rigorosa em produção, com base nas suas condições e requisitos.

Criar clusters privados do GKE

Nesta seção, você criará os dois clusters privados do GKE onde o aplicativo de exemplo será implantado. Neste tutorial, os nós do cluster privado do GKE têm endereços IP privados e o servidor de API tem um endpoint público. No entanto, o acesso ao servidor de API é restrito usando redes autorizadas.

  1. No Cloud Shell, crie dois clusters privados com redes autorizadas. Configure os clusters para permitir acesso a partir do intervalo CIDR de IP do Pod (para o plano de controle do Cloud Service Mesh) e do Cloud Shell para que você possa acessá-los a partir do seu terminal.

    gcloud container clusters create ${CLUSTER_1} \
      --project ${PROJECT_ID} \
      --zone=${CLUSTER_1_ZONE} \
      --machine-type "e2-standard-4" \
      --num-nodes "3" --min-nodes "3" --max-nodes "5" \
      --enable-ip-alias --enable-autoscaling \
      --workload-pool=${WORKLOAD_POOL} \
      --enable-private-nodes \
      --master-ipv4-cidr=${CLUSTER_1_MASTER_IPV4_CIDR} \
      --enable-master-authorized-networks \
      --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32
    
    gcloud container clusters create ${CLUSTER_2} \
      --project ${PROJECT_ID} \
      --zone=${CLUSTER_2_ZONE} \
      --machine-type "e2-standard-4" \
      --num-nodes "3" --min-nodes "3" --max-nodes "5" \
      --enable-ip-alias --enable-autoscaling \
      --workload-pool=${WORKLOAD_POOL} \
      --enable-private-nodes \
      --master-ipv4-cidr=${CLUSTER_2_MASTER_IPV4_CIDR} \
      --enable-master-authorized-networks \
      --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32
    

    As redes autorizadas contêm os endereços IP públicos nos gateways do Cloud NAT. Como o endpoint do servidor de API de um cluster privado é um endpoint público, os pods executados em um cluster privado devem usar um gateway do Cloud NAT para acessar os endpoints do servidor de API público.

    O endereço IP do Cloud Shell também faz parte das redes autorizadas, o que permite acessar e gerenciar clusters a partir do seu terminal do Cloud Shell. Os endereços IP públicos do Cloud Shell são dinâmicos, portanto, sempre que você iniciar o Cloud Shell, poderá obter um endereço IP público diferente. Ao obter um novo endereço IP, você perde o acesso aos clusters, pois ele não faz parte das redes autorizadas para os dois clusters.

    Se você perder o acesso aos clusters, atualize as redes autorizadas dos clusters para incluir o novo endereço IP do Cloud Shell:

    1. Obtenha o endereço IP público atualizado do Cloud Shell:

      export CLOUDSHELL_IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
      
    2. Atualize as redes autorizadas para os dois clusters:

      gcloud container clusters update ${CLUSTER_1} \
        --zone=${CLUSTER_1_ZONE} \
        --enable-master-authorized-networks \
        --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32
      
      gcloud container clusters update ${CLUSTER_2} \
        --zone=${CLUSTER_2_ZONE} \
        --enable-master-authorized-networks \
        --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32
      
  2. Verifique se todos os clusters estão em execução:

    gcloud container clusters list
    

    A saída se parece com o seguinte:

    NAME              LOCATION       MASTER_VERSION    MASTER_IP      MACHINE_TYPE   NODE_VERSION      NUM_NODES  STATUS
    gke-central-priv  us-central1-a  1.16.15-gke.6000  35.238.99.104  e2-standard-4  1.16.15-gke.6000  3          RUNNING
    gke-west-priv     us-west2-a     1.16.15-gke.6000  34.94.188.180  e2-standard-4  1.16.15-gke.6000  3          RUNNING
    
  3. Conecte-se aos dois clusters para gerar entradas no arquivo kubeconfig:

    touch ~/asm-kubeconfig && export KUBECONFIG=~/asm-kubeconfig
    gcloud container clusters get-credentials ${CLUSTER_1} --zone ${CLUSTER_1_ZONE}
    gcloud container clusters get-credentials ${CLUSTER_2} --zone ${CLUSTER_2_ZONE}
    

    Use o arquivo kubeconfig para autenticar em clusters, criando um usuário e um contexto para cada cluster. Após gerar entradas no arquivo kubeconfig, você pode alternar rapidamente o contexto entre os clusters.

  4. Renomeie os contextos do cluster para maior conveniência:

    kubectl config rename-context \
    gke_${PROJECT_ID}_${CLUSTER_1_ZONE}_${CLUSTER_1} ${CLUSTER_1}
    
    kubectl config rename-context \
    gke_${PROJECT_ID}_${CLUSTER_2_ZONE}_${CLUSTER_2} ${CLUSTER_2}
    
  5. Confirme se ambos os contextos de cluster estão renomeados e configurados corretamente:

    kubectl config get-contexts --output="name"
    

    A saída se parece com o seguinte:

    gke-central-priv
    gke-west-priv
    
  6. Registre seus clusters em uma frota:

    gcloud container fleet memberships register ${CLUSTER_1} --gke-cluster=${CLUSTER_1_ZONE}/${CLUSTER_1} --enable-workload-identity
    gcloud container fleet memberships register ${CLUSTER_2} --gke-cluster=${CLUSTER_2_ZONE}/${CLUSTER_2} --enable-workload-identity
    

Agora você criou e renomeou seus clusters privados do GKE.

Instalar Cloud Service Mesh

Nesta seção, você instala o Cloud Service Mesh nos dois clusters do GKE e configura os clusters para descoberta de serviços entre clusters.

  1. No Cloud Shell, instale o Cloud Service Mesh em ambos os clusters usando a fleet API :

    gcloud container fleet mesh update --management automatic --memberships ${CLUSTER_1},${CLUSTER_2}
    
  2. Depois que o Cloud Service Mesh gerenciado for habilitado nos clusters, defina uma observação para que o mesh seja instalado:

    watch -g "gcloud container fleet mesh describe | grep 'code: REVISION_READY'"
    
  3. Instale os gateways de entrada do Cloud Service Mesh para ambos os clusters:

    kubectl --context=${CLUSTER_1} create namespace asm-ingress
    kubectl --context=${CLUSTER_1} label namespace asm-ingress istio-injection=enabled --overwrite
    kubectl --context=${CLUSTER_2} create namespace asm-ingress
    kubectl --context=${CLUSTER_2} label namespace asm-ingress istio-injection=enabled --overwrite
    
    cat <<'EOF' > asm-ingress.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: asm-ingressgateway
      namespace: asm-ingress
    spec:
      type: LoadBalancer
      selector:
        asm: ingressgateway
      ports:
      - port: 80
        name: http
      - port: 443
        name: https
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: asm-ingressgateway
      namespace: asm-ingress
    spec:
      selector:
        matchLabels:
          asm: ingressgateway
      template:
        metadata:
          annotations:
            # This is required to tell Anthos Service Mesh to inject the gateway with the
            # required configuration.
            inject.istio.io/templates: gateway
          labels:
            asm: ingressgateway
        spec:
          containers:
          - name: istio-proxy
            image: auto # The image will automatically update each time the pod starts.
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: asm-ingressgateway-sds
      namespace: asm-ingress
    rules:
    - apiGroups: [""]
      resources: ["secrets"]
      verbs: ["get", "watch", "list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: asm-ingressgateway-sds
      namespace: asm-ingress
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: asm-ingressgateway-sds
    subjects:
    - kind: ServiceAccount
      name: default
    EOF
    
    kubectl --context=${CLUSTER_1} apply -f asm-ingress.yaml
    kubectl --context=${CLUSTER_2} apply -f asm-ingress.yaml
    
  4. Verifique se os gateways de entrada do Cloud Service Mesh estão implantados:

    kubectl --context=${CLUSTER_1} get pod,service -n asm-ingress
    kubectl --context=${CLUSTER_2} get pod,service -n asm-ingress
    

    A saída para ambos os clusters se parece com o seguinte:

    NAME                                        READY   STATUS    RESTARTS   AGE
    pod/asm-ingressgateway-5894744dbd-zxlgc   1/1     Running   0          84s
    
    NAME                           TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)                      AGE
    service/asm-ingressgateway   LoadBalancer   10.16.2.131   34.102.100.138   80:30432/TCP,443:30537/TCP   92s
    

    Após a instalação do plano de controle do Cloud Service Mesh e dos gateways de entrada para ambos os clusters, a descoberta de serviços entre clusters é habilitada com a API da frota. A descoberta de serviços entre clusters permite que os dois clusters descubram pontos de extremidade de serviço do cluster remoto. Serviços distribuídos são executados em vários clusters no mesmo namespace .

    Para que ambos os planos de controle do Cloud Service Mesh descubram todos os endpoints de um serviço distribuído, o Cloud Service Mesh precisa ter acesso a todos os clusters que executam o serviço distribuído. Este exemplo usa dois clusters, portanto, ambos os clusters precisam ser capazes de consultar o cluster remoto em busca de endpoints de serviço. Com o Cloud Service Mesh gerenciado habilitado com a API da frota, a descoberta de endpoints é configurada automaticamente.

Os clusters e o Cloud Service Mesh agora estão configurados.

Implantar o aplicativo Bank of Anthos

  1. No Cloud Shell, clone o repositório GitHub do Bank of Anthos:

    git clone https://github.com/GoogleCloudPlatform/bank-of-anthos.git ${HOME}/bank-of-anthos
    
  2. Crie e rotule um namespace bank-of-anthos em ambos os clusters. O rótulo permite a injeção automática dos proxies Envoy do sidecar em cada pod dentro do namespace rotulado.

    # cluster_1
    kubectl create --context=${CLUSTER_1} namespace bank-of-anthos
    kubectl label --context=${CLUSTER_1} namespace bank-of-anthos istio-injection=enabled
    
    # cluster_2
    kubectl create --context=${CLUSTER_2} namespace bank-of-anthos
    kubectl label --context=${CLUSTER_2} namespace bank-of-anthos istio-injection=enabled
    
  3. Implante o aplicativo Bank of Anthos em ambos os clusters no namespace bank-of-anthos .

    # The following secret is used for user account creation and authentication
    kubectl --context=$CLUSTER_1 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/extras/jwt/jwt-secret.yaml
    kubectl --context=$CLUSTER_2 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/extras/jwt/jwt-secret.yaml
    
    # Deploy all manifests to both clusters
    kubectl --context=$CLUSTER_1 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/kubernetes-manifests
    kubectl --context=$CLUSTER_2 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/kubernetes-manifests
    

    Os serviços do Kubernetes precisam estar em ambos os clusters para a descoberta de serviços. Quando um serviço em um dos clusters tenta fazer uma solicitação, ele primeiro realiza uma consulta DNS do nome do host para obter o endereço IP. No GKE, o servidor kube-dns em execução no cluster lida com essa consulta, portanto, uma definição de serviço configurada é necessária.

  4. Exclua os StatefulSets de um cluster para que os dois bancos de dados PostgreSQL existam em apenas um dos clusters:

    # Delete the two DB statefulSets from Cluster2
    kubectl --context=$CLUSTER_2 -n bank-of-anthos delete statefulset accounts-db
    kubectl --context=$CLUSTER_2 -n bank-of-anthos delete statefulset ledger-db
    
  5. Certifique-se de que todos os Pods estejam em execução em ambos os clusters:

    1. Obter Pods do cluster_1 :

      kubectl --context=${CLUSTER_1} -n bank-of-anthos get pod
      

      A saída se parece com o seguinte:

      NAME                                  READY   STATUS    RESTARTS   AGE
      accounts-db-0                         2/2     Running   0          9m54s
      balancereader-c5d664b4c-xmkrr         2/2     Running   0          9m54s
      contacts-7fd8c5fb6-wg9xn              2/2     Running   1          9m53s
      frontend-7b7fb9b665-m7cw7             2/2     Running   1          9m53s
      ledger-db-0                           2/2     Running   0          9m53s
      ledgerwriter-7b5b6db66f-xhbp4         2/2     Running   0          9m53s
      loadgenerator-7fb54d57f8-g5lz5        2/2     Running   0          9m52s
      transactionhistory-7fdb998c5f-vqh5w   2/2     Running   1          9m52s
      userservice-76996974f5-4wlpf          2/2     Running   1          9m52s
      
    2. Obter Pods do cluster_2 :

      kubectl --context=${CLUSTER_2} -n bank-of-anthos get pod
      

      A saída se parece com o seguinte:

      NAME                                  READY   STATUS    RESTARTS   AGE
      balancereader-c5d664b4c-bn2pl         2/2     Running   0          9m54s
      contacts-7fd8c5fb6-kv8cp              2/2     Running   0          9m53s
      frontend-7b7fb9b665-bdpp4             2/2     Running   0          9m53s
      ledgerwriter-7b5b6db66f-297c2         2/2     Running   0          9m52s
      loadgenerator-7fb54d57f8-tj44v        2/2     Running   0          9m52s
      transactionhistory-7fdb998c5f-xvmtn   2/2     Running   0          9m52s
      userservice-76996974f5-mg7t6          2/2     Running   0          9m51s
      
  6. Implante as configurações do Cloud Service Mesh em ambos os clusters. Isso cria um Gateway no namespace asm-ingress e um VirtualService nos namespaces bank-of-anthos para o serviço frontend , o que permite a entrada de tráfego para o serviço frontend .

    Gateways geralmente são de propriedade dos administradores da plataforma ou da equipe de administradores da rede. Portanto, o recurso Gateway é criado no namespace Ingress Gateway, de propriedade do administrador da plataforma, e pode ser usado em outros namespaces por meio de suas próprias entradas VirtualService . Este é um modelo de "Gateway Compartilhado".

    cat <<'EOF' > asm-vs-gateway.yaml
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: asm-ingressgateway
      namespace: asm-ingress
    spec:
      selector:
        asm: ingressgateway
      servers:
        - port:
            number: 80
            name: http
            protocol: HTTP
          hosts:
            - "*"
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: frontend
      namespace: bank-of-anthos
    spec:
      hosts:
      - "*"
      gateways:
      - asm-ingress/asm-ingressgateway
      http:
      - route:
        - destination:
            host: frontend
            port:
              number: 80
    EOF
    
    kubectl --context=$CLUSTER_1 apply -f asm-vs-gateway.yaml
    
    kubectl --context=$CLUSTER_2 apply -f asm-vs-gateway.yaml
    

Agora você implantou o aplicativo Bank of Anthos em dois clusters privados do GKE. Todos os serviços são executados como serviços distribuídos, exceto o banco de dados.

Inspecionar serviços distribuídos

Nesta seção, você usará a ferramenta istioctl para inspecionar a configuração de proxy de qualquer um dos proxies. Isso permitirá que você veja se os proxies sidecar veem dois Pods para cada serviço, com um Pod em execução em cada cluster.

  1. No Cloud Shell, inspecione a lista de endpoints do proxy-config no pod do frontend no cluster_1 :

    export FRONTEND1=$(kubectl get pod -n bank-of-anthos -l app=frontend \
      --context=${CLUSTER_1} -o jsonpath='{.items[0].metadata.name}')
    istioctl proxy-config endpoints \
    --context $CLUSTER_1 -n bank-of-anthos $FRONTEND1 | grep bank-of-anthos
    

    A saída se parece com o seguinte:

    10.12.0.6:5432                   HEALTHY     OK                outbound|5432||accounts-db.bank-of-anthos.svc.cluster.local
    10.12.0.7:8080                   HEALTHY     OK                outbound|8080||balancereader.bank-of-anthos.svc.cluster.local
    10.12.0.8:8080                   HEALTHY     OK                outbound|8080||transactionhistory.bank-of-anthos.svc.cluster.local
    10.12.0.9:8080                   HEALTHY     OK                outbound|8080||userservice.bank-of-anthos.svc.cluster.local
    10.12.1.10:8080                  HEALTHY     OK                outbound|8080||ledgerwriter.bank-of-anthos.svc.cluster.local
    10.12.1.9:8080                   HEALTHY     OK                outbound|8080||contacts.bank-of-anthos.svc.cluster.local
    10.12.2.11:5432                  HEALTHY     OK                outbound|5432||ledger-db.bank-of-anthos.svc.cluster.local
    10.12.2.13:8080                  HEALTHY     OK                outbound|80||frontend.bank-of-anthos.svc.cluster.local
    10.76.1.10:8080                  HEALTHY     OK                outbound|8080||transactionhistory.bank-of-anthos.svc.cluster.local
    10.76.1.8:8080                   HEALTHY     OK                outbound|8080||balancereader.bank-of-anthos.svc.cluster.local
    10.76.1.9:8080                   HEALTHY     OK                outbound|80||frontend.bank-of-anthos.svc.cluster.local
    10.76.2.10:8080                  HEALTHY     OK                outbound|8080||userservice.bank-of-anthos.svc.cluster.local
    10.76.2.8:8080                   HEALTHY     OK                outbound|8080||contacts.bank-of-anthos.svc.cluster.local
    10.76.2.9:8080                   HEALTHY     OK                outbound|8080||ledgerwriter.bank-of-anthos.svc.cluster.local
    

    Na saída anterior, cada serviço distribuído possui dois endereços IP de endpoint. Esses são os endereços IP de pod, um para cada cluster.

Acesso ao Banco Anthos

Para acessar o aplicativo Bank of Anthos, você pode usar o endereço IP público do serviço asm-ingressgateway de qualquer cluster.

  1. Obtenha endereços IP asm-ingressgateway de ambos os clusters:

    kubectl --context ${CLUSTER_1} \
    --namespace asm-ingress get svc asm-ingressgateway -o jsonpath='{.status.loadBalancer}' | grep "ingress"
    
    kubectl --context ${CLUSTER_2} \
    --namespace asm-ingress get svc asm-ingressgateway -o jsonpath='{.status.loadBalancer}' | grep "ingress"
    
    

    A saída se parece com o seguinte.

    {"ingress":[{"ip":"35.236.4.18"}]}
    {"ingress":[{"ip":"34.68.94.81"}]}
    

    Copie um dos endereços IP para usar na próxima etapa.

  2. Abra uma nova aba em um navegador e acesse o endereço IP da saída anterior. O frontend do Bank of Anthos deverá ser exibido, permitindo que você faça login, deposite fundos na sua conta e transfira fundos para outras contas. O aplicativo deverá estar totalmente funcional.

Visualize serviços distribuídos

Você pode visualizar serviços distribuídos no Cloud Service Mesh.

  1. Para visualizar seus serviços, acesse a página Anthos > Service Mesh no Google Cloud console.

    Ir para Service Mesh

    Você pode visualizar os serviços na visualização de Tabela ou na visualização de Topologia . A visualização padrão é a visualização de Tabela, que mostra todos os seus serviços distribuídos em execução em formato tabular. Para alterar as visualizações, clique na visualização que deseja exibir.

  2. Na visualização Tabelas , clique no frontend distributed service . Ao clicar em um serviço individual, você verá uma visão detalhada do serviço, juntamente com os serviços conectados.

    Na exibição de detalhes do serviço, você pode criar SLOs e visualizar um cronograma histórico do serviço clicando em Mostrar cronograma .

  3. Para visualizar sinais dourados, no painel lateral, clique em Métricas .

  4. No gráfico Solicitações por segundo , clique em Detalhamento por e selecione Local .

    Os resultados exibem as solicitações por segundo de ambos os clusters nas duas regiões. O serviço distribuído está íntegro e ambos os endpoints estão atendendo tráfego.

  5. Para visualizar a topologia da sua malha de serviço, no painel lateral, clique em Anthos Service Mesh e, em seguida, clique em Exibição de topologia .

  6. Para visualizar dados adicionais, mantenha o ponteiro do mouse sobre o serviço frontend . Isso exibirá informações como solicitações por segundo de e para o frontend para outros serviços.

  7. Para ver mais detalhes, clique em "Expandir" no serviço frontend . Um Serviço e uma Carga de Trabalho são exibidos. Você pode expandir a carga de trabalho em duas Implantações, expandir as implantações em ReplicaSets e expandir os ReplicaSets em Pods. Ao expandir todos os elementos, você verá o serviço frontend distribuído, que é essencialmente um Serviço e dois Pods.

Configurar entrada de vários clusters

Nesta seção, você criará um Ingress de vários clusters que enviará tráfego para os serviços frontend do Bank of GKE Enterprise em execução em ambos os clusters. Use o Cloud Load Balancing para criar um balanceador de carga que usa os serviços asm-ingressgateway em ambos os clusters como back-ends. Um cluster ingress-config é usado para orquestrar a configuração do Ingress de vários clusters.

Para criar o balanceador de carga, use um MultiClusterIngress e um ou mais MultiClusterServices . Os objetos MultiClusterIngress e MultiClusterService são análogos de vários clusters para os recursos de entrada e serviço existentes do Kubernetes que são usados ​​no contexto de cluster único.

  1. Habilite as APIs necessárias do GKE Enterprise, GKE Fleet e Multi Cluster Ingress:

    gcloud services enable \
      anthos.googleapis.com \
      multiclusterservicediscovery.googleapis.com \
      multiclusteringress.googleapis.com
    
  2. Crie o cluster ingress-config . Você pode usar qualquer cluster, mas recomendamos criar um cluster separado para essa finalidade.

    gcloud container clusters create ${CLUSTER_INGRESS} \
      --zone ${CLUSTER_INGRESS_ZONE} \
      --num-nodes=1 \
      --enable-ip-alias \
      --workload-pool=${WORKLOAD_POOL}
    
  3. Obtenha as credenciais do cluster e renomeie o contexto para sua conveniência:

    gcloud container clusters get-credentials ${CLUSTER_INGRESS} \
      --zone ${CLUSTER_INGRESS_ZONE} --project ${PROJECT_ID}
    
    kubectl config rename-context \
      gke_${PROJECT_ID}_${CLUSTER_INGRESS_ZONE}_${CLUSTER_INGRESS} ${CLUSTER_INGRESS}
    
  4. Para usar o Multi Cluster Ingress, registre todos os clusters participantes no GKE Enterprise Fleet, incluindo o cluster de configuração:

  5. Registre o cluster de configuração:

    gcloud container fleet memberships register ${CLUSTER_INGRESS} \
      --project=${PROJECT_ID} \
      --gke-cluster=${CLUSTER_INGRESS_ZONE}/${CLUSTER_INGRESS} \
      --enable-workload-identity
    
  6. Verifique se todos os clusters estão registrados no GKE Enterprise Fleet:

    gcloud container fleet memberships list
    

    A saída se parece com o seguinte:

    NAME            EXTERNAL_ID
    gke-west        7fe5b7ce-50d0-4e64-a9af-55d37b3dd3fa
    gke-central     6f1f6bb2-a3f6-4e9c-be52-6907d9d258cd
    gke-ingress     3574ee0f-b7e6-11ea-9787-42010a8a019c
    
  7. Habilite os recursos de entrada de vários clusters no cluster ingress-config . Isso cria as definições personalizadas de recursos (CRDs) MulticlusterService e MulticlusterIngress no cluster.

    gcloud container fleet ingress enable \
      --config-membership=projects/${PROJECT_ID}/locations/global/memberships/${CLUSTER_INGRESS}
    
  8. Verifique se o Multi Cluster Ingress está habilitado no cluster ingress-config :

    gcloud container fleet ingress describe
    

    A saída se parece com o seguinte:

    membershipStates:
      projects/986443280307/locations/global/memberships/gke-central-priv:
        state:
          code: OK
          updateTime: '2022-09-29T13:57:02.972748202Z'
      projects/986443280307/locations/global/memberships/gke-ingress:
        state:
          code: OK
          updateTime: '2022-09-29T13:57:02.972744692Z'
      projects/986443280307/locations/global/memberships/gke-west-priv:
        state:
          code: OK
          updateTime: '2022-09-29T13:57:02.972746497Z'
    
  9. Verifique se os dois CRDs estão implantados no cluster ingress-config :

    kubectl --context=${CLUSTER_INGRESS} get crd | grep multicluster
    

    A saída se parece com o seguinte.

    multiclusteringresses.networking.gke.io     2020-10-29T17:32:50Z
    multiclusterservices.networking.gke.io      2020-10-29T17:32:50Z
    
  10. Crie o namespace asm-ingress no cluster ingress-config :

    kubectl --context ${CLUSTER_INGRESS} create namespace asm-ingress
    
  11. Crie o recurso MultiClusterIngress :

    cat <<EOF > ${HOME}/mci.yaml
    apiVersion: networking.gke.io/v1beta1
    kind: MultiClusterIngress
    metadata:
      name: asm-ingressgateway-multicluster-ingress
    spec:
      template:
        spec:
          backend:
           serviceName: asm-ingressgateway-multicluster-svc
           servicePort: 80
    EOF
    
  12. Crie o recurso MultiClusterService :

    cat <<'EOF' > $HOME/mcs.yaml
    apiVersion: networking.gke.io/v1beta1
    kind: MultiClusterService
    metadata:
      name: asm-ingressgateway-multicluster-svc
      annotations:
        beta.cloud.google.com/backend-config: '{"ports": {"80":"gke-ingress-config"}}'
    spec:
      template:
        spec:
          selector:
            asm: ingressgateway
          ports:
          - name: frontend
            protocol: TCP
            port: 80 # servicePort defined in Multi Cluster Ingress
      clusters:
      - link: "us-west2-a/gke-west-priv"
      - link: "us-central1-a/gke-central-priv"
    EOF
    
  13. Crie o recurso BackendConfig para verificações de integridade:

    cat <<EOF > $HOME/backendconfig.yaml
    apiVersion: cloud.google.com/v1beta1
    kind: BackendConfig
    metadata:
      name: gke-ingress-config
    spec:
      healthCheck:
        type: HTTP
        port: 15021
        requestPath: /healthz/ready
    EOF
    
  14. Aplique os manifestos BackendConfig , MultiClusterService e MultiClusterIngress :

    kubectl --context ${CLUSTER_INGRESS} -n asm-ingress apply -f ${HOME}/backendconfig.yaml
    kubectl --context ${CLUSTER_INGRESS} -n asm-ingress apply -f ${HOME}/mci.yaml
    kubectl --context ${CLUSTER_INGRESS} -n asm-ingress apply -f ${HOME}/mcs.yaml
    
  15. O MultiClusterService que você implantou no Ingress Cluster criará um Service "sem interface" no cluster 1 e no cluster 2. Verifique se os Services "sem interface" foram criados:

    kubectl --context=${CLUSTER_1} -n asm-ingress \
      get services | grep multicluster-svc
    kubectl --context=${CLUSTER_2} -n asm-ingress \
      get services | grep multicluster-svc
    

    A saída é semelhante a:

    mci-frontend-multi-cluster-service-svc-f7rcyqry22iq8nmw   ClusterIP      None          <none>          80/TCP         77s
    mci-frontend-multi-cluster-service-svc-f7rcyqry22iq8nmw   ClusterIP      None          <none>          80/TCP         78s
    
  16. Execute o seguinte comando e aguarde até obter um endereço IP do Cloud Load Balancing:

    watch kubectl --context ${CLUSTER_INGRESS} -n asm-ingress get multiclusteringress \
      -o jsonpath="{.items[].status.VIP}"
    

    A saída se parece com o seguinte:

    35.35.23.11
    

    Para sair do comando watch, pressione Ctrl+C .

  17. Navegue até o endereço IP do Cloud Load Balancing em um navegador da web para acessar o frontend do Bank of Anthos:

    kubectl --context ${CLUSTER_INGRESS} \
      -n asm-ingress get multiclusteringress \
      -o jsonpath="{.items[].status.VIP}"
    

    Se você receber um erro 404 (ou 502), aguarde alguns minutos e atualize a página no seu navegador.

Limpar

Para evitar cobranças na sua conta, exclua o projeto ou os clusters.

Excluir o projeto

A maneira mais fácil de eliminar a cobrança é excluir o projeto que você criou para o tutorial.

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Excluir os clusters

  1. No Cloud Shell, cancele o registro e exclua os clusters blue e green :

    gcloud container fleet memberships unregister ${CLUSTER_1} \
      --project=${PROJECT} \
      --gke-uri=${CLUSTER_1_URI}
    gcloud container clusters delete ${CLUSTER_1} \
      --zone ${CLUSTER_1_ZONE} \
      --quiet
    
    gcloud container fleet memberships unregister ${CLUSTER_2} \
      --project=${PROJECT} \
      --gke-uri=${CLUSTER_2_URI}
    gcloud container clusters delete ${CLUSTER_2} \
      --zone ${CLUSTER_2_ZONE} \
      --quiet
    
  2. Exclua o recurso MuticlusterIngress do cluster ingress-config:

    kubectl --context ${CLUSTER_INGRESS} -n istio-system delete -f $HOME/mci.yaml
    

    Isso exclui os recursos do Cloud Load Balancing do projeto.

  3. Cancele o registro e exclua o cluster ingress-config :

    gcloud container fleet memberships unregister ${CLUSTER_INGRESS} \
      --project=${PROJECT} \
      --gke-uri=${CLUSTER_INGRESS_URI}
    gcloud container clusters delete ${CLUSTER_INGRESS} \
      --zone ${CLUSTER_INGRESS_ZONE} \
      --quiet
    
  4. Verifique se todos os clusters foram excluídos:

    gcloud container clusters list
    

    A saída é a seguinte:

    <null>
  5. Redefina o arquivo kubeconfig :

    unset KUBECONFIG
    

O que vem a seguir