Como implantar gateways de vários clusters


Nesta página, descrevemos como implantar recursos de gateway do Kubernetes para fazer o balanceamento de carga de tráfego de entrada em vários clusters (ou frotas) do Google Kubernetes Engine (GKE). Antes de implantar gateways de vários clusters, consulte Como ativar gateways de vários clusters para preparar o ambiente.

Para implantar gateways para balancear a carga de tráfego de entrada em apenas um cluster do GKE, consulte Como implantar gateways.

Gateways de vários clusters

Um gateway de vários clusters é um recurso de gateway que faz o balanceamento de carga do tráfego em vários clusters do Kubernetes. No GKE, os GatewayClasses gke-l7-global-external-managed-mc, gke-l7-regional-external-managed-mc, gke-l7-rilb-mc e gke-l7-gxlb-mc implantam gateways de vários clusters que fornecem roteamento HTTP, divisão de tráfego, espelhamento de tráfego, failover baseado em integridade e muito mais em diferentes clusters do GKE, Namespaces do Kubernetes e em regiões diferentes. Os gateways de vários clusters facilitam o gerenciamento da rede de aplicativos em vários clusters e equipes, são seguros e escalonáveis para administradores de infraestrutura.

Um gateway de vários clusters é um recurso de gateway que faz o balanceamento de carga do tráfego em
vários clusters do Kubernetes.

Nesta página, apresentamos três exemplos de como implantar gateways de vários clusters usando o GKE Gateway Controller:

  • Exemplo 1: um gateway de vários clusters externo que fornece balanceamento de carga em dois clusters do GKE para tráfego da Internet.
  • Exemplo 2: divisão de tráfego azul-verde baseada em peso e espelhamento de tráfego em dois clusters do GKE para tráfego VPC interno.
  • Exemplo 3: um gateway com base em capacidade para balancear a carga para diferentes back-ends com base na capacidade máxima.

Cada um dos exemplos usará os mesmos aplicativos de store e site para modelar um cenário real em que um serviço de compras on-line e um serviço de site são pertencentes e operados por equipes separadas e implantadas em uma frota de clusters compartilhados do GKE. Cada um dos exemplos destaca diferentes topologias e casos de uso ativados por gateways de vários clusters.

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

  1. Implante cluster do GKE.

  2. Registre os clusters em uma frota.

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

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

Gateway externo multicluster e multirregional

Neste tutorial, você criará um gateway externo de vários clusters que exibe o tráfego externo em um aplicativo executado em dois clusters do GKE.

store.example.com é implantado em dois clusters do GKE e expostos
à internet por meio de um gateway de vários clusters

Nas etapas a seguir, você:

  1. Implante o aplicativo store de amostra nos clusters gke-west-1 e gke-east-1.
  2. Configure serviços em cada cluster a ser exportado para sua frota (serviços de vários clusters).
  3. Implante um gateway de vários clusters externos e uma HTTPRoute no cluster de configuração (gke-west-1).

Depois que os recursos de aplicativo e de gateway forem implantados, será possível controlar o tráfego nos dois clusters do GKE usando o roteamento baseado em caminho:

  • As solicitações para /west são roteadas para pods store no cluster gke-west-1.
  • As solicitações para /east são roteadas para pods store no cluster gke-east-1.
  • As solicitações para qualquer outro caminho são roteadas para qualquer cluster, de acordo com a integridade, a capacidade e a proximidade do cliente solicitante.

Como implantar o aplicativo de demonstração

  1. Crie a implantação e o namespace store em todos os três clusters que foram implantados em Como ativar gateways de vários clusters:

    kubectl apply --context gke-west-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml
    kubectl apply --context gke-west-2 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml
    kubectl apply --context gke-east-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml
    

    Ele implanta os seguintes recursos em cada cluster:

    namespace/store created
    deployment.apps/store created
    

    Todos os exemplos nesta página usam o aplicativo implantado nesta etapa. Verifique se o app está implantado nos três clusters antes de tentar qualquer uma das etapas restantes. Neste exemplo, usamos apenas os clusters gke-west-1 e gke-east-1, e o gke-west-2 é usado em outro exemplo.

Serviços de vários clusters

Os serviços são como os pods são expostos aos clientes. Como o controlador de gateway do GKE usa balanceamento de carga nativo de contêiner, ele não usa o balanceamento de carga ClusterIP ou Kubernetes para alcançar pods. O tráfego é enviado diretamente do balanceador de carga para os endereços IP do pod. No entanto, os serviços ainda desempenham um papel crítico como um identificador lógico para o agrupamento de pods.

Serviços de vários clusters (MCS, na sigla em inglês) é um padrão de API para serviços que abrange clusters e o controlador do GKE dele fornece descoberta de serviços em clusters do GKE. O controlador de gateway de vários clusters usa recursos da API MCS para agrupar pods em um serviço endereçável ou que abrange vários clientes.

A API de serviços de vários clusters define os seguintes recursos personalizados:

  • ServiceExports mapeia para um serviço do Kubernetes, exportando os endpoints desse serviço para todos os clusters registrados na frota. Quando um Serviço tem um ServiceExport correspondente, ele pode ser endereçado por um gateway de vários clusters.
  • Os ServiceImports são gerados automaticamente pelo controlador do Serviço de vários clusters. O ServiceExport e o ServiceImport vêm em pares. Se houver uma ServiceExport na frota, uma ServiceImport correspondente será criada para permitir que o Service mapeado para a ServiceExport seja acessado entre os clusters.

A exportação de Serviços funciona da seguinte forma. Há um serviço de armazenamento em gke-west-1, que seleciona um grupo de pods nesse cluster. Uma ServiceExport é criada no cluster, o que permite que os pods em gke-west-1 fiquem acessíveis para os outros clusters na frota. A ServiceExport será mapeada e exibirá Serviços com o mesmo nome e namespace que o recurso ServiceExport.

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

O diagrama a seguir mostra o que acontece depois que um ServiceExport é implantado. Se houver um par de ServiceExport e Service, o controlador de serviço de vários clusters implantará um ServiceImport correspondente em cada cluster do GKE na frota. O ServiceImport é a representação local do serviço store em cada cluster. Isso permite que o pod client em gke-east-1 use ClusterIP ou serviços headless para alcançar os pods store em gke-west-1. Quando usados dessa maneira, os serviços de vários clusters fornecem balanceamento de carga de leste-oeste entre clusters sem exigir um serviço LoadBalancer interno. Para usar serviços de vários clusters no balanceamento de carga de cluster para cluster, consulte Como configurar serviços de vários clusters.

Os serviços com vários clusters exportam serviços entre clusters, o que permite
a comunicação entre eles

Os gateways de vários clusters também usam ServiceImports, mas não para balanceamento de carga de cluster para cluster. Em vez disso, os gateways usam ServiceImports como identificadores lógicos de um serviço que existe em outro cluster ou que se estende por vários clusters. O HTTPRoute a seguir refere-se a um ServiceImport em vez de um recurso Serviço. Ao referenciar um ServiceImport, isso indica que ele está encaminhando tráfego para um grupo de pods de back-end que são executados em um ou mais clusters.

kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
  name: store-route
  namespace: store
  labels:
    gateway: multi-cluster-gateway
spec:
  parentRefs:
  - kind: Gateway
    namespace: store
    name: external-http
  hostnames:
  - "store.example.com"
  rules:
  - backendRefs:
    - group: net.gke.io
      kind: ServiceImport
      name: store
      port: 8080

O diagrama a seguir mostra como o HTTPRoute encaminha o tráfego store.example.com para pods store em gke-west-1 e gke-east-1. O balanceador de carga os trata como um pool de back-ends. Se os pods de um dos clusters se tornarem não íntegros, inacessíveis ou sem capacidade de tráfego, a carga de tráfego será balanceada para os pods restantes no outro cluster. Novos clusters podem ser adicionados ou removidos com o serviço store e o ServiceExport. Isso adicionará ou removerá de maneira transparente os pods de back-end sem alterações explícitas na configuração de roteamento.

Recurso MCS

Como exportar serviços

Neste ponto, o aplicativo está em execução nos dois clusters. Em seguida, você vai expor e exportar os aplicativos implantando Services e ServiceExports em cada cluster.

  1. Aplique o manifesto a seguir ao cluster gke-west-1 para criar os serviços e o ServiceExports store e store-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -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
      namespace: store
    spec:
      selector:
        app: store
      ports:
      - port: 8080
        targetPort: 8080
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store-west-1
      namespace: store
    EOF
    
  2. Aplique o manifesto a seguir ao cluster gke-east-1 para criar os serviços e o ServiceExports store e store-east-1:

    cat << EOF | kubectl apply --context gke-east-1 -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
      namespace: store
    spec:
      selector:
        app: store
      ports:
      - port: 8080
        targetPort: 8080
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store-east-1
      namespace: store
    EOF
    
  3. Verifique se as ServiceExports corretas foram criadas no cluster.

    kubectl get serviceexports --context CLUSTER_NAME --namespace store
    

    Substitua CLUSTER_NAME por gke-west-1 e gke-east-1. A saída será semelhante a esta:

    # gke-west-1
    NAME           AGE
    store          2m40s
    store-west-1   2m40s
    
    # gke-east-1
    NAME           AGE
    store          2m25s
    store-east-1   2m25s
    

    Isso demonstra que o Serviço store contém pods store nos dois clusters, enquanto os Serviços store-west-1 e store-east-1 contêm apenas pods store nos respectivos clusters. Esses serviços sobrepostos são usados para segmentar os pods em vários clusters ou em um subconjunto de pods em um único cluster.

  4. Após alguns minutos, verifique se o ServiceImports complementar foi criado automaticamente pelo controlador de vários clusters dos serviços em todos os clusters da frota.

    kubectl get serviceimports --context CLUSTER_NAME --namespace store
    

    Substitua CLUSTER_NAME por gke-west-1 e gke-east-1. A saída será semelhante a esta:

    # gke-west-1
    NAME           TYPE           IP                  AGE
    store          ClusterSetIP   ["10.112.31.15"]    6m54s
    store-east-1   ClusterSetIP   ["10.112.26.235"]   5m49s
    store-west-1   ClusterSetIP   ["10.112.16.112"]   6m54s
    
    # gke-east-1
    NAME           TYPE           IP                  AGE
    store          ClusterSetIP   ["10.72.28.226"]    5d10h
    store-east-1   ClusterSetIP   ["10.72.19.177"]    5d10h
    store-west-1   ClusterSetIP   ["10.72.28.68"]     4h32m
    

    Isso demonstra que os três serviços podem ser acessados pelos dois clusters na frota. No entanto, como há apenas um único cluster de configuração ativo por frota, só é possível implantar gateways e HTTPRoutes que referenciam esses ServiceImports em gke-west-1. Quando um HTTPRoute no cluster de configuração referencia esses ServiceImports como back-ends, o gateway pode encaminhar o tráfego para esses Services, independentemente do cluster de onde eles foram exportados.

Como implantar o gateway e o HTTPRoute

Depois que os aplicativos forem implantados, é possível configurar um gateway usando o GatewayClass gke-l7-global-external-managed-mc. Esse gateway cria um balanceador de carga de aplicativo externo configurado para distribuir o tráfego entre os clusters de destino.

  1. Aplique o manifesto Gateway ao cluster de configuração, neste exemplo gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: external-http
      namespace: store
    spec:
      gatewayClassName: gke-l7-global-external-managed-mc
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          kinds:
          - kind: HTTPRoute
    EOF
    

    Essa configuração de gateway implanta recursos externos do balanceador de carga de aplicativo com a seguinte convenção de nomenclatura: gkemcg1-NAMESPACE-GATEWAY_NAME-HASH.

    Os recursos padrão criados com essa configuração são:

    • 1 balanceador de carga: gkemcg1-store-external-http-HASH
    • 1 Endereço IP público: gkemcg1-store-external-http-HASH
    • 1 Regra de encaminhamento: gkemcg1-store-external-http-HASH
    • 2 Serviços de back-end:
      • Serviço de back-end padrão 404: gkemcg1-store-gw-serve404-HASH
      • Serviço de back-end padrão 500: gkemcg1-store-gw-serve500-HASH
    • 1 Verificação de integridade:
      • Verificação de integridade 404 padrão: gkemcg1-store-gw-serve404-HASH
    • 0 regras de roteamento (o mapa de URL está vazio)

    Nesta etapa, qualquer solicitação para GATEWAY_IP:80 resultará em uma página padrão exibindo a seguinte mensagem: fault filter abort.

  2. Aplique o manifesto HTTPRoute ao cluster de configuração, neste exemplo gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: public-store-route
      namespace: store
      labels:
        gateway: external-http
    spec:
      hostnames:
      - "store.example.com"
      parentRefs:
      - name: external-http
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /west
        backendRefs:
        - group: net.gke.io
          kind: ServiceImport
          name: store-west-1
          port: 8080
      - matches:
        - path:
            type: PathPrefix
            value: /east
        backendRefs:
          - group: net.gke.io
            kind: ServiceImport
            name: store-east-1
            port: 8080
      - backendRefs:
        - group: net.gke.io
          kind: ServiceImport
          name: store
          port: 8080
    EOF
    

    Nesta etapa, qualquer solicitação para GATEWAY_IP:80 resultará em uma página padrão exibindo a seguinte mensagem: fault filter abort.

    Depois de implantado, esse HTTPRoute configurará o seguinte comportamento de roteamento:

    • As solicitações para /west são roteadas para pods store no cluster gke-west-1, porque os pods selecionados pelo ServiceExport store-west-1 só existem no cluster gke-west-1.
    • As solicitações para /east são roteadas para pods store no cluster gke-east-1, porque os pods selecionados pelo ServiceExport store-east-1 só existem no cluster gke-east-1.
    • As solicitações para qualquer outro caminho são roteadas para Pods store em qualquer cluster, de acordo com a integridade, a capacidade e a proximidade do cliente solicitante.
    • As solicitações para GATEWAY_IP:80 resultarão em uma página padrão exibindo a seguinte mensagem: fault filter abort.

    O HTTPRoute permite o roteamento para diferentes subconjuntos de clusters usando serviços sobrepostos.

    Se todos os pods em um determinado cluster não forem íntegros (ou não existirem), o tráfego para o serviço store só será enviado para clusters que realmente tenham pods store. A existência de um ServiceExport e um Service em um determinado cluster não garante que o tráfego seja enviado para esse cluster. Os pods precisam existir e responder à verificação de integridade do balanceador de carga. Caso contrário, o balanceador de carga enviará apenas tráfego para pods store íntegros em outros clusters.

    Novos recursos são criados com esta configuração:

    • 3 Serviços de back-end:
      • O serviço de back-end store: gkemcg1-store-store-8080-HASH
      • O serviço de back-end store-east-1: gkemcg1-store-store-east-1-8080-HASH
      • O serviço de back-end store-west-1: gkemcg1-store-store-west-1-8080-HASH
    • 3 Verificações de integridade:
      • A verificação de integridade store: gkemcg1-store-store-8080-HASH
      • A verificação de integridade store-east-1: gkemcg1-store-store-east-1-8080-HASH
      • A verificação de integridade store-west-1: gkemcg1-store-store-west-1-8080-HASH
    • 1 regra de roteamento no URLmap:
      • A regra de roteamento store.example.com:
      • 1 Host: store.example.com
      • Vários matchRules para rotear aos novos serviços de back-end

O diagrama a seguir mostra os recursos que você implantou nos dois clusters. Como gke-west-1 é o cluster de configuração do gateway, ele é o cluster em que nosso gateway, HTTPRoutes e ServiceImports são assistidos pelo controlador de gateway. Cada cluster tem um ServiceImport store e outro específico dele. Ambos apontam para os mesmos pods. Isso permite que o HTTPRoute especifique exatamente para onde o tráfego precisa ir: para os pods store em um cluster específico ou para os pods store em todos os clusters.

Este é o modelo de recurso de serviço de gateway e de vários clusters nos dois clusters

Esse é um modelo de recurso lógico, e não uma representação do fluxo de tráfego. O caminho do tráfego vai diretamente do balanceador de carga para pods de back-end e não tem relação direta com o cluster da configuração.

Como validar a implantação

Agora é possível emitir solicitações para o gateway de vários clusters e distribuir o tráfego entre vários clusters do GKE.

  1. Confirme se o gateway e o HTTPRoute foram implantados com sucesso, inspecionando o status e os eventos do gateway.

    kubectl describe gateways.gateway.networking.k8s.io external-http --context gke-west-1 --namespace store
    

    A saída será parecida com esta:

    Name:         external-http
    Namespace:    store
    Labels:       <none>
    Annotations:  networking.gke.io/addresses: /projects/PROJECT_NUMBER/global/addresses/gkemcg1-store-external-http-laup24msshu4
                  networking.gke.io/backend-services:
                    /projects/PROJECT_NUMBER/global/backendServices/gkemcg1-store-gw-serve404-80-n65xmts4xvw2, /projects/PROJECT_NUMBER/global/backendServices/gke...
                  networking.gke.io/firewalls: /projects/PROJECT_NUMBER/global/firewalls/gkemcg1-l7-default-global
                  networking.gke.io/forwarding-rules: /projects/PROJECT_NUMBER/global/forwardingRules/gkemcg1-store-external-http-a5et3e3itxsv
                  networking.gke.io/health-checks:
                    /projects/PROJECT_NUMBER/global/healthChecks/gkemcg1-store-gw-serve404-80-n65xmts4xvw2, /projects/PROJECT_NUMBER/global/healthChecks/gkemcg1-s...
                  networking.gke.io/last-reconcile-time: 2023-10-12T17:54:24Z
                  networking.gke.io/ssl-certificates: 
                  networking.gke.io/target-http-proxies: /projects/PROJECT_NUMBER/global/targetHttpProxies/gkemcg1-store-external-http-94oqhkftu5yz
                  networking.gke.io/target-https-proxies: 
                  networking.gke.io/url-maps: /projects/PROJECT_NUMBER/global/urlMaps/gkemcg1-store-external-http-94oqhkftu5yz
    API Version:  gateway.networking.k8s.io/v1beta1
    Kind:         Gateway
    Metadata:
      Creation Timestamp:  2023-10-12T06:59:32Z
      Finalizers:
        gateway.finalizer.networking.gke.io
      Generation:        1
      Resource Version:  467057
      UID:               1dcb188e-2917-404f-9945-5f3c2e907b4c
    Spec:
      Gateway Class Name:  gke-l7-global-external-managed-mc
      Listeners:
        Allowed Routes:
          Kinds:
            Group:  gateway.networking.k8s.io
            Kind:   HTTPRoute
          Namespaces:
            From:  Same
        Name:      http
        Port:      80
        Protocol:  HTTP
    Status:
      Addresses:
        Type:   IPAddress
        Value:  34.36.127.249
      Conditions:
        Last Transition Time:  2023-10-12T07:00:41Z
        Message:               The OSS Gateway API has deprecated this condition, do not depend on it.
        Observed Generation:   1
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
        Last Transition Time:  2023-10-12T07:00:41Z
        Message:               
        Observed Generation:   1
        Reason:                Accepted
        Status:                True
        Type:                  Accepted
        Last Transition Time:  2023-10-12T07:00:41Z
        Message:               
        Observed Generation:   1
        Reason:                Programmed
        Status:                True
        Type:                  Programmed
        Last Transition Time:  2023-10-12T07:00:41Z
        Message:               The OSS Gateway API has altered the "Ready" condition semantics and reservedit for future use.  GKE Gateway will stop emitting it in a future update, use "Programmed" instead.
        Observed Generation:   1
        Reason:                Ready
        Status:                True
        Type:                  Ready
      Listeners:
        Attached Routes:  1
        Conditions:
          Last Transition Time:  2023-10-12T07:00:41Z
          Message:               
          Observed Generation:   1
          Reason:                Programmed
          Status:                True
          Type:                  Programmed
          Last Transition Time:  2023-10-12T07:00:41Z
          Message:               The OSS Gateway API has altered the "Ready" condition semantics and reservedit for future use.  GKE Gateway will stop emitting it in a future update, use "Programmed" instead.
          Observed Generation:   1
          Reason:                Ready
          Status:                True
          Type:                  Ready
        Name:                    http
        Supported Kinds:
          Group:  gateway.networking.k8s.io
          Kind:   HTTPRoute
    Events:
      Type    Reason  Age                    From                   Message
      ----    ------  ----                   ----                   -------
      Normal  UPDATE  35m (x4 over 10h)      mc-gateway-controller  store/external-http
      Normal  SYNC    4m22s (x216 over 10h)  mc-gateway-controller  SYNC on store/external-http was a success
    
  2. Depois que o gateway for implantado, recupere com sucesso o endereço IP externo do gateway external-http.

    kubectl get gateways.gateway.networking.k8s.io external-http -o=jsonpath="{.status.addresses[0].value}" --context gke-west-1 --namespace store
    

    Substitua VIP nas etapas a seguir pelo endereço IP que você recebe como saída.

  3. Envie tráfego para o caminho raiz do domínio. Isso balanceia a carga do tráfego para o ServiceImport store que está no cluster gke-west-1 e gke-east-1. O balanceador de carga envia o tráfego para a região mais próxima e talvez você não veja respostas da outra região.

    curl -H "host: store.example.com" http://VIP
    

    A saída confirma que a solicitação foi atendida pelo pod do cluster gke-east-1:

    {
      "cluster_name": "gke-east-1",
      "zone": "us-east1-b",
      "host_header": "store.example.com",
      "node_name": "gke-gke-east-1-default-pool-7aa30992-t2lp.c.agmsb-k8s.internal",
      "pod_name": "store-5f5b954888-dg22z",
      "pod_name_emoji": "",
      "project_id": "agmsb-k8s",
      "timestamp": "2021-06-01T17:32:51"
    }
    
  4. Em seguida, envie o tráfego para o caminho /west. Isso direciona o tráfego para o ServiceImport store-west-1, que só tem pods em execução no cluster gke-west-1. Um ServiceImport específico do cluster, como store-west-1, permite que um proprietário de aplicativo envie tráfego explicitamente para um cluster específico, em vez de permitir que o balanceador de carga tome a decisão.

    curl -H "host: store.example.com" http://VIP/west
    

    A saída confirma que a solicitação foi atendida pelo pod do cluster gke-west-1:

    {
      "cluster_name": "gke-west-1", 
      "zone": "us-west1-a", 
      "host_header": "store.example.com",
      "node_name": "gke-gke-west-1-default-pool-65059399-2f41.c.agmsb-k8s.internal",
      "pod_name": "store-5f5b954888-d25m5",
      "pod_name_emoji": "🍾",
      "project_id": "agmsb-k8s",
      "timestamp": "2021-06-01T17:39:15",
    }
    
  5. Por fim, envie o tráfego para o caminho /east.

    curl -H "host: store.example.com" http://VIP/east
    

    A saída confirma que a solicitação foi atendida pelo pod do cluster gke-east-1:

    {
      "cluster_name": "gke-east-1",
      "zone": "us-east1-b",
      "host_header": "store.example.com",
      "node_name": "gke-gke-east-1-default-pool-7aa30992-7j7z.c.agmsb-k8s.internal",
      "pod_name": "store-5f5b954888-hz6mw",
      "pod_name_emoji": "🧜🏾",
      "project_id": "agmsb-k8s",
      "timestamp": "2021-06-01T17:40:48"
    }
    

Roteamento azul-verde com vários clusters usando o Gateway

O GatewayClasses gke-l7-global-external-managed-*, gke-l7-regional-external-managed-* e gke-l7-rilb-* tem muitos recursos avançados de roteamento de tráfego, incluindo divisão de tráfego, correspondência de cabeçalho, manipulação de cabeçalho, espelhamento de tráfego e muito mais. Neste exemplo, mostraremos como usar a divisão de tráfego baseada em peso para controlar explicitamente a proporção de tráfego em dois clusters do GKE.

Este exemplo mostra algumas etapas realistas que um proprietário de serviço faria ao mover ou expandir o aplicativo para um novo cluster do GKE. O objetivo das implantações azul-verde é reduzir o risco por meio de várias etapas de validação que confirmam se o novo cluster está funcionando corretamente. Este exemplo mostra quatro etapas de implantação:

  1. 100%-Canário baseado em cabeçalho: use o roteamento de cabeçalho HTTP para enviar apenas tráfego de teste ou sintético no novo cluster.
  2. 100%-Espelhar o tráfego: espelha o tráfego de usuários para o cluster canário. Isso testa a capacidade do cluster canário copiando 100% do tráfego do usuário para esse cluster.
  3. 90%-10%: canário de uma divisão de tráfego de 10% para expor lentamente o novo cluster para o tráfego em tempo real.
  4. 0%-100%: mude totalmente para o novo cluster com a opção de reverter se os erros observados.

Divisão de tráfego azul-verde em dois clusters do GKE

Este exemplo é semelhante ao anterior, mas implanta um gateway interno de vários clusters. Ele implanta um balanceador de carga de aplicativo interno que só pode ser acessado de maneira particular dentro da VPC. Você usará os mesmos clusters e o mesmo aplicativo implantados nas etapas anteriores, mas irá implantá-los em um Gateway diferente.

Pré-requisitos

O exemplo a seguir se baseia em algumas das etapas de Como implantar um gateway externo de vários clusters. Certifique-se de ter concluído as seguintes etapas antes de continuar com este exemplo:

  1. Como ativar gateways de vários clusters

  2. Como implantar um aplicativo de demonstração

    Neste exemplo, usamos os clusters gke-west-1 e gke-west-2 que você já configurou. Esses clusters estão na mesma região porque o GatewayClass gke-l7-rilb-mc é regional e só aceita back-ends de cluster na mesma região.

  3. Implantar o Service e o ServiceExports necessários em cada cluster. Se você implantou os Services e ServiceExports do exemplo anterior, então já implantou alguns deles.

    kubectl apply --context gke-west-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store-west-1-service.yaml
    kubectl apply --context gke-west-2 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store-west-2-service.yaml
    

    Ele implanta um conjunto semelhante de recursos em cada cluster:

    service/store created
    serviceexport.net.gke.io/store created
    service/store-west-2 created
    serviceexport.net.gke.io/store-west-2 created
    

Como configurar uma sub-rede somente proxy

Se você ainda não tiver feito isso, configure uma sub-rede somente proxy para cada região em que os gateways internos estão sendo implantados. Essa sub-rede é usada para fornecer endereços IP internos aos proxies do balanceador de carga e precisa ser configurada com --purpose definido apenas como REGIONAL_MANAGED_PROXY.

Crie uma sub-rede apenas de proxy antes de criar gateways que gerenciem balanceadores de carga de aplicativo internos. Cada região de uma rede de nuvem privada virtual (VPC) em que você usa balanceadores de carga de aplicativos internos precisa ter uma sub-rede apenas de proxy.

O comando gcloud compute networks subnets create cria uma sub-rede somente proxy.

gcloud compute networks subnets create SUBNET_NAME \
    --purpose=REGIONAL_MANAGED_PROXY \
    --role=ACTIVE \
    --region=REGION \
    --network=VPC_NETWORK_NAME \
    --range=CIDR_RANGE

Substitua:

  • SUBNET_NAME: o nome da sub-rede somente proxy.
  • REGION: a região da sub-rede somente proxy.
  • VPC_NETWORK_NAME: o nome da rede VPC que contém a sub-rede.
  • CIDR_RANGE: o intervalo de endereços IP principal da sub-rede. Use uma máscara de sub-rede de até /26 de comprimento para que ao menos 64 endereços IP estejam disponíveis para os proxies na região. A máscara de sub-rede recomendada é /23.

Como implantar o gateway

O gateway a seguir é criado a partir do GatewayClass gke-l7-rilb-mc. Este é um gateway regional que só pode segmentar clusters do GKE na mesma região.

  1. Aplique o manifesto Gateway ao cluster de configuração, neste exemplo gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: internal-http
      namespace: store
    spec:
      gatewayClassName: gke-l7-rilb-mc
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          kinds:
          - kind: HTTPRoute
    EOF
    
  2. Confira se o gateway foi criado. É possível filtrar apenas os eventos desse gateway com o seguinte comando:

    kubectl get events --field-selector involvedObject.kind=Gateway,involvedObject.name=internal-http --context=gke-west-1 --namespace store
    

    A implantação do gateway foi bem-sucedida se a saída for semelhante a esta:

    LAST SEEN   TYPE     REASON   OBJECT                  MESSAGE
    5m18s       Normal   ADD      gateway/internal-http   store/internal-http
    3m44s       Normal   UPDATE   gateway/internal-http   store/internal-http
    3m9s        Normal   SYNC     gateway/internal-http   SYNC on store/internal-http was a success
    

Canário com base em cabeçalho

O canário baseado em cabeçalho permite que o proprietário do serviço corresponda ao tráfego de teste sintético que não vem de usuários reais. Isso facilita a validação de que a rede básica do aplicativo está funcionando sem expor os usuários diretamente.

  1. Aplique o manifesto HTTPRoute ao cluster de configuração, neste exemplo gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: internal-store-route
      namespace: store
      labels:
        gateway: internal-http
    spec:
      parentRefs:
      - kind: Gateway
        namespace: store
        name: internal-http
      hostnames:
      - "store.example.internal"
      rules:
      # Matches for env=canary and sends it to store-west-2 ServiceImport
      - matches:
        - headers:
          - name: env
            value: canary
        backendRefs:
          - group: net.gke.io
            kind: ServiceImport
            name: store-west-2
            port: 8080
      # All other traffic goes to store-west-1 ServiceImport
      - backendRefs:
        - group: net.gke.io
          kind: ServiceImport
          name: store-west-1
          port: 8080
    EOF
    

    Depois de implantado, esse HTTPRoute configura o seguinte comportamento de roteamento:

    • Solicitações internas para store.example.internal sem o cabeçalho HTTP env: canary são roteadas para pods store no cluster gke-west-1
    • Solicitações internas para store.example.internal com o cabeçalho HTTP env: canary são roteadas para pods store no cluster gke-west-2

    O HTTPRoute permite o roteamento para clusters diferentes com base nos cabeçalhos HTTP

    Envie tráfego para o endereço IP do gateway para validar o funcionamento correto do HTTPRoute.

  2. Recupere o endereço IP interno de internal-http.

    kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}" --context gke-west-1 --namespace store
    

    Substitua VIP nas etapas a seguir pelo endereço IP que você recebe como saída.

  3. Envie uma solicitação para o gateway usando o cabeçalho HTTP env: canary. Isso confirmará que o tráfego está sendo roteado para gke-west-2. Use um cliente particular na mesma VPC que os clusters do GKE para confirmar se as solicitações estão sendo roteadas corretamente. O comando a seguir precisa ser executado em uma máquina que tenha acesso particular ao endereço IP do gateway. Caso contrário, ela não funcionará.

    curl -H "host: store.example.internal" -H "env: canary" http://VIP
    

    A saída confirma que a solicitação foi exibida por um pod do cluster gke-west-2:

    {
        "cluster_name": "gke-west-2", 
        "host_header": "store.example.internal",
        "node_name": "gke-gke-west-2-default-pool-4cde1f72-m82p.c.agmsb-k8s.internal",
        "pod_name": "store-5f5b954888-9kdb5",
        "pod_name_emoji": "😂",
        "project_id": "agmsb-k8s",
        "timestamp": "2021-05-31T01:21:55",
        "zone": "us-west1-a"
    }
    

Espelhamento do tráfego

Esse estágio envia o tráfego para o cluster pretendido, mas também espelha esse tráfego para o cluster canário.

Usar o espelhamento é útil para determinar como a carga do tráfego afetará o desempenho do aplicativo sem afetar as respostas aos clientes. Talvez não seja necessário para todos os tipos de lançamentos, mas pode ser útil ao implementar grandes alterações que podem afetar o desempenho ou a carga.

  1. Aplique o manifesto HTTPRoute ao cluster de configuração, neste exemplo gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: internal-store-route
      namespace: store
      labels:
        gateway: internal-http
    spec:
      parentRefs:
      - kind: Gateway
        namespace: store
        name: internal-http
      hostnames:
      - "store.example.internal"
      rules:
      # Sends all traffic to store-west-1 ServiceImport
      - backendRefs:
        - name: store-west-1
          group: net.gke.io
          kind: ServiceImport
          port: 8080
        # Also mirrors all traffic to store-west-2 ServiceImport
        filters:
        - type: RequestMirror
          requestMirror:
            backendRef:
              group: net.gke.io
              kind: ServiceImport
              name: store-west-2
              port: 8080
    EOF
    
  2. Usando seu cliente particular, envie uma solicitação para o gateway internal-http. Use o caminho /mirror para identificar exclusivamente essa solicitação nos registros do aplicativo em uma etapa posterior.

    curl -H "host: store.example.internal" http://VIP/mirror
    
  3. A resposta confirma que o cliente recebeu uma resposta de um pod no cluster gke-west-1:

    {
        "cluster_name": "gke-west-1", 
        "host_header": "store.example.internal",
        "node_name": "gke-gke-west-1-default-pool-65059399-ssfq.c.agmsb-k8s.internal",
        "pod_name": "store-5f5b954888-brg5w",
        "pod_name_emoji": "🎖",
        "project_id": "agmsb-k8s",
        "timestamp": "2021-05-31T01:24:51",
        "zone": "us-west1-a"
    }
    

    Isso confirma que o cluster principal está respondendo ao tráfego. Você ainda precisa confirmar se o cluster para o qual está migrando está recebendo tráfego espelhado.

  4. Verifique os registros do aplicativo de um pod store no cluster gke-west-2. Os registros precisam confirmar que o pod recebeu tráfego espelhado do balanceador de carga.

    kubectl logs deployment/store --context gke-west-2 -n store | grep /mirror
    
  5. Essa saída confirma que os pods no cluster gke-west-2 também estão recebendo as mesmas solicitações. No entanto, as respostas a essas solicitações não são enviadas de volta ao cliente. Os endereços IP vistos nos registros são os dos endereços IP internos do balanceador de carga que estão se comunicando com seus pods.

    Found 2 pods, using pod/store-5c65bdf74f-vpqbs
    [2023-10-12 21:05:20,805] INFO in _internal: 192.168.21.3 - - [12/Oct/2023 21:05:20] "GET /mirror HTTP/1.1" 200 -
    [2023-10-12 21:05:27,158] INFO in _internal: 192.168.21.3 - - [12/Oct/2023 21:05:27] "GET /mirror HTTP/1.1" 200 -
    [2023-10-12 21:05:27,805] INFO in _internal: 192.168.21.3 - - [12/Oct/2023 21:05:27] "GET /mirror HTTP/1.1" 200 -
    

Divisão de tráfego

A divisão de tráfego é um dos métodos mais comuns de lançar novo código ou implantar em novos ambientes com segurança. O proprietário do serviço define uma porcentagem explícita de tráfego enviada para os back-ends canários, que geralmente é uma quantidade muito pequena do tráfego geral. Assim, o sucesso do lançamento pode ser determinado com uma quantidade aceitável de risco para solicitações reais de usuários.

Fazer uma divisão de tráfego com uma minoria de tráfego permite que o proprietário do serviço inspecione a integridade do aplicativo e as respostas. Se todos os sinais parecerem íntegros, eles poderão prosseguir para a transição completa.

  1. Aplique o manifesto HTTPRoute ao cluster de configuração, neste exemplo gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: internal-store-route
      namespace: store
      labels:
        gateway: internal-http
    spec:
      parentRefs:
      - kind: Gateway
        namespace: store
        name: internal-http
      hostnames:
      - "store.example.internal"
      rules:
      - backendRefs:
        # 90% of traffic to store-west-1 ServiceImport
        - name: store-west-1
          group: net.gke.io
          kind: ServiceImport
          port: 8080
          weight: 90
        # 10% of traffic to store-west-2 ServiceImport
        - name: store-west-2
          group: net.gke.io
          kind: ServiceImport
          port: 8080
          weight: 10
    EOF
    
  2. Usando seu cliente particular, envie uma solicitação curl contínua para o gateway internal- http.

    while true; do curl -H "host: store.example.internal" -s VIP | grep "cluster_name"; sleep 1; done
    

    A saída será semelhante a esta, indicando que está ocorrendo uma divisão de tráfego de 90/10.

    "cluster_name": "gke-west-1",
    "cluster_name": "gke-west-1",
    "cluster_name": "gke-west-1",
    "cluster_name": "gke-west-1",
    "cluster_name": "gke-west-1",
    "cluster_name": "gke-west-1",
    "cluster_name": "gke-west-1",
    "cluster_name": "gke-west-1",
    "cluster_name": "gke-west-2",
    "cluster_name": "gke-west-1",
    "cluster_name": "gke-west-1",
    ...
    

Redução do tráfego

A última etapa da migração azul-verde é totalmente transferida para o novo cluster e remove o antigo. Se o proprietário do serviço estivesse realmente integrando um segundo cluster a um cluster existente, essa última etapa seria diferente, porque a etapa final teria o tráfego fluindo para os dois clusters. Nesse cenário, é recomendado um único ServiceImport store que tenha pods dos clusters gke-west-1 e gke-west-2. Isso permite que o balanceador de carga tome a decisão de onde o tráfego deve ir para um aplicativo ativo-ativo, com base em proximidade, integridade e capacidade.

  1. Aplique o manifesto HTTPRoute ao cluster de configuração, neste exemplo gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: internal-store-route
      namespace: store
      labels:
        gateway: internal-http
    spec:
      parentRefs:
      - kind: Gateway
        namespace: store
        name: internal-http
      hostnames:
      - "store.example.internal"
      rules:
        - backendRefs:
          # No traffic to the store-west-1 ServiceImport
          - name: store-west-1
            group: net.gke.io
            kind: ServiceImport
            port: 8080
            weight: 0
          # All traffic to the store-west-2 ServiceImport
          - name: store-west-2
            group: net.gke.io
            kind: ServiceImport
            port: 8080
            weight: 100
    EOF
    
  2. Usando seu cliente particular, envie uma solicitação curl contínua para o gateway internal- http.

    while true; do curl -H "host: store.example.internal" -s VIP | grep "cluster_name"; sleep 1; done
    

    A saída será semelhante a esta, indicando que todo o tráfego está indo agora para gke-west-2.

    "cluster_name": "gke-west-2",
    "cluster_name": "gke-west-2",
    "cluster_name": "gke-west-2",
    "cluster_name": "gke-west-2",
    ...
    

Essa etapa final conclui uma migração completa de aplicativos azul-verde de um cluster do GKE para outro cluster do GKE.

Implantar o balanceamento de carga com base na capacidade

O exercício nesta seção demonstra conceitos de balanceamento de carga e capacidade de serviço globais implantando um aplicativo em dois clusters do GKE em regiões diferentes. O tráfego gerado é enviado em vários níveis de solicitação por segundo (RPS) para mostrar como o tráfego é balanceado em cargas em clusters e regiões.

Veja no diagrama a seguir a topologia que você implantará e como o tráfego transborda entre os clusters e as regiões quando a capacidade do serviço for excedida:

Tráfego transbordante de um cluster para outro

Para saber mais sobre gerenciamento de tráfego, consulte Gerenciamento de tráfego do GKE.

prepare o ambiente

  1. Siga Como ativar gateways de vários clusters para preparar o ambiente.

  2. Confirme se os recursos da GatewayClass estão instalados no cluster de configuração:

    kubectl get gatewayclasses --context=gke-west-1
    

    A saída será assim:

    NAME                                  CONTROLLER                  ACCEPTED   AGE
    gke-l7-global-external-managed        networking.gke.io/gateway   True       16h
    gke-l7-global-external-managed-mc     networking.gke.io/gateway   True       14h
    gke-l7-gxlb                           networking.gke.io/gateway   True       16h
    gke-l7-gxlb-mc                        networking.gke.io/gateway   True       14h
    gke-l7-regional-external-managed      networking.gke.io/gateway   True       16h
    gke-l7-regional-external-managed-mc   networking.gke.io/gateway   True       14h
    gke-l7-rilb                           networking.gke.io/gateway   True       16h
    gke-l7-rilb-mc                        networking.gke.io/gateway   True       14h
    

Implementar um aplicativo

Implante o servidor de aplicativos da Web de amostra nos dois clusters:

kubectl apply --context gke-west-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/master/gateway/docs/store-traffic-deploy.yaml
kubectl apply --context gke-east-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/master/gateway/docs/store-traffic-deploy.yaml

A saída será assim:

namespace/store created
deployment.apps/store created

Implantar um serviço, gateway e HTTPRoute

  1. Aplique o manifesto Service a seguir aos clusters gke-west-1 e gke-east-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    apiVersion: v1
    kind: Service
    metadata:
      name: store
      namespace: traffic-test
      annotations:
        networking.gke.io/max-rate-per-endpoint: "10"
    spec:
      ports:
      - port: 8080
        targetPort: 8080
        name: http
      selector:
        app: store
      type: ClusterIP
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store
      namespace: traffic-test
    EOF
    
    cat << EOF | kubectl apply --context gke-east-1 -f -
    apiVersion: v1
    kind: Service
    metadata:
      name: store
      namespace: traffic-test
      annotations:
        networking.gke.io/max-rate-per-endpoint: "10"
    spec:
      ports:
      - port: 8080
        targetPort: 8080
        name: http
      selector:
        app: store
      type: ClusterIP
    ---
    kind: ServiceExport
    apiVersion: net.gke.io/v1
    metadata:
      name: store
      namespace: traffic-test
    EOF
    

    O serviço é anotado com max-rate-per-endpoint definido para 10 solicitações por segundo. Com duas réplicas por cluster, cada serviço tem 20 RPS de capacidade por cluster.

    Para mais informações sobre como escolher um nível de capacidade do Serviço, consulte Determinar a capacidade do Serviço.

  2. Aplique o manifesto Gateway a seguir ao cluster de configuração, gke-west-1 neste exemplo:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store
      namespace: traffic-test
    spec:
      gatewayClassName: gke-l7-global-external-managed-mc
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          kinds:
          - kind: HTTPRoute
    EOF
    

    O manifesto descreve um gateway externo, global e de vários clusters que implanta um balanceador de carga de aplicativo externo com um endereço IP acessível publicamente.

  3. Aplique o manifesto HTTPRoute ao cluster de configuração, neste exemplo gke-west-1:

    cat << EOF | kubectl apply --context gke-west-1 -f -
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store
      namespace: traffic-test
      labels:
        gateway: store
    spec:
      parentRefs:
      - kind: Gateway
        namespace: traffic-test
        name: store
      rules:
      - backendRefs:
        - name: store
          group: net.gke.io
          kind: ServiceImport
          port: 8080
    EOF
    

    O manifesto descreve um HTTPRoute que configura o gateway com uma regra de roteamento que direciona todo o tráfego para o ServiceImport de armazenamento. O ServiceImport store agrupa o armazenamento dos pods de serviço store nos dois clusters e permite que eles sejam resolvidos pelo balanceador de carga como um único Serviço.

    É possível verificar os eventos do gateway após alguns minutos para ver se a implantação foi concluída:

    kubectl describe gateway store -n traffic-test --context gke-west-1
    

    A saída será assim:

    ...
    Status:
      Addresses:
        Type:   IPAddress
        Value:  34.102.159.147
      Conditions:
        Last Transition Time:  2023-10-12T21:40:59Z
        Message:               The OSS Gateway API has deprecated this condition, do not depend on it.
        Observed Generation:   1
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
        Last Transition Time:  2023-10-12T21:40:59Z
        Message:               
        Observed Generation:   1
        Reason:                Accepted
        Status:                True
        Type:                  Accepted
        Last Transition Time:  2023-10-12T21:40:59Z
        Message:               
        Observed Generation:   1
        Reason:                Programmed
        Status:                True
        Type:                  Programmed
        Last Transition Time:  2023-10-12T21:40:59Z
        Message:               The OSS Gateway API has altered the "Ready" condition semantics and reservedit for future use.  GKE Gateway will stop emitting it in a future update, use "Programmed" instead.
        Observed Generation:   1
        Reason:                Ready
        Status:                True
        Type:                  Ready
      Listeners:
        Attached Routes:  1
        Conditions:
          Last Transition Time:  2023-10-12T21:40:59Z
          Message:               
          Observed Generation:   1
          Reason:                Programmed
          Status:                True
          Type:                  Programmed
          Last Transition Time:  2023-10-12T21:40:59Z
          Message:               The OSS Gateway API has altered the "Ready" condition semantics and reservedit for future use.  GKE Gateway will stop emitting it in a future update, use "Programmed" instead.
          Observed Generation:   1
          Reason:                Ready
          Status:                True
          Type:                  Ready
        Name:                    http
        Supported Kinds:
          Group:  gateway.networking.k8s.io
          Kind:   HTTPRoute
    Events:
      Type    Reason  Age                  From                   Message
      ----    ------  ----                 ----                   -------
      Normal  ADD     12m                  mc-gateway-controller  traffic-test/store
      Normal  SYNC    6m43s                mc-gateway-controller  traffic-test/store
      Normal  UPDATE  5m40s (x4 over 12m)  mc-gateway-controller  traffic-test/store
      Normal  SYNC    118s (x6 over 10m)   mc-gateway-controller  SYNC on traffic-test/store was a success
    

    Nesta saída, vemos que o gateway foi implantado. Pode levar alguns minutos para que o tráfego comece a ser transmitido após a implantação do gateway. Anote o endereço IP dessa saída, porque ele será usado nas próximas etapas.

Confirmar o trânsito

Confirme se o tráfego está passando para o aplicativo testando o endereço IP do gateway com um comando curl:

curl GATEWAY_IP_ADDRESS

A saída será assim:

{
  "cluster_name": "gke-west-1",
  "host_header": "34.117.182.69",
  "pod_name": "store-54785664b5-mxstv",
  "pod_name_emoji": "👳🏿",
  "project_id": "project",
  "timestamp": "2021-11-01T14:06:38",
  "zone": "us-west1-a"
}

Nessa saída, vemos os metadados do pod, que indicam a região de origem da solicitação.

Verificar o tráfego usando o teste de carga

Para verificar se o balanceador de carga está funcionando, implante um gerador de tráfego no cluster gke-west-1. O gerador de tráfego gera tráfego em diferentes níveis de carga, para demonstrar a capacidade e os recursos de sobrecarga do balanceador de carga. As etapas a seguir demonstram três níveis de carga:

  • 10 RPS, que está abaixo da capacidade do Serviço de armazenamento em gke-west-1.
  • 30 RPS, que é maior que a capacidade do Serviço de armazenamento gke-west-1 e causa estouro de tráfego para gke-east-1.
  • 60 RPS, que é maior que a capacidade dos Serviços nos dois clusters.

Configurar o painel

  1. Consiga o nome do URLmap subjacente para o gateway:

    kubectl get gateway store -n traffic-test --context=gke-west-1 -o=jsonpath="{.metadata.annotations.networking\.gke\.io/url-maps}"
    

    A saída será assim:

    /projects/PROJECT_NUMBER/global/urlMaps/gkemcg1-traffic-test-store-armvfyupay1t
    
  2. No Console do Google Cloud, acesse a página do Metrics Explorer.

    Acessar o Metrics Explorer

  3. Em Selecionar uma métrica, clique em CÓDIGO: MQL.

  4. Insira a seguinte consulta para observar as métricas de tráfego do serviço de armazenamento nos dois clusters:

    fetch https_lb_rule
    | metric 'loadbalancing.googleapis.com/https/backend_request_count'
    | filter (resource.url_map_name == 'GATEWAY_URL_MAP')
    | align rate(1m)
    | every 1m
    | group_by [resource.backend_scope],
        [value_backend_request_count_aggregate:
            aggregate(value.backend_request_count)]
    

    Substitua GATEWAY_URL_MAP pelo nome do URLmap do passo anterior.

  5. Clique em Run query. Aguarde pelo menos cinco minutos depois de implantar o gerador de carga na próxima seção para que as métricas sejam exibidas no gráfico.

Testar com 10 RPS

  1. Implante um pod no cluster gke-west-1:

    kubectl run --context gke-west-1 -i --tty --rm loadgen  \
        --image=cyrilbkr/httperf  \
        --restart=Never  \
        -- /bin/sh -c 'httperf  \
        --server=GATEWAY_IP_ADDRESS  \
        --hog --uri="/zone" --port 80  --wsess=100000,1,1 --rate 10'
    

    Substitua GATEWAY_IP_ADDRESS pelo endereço IP do gateway da etapa anterior.

    A saída é semelhante à seguinte, indicando que o gerador de tráfego está enviando tráfego:

    If you don't see a command prompt, try pressing enter.
    

    O gerador envia continuamente 10 RPS para o gateway. Mesmo que o tráfego venha de dentro de uma região do Google Cloud, o balanceador de carga trata o tráfego do cliente como proveniente da costa oeste dos EUA. Para simular a diversidade realista de clientes, o gerador de carga envia cada solicitação HTTP como uma nova conexão TCP, o que significa que o tráfego é distribuído entre os pods de back-end mais uniformemente.

    O gerador leva até cinco minutos para gerar tráfego para o painel.

  2. Veja seu painel do Metrics Explorer. Duas linhas são exibidas, indicando quanto tráfego é balanceado por carga para cada um dos clusters:

    Gráfico com a carga de tráfego balanceada para clusters

    Você verá que us-west1-a está recebendo aproximadamente 10 RPS de tráfego enquanto us-east1-b não está recebendo nenhum tráfego. Como o gerador de tráfego está em execução em us-west1, todo o tráfego é enviado para o Serviço no cluster gke-west-1.

  3. Pare o gerador de carga usando Ctrl+C e exclua o pod:

    kubectl delete pod loadgen --context gke-west-1
    

Testar com 30 RPS

  1. Implante o gerador de carga novamente, mas configurado para enviar 30 RPS:

    kubectl run --context gke-west-1 -i --tty --rm loadgen  \
        --image=cyrilbkr/httperf  \
        --restart=Never  \
        -- /bin/sh -c 'httperf  \
        --server=GATEWAY_IP_ADDRESS  \
        --hog --uri="/zone" --port 80  --wsess=100000,1,1 --rate 30'
    

    O gerador leva até cinco minutos para gerar tráfego para o painel.

  2. Veja seu painel do Cloud Operations.

    Gráfico mostrando o tráfego em excesso para o gke-east-1

    Você verá que aproximadamente 20 RPS estão sendo enviados para us-west1-a e 10 RPS para us-east1-b. Isso indica que o Serviço em gke-west-1 é totalmente utilizado e transborda 10 RPS de tráfego para o Serviço em gke-east-1.

  3. Pare o gerador de carga usando Ctrl+C e exclua o pod:

    kubectl delete pod loadgen --context gke-west-1
    

Testar com 60 RPS

  1. Implante o gerador de carga configurado para enviar 60 RPS:

    kubectl run --context gke-west-1 -i --tty --rm loadgen  \
        --image=cyrilbkr/httperf  \
        --restart=Never  \
        -- /bin/sh -c 'httperf  \
        --server=GATEWAY_IP_ADDRESS  \
        --hog --uri="/zone" --port 80  --wsess=100000,1,1 --rate 60'
    
  2. Aguarde cinco minutos e veja seu painel do Cloud Operations. Agora, ele mostrará que os dois clusters estão recebendo aproximadamente 30 RPS. Como todos os serviços são superutilizados globalmente, não há vazamento de tráfego e os serviços absorvem todo o tráfego possível.

    Gráfico com o uso excessivo dos serviços

  3. Pare o gerador de carga usando Ctrl+C e exclua o pod:

    kubectl delete pod loadgen --context gke-west-1
    

Limpar

Depois de concluir os exercícios nesta página, 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 a Entrada 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
    

Usar o gateway de vários clusters com a VPC compartilhada

Um gateway de vários clusters também pode ser implantado em um ambiente de VPC compartilhada, com topologias diferentes, dependendo do caso de uso.

Na tabela a seguir, descrevemos as topologias de gateway de vários clusters compatíveis em um ambiente de VPC compartilhada:

Cenário Projeto host da frota Cluster de configuração Clusters de carga de trabalho
1 Projeto de host de VPC compartilhada Projeto de host de VPC compartilhada Projeto de host de VPC compartilhada
2 Projeto de serviço de VPC compartilhada Projeto de serviço de VPC compartilhada
(o mesmo que o projeto de serviço da frota)
Projeto de serviço de VPC compartilhada
(o mesmo que o projeto de serviço da frota)

Para criar gateways de vários clusters em um ambiente de VPC compartilhada, use as seguintes etapas:

  1. Siga as etapas para configurar os serviços de vários clusters com a VPC compartilhada.

  2. Criar os serviços e exportá-los para o cluster de configuração

  3. Se você planeja usar um gateway interno de vários clusters, crie uma sub-rede somente proxy

  4. Criar o gateway externo ou interno de vários clusters e o HTTPRoutes

Depois de concluir essas etapas, você pode validar a implantação, dependendo da sua topologia.

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