Implemente um gateway de vários clusters para o balanceamento de carga baseado na capacidade

Este documento explica como implementar uma aplicação de exemplo em dois clusters do GKE em regiões diferentes e mostra como o Gateway de vários clusters encaminha o tráfego de forma inteligente quando excede os limites de capacidade do serviço.

O equilíbrio de carga baseado na capacidade é uma funcionalidade das gateways de vários clusters que ajuda a criar aplicações altamente fiáveis e resilientes. Ao definir a capacidade dos seus serviços, pode protegê-los contra sobrecarga e ajudar a garantir uma experiência consistente para os seus utilizadores. Quando um serviço num cluster atinge a respetiva capacidade, o balanceador de carga redireciona automaticamente o tráfego para outro cluster com capacidade disponível. Para mais informações sobre a gestão de tráfego, consulte o artigo Gestão de tráfego do GKE.

Neste tutorial, vai usar uma aplicação de exemplo store para simular um cenário real em que um serviço de compras online é detido e operado por equipas separadas e implementado numa frota de clusters do GKE partilhados.

Antes de começar

Os gateways de vários clusters requerem alguma preparação ambiental antes de poderem ser implementados. Antes de continuar, siga os passos em Prepare o seu ambiente para gateways multicluster:

  1. Implemente clusters do GKE.

  2. Registe os seus clusters numa frota (se ainda não o tiverem feito).

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

Por último, reveja as limitações e os problemas conhecidos do controlador do GKE Gateway antes de usar o controlador no seu ambiente.

Implemente o balanceamento de carga baseado na capacidade

O exercício nesta secção demonstra os conceitos de equilíbrio de carga global e capacidade de serviço através da implementação de uma aplicação em dois clusters do GKE em diferentes regiões. O tráfego gerado é enviado a vários níveis de pedidos por segundo (RPS) para mostrar como o tráfego é equilibrado em termos de carga em clusters e regiões.

O diagrama seguinte mostra a topologia que vai implementar e como o tráfego transborda entre clusters e regiões quando o tráfego excede a capacidade do serviço:

Tráfego a transbordar de um cluster para outro

Prepare o seu ambiente

  1. Siga o artigo Prepare o seu ambiente para gateways de vários clusters para preparar o seu ambiente.

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

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

    O resultado é semelhante ao seguinte:

    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
    

Implemente uma aplicação

Implemente o servidor de aplicações Web de exemplo em ambos os 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

O resultado é semelhante ao seguinte:

namespace/store created
deployment.apps/store created

Implemente um serviço, um gateway e uma HTTPRoute

  1. Aplique o seguinte manifesto Service 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 está anotado com max-rate-per-endpoint definido como 10 pedidos por segundo. Com 2 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 para o seu serviço, consulte o artigo Determine a capacidade do seu serviço.

  2. Aplique o manifesto Gateway seguinte 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 com vários clusters que implementa um balanceador de carga de aplicações externo com um endereço IP acessível publicamente.

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

    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 encaminhamento que direciona todo o tráfego para o ServiceImport da loja. O store ServiceImport agrupa os store Service Pods em ambos os clusters e permite que sejam resolvidos pelo balanceador de carga como um único serviço.

    Pode verificar os eventos do gateway após alguns minutos para ver se a implementação foi concluída:

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

    O resultado é semelhante ao seguinte:

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

    Este resultado mostra que o gateway foi implementado com êxito. Pode demorar alguns minutos até que o tráfego comece a passar depois de a gateway ter sido implementada. Tome nota do endereço IP neste resultado, uma vez que é usado num passo seguinte.

Confirme o tráfego

Confirme se o tráfego está a ser transmitido para a aplicação testando o endereço IP do gateway com um comando curl:

curl GATEWAY_IP_ADDRESS

O resultado é semelhante ao seguinte:

{
  "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"
}

Este resultado mostra os metadados do pod, que indicam a região a partir da qual o pedido foi publicado.

Valide o tráfego através de testes de carga

Para verificar se o equilibrador de carga está a funcionar, pode implementar um gerador de tráfego no seu cluster gke-west-1. O gerador de tráfego gera tráfego a diferentes níveis de carga para demonstrar a capacidade e as capacidades de overflow do balanceador de carga. Os passos seguintes demonstram três níveis de carga:

  • 10 RPS, que está abaixo da capacidade do serviço de loja em gke-west-1.
  • 30 RPS, que está acima da capacidade do serviço da loja gke-west-1 e provoca um excesso de tráfego para gke-east-1.
  • 60 RPS, que excede a capacidade dos serviços em ambos os clusters.

Configure o painel de controlo

  1. Obtenha o nome do URLmap subjacente para o seu gateway:

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

    O resultado é semelhante ao seguinte:

    /projects/PROJECT_NUMBER/global/urlMaps/gkemcg1-traffic-test-store-armvfyupay1t
    
  2. Na Google Cloud consola, aceda à página Explorador de métricas.

    Aceda ao Metrics Explorer

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

  4. Introduza a seguinte consulta para observar as métricas de tráfego para o serviço de loja 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 Executar consulta. Aguarde, pelo menos, 5 minutos após implementar o gerador de carga na secção seguinte para que as métricas sejam apresentadas no gráfico.

Teste com 10 RPS

  1. Implemente um Pod no seu 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 do passo anterior.

    O resultado é semelhante ao seguinte, o que indica que o gerador de tráfego está a enviar tráfego:

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

    O gerador de carga envia continuamente 10 RPS para o gateway. Embora o tráfego seja proveniente de uma região, o balanceador de carga trata-o como tráfego de cliente proveniente da Costa Oeste dos EUA. Google Cloud Para simular uma diversidade de clientes realista, o gerador de carga envia cada pedido HTTP como uma nova ligação TCP, o que significa que o tráfego é distribuído pelos pods de back-end de forma mais uniforme.

    O gerador demora até 5 minutos a gerar tráfego para o painel de controlo.

  2. Veja o painel de controlo do explorador de métricas. São apresentadas duas linhas que indicam a quantidade de tráfego com equilíbrio de carga para cada um dos clusters:

    Gráfico a mostrar o tráfego com balanceamento de carga para clusters

    Deve ver que us-west1-a está a receber aproximadamente 10 RPS de tráfego, enquanto us-east1-b não está a receber tráfego. Uma vez que o gerador de tráfego está a ser executado em us-west1, todo o tráfego é enviado para o serviço no cluster gke-west-1.

  3. Pare o gerador de carga com Ctrl+C e, em seguida, elimine o pod:

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

Teste com 30 RPS

  1. Implemente novamente o gerador de carga, 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 demora até 5 minutos a gerar tráfego para o painel de controlo.

  2. Veja o seu painel de controlo do Cloud Ops.

    Gráfico que mostra o tráfego a transbordar para gke-east-1

    Deve ver que estão a ser enviados aproximadamente 20 RPS para us-west1-a e 10 RPS para us-east1-b. Isto indica que o serviço em gke-west-1 está totalmente utilizado e está a transbordar 10 RPS de tráfego para o serviço em gke-east-1.

  3. Pare o gerador de carga com Ctrl+C e, em seguida, elimine o pod:

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

Teste com 60 RPS

  1. Implemente 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 5 minutos e consulte o painel de controlo do Cloud Ops. Agora, deve mostrar que ambos os clusters estão a receber aproximadamente 30 RPS. Uma vez que todos os serviços estão sobreutilizados a nível global, não existe transbordo de tráfego e os serviços absorvem todo o tráfego que conseguem.

    Gráfico que mostra os serviços sobreutilizados

  3. Pare o gerador de carga com Ctrl+C e, em seguida, elimine o pod:

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

Limpar

Depois de concluir os exercícios neste documento, siga estes passos para remover recursos e evitar a incorrência de cobranças indesejadas na sua conta:

  1. Elimine os clusters.

  2. Anule o registo dos clusters da frota se não precisarem de ser registados para outro fim.

  3. Desative a funcionalidade multiclusterservicediscovery:

    gcloud container fleet multi-cluster-services disable
    
  4. Desative a entrada em 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
    

Resolução de problemas

Não existe um upstream em bom estado

Sintoma:

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

no healthy upstream

Motivo:

Esta mensagem de erro indica que o verificador de estado de funcionamento não consegue encontrar serviços de back-end em bom estado. É possível que os seus serviços de back-end estejam em bom estado, mas pode ter de personalizar as verificações de funcionamento.

Solução alternativa:

Para resolver este problema, personalize a verificação de estado com base nos requisitos da sua aplicação (por exemplo, /health) através de um HealthCheckPolicy.

O que se segue?