Implantar um gateway interno de vários clusters

Este documento orienta você em um exemplo prático para implantar um gateway interno de vários clusters para rotear o tráfego na rede VPC para um aplicativo executado em dois clusters diferentes do GKE.

Os gateways de vários clusters oferecem uma maneira eficiente de gerenciar o tráfego de serviços implantados em vários clusters do GKE. Ao usar a infraestrutura global de balanceamento de carga do Google, você pode criar um único ponto de entrada para seus aplicativos, o que simplifica o gerenciamento e melhora a confiabilidade.

Neste tutorial, você usará um aplicativo de exemplo store para simular um cenário real em que um serviço de compras on-line é pertencente e operado por equipes separadas e implantado em uma frota de clusters compartilhados do GKE.

Este exemplo mostra como configurar o roteamento baseado em caminho para direcionar o tráfego a clusters diferentes.

Antes de começar

Os gateways de vários clusters precisam de preparação do ambiente para serem implantados. Antes de continuar, siga as etapas em Preparar o ambiente para gateways de vários clusters Gateways:

  1. Implante cluster do GKE.

  2. Registre os clusters em uma frota (se eles ainda não estiverem).

  3. Ative os controladores do gateway de vários clusters e do serviço de vários clusters.

Por fim, analise as limitações e problemas conhecidos do GKE Gateway controller antes de usá-lo no seu ambiente.

Implantar um gateway interno de vários clusters em regiões

É possível implantar gateways de vários clusters que fornecem balanceamento de carga interno da camada 7 em clusters do GKE em várias regiões. Esses gateways usam a GatewayClass gke-l7-cross-regional-internal-managed-mc. Essa GatewayClass provisiona um balanceador de carga de aplicativo interno entre regiões gerenciado por Google Cloud e que permite VIPs internos que clientes na sua rede VPC podem acessar. Esses gateways podem ser expostos por front-ends nas regiões de sua escolha, basta usar o gateway para solicitar endereços nessas regiões. O VIP interno pode ser um único endereço IP ou endereços IP em várias regiões, com um endereço IP por região especificado no gateway. O tráfego é direcionado ao cluster do GKE de back-end íntegro mais próximo que pode atender à solicitação.

Pré-requisitos

  1. Configure seu projeto e shell configurando o ambiente gcloud com o ID do projeto:

    export PROJECT_ID="YOUR_PROJECT_ID"
    gcloud config set project ${PROJECT_ID}
    
  2. Crie clusters do GKE em regiões diferentes.

    Este exemplo usa dois clusters, gke-west-1 em us-west1 e gke-east-1 em us-east1. Verifique se a API Gateway está ativada (--gateway-api=standard) e se os clusters estão registrados em uma frota.

    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
    

    Renomeie os contextos para facilitar o acesso:

    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. Ative os serviços de vários clusters (MCS) e a entrada de vários clusters (MCI/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. Configure sub-redes somente proxy. Uma sub-rede somente proxy é necessária em cada região em que os clusters do GKE estão localizados e em que o balanceador de carga vai operar. Os balanceadores de carga de aplicativo internos entre regiões exigem que a finalidade dessa sub-rede seja definida 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
    

    Se você não estiver usando a rede padrão, substitua default pelo nome da sua rede VPC. Verifique se os intervalos de CIDR são exclusivos e não se sobrepõem.

  5. Implante seus aplicativos de demonstração, como store, nos dois clusters. O arquivo de exemplo store.yaml de gke-networking-recipes cria um namespace store e uma implantação.

    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. Exporte serviços de cada cluster criando recursos Service e ServiceExport do Kubernetes em cada cluster, o que torna os serviços detectáveis em toda a frota. O exemplo a seguir exporta um serviço genérico store e serviços específicos da região (store-west-1, store-east-1) de cada cluster, tudo dentro do namespace store.

    Aplicar a 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
    

    Aplicar a 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. Verifique as ServiceImports: verifique se os recursos ServiceImport são criados em cada cluster no namespace store. Pode levar alguns minutos para que eles sejam criados. bash kubectl get serviceimports --context gke-west1 -n store kubectl get serviceimports --context gke-east1 -n store Você verá store, store-west-1 e store-east-1 listados (ou entradas relevantes com base na propagação).

Configurar um gateway interno multirregional

Defina um recurso Gateway que referencia a GatewayClass gke-l7-cross-regional-internal-managed-mc. Você aplica esse manifesto ao cluster de configuração designado, como gke-west-1.

O campo spec.addresses permite solicitar endereços IP efêmeros em regiões específicas ou usar endereços IP estáticos pré-alocados.

  1. Para usar endereços IP efêmeros, salve o seguinte manifesto 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
    

    A lista a seguir define alguns dos campos no arquivo YAML anterior:

    • metadata.namespace: o namespace em que o recurso do gateway é criado, por exemplo, store.
    • spec.gatewayClassName: o nome da GatewayClass. Precisa ser gke-l7-cross-regional-internal-managed-mc.
    • spec.listeners.allowedRoutes.kinds: os tipos de objetos de rota que podem ser anexados, por exemplo, HTTPRoute.
    • spec.addresses:
      • type: networking.gke.io/ephemeral-ipv4-address/REGION: solicita um endereço IP efêmero.
      • value: especifica a região do endereço, por exemplo, "us-west1" ou "us-east1".
  2. Aplique o manifesto ao cluster de configuração, por exemplo, gke-west1:

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

Anexar HTTPRoutes ao gateway

Defina recursos HTTPRoute para gerenciar o roteamento de tráfego e aplique-os ao cluster de configuração.

  1. Salve o seguinte manifesto 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
    

    A lista a seguir define alguns dos campos no arquivo YAML anterior:

    • spec.parentRefs: anexa essa rota a internal-cross-region-gateway no namespace store.
    • spec.hostnames: representa o nome do host que os clientes usam para acessar o serviço.
    • spec.rules: define a lógica de roteamento. Este exemplo usa o roteamento baseado em caminho:
      • O tráfego /west vai para store-west-1 ServiceImport.
      • O tráfego /east vai para store-east-1 ServiceImport.
      • Todo o outro tráfego, como /, vai para o ServiceImport genérico store.
    • backendRefs:
      • group: net.gke.io e kind: ServiceImport segmentam serviços de vários clusters.
  2. Aplique o manifesto HTTPRoute ao cluster de configuração:

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

Verificar o status do gateway e da rota

  1. Verifique o status do gateway:

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

    Procure uma condição com type:Programmedandstatus: "True". Você verá endereços IP atribuídos no campo. You should see IP addresses assigned in thestatus.addresses, correspondentes às regiões especificadas (por exemplo, um parafield, corresponding to the regions you specified (e.g., one forus-west1 e um paraand one forus-east1).

  2. Verifique o status do HTTPRoute:

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

    Procure uma condição em status.parents[].conditions com type: Accepted (ou ResolvedRefs) e status: "True".

Confirmar o trânsito

Depois de atribuir os endereços IP ao gateway, é possível testar o tráfego de uma VM de cliente que esteja na sua rede VPC e em uma das regiões ou em uma região que possa se conectar ao endereço IP do gateway.

  1. Recupere os endereços IP do gateway.

    O comando a seguir tenta analisar a saída JSON. Talvez seja necessário ajustar o jsonpath com base na estrutura exata.

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

    A saída desse comando precisa incluir os VIPs, como VIP1_WEST ou VIP2_EAST.

  2. Envie solicitações de teste: de uma VM de cliente na sua 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/
    

    A resposta precisa incluir detalhes do aplicativo store que indicam qual pod de back-end atendeu à solicitação, como cluster_name ou zone.

Usar endereços IP estáticos

Em vez de endereços IP efêmeros, é possível usar endereços IP internos estáticos pré-alocados.

  1. Crie endereços IP estáticos nas regiões que você quer 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}
    

    Se você não estiver usando a sub-rede padrão, substitua default pelo nome da sub-rede que tem o endereço IP que você quer alocar. Essas sub-redes são sub-redes normais, não as sub-redes somente proxy.

  2. Atualize o manifesto do gateway modificando a seção spec.addresses no arquivo 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. Aplique o manifesto do gateway atualizado.

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

Considerações especiais para sub-redes não padrão

Esteja ciente das seguintes considerações ao usar sub-redes não padrão:

  • Mesma rede VPC:todos os recursos criados pelo usuário, como endereços IP estáticos, sub-redes somente proxy e clusters do GKE, precisam residir na mesma rede VPC.

  • Sub-rede de endereço:ao criar endereços IP estáticos para o gateway, eles são alocados de sub-redes normais nas regiões especificadas.

  • Nomeação de sub-rede de cluster:cada região precisa ter uma sub-rede com o mesmo nome da sub-rede em que o cluster de configuração do MCG reside.

    • Por exemplo, se o cluster de configuração gke-west-1 estiver em projects/YOUR_PROJECT/regions/us-west1/subnetworks/my-custom-subnet, as regiões para as quais você está solicitando endereços também precisam ter a sub-rede my-custom-subnet. Se você solicitar endereços nas regiões us-east1 e us-centra1, uma sub-rede chamada my-custom-subnet também precisará existir nessas regiões.

Limpar

Depois de concluir os exercícios neste documento, siga estas etapas para remover os recursos e evitar cobranças indesejadas na conta:

  1. Excluir os clusters.

  2. Cancele o registro dos clusters da frota se eles não precisarem ser registrados para outra finalidade.

  3. Desative o recurso multiclusterservicediscovery:

    gcloud container fleet multi-cluster-services disable
    
  4. Desativar o Ingress de vários clusters:

    gcloud container fleet ingress disable
    
  5. Desative as APIs:

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

Solução de problemas

Não existe uma sub-rede somente proxy para o gateway interno

Se o evento a seguir aparecer no gateway interno, não existe uma sub-rede apenas proxy nessa região. Para resolver esse problema, implante uma sub-rede apenas 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.

Nenhum upstream íntegro

Sintoma:

O seguinte problema pode ocorrer quando você cria um gateway mas não pode acessar os serviços de back-end (código de resposta 503):

no healthy upstream

Motivo:

Esta mensagem de erro indica que a sondagem da verificação de integridade não consegue encontrar a integridade dos serviços de back-end. É possível que os serviços de back-end estejam íntegros, mas talvez seja necessário personalizar as verificações de integridade.

Alternativa:

Para resolver esse problema, personalize a verificação de integridade com base nas condições (por exemplo, /health) usando um HealthCheckPolicy.

A seguir