Ejecutar servicios distribuidos en clústeres privados de GKE con Cloud Service Mesh

En este documento se explica cómo ejecutar servicios distribuidos en varios clústeres de Google Kubernetes Engine (GKE) en Google Cloud con Cloud Service Mesh. En este documento también se explica cómo exponer un servicio distribuido mediante Multi Cluster Ingress y Cloud Service Mesh. Puedes usar este documento para configurar clústeres de GKE no privados. En él se destaca la configuración que está pensada estrictamente para clústeres privados.

Este documento está dirigido a administradores de plataformas y operadores de servicios que tengan conocimientos básicos de Kubernetes. Es recomendable tener algunos conocimientos sobre mallas de servicios, pero no es obligatorio. Cloud Service Mesh se basa en la tecnología de código abierto Istio. Para obtener más información sobre la malla de servicios e Istio, consulta istio.io.

Un servicio distribuido es un servicio de Kubernetes que actúa como un único servicio lógico. Los servicios distribuidos son más resilientes que los servicios de Kubernetes porque se ejecutan en varios clústeres de Kubernetes del mismo espacio de nombres. Un servicio distribuido sigue funcionando aunque uno o varios clústeres de GKE estén inactivos, siempre que los clústeres en buen estado puedan atender la carga deseada.

Los servicios de Kubernetes solo los conoce el servidor de la API de Kubernetes del clúster en el que se ejecutan. Si el clúster de Kubernetes no funciona (por ejemplo, durante un mantenimiento programado), tampoco funcionarán todos los servicios de Kubernetes que se ejecuten en ese clúster. Al ejecutar servicios distribuidos, la gestión del ciclo de vida de los clústeres es más sencilla, ya que puedes desactivar los clústeres para realizar tareas de mantenimiento o actualizaciones mientras otros clústeres atienden el tráfico. Para crear un servicio distribuido, se usa la función de malla de servicios que proporciona Cloud Service Mesh para vincular servicios que se ejecutan en varios clústeres y que actúen como un único servicio lógico.

Los clústeres privados de GKE te permiten configurar los nodos y el servidor de la API como recursos privados disponibles solo en la red de nube privada virtual (VPC). Ejecutar servicios distribuidos en clústeres privados de GKE ofrece a las empresas servicios seguros y fiables.

Arquitectura

En este tutorial se usa la arquitectura que se muestra en el siguiente diagrama:

Arquitectura de servicios distribuidos en clústeres privados de GKE con Cloud Service Mesh

En el diagrama anterior, la arquitectura incluye los siguientes clústeres:

  • Dos clústeres (gke-central-priv y gke-west-priv) actúan como clústeres privados de GKE idénticos en dos regiones diferentes.
  • Un clúster independiente (ingress-config) actúa como clúster de plano de control que configura Ingress de varios clústeres.

En este tutorial, desplegarás la aplicación de ejemplo Bank of Anthos en dos clústeres privados de GKE (gke-central-priv y gke-west-priv). Bank of Anthos es una aplicación de microservicios de ejemplo que consta de varios microservicios y bases de datos SQL que simulan una aplicación de banca online. La aplicación consta de un frontend web al que pueden acceder los clientes y de varios servicios de backend, como los servicios de saldo, libro de contabilidad y cuenta, que simulan un banco.

La aplicación incluye dos bases de datos PostgreSQL que se instalan en Kubernetes como StatefulSets. Una base de datos se usa para las transacciones, mientras que la otra se usa para las cuentas de usuario. Todos los servicios, excepto las dos bases de datos, se ejecutan como servicios distribuidos. Esto significa que los pods de todos los servicios se ejecutan en ambos clústeres de aplicaciones (en el mismo espacio de nombres) y que Cloud Service Mesh está configurado de forma que cada servicio aparezca como un único servicio lógico.

Objetivos

  • Crea tres clústeres de GKE.
  • Configura dos de los clústeres de GKE como clústeres privados (gke-central-priv y gke-west-priv).
  • Configura un clúster de GKE (ingress-config) como clúster de configuración central. Este clúster actúa como clúster de configuración para Ingress de varios clústeres.
  • Configura la red (pasarelas NAT, Cloud Router y reglas de cortafuegos) para permitir el tráfico entre clústeres y el tráfico de salida de los dos clústeres privados de GKE.
  • Configura las redes autorizadas para permitir el acceso al servicio de la API desde Cloud Shell a los dos clústeres privados de GKE.
  • Despliega y configura Cloud Service Mesh de varios clústeres en los dos clústeres privados en modo multiprimario. En el modo multiprimario, se implementa un plano de control de Cloud Service Mesh en ambos clústeres.
  • Despliega la aplicación Bank of Anthos en los dos clústeres privados. Todos los servicios, excepto las bases de datos, se implementan como servicios distribuidos (pods que se ejecutan en clústeres privados).
  • Monitoriza los servicios mediante Cloud Service Mesh.
  • Configura Ingress con varios clústeres en los servicios de Bank of Anthos. frontend De esta forma, los clientes externos (por ejemplo, tu navegador web) pueden acceder a un servicio distribuido que se ejecuta en una flota de clústeres de GKE privados.

Costes

En este documento, se utilizan los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costes basada en el uso previsto, utiliza la calculadora de precios.

Los usuarios nuevos Google Cloud pueden disfrutar de una prueba gratuita.

Antes de empezar

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

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  2. Verify that billing is enabled for your Google Cloud project.

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

    Activate Cloud Shell

    En este tutorial, ejecutarás todos los comandos desde Cloud Shell.

  4. Define las variables de entorno que se usan en este tutorial. Las variables definen los nombres de los clústeres, las regiones, las zonas, las direcciones IP y las versiones de Cloud Service Mesh que se usan en este tutorial.

    1. Sustituye YOUR_PROJECT_ID por el ID del proyecto:

      export PROJECT_ID=YOUR_PROJECT_ID
      gcloud config set project ${PROJECT_ID}
      
    2. Define las variables de entorno 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)
      
  5. Prepara tu entorno

    1. En Cloud Shell, habilita las APIs:

      gcloud services enable \
        --project=${PROJECT_ID} \
        container.googleapis.com \
        mesh.googleapis.com \
        gkehub.googleapis.com
      
    2. Habilita la flota de Cloud Service Mesh en tu proyecto:

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

    Preparar la red para clústeres privados de GKE

    En esta sección, preparará la red para los clústeres de GKE privados que utilice para ejecutar servicios distribuidos.

    A los nodos de los clústeres de GKE privados no se les asigna una dirección IP pública. Todos los nodos de un clúster privado de GKE tienen asignada una dirección IP de VPC privada (en el espacio de direcciones RFC 1918). Esto significa que los pods que necesiten acceder a recursos externos (fuera de la red VPC) requieren una pasarela de Cloud NAT. Las pasarelas de Cloud NAT son pasarelas de NAT regionales que permiten que los pods con direcciones IP internas se comuniquen con Internet. En este tutorial, configurarás una pasarela de Cloud NAT en cada una de las dos regiones. Varios clústeres de una región pueden usar la misma pasarela NAT.

    1. En Cloud Shell, crea y reserva dos direcciones IP externas para las dos pasarelas 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. Almacena la dirección IP y el nombre de las direcciones IP en variables:

      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. Crea pasarelas de Cloud NAT en las dos regiones de los clústeres privados de 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. Crea una regla de cortafuegos que permita la comunicación entre pods y entre pods y servidores de API. La comunicación entre pods permite que los servicios distribuidos se comuniquen entre sí en los clústeres de GKE. La comunicación de pod a servidor de la API permite que el plano de control de Cloud Service Mesh consulte los clústeres de GKE para descubrir servicios.

      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}
      

    La conexión de red ya está preparada. En este tutorial, se usa todo el intervalo de direcciones IP 10.0.0.0/8, que incluye todos los intervalos de pods. Te recomendamos que crees una regla de firewall más estricta en producción, en función de tus condiciones y requisitos.

    Crear clústeres privados de GKE

    En esta sección, crearás los dos clústeres privados de GKE en los que se desplegará la aplicación de ejemplo. En este tutorial, los nodos del clúster de GKE privado tienen direcciones IP privadas y el servidor de la API tiene un endpoint público. Sin embargo, el acceso al servidor de la API está restringido mediante redes autorizadas.

    1. En Cloud Shell, crea dos clústeres privados que tengan redes autorizadas. Configura los clústeres para permitir el acceso desde el intervalo CIDR de la IP de los pods (para el plano de control de Cloud Service Mesh) y desde Cloud Shell para que puedas acceder a los clústeres desde tu 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
      

      Las redes autorizadas contienen las direcciones IP públicas de las pasarelas Cloud NAT. Dado que el endpoint del servidor de la API de un clúster privado es un endpoint público, los pods que se ejecutan en un clúster privado deben usar una pasarela Cloud NAT para acceder a los endpoints públicos del servidor de la API.

      La dirección IP de Cloud Shell también forma parte de las redes autorizadas, lo que te permite acceder a los clústeres y gestionarlos desde tu terminal de Cloud Shell. Las direcciones IP públicas de Cloud Shell son dinámicas, por lo que cada vez que inicies Cloud Shell, es posible que obtengas una dirección IP pública diferente. Cuando obtienes una nueva dirección IP, pierdes el acceso a los clústeres porque la nueva dirección IP no forma parte de las redes autorizadas de los dos clústeres.

      Si pierdes el acceso a los clústeres, actualiza las redes autorizadas de los clústeres para incluir la nueva dirección IP de Cloud Shell:

      1. Obtén la dirección IP pública actualizada de Cloud Shell:

        export CLOUDSHELL_IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
        
      2. Actualiza las redes autorizadas de los dos clústeres:

        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. Verifica que todos los clústeres se estén ejecutando:

      gcloud container clusters list
      

      La salida tiene este aspecto:

      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. Conéctate a ambos clústeres para generar entradas en el archivo 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}
      

      El archivo kubeconfig se usa para autenticar clústeres creando un usuario y un contexto para cada clúster. Después de generar entradas en el archivo kubeconfig, puedes cambiar rápidamente de contexto entre clústeres.

    4. Cambia el nombre de los contextos del clúster para que te resulte más fácil:

      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. Confirma que los dos contextos de clúster se han renombrado y configurado correctamente:

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

      La salida tiene este aspecto:

      gke-central-priv
      gke-west-priv
      
    6. Registra tus clústeres en una flota:

      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
      

    Ahora ya has creado y cambiado el nombre de tus clústeres privados de GKE.

    Instalar Cloud Service Mesh

    En esta sección, instalarás Cloud Service Mesh en los dos clústeres de GKE y los configurarás para el descubrimiento de servicios entre clústeres.

    1. En Cloud Shell, instala Cloud Service Mesh en ambos clústeres con fleet API:

      gcloud container fleet mesh update --management automatic --memberships ${CLUSTER_1},${CLUSTER_2}
      
    2. Una vez que se haya habilitado Cloud Service Mesh gestionado en los clústeres, define una comprobación para que se instale la malla:

      watch -g "gcloud container fleet mesh describe | grep 'code: REVISION_READY'"
      
    3. Instala las pasarelas de entrada de Cloud Service Mesh en ambos clústeres:

      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. Verifica que las pasarelas de entrada de Cloud Service Mesh se hayan implementado:

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

      La salida de ambos clústeres es similar a la siguiente:

      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
      

      Una vez que se hayan instalado el plano de control de Cloud Service Mesh y las pasarelas de entrada en ambos clústeres, se habilitará el descubrimiento de servicios entre clústeres con la API Fleet. El descubrimiento de servicios entre clústeres permite que los dos clústeres descubran los endpoints de servicio del clúster remoto. Los servicios distribuidos se ejecutan en varios clústeres del mismo espacio de nombres.

      Para que ambos planos de control de Cloud Service Mesh puedan descubrir todos los endpoints de un servicio distribuido, Cloud Service Mesh debe tener acceso a todos los clústeres que ejecuten el servicio distribuido. En este ejemplo se usan dos clústeres, por lo que ambos deben poder consultar el clúster remoto para obtener los endpoints de servicio. Si tienes habilitado Cloud Service Mesh gestionado con la API Fleet, la detección de endpoints se configura automáticamente.

    Los clústeres y Cloud Service Mesh ya están configurados.

    Desplegar la aplicación Bank of Anthos

    1. En Cloud Shell, clona el repositorio de GitHub de Bank of Anthos:

      git clone https://github.com/GoogleCloudPlatform/bank-of-anthos.git ${HOME}/bank-of-anthos
      
    2. Crea y etiqueta un espacio de nombres bank-of-anthos en ambos clústeres. La etiqueta permite la inserción automática de los proxies Envoy adicionales en cada pod del espacio de nombres etiquetado.

      # 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. Despliega la aplicación Bank of Anthos en ambos clústeres del espacio de nombres 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
      

      Los servicios de Kubernetes deben estar en ambos clústeres para que se puedan detectar los servicios. Cuando un servicio de uno de los clústeres intenta hacer una solicitud, primero realiza una búsqueda de DNS del nombre de host para obtener la dirección IP. En GKE, el servidor kube-dns que se ejecuta en el clúster gestiona esta búsqueda, por lo que se necesita una definición de servicio configurada.

    4. Elimina el StatefulSets de un clúster para que las dos bases de datos de PostgreSQL solo estén en uno de los clústeres:

      # 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. Asegúrate de que todos los pods se estén ejecutando en ambos clústeres:

      1. Obtener pods de cluster_1:

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

        La salida tiene este aspecto:

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

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

        La salida tiene este aspecto:

        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. Despliega las configuraciones de Cloud Service Mesh en ambos clústeres. De esta forma, se crea una pasarela en el espacio de nombres asm-ingress y un VirtualService en los espacios de nombres bank-of-anthos del servicio frontend, lo que te permite dirigir el tráfico entrante al servicio frontend.

      Gateways suelen ser propiedad de los administradores de la plataforma o del equipo de administradores de la red. Por lo tanto, el recurso Gateway se crea en el espacio de nombres de Ingress Gateway, que es propiedad del administrador de la plataforma, y se puede usar en otros espacios de nombres mediante sus propias entradas VirtualService. Este es un modelo de pasarela compartida.

      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
      

    Ahora has desplegado la aplicación Bank of Anthos en dos clústeres de GKE privados. Todos los servicios se ejecutan como servicios distribuidos, excepto la base de datos.

    Inspeccionar servicios distribuidos

    En esta sección, usarás la herramienta istioctl para inspeccionar la configuración de proxy de cualquiera de los proxies. De esta forma, puedes ver que los proxies adicionales ven dos pods por cada servicio, con un pod ejecutándose en cada clúster.

    1. En Cloud Shell, inspecciona la lista de Endpoints de proxy-config en el pod frontend de 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
      

      La salida tiene este aspecto:

      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
      

      En el resultado anterior, cada servicio distribuido tiene dos direcciones IP de Endpoint. Estas son las direcciones IP de los pods, una por cada clúster.

    Access Bank of Anthos

    Para acceder a la aplicación Bank of Anthos, puedes usar la asm-ingressgatewaydirección IP pública del servicio de cualquiera de los clústeres.

    1. Obtén las direcciones IP de asm-ingressgateway de ambos clústeres:

      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"
      
      

      La salida tiene el siguiente aspecto.

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

      Copia una de las direcciones IP para usarla en el siguiente paso.

    2. Abre una pestaña en un navegador web y ve a cualquiera de las direcciones IP del resultado anterior. Debería mostrarse el frontend de Bank of Anthos, que te permite iniciar sesión, ingresar fondos en tu cuenta y transferir fondos a otras cuentas. La aplicación debe ser totalmente funcional.

    Visualizar servicios distribuidos

    Puedes visualizar los servicios distribuidos en Cloud Service Mesh.

    1. Para ver tus servicios, ve a la página Anthos > Service Mesh de la Google Cloud consola.

      Ir a Service Mesh

      Puedes ver los servicios en la vista Tabla o en la vista Topología. La vista predeterminada es la vista de tabla, que muestra todos los servicios distribuidos que se están ejecutando en formato tabular. Para cambiar de vista, haz clic en la que quieras mostrar.

    2. En la vista Tablas, haz clic en frontend distributed service. Cuando haces clic en un servicio concreto, se muestra una vista detallada del servicio junto con los servicios conectados.

      En la vista de detalles del servicio, puedes crear SLOs y ver una cronología del servicio haciendo clic en Mostrar cronología.

    3. Para ver las señales de oro, en el panel lateral, haga clic en Métricas.

    4. En el gráfico Solicitudes por segundo, haga clic en Desglose por y, a continuación, seleccione Ubicación.

      Los resultados muestran las solicitudes por segundo de ambos clústeres en las dos regiones. El servicio distribuido está en buen estado y ambos endpoints están sirviendo tráfico.

    5. Para ver la topología de tu malla de servicios, en el panel lateral, haz clic en Anthos Service Mesh y, a continuación, en Vista de topología.

    6. Para ver más datos, coloca el cursor sobre el servicio frontend. Muestra información como las solicitudes por segundo enviadas y recibidas entre el frontend y otros servicios.

    7. Para ver más detalles, haga clic en Ampliar en el servicio frontend. Se muestran un servicio y una carga de trabajo. Puedes ampliar aún más la carga de trabajo en dos implementaciones, ampliar las implementaciones en ReplicaSets y ampliar los ReplicaSets en pods. Si despliegas todos los elementos, verás el servicio frontend distribuido, que es básicamente un servicio y dos pods.

    Configurar entrada de varios clústeres

    En esta sección, crearás un MultiClusterIngress que envíe tráfico a los servicios de Bank of GKE Enterprise frontend que se ejecutan en ambos clústeres. Usa Cloud Load Balancing para crear un balanceador de carga que utilice los servicios asm-ingressgateway de ambos clústeres como backends. Se usa un clúster ingress-config para orquestar la configuración de Ingress con varios clústeres.

    Para crear el balanceador de carga, se usa un MultiClusterIngress y uno o varios MultiClusterServices. Los objetos MultiClusterIngress y MultiClusterService son análogos multiclúster de los recursos Ingress y Service de Kubernetes que se usan en el contexto de un solo clúster.

    1. Habilita las APIs de GKE Enterprise, GKE Fleet y Multi Cluster Ingress necesarias:

      gcloud services enable \
        anthos.googleapis.com \
        multiclusterservicediscovery.googleapis.com \
        multiclusteringress.googleapis.com
      
    2. Crea el clúster ingress-config. Puedes usar cualquier clúster, pero te recomendamos que crees uno específico para este fin.

      gcloud container clusters create ${CLUSTER_INGRESS} \
        --zone ${CLUSTER_INGRESS_ZONE} \
        --num-nodes=1 \
        --enable-ip-alias \
        --workload-pool=${WORKLOAD_POOL}
      
    3. Obtén las credenciales del clúster y cambia el nombre del contexto para mayor comodidad:

      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 Ingress de varios clústeres, registra todos los clústeres participantes en GKE Enterprise Fleet, incluido el clúster de configuración:

    5. Registra el clúster de configuración:

      gcloud container fleet memberships register ${CLUSTER_INGRESS} \
        --project=${PROJECT_ID} \
        --gke-cluster=${CLUSTER_INGRESS_ZONE}/${CLUSTER_INGRESS} \
        --enable-workload-identity
      
    6. Verifica que todos los clústeres estén registrados en la flota de GKE Enterprise:

      gcloud container fleet memberships list
      

      La salida tiene este aspecto:

      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. Habilita las funciones de Multi Cluster Ingress en el clúster ingress-config. De esta forma, se crean los MulticlusterService y MulticlusterIngress CustomResourceDefinitions (CRDs) en el clúster.

      gcloud container fleet ingress enable \
        --config-membership=projects/${PROJECT_ID}/locations/global/memberships/${CLUSTER_INGRESS}
      
    8. Verifica que la entrada de varios clústeres esté habilitada en el clúster ingress-config:

      gcloud container fleet ingress describe
      

      La salida tiene este aspecto:

      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. Verifica que los dos CRDs se hayan desplegado en el clúster ingress-config:

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

      La salida tiene el siguiente aspecto.

      multiclusteringresses.networking.gke.io     2020-10-29T17:32:50Z
      multiclusterservices.networking.gke.io      2020-10-29T17:32:50Z
      
    10. Crea el espacio de nombres asm-ingress en el clúster ingress-config:

      kubectl --context ${CLUSTER_INGRESS} create namespace asm-ingress
      
    11. Crea el 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. Crea el 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. Crea el recurso BackendConfig para las comprobaciones del estado:

      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. Aplica los manifiestos BackendConfig, MultiClusterService y 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. El MultiClusterService que has desplegado en el clúster de entrada creará un Service sin encabezado en el clúster 1 y el clúster 2. Comprueba que se hayan creado los Services sin interfaz:

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

      La salida es similar a la siguiente:

      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. Ejecuta el siguiente comando y espera hasta que obtengas una dirección IP de Cloud Load Balancing:

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

      La salida tiene este aspecto:

      35.35.23.11
      

      Para salir del comando watch, pulsa Ctrl+C.

    17. Ve a la dirección IP de Cloud Load Balancing en un navegador web para acceder al frontend de Bank of Anthos:

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

      Si recibes un error 404 (o un error 502), espera unos minutos y, a continuación, actualiza la página en tu navegador web.

    Limpieza

    Para evitar que se apliquen cargos a tu cuenta, elimina el proyecto o los clústeres.

    Eliminar el proyecto

    La forma más fácil de evitar que te cobren es eliminar el proyecto que has creado para el 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.

    Eliminar los clústeres

    1. En Cloud Shell, da de baja y elimina los clústeres blue y 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. Elimina el recurso MuticlusterIngress del clúster ingress-config:

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

      De esta forma, se eliminan los recursos de Cloud Load Balancing del proyecto.

    3. Da de baja y elimina el clúster 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. Verifica que se hayan eliminado todos los clústeres:

      gcloud container clusters list
      

      El resultado es el siguiente:

      <null>
    5. Restablece el archivo kubeconfig:

      unset KUBECONFIG
      

    Siguientes pasos