Desplegar una pasarela interna de varios clústeres

En este documento se explica un ejemplo práctico para desplegar una pasarela interna multiclúster con el fin de enrutar el tráfico dentro de tu red de VPC a una aplicación que se ejecuta en dos clústeres de GKE diferentes.

Las pasarelas de varios clústeres ofrecen una forma eficaz de gestionar el tráfico de los servicios desplegados en varios clústeres de GKE. Si usas la infraestructura de balanceo de carga global de Google, puedes crear un único punto de entrada para tus aplicaciones, lo que simplifica la gestión y mejora la fiabilidad.

En este tutorial, usarás una aplicación store de ejemplo para simular una situación real en la que un servicio de compras online es propiedad de equipos independientes y está gestionado por ellos, y se despliega en una flota de clústeres de GKE compartidos.

En este ejemplo se muestra cómo configurar el enrutamiento basado en rutas para dirigir el tráfico a diferentes clústeres.

Antes de empezar

Las pasarelas multiclúster requieren cierta preparación del entorno antes de poder implementarse. Antes de continuar, sigue los pasos que se indican en el artículo Preparar el entorno para usar Gateways multiclúster:

  1. Despliega clústeres de GKE.

  2. Registra tus clústeres en una flota (si aún no lo has hecho).

  3. Habilita los controladores de servicio y de pasarela de varios clústeres.

Por último, consulta las limitaciones y los problemas conocidos del controlador de Gateway de GKE antes de usarlo en tu entorno.

Desplegar una pasarela de varios clústeres interna en varias regiones

Puedes desplegar pasarelas de varios clústeres que proporcionen balanceo de carga interno de capa 7 en clústeres de GKE de varias regiones. Estas pasarelas usan gke-l7-cross-regional-internal-managed-mc GatewayClass. Esta GatewayClass aprovisiona un balanceador de carga de aplicaciones interno entre regiones gestionado por Google Cloud que habilita IPs virtuales internas a las que pueden acceder los clientes de tu red de VPC. Puedes exponer estas pasarelas mediante front-ends en las regiones que elijas. Para ello, solo tienes que usar la pasarela para solicitar direcciones en esas regiones. La dirección IP virtual interna puede ser una sola dirección IP o varias direcciones IP de distintas regiones, con una dirección IP por región especificada en la pasarela. El tráfico se dirige al clúster de GKE de backend en buen estado más cercano que pueda atender la solicitud.

Requisitos previos

  1. Configura tu proyecto y shell configurando tu entorno gcloud con el ID de tu proyecto:

    export PROJECT_ID="YOUR_PROJECT_ID"
    gcloud config set project ${PROJECT_ID}
    
  2. Crea clústeres de GKE en diferentes regiones.

    En este ejemplo se usan dos clústeres: gke-west-1 en us-west1 y gke-east-1 en us-east1. Asegúrate de que la API Gateway esté habilitada (--gateway-api=standard) y de que los clústeres estén registrados en una flota.

    gcloud container clusters create gke-west-1 \
        --location=us-west1-a \
        --workload-pool=${PROJECT_ID}.svc.id.goog \
        --project=${PROJECT_ID} \
        --enable-fleet \
        --gateway-api=standard
    
    gcloud container clusters create gke-east-1 \
        --location=us-east1-c \
        --workload-pool=${PROJECT_ID}.svc.id.goog \
        --project=${PROJECT_ID} \
        --enable-fleet \
        --gateway-api=standard
    

    Cambiar el nombre de los contextos para acceder a ellos más fácilmente:

    gcloud container clusters get-credentials gke-west-1 \
      --location=us-west1-a \
      --project=${PROJECT_ID}
    
    gcloud container clusters get-credentials gke-east-1 \
      --location=us-east1-c \
      --project=${PROJECT_ID}
    kubectl config rename-context gke_${PROJECT_ID}_us-west1-a_gke-west-1 gke-west1
    kubectl config rename-context gke_${PROJECT_ID}_us-east1-c_gke-east-1 gke-east1
    
  3. Habilita los servicios de varios clústeres (MCS) y la entrada de varios clústeres (MCI o Gateway):

    gcloud container fleet multi-cluster-services enable --project=${PROJECT_ID}
    
    # Set the config membership to one of your clusters (e.g., gke-west-1)
    # This cluster will be the source of truth for multi-cluster Gateway and Route resources.
    gcloud container fleet ingress enable \
        --config-membership=projects/${PROJECT_ID}/locations/us-west1/memberships/gke-west-1 \
        --project=${PROJECT_ID}
    
  4. Configura subredes de solo proxy. Se necesita una subred de solo proxy en cada región en la que se encuentren tus clústeres de GKE y en la que vaya a funcionar el balanceador de carga. Los balanceadores de carga de aplicación internos entre regiones requieren que el propósito de esta subred se defina como GLOBAL_MANAGED_PROXY.

    # Proxy-only subnet for us-west1
    gcloud compute networks subnets create us-west1-proxy-only-subnet \
        --purpose=GLOBAL_MANAGED_PROXY \
        --role=ACTIVE \
        --region=us-west1 \
        --network=default \
        --range=10.129.0.0/23 # Choose an appropriate unused CIDR range
    
    # Proxy-only subnet for us-east1
    gcloud compute networks subnets create us-east1-proxy-only-subnet \
        --purpose=GLOBAL_MANAGED_PROXY \
        --role=ACTIVE \
        --region=us-east1 \
        --network=default \
        --range=10.130.0.0/23 # Choose an appropriate unused CIDR range
    

    Si no usas la red predeterminada, sustituye default por el nombre de tu red de VPC. Asegúrate de que los intervalos CIDR sean únicos y no se solapen.

  5. Despliega tus aplicaciones de demostración, como store, en ambos clústeres. El archivo de ejemplo store.yaml de gke-networking-recipes crea un espacio de nombres store y una implementación.

    kubectl apply --context gke-west1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml
    kubectl apply --context gke-east1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml
    
  6. Exporta los servicios de cada clúster creando recursos Service y ServiceExport de Kubernetes en cada clúster, lo que permite que los servicios se puedan descubrir en toda la flota. En el siguiente ejemplo se exportan un servicio store genérico y servicios específicos de la región (store-west-1 y store-east-1) de cada clúster, todos ellos en el espacio de nombres store.

    Solicitar gke-west1:

    cat << EOF | kubectl apply --context gke-west1 -f -
    apiVersion: v1
    kind: Service
    metadata:
      name: store
      namespace: store
    spec:
      selector:
        app: store
      ports:
      - port: 8080
        targetPort: 8080
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store
      namespace: store
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: store-west-1 # Specific to this cluster
      namespace: store
    spec:
      selector:
        app: store
      ports:
      - port: 8080
        targetPort: 8080
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store-west-1 # Exporting the region-specific service
      namespace: store
    EOF
    

    Solicitar gke-east1:

    cat << EOF | kubectl apply --context gke-east1 -f -
    apiVersion: v1
    kind: Service
    metadata:
      name: store
      namespace: store
    spec:
      selector:
        app: store
      ports:
      - port: 8080
        targetPort: 8080
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store
      namespace: store
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: store-east-1 # Specific to this cluster
      namespace: store
    spec:
      selector:
        app: store
      ports:
      - port: 8080
        targetPort: 8080
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store-east-1 # Exporting the region-specific service
      namespace: store
    EOF
    
  7. Comprueba ServiceImports: Verifica que se hayan creado recursos ServiceImport en cada clúster del espacio de nombres store. La creación puede tardar unos minutos. bash kubectl get serviceimports --context gke-west1 -n store kubectl get serviceimports --context gke-east1 -n store Deberías ver store, store-west-1 y store-east-1 (o las entradas correspondientes en función de la propagación).

Configurar una pasarela interna multirregional

Define un recurso Gateway que haga referencia a gke-l7-cross-regional-internal-managed-mc GatewayClass. Aplica este manifiesto al clúster de configuración que hayas designado, como gke-west-1.

El campo spec.addresses te permite solicitar direcciones IP efímeras en regiones concretas o usar direcciones IP estáticas preasignadas.

  1. Para usar direcciones IP efímeras, guarda el siguiente manifiesto Gateway como cross-regional-gateway.yaml:

    # cross-regional-gateway.yaml
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: internal-cross-region-gateway
      namespace: store # Namespace for the Gateway resource
    spec:
      gatewayClassName: gke-l7-cross-regional-internal-managed-mc
      addresses:
      # Addresses across regions. Address value is allowed to be empty or matching
      # the region name.
      - type: networking.gke.io/ephemeral-ipv4-address/us-west1
        value: "us-west1"
      - type: networking.gke.io/ephemeral-ipv4-address/us-east1
        value: "us-east1"
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          kinds:
          - kind: HTTPRoute # Only allow HTTPRoute to attach
    

    En la siguiente lista se definen algunos de los campos del archivo YAML anterior:

    • metadata.namespace: el espacio de nombres en el que se crea el recurso Gateway (por ejemplo, store).
    • spec.gatewayClassName: el nombre de GatewayClass. Debe ser gke-l7-cross-regional-internal-managed-mc.
    • spec.listeners.allowedRoutes.kinds: los tipos de objetos Route que se pueden adjuntar, como HTTPRoute.
    • spec.addresses:
      • type: networking.gke.io/ephemeral-ipv4-address/REGION: solicita una dirección IP efímera.
      • value: especifica la región de la dirección; por ejemplo, "us-west1" o "us-east1".
  2. Aplica el manifiesto a tu clúster de configuración. Por ejemplo, gke-west1:

    kubectl apply --context gke-west1 -f cross-regional-gateway.yaml
    

Asociar HTTPRoutes a la Gateway

Define los recursos HTTPRoute para gestionar el enrutamiento del tráfico y aplícalos a tu clúster de configuración.

  1. Guarda el siguiente manifiesto HTTPRoute como store-route.yaml:

    # store-route.yaml
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: store-route
      namespace: store
      labels:
        gateway: cross-regional-internal
    spec:
      parentRefs:
      - name: internal-cross-region-gateway
        namespace: store # Namespace where the Gateway is deployed
      hostnames:
      - "store.example.internal" # Hostname clients will use
      rules:
      - matches: # Rule for traffic to /west
        - path:
            type: PathPrefix
            value: /west
        backendRefs:
        - group: net.gke.io # Indicates a multi-cluster ServiceImport
          kind: ServiceImport
          name: store-west-1 # Targets the ServiceImport for the west cluster
          port: 8080
      - matches: # Rule for traffic to /east
        - path:
            type: PathPrefix
            value: /east
        backendRefs:
        - group: net.gke.io
          kind: ServiceImport
          name: store-east-1 # Targets the ServiceImport for the east cluster
          port: 8080
      - backendRefs: # Default rule for other paths (e.g., /)
        - group: net.gke.io
          kind: ServiceImport
          name: store # Targets the generic 'store' ServiceImport (any region)
          port: 8080
    

    En la siguiente lista se definen algunos de los campos del archivo YAML anterior:

    • spec.parentRefs: asocia esta ruta a internal-cross-region-gateway en el espacio de nombres store.
    • spec.hostnames: representa el nombre de host que usan los clientes para acceder al servicio.
    • spec.rules: define la lógica de enrutamiento. En este ejemplo se usa el enrutamiento basado en rutas:
      • El tráfico de /west se dirige a ServiceImport de store-west-1.
      • El tráfico de /east se dirige a ServiceImport store-east-1.
      • El resto del tráfico, como /, se dirige al ServiceImport genérico store.
    • backendRefs:
      • group: net.gke.io y kind: ServiceImport se dirigen a servicios de varios clústeres.
  2. Aplica el manifiesto HTTPRoute a tu clúster de configuración:

    kubectl apply --context gke-west1 -f store-route.yaml
    

Verificar el estado de la pasarela y la ruta

  1. Comprueba el estado de la pasarela:

    kubectl get gateway internal-cross-region-gateway -n store -o yaml --context gke-west1
    

    Busca una condición con el estado type:Programadoand: "True". You should see IP addresses assigned in thestatus.addressesfield, corresponding to the regions you specified (e.g., one forus-west1and one forus-east1`).

  2. Comprueba el estado de HTTPRoute:

    kubectl get httproute store-route -n store -o yaml --context gke-west1
    

    Busca una condición en status.parents[].conditions con type: Accepted (o ResolvedRefs) y status: "True".

Confirmar tráfico

Después de asignar las direcciones IP a la pasarela, puedes probar el tráfico desde una máquina virtual cliente que esté en tu red de VPC y en una de las regiones, o en una región que pueda conectarse a la dirección IP de la pasarela.

  1. Recupera las direcciones IP de la pasarela.

    El siguiente comando intenta analizar el resultado JSON. Es posible que tengas que ajustar el jsonpath en función de la estructura exacta.

    kubectl get gateway cross-region-gateway -n store --context gke-west1 -o=jsonpath="{.status.addresses[*].value}".
    

    El resultado de este comando debe incluir las IPs virtuales, como VIP1_WEST o VIP2_EAST.

  2. Envía solicitudes de prueba: Desde una VM cliente de tu VPC:

    # Assuming VIP_WEST is an IP in us-west1 and VIP_EAST is an IP in us-east1
    # Traffic to /west should ideally be served by gke-west-1
    curl -H "host: store.example.internal" http://VIP_WEST/west
    curl -H "host: store.example.internal" http://VIP_EAST/west # Still targets store-west-1 due to path
    
    # Traffic to /east should ideally be served by gke-east-1
    curl -H "host: store.example.internal" http://VIP_WEST/east # Still targets store-east-1 due to path
    curl -H "host: store.example.internal" http://VIP_EAST/east
    
    # Traffic to / (default) could be served by either cluster
    curl -H "host: store.example.internal" http://VIP_WEST/
    curl -H "host: store.example.internal" http://VIP_EAST/
    

    La respuesta debe incluir detalles de la aplicación store que indiquen qué pod de backend ha servido la solicitud, como cluster_name o zone.

Usar direcciones IP estáticas

En lugar de direcciones IP efímeras, puedes usar direcciones IP internas estáticas preasignadas.

  1. Crea direcciones IP estáticas en las regiones que quieras usar:

    gcloud compute addresses create cross-region-gw-ip-west --region us-west1 --subnet default --project=${PROJECT_ID}
    gcloud compute addresses create cross-region-gw-ip-east --region us-east1 --subnet default --project=${PROJECT_ID}
    

    Si no usas la subred predeterminada, sustituye default por el nombre de la subred que tenga la dirección IP que quieras asignar. Estas subredes son subredes normales, no subredes de solo proxy.

  2. Actualiza el manifiesto de la pasarela modificando la sección spec.addresses de tu archivo cross-regional-gateway.yaml:

    # cross-regional-gateway-static-ip.yaml
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: internal-cross-region-gateway # Or a new name if deploying alongside
      namespace: store
    spec:
      gatewayClassName: gke-l7-cross-regional-internal-managed-mc
      addresses:
      - type: networking.gke.io/named-address-with-region # Use for named static IP
        value: "regions/us-west1/addresses/cross-region-gw-ip-west"
      - type: networking.gke.io/named-address-with-region
        value: "regions/us-east1/addresses/cross-region-gw-ip-east"
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          kinds:
          - kind: HTTPRoute
    
  3. Aplica el archivo de manifiesto de la pasarela actualizado.

    kubectl apply --context gke-west1 -f cross-regional-gateway.yaml
    

Consideraciones especiales para subredes no predeterminadas

Ten en cuenta lo siguiente cuando uses subredes no predeterminadas:

  • Misma red de VPC: todos los recursos creados por el usuario, como las direcciones IP estáticas, las subredes solo proxy y los clústeres de GKE, deben residir en la misma red de VPC.

  • Subred de direcciones: cuando creas direcciones IP estáticas para la pasarela, se asignan desde subredes normales de las regiones especificadas.

  • Nombres de subredes de clústeres: cada región debe tener una subred con el mismo nombre que la subred en la que se encuentra el clúster de configuración de MCG.

    • Por ejemplo, si tu clúster de configuración gke-west-1 está en projects/YOUR_PROJECT/regions/us-west1/subnetworks/my-custom-subnet, las regiones para las que solicitas direcciones también deben tener la subred my-custom-subnet. Si solicitas direcciones en las regiones us-east1 y us-centra1, también debe haber una subred llamada my-custom-subnet en esas regiones.

Limpieza

Después de completar los ejercicios de este documento, siga estos pasos para quitar recursos y evitar que se apliquen cargos no deseados a su cuenta:

  1. Elimina los clústeres.

  2. Anula el registro de los clústeres de la flota si no es necesario que estén registrados para otro propósito.

  3. Para inhabilitar la función multiclusterservicediscovery, sigue estos pasos:

    gcloud container fleet multi-cluster-services disable
    
  4. Inhabilita la entrada de varios clústeres:

    gcloud container fleet ingress disable
    
  5. Inhabilita las APIs:

    gcloud services disable \
        multiclusterservicediscovery.googleapis.com \
        multiclusteringress.googleapis.com \
        trafficdirector.googleapis.com \
        --project=PROJECT_ID
    

Solución de problemas

No existe una subred de solo proxy para la pasarela interna

Si aparece el siguiente evento en tu pasarela interna, significa que no existe una subred solo de proxy para esa región. Para solucionar este problema, implementa una subred solo de proxy.

generic::invalid_argument: error ensuring load balancer: Insert: Invalid value for field 'resource.target': 'regions/us-west1/targetHttpProxies/gkegw-x5vt-default-internal-http-2jzr7e3xclhj'. A reserved and active subnetwork is required in the same region and VPC as the forwarding rule.

No hay upstream en buen estado

Síntoma:

El siguiente problema puede producirse cuando crea una pasarela, pero no puede acceder a los servicios de backend (código de respuesta 503):

no healthy upstream

Motivo:

Este mensaje de error indica que el comprobador de estado no puede encontrar servicios de backend en buen estado. Es posible que tus servicios de backend estén en buen estado, pero que tengas que personalizar las comprobaciones del estado.

Solución alternativa:

Para solucionar este problema, personaliza la comprobación de estado según los requisitos de tu aplicación (por ejemplo, /health) mediante un HealthCheckPolicy.

Siguientes pasos