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

En este documento, se muestra cómo ejecutar servicios distribuidos en varios clústeres de Google Kubernetes Engine (GKE) en Google Cloud mediante Cloud Service Mesh. En este documento, también se muestra cómo exponer un servicio distribuido mediante Ingress de varios clústeres y Cloud Service Mesh. Puedes usar este documento para configurar clústeres de GKE no privados. En el documento, se destaca la configuración diseñada para clústeres privados.

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

Un servicio distribuido es un Service de Kubernetes que actúa como un servicio único lógico. Los servicios distribuidos son más resilientes que los servicios de Kubernetes porque se ejecutan en varios clústeres de Kubernetes en el mismo espacio de nombres. Un servicio distribuido permanece activo incluso si uno o más clústeres de GKE están inactivos, siempre que los clústeres en buen estado puedan entregar la carga deseada.

Los services de Kubernetes solo son conocidos para el servidor de la API de Kubernetes del clúster en el que se ejecutan. Si el clúster de Kubernetes está inactivo (por ejemplo, durante un mantenimiento programado), todos los servicios de Kubernetes que se ejecutan en ese clúster también están inactivos. Ejecutar servicios distribuidos facilita la administración del ciclo de vida de los clústeres porque puedes reducirlos para mantenimiento o actualizaciones, mientras que otros clústeres entregan tráfico de servicios. A fin de crear un servicio distribuido, la funcionalidad de la malla de servicios que proporciona Cloud Service Mesh se usa para vincular los servicios que se ejecutan en varios clústeres y, así, actuar como un solo 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 brinda a las empresas servicios seguros y confiables.

Arquitectura

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

Arquitectura de servicios distribuidos en clústeres privados de GKE que usan 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 el clúster del plano de control que configura Ingress de varios clústeres.

En este instructivo, implementarás la aplicación de muestra de 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 muestra que consiste en varios microservicios y bases de datos de SQL que simulan una app de banca en línea. La aplicación consiste en un frontend web al que los clientes pueden acceder y varios servicios de backend, como los de saldo, de registro y de cuenta, que simulan un banco.

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

Objetivos

  • Crear tres clústeres de GKE
  • Configurar dos de los clústeres de GKE como clústeres privados (gke-central-priv y gke-west-priv).
  • Configurar un clúster de GKE (ingress-config) como el clúster de configuración central. Este clúster actúa como un clúster de configuración para Ingress de varios clústeres.
  • Configurar las herramientas de redes (puertas de enlace NAT, Cloud Router y reglas de firewall) para permitir el tráfico entre clústeres y de salida de los dos clústeres privados de GKE.
  • Configurar las redes autorizadas para permitir el acceso a los servicios de API desde Cloud Shell a los dos clústeres privados de GKE.
  • Implementa y configura Cloud Service Mesh de varios clústeres en dos clústeres privados en el modo de varias instancias principales. El modo principal múltiple implementa un plano de control de Cloud Service Mesh en ambos clústeres.
  • Implementar la aplicación del 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 ambos clústeres privados).
  • Supervisar servicios con Cloud Service Mesh
  • Configura Ingress de varios clústeres en los servicios frontend de Bank of Anthos. Esto permite que los clientes externos (por ejemplo, el navegador web) accedan a un servicio distribuido que se ejecuta en una flota de clústeres de GKE privados.

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud califiquen para obtener una prueba gratuita.

Antes de comenzar

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

    Go to project selector

  2. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  3. En la consola de Google Cloud, activa Cloud Shell.

    Activar Cloud Shell

    En la parte inferior de la consola de Google Cloud, se inicia una sesión de Cloud Shell en la que se muestra una ventana de línea de comandos. Cloud Shell es un entorno de shell con Google Cloud CLI ya instalada y con valores ya establecidos para el proyecto actual. La sesión puede tardar unos segundos en inicializarse.

    Ejecuta todos los comandos de este instructivo desde Cloud Shell.

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

    1. Reemplaza YOUR_PROJECT_ID por el ID del proyecto:

      export PROJECT_ID=YOUR_PROJECT_ID
      gcloud config set project ${PROJECT_ID}
      
    2. Configura 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)
      

Prepare el entorno

  1. En Cloud Shell, habilita las API:

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

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

Preparar las herramientas de redes para clústeres de GKE privados

En esta sección, prepararás las herramientas de redes para los clústeres de GKE privados que uses a fin de ejecutar servicios distribuidos.

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

  1. En Cloud Shell, crea y reserva dos direcciones IP externas para las dos puertas de enlace 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 las 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 puertas de enlace de Cloud NAT en las dos regiones de los clústeres de GKE privados:

    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 firewall que permita la comunicación de Pod a Pod y la comunicación de servidor de Pod a API. La comunicación de Pod a Pod permite que los servicios distribuidos se comuniquen entre sí en todos los clústeres de GKE. La comunicación de Pod a la API permite que el plano de control de la malla de servicios de Cloud consulte clústeres de GKE para el descubrimiento de 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}
    

Las herramientas de redes ya están preparadas. En este instructivo, usarás todo el rango de direcciones IP 10.0.0.0/8, que incluye todos los rangos de Pods. Te recomendamos crear una regla de firewall más estricta en producción, según las condiciones y los requisitos.

Crea clústeres de GKE privados

En esta sección, crearás los dos clústeres privados de GKE en los que se implementa la app de ejemplo. En este instructivo, los nodos privados del clúster de GKE tienen direcciones IP privadas, y el servidor de la API tiene un extremo público. Sin embargo, el acceso al servidor de la API se restringe 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 rango de CIDR de IP del Pod (para el plano de control de Cloud Service Mesh) y desde Cloud Shell para que puedas acceder a los clústeres desde la 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 en las puertas de enlace de Cloud NAT. Debido a que el extremo del servidor de API de un clúster privado es un extremo público, los Pods que se ejecutan en un clúster privado deben usar una puerta de enlace de Cloud NAT para acceder a los extremos del servidor de API pública.

    La dirección IP de Cloud Shell también forma parte de las redes autorizadas, lo que te permite acceder y administrar clústeres 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 dirección IP nueva, pierdes acceso a los clústeres porque la dirección IP nueva 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 dirección IP nueva 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 estén en ejecución:

    gcloud container clusters list
    

    El resultado luce de la siguiente manera:

    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}
    

    Crea un usuario y un contexto para cada clúster a fin de autenticarte en el archivo kubeconfig. Después de generar entradas en el archivo kubeconfig, puedes cambiar el contexto entre clústeres con rapidez.

  4. Cambia el nombre de los contextos del clúster para mayor comodidad:

    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 ambos contextos del clúster cambiaron el nombre y se configuraron de forma correcta:

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

    El resultado luce de la siguiente manera:

    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
    

Ya creaste y cambiaste el nombre de tus clústeres privados de GKE.

Instala Cloud Service Mesh

En esta sección, instalarás Cloud Service Mesh en los dos clústeres de GKE y configurarás los clústeres 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. Después de habilitar Cloud Service Mesh administrado en los clústeres, configura un reloj para que se instale la malla:

    watch -g "gcloud container fleet mesh describe | grep 'code: REVISION_READY'"
    
  3. Instala las puertas de enlace de entrada de Cloud Service Mesh para 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 puertas de enlace de entrada de la malla de servicios de Cloud estén implementadas:

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

    El resultado de ambos clústeres se verá de la siguiente manera:

    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
    

    Después de instalar el plano de control de la malla de servicios de Cloud y las puertas de enlace de entrada para ambos clústeres, el descubrimiento de servicios entre clústeres se habilita con la API de la flota. El descubrimiento de servicios entre clústeres permite que los dos clústeres descubran extremos de servicio desde el clúster remoto. Los servicios distribuidos se ejecutan en varios clústeres en el mismo espacio de nombres.

    Para que ambos planos de control de Cloud Service Mesh descubran todos los extremos de un servicio distribuido, Cloud Service Mesh debe tener acceso a todos los clústeres que ejecutan el servicio distribuido. En este ejemplo, se usan dos clústeres, por lo que ambos deben poder consultar al clúster remoto para los extremos del servicio. Con la malla de servicios administrados de Cloud habilitada con la API de flota, el descubrimiento de extremos se configura automáticamente.

Los clústeres y la malla de servicios de Cloud ya están configurados.

Implementa 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 de sidecar de Envoy en cada Pod dentro 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. Implementa la aplicación Bank of Anthos en ambos clústeres en el 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 el descubrimiento de servicios. Cuando un servicio de uno de los clústeres intenta realizar una solicitud, primero realiza una búsqueda de DNS para el nombre de host a fin de obtener la dirección IP. En GKE, el servidor de kube-dns que se ejecuta en el clúster controla esta búsqueda, por lo que se requiere una definición de servicio configurada.

  4. Borra el StatefulSets de un clúster para que las dos bases de datos de PostgreSQL existan solo 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 ejecuten en ambos clústeres:

    1. Obtén Pods de cluster_1:

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

      El resultado luce de la siguiente manera:

      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. Obtén Pods de cluster_2:

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

      El resultado luce de la siguiente manera:

      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. Implementar la configuración de la malla de servicios de Cloud en ambos clústeres Esto crea una Gateway en el espacio de nombres asm-ingress y un VirtualService en los espacios de nombres bank-of-anthos para el servicio frontend, lo que te permite ingresar tráfico al servicio frontend.

    Por lo general, Gateways son propiedad de los administradores de la plataforma o del equipo de administradores de redes. Por lo tanto, el recurso Gateway se crea en el espacio de nombres de la puerta de enlace de Ingress que pertenece al administrador de la plataforma y se puede usar en otros espacios de nombres a través de sus propias entradas VirtualService. Este es un modelo de “Gateway 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
    

Ya implementaste la aplicación del Banco de Anthos en dos clústeres de GKE privados. Todos los servicios se ejecutan como servicios distribuidos, excepto la base de datos.

Inspecciona servicios distribuidos

En esta sección, usarás la herramienta de istioctl para inspeccionar la configuración del proxy de cualquiera de los proxies. Esto te permite ver que los proxies de sidecar vean dos Pods para cada servicio, con un Pod en ejecución en cada clúster.

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

    El resultado luce de la siguiente manera:

    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 extremos. Estas son las direcciones IP del Pod, una para cada clúster.

Accede a Bank of Anthos

Para acceder a la aplicación del Banco de Anthos, puedes usar la dirección IP pública del Service de asm-ingressgateway desde cualquier clúster.

  1. Obtén direcciones IP 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 se verá de la siguiente manera.

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

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

  2. Abre una pestaña nueva en un navegador web y ve a cualquier dirección IP del resultado anterior. Debería aparecer el frontend de Bank for Anthos, que te permite acceder a tu cuenta, depositar fondos y transferirlos a otras cuentas. La aplicación debe ser completamente funcional.

Visualiza servicios distribuidos

Puedes visualizar servicios distribuidos en Cloud Service Mesh.

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

    Ir a Service Mesh

    Puedes ver los servicios en la vista de tabla o en una vista de topología. La vista predeterminada es la vista de tabla, que muestra todos los servicios distribuidos que se ejecutan en formato tabular. Para cambiar las vistas, haz clic en la vista que deseas mostrar.

  2. En la vista Tablas, haz clic en frontend distributed service. Cuando haces clic en un servicio individual, verás una vista detallada del servicio junto con los servicios conectados.

    En la vista de detalles del servicio, puedes hacer clic en Mostrar cronograma para crear un SLO y ver un cronograma histórico del servicio.

  3. Para ver los indicadores dorados, en el panel lateral, haz clic en Métricas.

  4. En el gráfico Solicitudes por segundos, haz clic en Desglose por y, luego, selecciona 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 extremos entregan tráfico.

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

  6. Para ver datos adicionales, mantén el puntero del mouse sobre el servicio frontend. Esto muestra información como solicitudes por segundo hacia y desde el frontend a otros servicios.

  7. Para ver más detalles, haz clic en Expandir en el servicio frontend. Se muestran un servicio y una carga de trabajo. Puedes expandir aún más la carga de trabajo en dos Deployments, expandir las implementaciones en ReplicaSets y expandir los ReplicaSets a los Pods. Cuando expandes todos los elementos, puedes ver el servicio distribuido frontend, que es un servicio y dos pods.

Configura Ingress de varios clústeres

En esta sección, crearás un Ingress de varios clústeres que envía tráfico a los servicios frontend del banco de GKE Enterprise que se ejecutan en ambos clústeres. Usa Cloud Load Balancing para crear un balanceador de cargas que use los servicios de asm-ingressgateway en ambos clústeres como backends. Un clúster ingress-config se usa para organizar la configuración de Ingress de varios clústeres.

Para crear el balanceador de cargas, usa un MultiClusterIngress y uno o más MultiClusterServices. Los objetos MultiClusterIngress y MultiClusterService son análogos de varios clústeres para los recursos de Ingress y servicio de Kubernetes existentes que se usan en el contexto de clúster único.

  1. Habilita las APIs necesarias de GKE Enterprise, de flota de GKE y de Ingress de varios clústeres:

    gcloud services enable \
      anthos.googleapis.com \
      multiclusterservicediscovery.googleapis.com \
      multiclusteringress.googleapis.com
    
  2. Cree el clúster ingress-config. Puedes usar cualquier clúster, pero te recomendamos que crees un clúster independiente 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 la flota de GKE Enterprise, 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 empresarial de GKE:

    gcloud container fleet memberships list
    

    El resultado luce de la siguiente manera:

    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 entrada de clústeres múltiples en el clúster ingress-config. Esto crea las CustomResourceDefinitions (CRD) MulticlusterService y MulticlusterIngress en el clúster.

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

    gcloud container fleet ingress describe
    

    El resultado luce de la siguiente manera:

    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 las dos CRD se implementen en el clúster ingress-config:

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

    La salida se verá de la siguiente manera.

    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 verificaciones de 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 implementaste en el clúster de Ingress creará un Service “sin interfaz gráfica” en los clústeres 1 y 2. Verifica que se hayan creado los Services “sin interfaz gráfica”:

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

    El resultado es similar al 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}"
    

    El resultado luce de la siguiente manera:

    35.35.23.11
    

    Para salir del comando watch, presiona Ctrl+C.

  17. Navega 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 502), espera unos minutos y, luego, actualiza la página en tu navegador web.

Limpia

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

Borra el proyecto

La manera más fácil de eliminar la facturación es borrar el proyecto que creaste para el instructivo.

  1. En la consola de Google Cloud, ve a la página Administrar recursos.

    Ir a Administrar recursos

  2. En la lista de proyectos, elige el proyecto que quieres borrar y haz clic en Borrar.
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.

Borra los clústeres

  1. En Cloud Shell, anula el registro y borra 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. Borra el recurso MuticlusterIngress del clúster de configuración de Ingress:

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

    Con este comando, se borran los recursos de Cloud Load Balancing del proyecto.

  3. Cancela el registro del clúster ingress-config y bórralo:

    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 borren todos los clústeres:

    gcloud container clusters list
    

    Esta es la salida:

    <null>
  5. Restablece el archivo kubeconfig:

    unset KUBECONFIG
    

¿Qué sigue?