Implantar um gateway de vários clusters para balanceamento de carga com base na capacidade

Este documento orienta você na implantação de um aplicativo de exemplo em dois clusters do GKE em regiões diferentes e mostra como um gateway de vários clusters roteia o tráfego de maneira inteligente quando ele excede os limites de capacidade do serviço.

O balanceamento de carga com base na capacidade é um recurso dos gateways de vários clusters que ajuda a criar aplicativos altamente confiáveis e resilientes. Ao definir a capacidade dos seus serviços, você os protege contra sobrecarga e ajuda a garantir uma experiência consistente para os usuários. Quando um serviço em um cluster atinge a capacidade máxima, o balanceador de carga redireciona automaticamente o tráfego para outro cluster com capacidade disponível. Para mais informações sobre gerenciamento de tráfego, consulte Gerenciamento de tráfego do GKE.

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

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:

  1. Implante cluster do GKE.

  2. Registre os clusters em uma frota, se ainda não tiver feito isso.

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

Preparar o ambiente

  1. Siga Preparar o ambiente para gateways de vários clusters.

  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/v1
    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/v1
    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
    

    O resultado 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}"
    

    O resultado será o seguinte:

    /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 Google Cloud , o balanceador de carga trata o tráfego do cliente como proveniente da costa oeste dos EUA. Para simular uma 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 de maneira mais uniforme.

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

Solução de problemas

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