Como executar serviços distribuídos em clusters particulares do GKE usando o Cloud Service Mesh

Neste documento, mostramos como executar serviços distribuídos em vários clusters do Google Kubernetes Engine (GKE) no Google Cloud usando o Cloud Service Mesh. Este documento também mostra como expor um serviço distribuído usando o Ingress de vários clusters e o Cloud Service Mesh. É possível usar este documento para configurar clusters do GKE não particulares. O documento destaca a configuração que se destina estritamente a clusters particulares.

Este documento é destinado a administradores de plataformas e operadores de serviços que têm conhecimento básico sobre o Kubernetes. Alguns conhecimentos sobre malha de serviço são benéficos, embora não sejam obrigatórios. O Cloud Service Mesh é baseado na tecnologia de código aberto do Istio. Para mais informações sobre a malha de serviço e o Istio, consulte istio.io (em inglês).

Um serviço distribuído é um serviço do Kubernetes que atua como um único serviço lógico. Os serviços distribuídos são mais resilientes que os 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 possam atender à carga desejada.

Os serviços do Kubernetes são conhecidos apenas pelo servidor da API 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. Executar serviços distribuídos facilita o gerenciamento do ciclo de vida do cluster, porque é possível removê-los para manutenção ou upgrades enquanto outros clusters atendem ao tráfego. Para criar um serviço distribuído, a funcionalidade da malha de serviço fornecida pelo Cloud Service Mesh é usada para vincular serviços executados em vários clusters para atuar como um único serviço lógico.

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

Arquitetura

Neste tutorial, usamos a arquitetura mostrada no diagrama a seguir:

Arquitetura de serviços distribuídos em clusters particulares 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 particulares do GKE idênticos em duas regiões diferentes.
  • Um cluster separado (ingress-config) atua como o cluster do plano de controle que configura a Entrada de vários clusters.

Neste tutorial, você implanta o aplicativo de exemplo Bank of Anthos em dois clusters particulares do GKE (gke-central-priv e gke-west-priv). O Bank of Anthos é um exemplo de aplicativo de microsserviços que consiste em vários microsserviços e bancos de dados SQL que simulam um aplicativo de internet banking. O aplicativo consiste em um front-end da Web que os clientes podem acessar e vários serviços de back-end, como saldo, livro-razão e serviços de 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, são executados como serviços distribuídos. Isso significa que os pods de todos os serviços são executados clusters de aplicativos (no mesmo namespace), e o Cloud Service Mesh é configuradas para que cada serviço apareça como um único serviço lógico.

Objetivos

  • Crie três clusters do GKE.
  • Configurar dois dos clusters do GKE como clusters particulares (gke-central-priv e gke-west-priv).
  • Configurar um cluster do GKE (ingress-config) como o cluster de configuração central. Esse cluster atua como um cluster de configuração para Entrada de vários clusters.
  • Configurar a rede (gateways NAT, Cloud Router e regras de firewall) para permitir tráfego entre clusters e de saída dos dois clusters GKE particulares.
  • Configurar redes autorizadas para permitir o acesso do serviço da API do Cloud Shell aos dois clusters particulares do GKE.
  • Implante e configure o Cloud Service Mesh de vários clusters nos dois clusters particulares no modo multiprimário. O modo multiprimário implanta um plano de controle da Cloud Service Mesh nos dois clusters.
  • Implante o aplicativo Bank of Anthos nos dois clusters particulares. Todos os serviços, exceto os bancos de dados, são implantados como serviços distribuídos (pods em execução nos dois clusters particulares).
  • Monitorar serviços usando o Cloud Service Mesh.
  • Configurar a Entrada de vários clusters 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 GKE particulares.

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.

    Execute todos os comandos deste tutorial no Cloud Shell.

  4. Defina as variáveis de ambiente usadas neste tutorial. Elas definem nomes de clusters, regiões, zonas, endereços IP e Versões do Cloud Service Mesh usadas neste tutorial.

    1. Substitua YOUR_PROJECT_ID pelo código do 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 o ambiente

  1. No Cloud Shell, ative as APIs:

    gcloud services enable \
      --project=${PROJECT_ID} \
      container.googleapis.com \
      mesh.googleapis.com \
      gkehub.googleapis.com
    
  2. Ative a frota do Cloud Service Mesh para seu projeto:

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

Preparar a rede para clusters particulares do GKE

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

Os nós de cluster do GKE particulares não recebem um endereço IP público. Todos os nós em um cluster particular do GKE recebem um endereço IP VPC particular (no espaço de endereço RFC 1918). Isso significa que os pods que precisam acessar recursos externos (fora da rede VPC) exigem um gateway Cloud NAT. Os gateways NAT da nuvem são gateways NAT regionais que permitem que os pods com endereços IP internos se comuniquem com a Internet. Neste tutorial, você configura um gateway do Cloud NAT em cada uma das duas regiões. Vários clusters dentro de 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 particulares do Cloud 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 a comunicação entre servidores. A comunicação entre pods permite que os serviços distribuídos se comuniquem entre si nos clusters do GKE. A comunicação entre o pod e o servidor da API permite que o Cloud Service Mesh plano de controle consultar 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 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 rígida na produção, com base em suas condições e requisitos.

Criar clusters particulares do GKE

Nesta seção, você cria os dois clusters particulares do GKE em que o aplicativo de amostra é implantado. Neste tutorial, os nós do cluster particulares do GKE têm endereços IP privados, e o servidor da API tem um endpoint público. No entanto, o acesso ao servidor de API é restrito por meio de redes autorizadas.

  1. No Cloud Shell, crie dois clusters particulares que tenham redes autorizadas. Configure os clusters para permitir o acesso do intervalo de CIDR de IP do pod (para o plano de controle do Cloud Service Mesh) e do Cloud Shell para que você possa acessar os clusters 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 \
      --labels=mesh_id=${MESH_ID} --async
    
    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 \
      --labels=mesh_id=${MESH_ID}
    

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

    O endereço IP do Cloud Shell também faz parte das redes autorizadas, que permite acessar e gerenciar clusters 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á receber um endereço IP público diferente. Ao receber um novo endereço IP, você perde o acesso aos clusters porque o novo endereço IP 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. Receba 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 será assim:

    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 clusters criando um usuário e contexto para cada cluster. Depois de gerar entradas no arquivo kubeconfig, é possível alternar rapidamente o contexto entre clusters.

  4. Renomeie os contextos de cluster para 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 os dois contextos de cluster foram renomeados e configurados corretamente

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

    A saída será assim:

    gke-central-priv
    gke-west-priv
    
  6. Registre os 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
    

Você criou e renomeou seus clusters particulares do GKE.

Instalar o Cloud Service Mesh

Nesta seção, você vai instalar o Cloud Service Mesh nos dois clusters do GKE e configurar os clusters para cross-cluster descoberta de serviços.

  1. No Cloud Shell, instale o Cloud Service Mesh nos dois clusters usando fleet API:

    gcloud container fleet mesh update --management automatic --memberships ${CLUSTER_1},${CLUSTER_2}
    
  2. Depois que o Cloud Service Mesh gerenciado for ativado nos clusters, defina um relógio para a instalação da malha:

    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 dos dois clusters será semelhante a esta:

    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
    

    Depois que o plano de controle e os gateways de entrada do Cloud Service Mesh forem instalados para os dois clusters, a descoberta de serviços entre clusters será ativada com a API Fleet. A descoberta de serviços entre clusters permite que os dois clusters descubram endpoints do serviço do cluster remoto. Os serviços distribuídos são executados em vários clusters no mesmo namespace.

    Para que os dois 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. Neste exemplo, usamos dois clusters, portanto, os dois clusters precisam ser capazes de consultar o cluster remoto para encontrar os endpoints do serviço. Com o Cloud Service Mesh gerenciado ativado com a API Fleet, a descoberta de endpoints é configurada automaticamente.

Os clusters e o Cloud Service Mesh já estão configurados.

Implante o aplicativo do Bank of Anthos

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

    git clone https://github.com/GoogleCloudPlatform/bank-of-anthos.git ${HOME}/bank-of-anthos
    
  2. Criar e rotular um namespace bank-of-anthos em ambos os clusters. O rótulo permite a injeção automática dos proxies sidecar Envoy 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 nos dois 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 nos dois clusters para a descoberta de serviços. Quando um serviço em um dos clusters tenta fazer uma solicitação, primeiro ele executa uma pesquisa de DNS para o nome do host para receber o endereço IP. No GKE, o servidor kube-dns em execução no cluster processa essa pesquisa. Portanto, é necessária uma definição de serviço configurada.

  4. Exclua o StatefulSets de um cluster para que os dois bancos de dados do 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. Verifique se todos os pods estão sendo executados nos dois clusters:

    1. Receber pods de cluster_1:

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

      A saída será assim:

      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. Receber pods de cluster_2:

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

      A saída será assim:

      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. Implantar as configurações do Cloud Service Mesh nos dois clusters. Isso cria uma Gateway no namespace asm-ingress e VirtualService nos namespaces bank-of-anthos do serviço frontend, o que permite o tráfego de entrada para frontend serviço.

    Os Gateways geralmente são de propriedade dos administradores da plataforma ou da equipe de administradores de rede. Portanto, o recurso Gateway é criado no namespace do gateway de entrada de propriedade do administrador da plataforma e pode ser usado em outros namespaces por meio das 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
    

Você agora implantou o aplicativo Bank of Anthos em dois clusters particulares 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 permite que você veja que 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 do Endpoints "config-config" no pod frontend em 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 será assim:

    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 tem dois endereços IP de endpoint. Esses são os endereços IP do pod, um para cada cluster.

Acessar o Bank of Anthos

Para acessar o aplicativo Bank of Anthos, use o endereço IP público do Serviço asm-ingressgateway de qualquer um dos clusters.

  1. Conseguir endereços IP asm-ingressgateway dos dois 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"
    
    

    O resultado será semelhante ao mostrado a seguir.

    {"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 guia em um navegador da Web e acesse o endereço IP da saída anterior. O front-end do Banco do Anthos será exibido, o que permite fazer login, depositar fundos na conta e transferir fundos para outras contas. O aplicativo deve ser totalmente funcional.

Visualizar os serviços distribuídos

É possível visualizar serviços distribuídos no Cloud Service Mesh.

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

    Acessar o Service Mesh

    É possível visualizar serviços na visualização de tabela ou em topologia. A visualização padrão é a visualização em tabela, que mostra todos os serviços distribuídos em execução em um formato tabular. Para mudar as visualizações, clique naquela que você quer exibir.

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

    Na visualização de detalhes do serviço, é possível criar SLOs e ver um cronograma histórico do serviço clicando em Mostrar linha do tempo.

  3. Para ver os indicadores 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 dos dois clusters nas duas regiões. O serviço distribuído está íntegro e os dois endpoints estão disponibilizando tráfego.

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

  6. Para ver mais dados, mantenha o ponteiro do mouse sobre o serviço frontend. Isso exibe informações como solicitações por segundo de e para o front-end e outros serviços.

  7. Para ver mais detalhes, clique em Expandir no serviço frontend. Um Serviço e uma Carga de trabalho serão exibidos. É possível expandir ainda mais 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, é possível ver o serviço frontend distribuído, que é basicamente um serviço e dois pods.

Configurar o Ingress de vários clusters

Nesta seção, você cria um Ingress de vários clusters que envia tráfego aos serviços frontend do Bank of GKE Enterprise em execução nos dois clusters. Você usa Cloud Load Balancing para criar um balanceador de carga que use os serviços do asm-ingressgateway em ambos e clusters como back-ends. Um cluster ingress-config é usado para orquestrar a configuração da Entrada 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 dos recursos existentes Ingress e Service do Kubernetes usados no contexto de cluster único.

  1. Ative as APIs necessárias do GKE Enterprise, da frota do GKE e do Ingress em vários clusters:

    gcloud services enable \
      anthos.googleapis.com \
      multiclusterservicediscovery.googleapis.com \
      multiclusteringress.googleapis.com
    
  2. Crie o cluster ingress-config Use qualquer cluster, mas recomendamos que você crie 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. Receba as credenciais do cluster e renomeie o contexto para 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 a Ingress de vários clusters, registre todos os clusters participantes na frota do GKE Enterprise, 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 na frota do GKE Enterprise:

    gcloud container fleet memberships list
    

    A saída será assim:

    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. Ative os recursos da Entrada de vários clusters no cluster ingress-config. Isso cria os CRDs do MulticlusterService e MulticlusterIngress personalizados no cluster.

    gcloud container fleet ingress enable \
      --config-membership=projects/${PROJECT_ID}/locations/global/memberships/${CLUSTER_INGRESS}
    
  8. Verifique se a Entrada de vários clusters está ativada no cluster ingress-config:

    gcloud container fleet ingress describe
    

    A saída será assim:

    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
    

    O resultado será semelhante ao mostrado a seguir.

    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. Criar 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. Criar 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 cluster de entrada criará um Service "sem comando" no cluster 1 e no cluster 2. Verifique se o Services "headless" foi criado:

    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é receber 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 será assim:

    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 front-end do Banco do Anthos:

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

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

Limpar

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

Excluir o projeto

A maneira mais fácil de eliminar o faturamento é excluir o projeto criado 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
    

    Esse comando exclui os recursos do Cloud Load Balancing do projeto.

  3. Cancelar o registro e excluir 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 é esta:

    <null>
  5. Redefinir o arquivo kubeconfig:

    unset KUBECONFIG
    

A seguir