Balanceamento de carga avançado em clusters do GKE

Nesta página, mostramos como configurar o balanceamento de carga avançado em clusters do GKE para usuários gerenciados do Cloud Service Mesh (TD) usando a API do Kubernetes. Para acessar o guia do usuário correspondente para configurar o balanceamento de carga avançado usando a API Google Cloud , consulte Configurar o balanceamento de carga avançado.

É possível usar o balanceamento de carga avançado para:

  • Manter o tráfego em uma zona de serviço até que a capacidade local seja esgotada.
  • Envie tráfego para o serviço em um local "principal" com failover para um local secundário quando endpoints suficientes no local principal ficarem inativos.
  • Controle quando o failover acontece (com base na porcentagem de hosts saudáveis).

Limitações

  • Limitações gerais sobre o uso do balanceamento de carga avançado no Google Cloud .
  • Esse recurso está disponível apenas para usuários gerenciados do Cloud Service Mesh que usam o Traffic Director como plano de controle e exige a versão 1.19.10-asm.22 ou mais recente do plano de dados.
  • Nem todos os campos em GCPTrafficDistributionPolicy e GCPBackendPolicy são compatíveis com o managedCloud Service Mesh (TD). Os campos aceitos são os seguintes:
    • GCPTrafficDistributionPolicy
      • ServiceLbAlgorithm
      • AutoCapacityDrain
      • FailoverConfig
    • GCPBackendPolicy
      • MaxRatePerEndpoint
      • BackendPreference
  • O balanceamento de carga avançado só pode ser aplicado a serviços do Kubernetes com suporte de cargas de trabalho executadas no Google Cloud. Não há suporte para serviços ou cargas de trabalho externos (como ServiceEntry).
  • As políticas de balanceamento de carga só podem ser aplicadas a serviços individuais do Kubernetes. Não há suporte para políticas de balanceamento de carga em todo o namespace/mesh.
  • Somente a capacidade QPS é aceita.
  • Somente as versões do GKE >= 1.31.1 são compatíveis.
  • As políticas de balanceamento de carga avançadas da malha de serviço precisam ser aplicadas apenas a serviços que atendem apenas o tráfego da malha. Ele não pode ser aplicado a serviços que servem como back-ends do GKE Gateway. Os comportamentos de tráfego são indefinidos quando um tráfego de balanceamento de carga avançado é direcionado a um serviço do Kubernetes que atende ao tráfego da malha e ao tráfego de um gateway do GKE.

Configurar o balanceamento de carga avançado

É possível usar os recursos personalizados abaixo para configurar o balanceamento de carga avançado no GKE. A definição detalhada do recurso está disponível no repositório gke-gateway-api.

GCPTrafficDistributionPolicy

A GCPTrafficDistributionPolicy configura a política de balanceamento de carga no nível do serviço para serviços do Kubernetes. Ele permite que você:

Se várias políticas GCPTrafficDistributionPolicies forem direcionadas ao mesmo serviço, a mais antiga será aplicada.

GCPBackendPolicy

A GCPBackendPolicy configura propriedades de back-end de serviço que afetam o comportamento do balanceamento de carga, incluindo:

Se várias GCPBackendPolicies segmentarem o mesmo serviço em um cluster, a política mais antiga será aplicada.

Status da política

Tanto a GCPTrafficDistributionPolicy quanto a GCPBackendPolicy têm um campo de status que indica o status de anexo da política.

Por exemplo, executar kubectl describe gcpbackendpolicies example-policy -n example produziria uma saída semelhante a:

...
Status:
  Ancestors:
    Ancestor Ref:
      Group:
      Kind:       Service
      Name:       example-svc
      Namespace:  example
    Conditions:
      Last Transition Time:  2024-10-13T01:15:03Z
      Message:
      Observed Generation:   1
      Reason:                Attached
      Status:                True
      Type:                  Attached
    Controller Name:         gsmconfig.gke.io/controller

Configuração preliminar

Antes de concluir este guia, provisione o Cloud Service Mesh em um cluster do GKE.

  1. Verifique se os CRDs estão instalados:

    kubectl get crd
    

    A saída é semelhante a:

    ...
    gcptrafficdistributionpolicies.networking.gke.io   2024-07-18T21:50:12Z
    gcpbackendpolicies.networking.gke.io               2024-07-18T21:50:12Z
    ...
    
  2. Instale o CRD GCPBackendPolicy, se ainda não estiver instalado:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-gateway-api/refs/heads/main/config/crd/networking.gke.io_gcpbackendpolicies.yaml
    
  3. Instale o CRD GCPTrafficDistributionPolicy, se ainda não estiver instalado:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-gateway-api/refs/heads/main/config/crd/networking.gke.io_gcptrafficdistributionpolicies.yaml
    

Os exemplos de políticas neste guia do usuário têm como alvo o serviço foo no namespace foo para fins de demonstração. Execute o comando abaixo para criar o serviço e o namespace de teste ou, se preferir, use seu próprio serviço e namespace:

kubectl apply -f - <<EOF
kind: Namespace
apiVersion: v1
metadata:
  name: foo
  labels:
    istio-injection: enabled
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: foo
  namespace: foo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test-backend
  template:
    metadata:
      labels:
        app: test-backend
    spec:
      containers:
      - name: whereami
        image: gcr.io/google-samples/whereami:v1.2.23
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: foo
  namespace: foo
spec:
  selector:
    app: test-backend
  ports:
  - port: 8080
    targetPort: 8080
EOF

Como configurar o algoritmo de balanceamento de carga

Por padrão, o tráfego para um serviço é distribuído de maneira uniforme para cada back-end de serviço saudável em uma malha de serviço do Cloud Service Mesh. É possível criar a política GCPTrafficDistributionPolicy a seguir para que o tráfego seja distribuído para a zona mais próxima até a capacidade do back-end:

kubectl apply -f - <<EOF
apiVersion: networking.gke.io/v1
kind: GCPTrafficDistributionPolicy
metadata:
  name: lb-policy
  namespace: foo
spec:
  targetRefs:
  - kind: Service
    group: ""
    name: foo-service
  default:
    serviceLbAlgorithm: WATERFALL_BY_ZONE
EOF

Por padrão, os back-ends de serviço são tratados como se tivessem capacidade infinita. Quando há hosts íntegros suficientes na zona local/mais próxima, o tráfego nunca é distribuído fora da zona local/mais próxima para uma determinada localidade do cliente. Você pode configurar a capacidade do back-end do serviço usando a GCPBackendPolicy para que uma única zona não fique sobrecarregada.

kubectl apply -f - <<EOF
apiVersion: networking.gke.io/v1
kind: GCPBackendPolicy
metadata:
  name: backend-policy
  namespace: foo
spec:
  targetRef:
    kind: Service
    group: ""
    name: foo-backend
  default:
    maxRatePerEndpoint: 5
EOF

Como ajustar o comportamento de failover

Por padrão, o failover não será acionado enquanto uma porcentagem suficiente de hosts estiver íntegra nos back-ends principais. Para mais informações sobre back-ends principais e outras terminologias, consulte a Visão geral do balanceamento de carga avançado. A GCPTrafficDistributionPolicy permite configurar o limite de porcentagem de hosts saudáveis até que o tráfego seja desviado dos back-ends principais para os back-ends de failover. O failover é acionado mais cedo com um limite maior. Por exemplo, se você quiser que o failover seja acionado assim que a porcentagem de hosts íntegros cair abaixo de 90% nos back-ends principais, configure a política GCPTrafficDistributionPolicy:

kubectl apply -f - <<EOF
apiVersion: networking.gke.io/v1
kind: GCPTrafficDistributionPolicy
metadata:
  name: lb-policy
  namespace: foo
spec:
  targetRefs:
  - kind: Service
    group: ""
    name: foo-service
  default:
   failoverConfig:
     failoverHealthThreshold: 90
EOF

Como configurar o balanceamento de carga avançado em uma malha de serviço de vários clusters

A GCPTrafficDistributionPolicy e a GCPBackendPolicy são aplicadas em diferentes escopos em uma malha de serviços de vários clusters.

Quando uma GCPTrafficDistributionPolicy é direcionada a um serviço de vários clusters, ela define o comportamento de balanceamento de carga do nível de serviço em todos os clusters. Apenas uma política de distribuição de tráfego do GCP precisa ser criada para um serviço de vários clusters específico. Se você estiver usando a API Istio para configurar a malha de serviço, poderá criar a GCPTrafficDistributionPolicy em qualquer cluster da frota. Para verificar se uma política conflita com outra, inspecione o status da política.

Quando uma GCPBackendPolicy é direcionada a um serviço de vários clusters, ela define as configurações do nível de back-end (por exemplo, a capacidade por pod) para os pods de back-end selecionados pelo serviço de segmentação no cluster local. Para o mesmo serviço com vários clusters, é possível definir diferentes configurações de nível de back-end em clusters diferentes.

No exemplo a seguir, uma GCPTrafficDistributionPolicy é criada no cluster A para definir o algoritmo de balanceamento de carga a ser usado em toda a frota, enquanto as GCPBackendPolicies estão em cada cluster. Ambas as políticas GCPBackendPolicy configuram uma capacidade de 10qps por pod para os pods de back-end no cluster local, enquanto a GCPBackendPolicy no cluster A configura os pods de back-end no cluster A como back-end preferencial.

Juntas, essas políticas configuram os comportamentos de balanceamento de carga para o tráfego no mesh enviado ao serviço foo:

  • O tráfego de qualquer lugar prefere back-ends no cluster A até que os pods de back-end no cluster A precisem processar 10 qps por pod.
    • Esse comportamento é definido principalmente pela GCPBackendPolicy que define backendPreference como PREFERRED no cluster A.
  • O tráfego que excede a capacidade configurada dos back-ends no cluster A é roteado usando o algoritmo WATERFALL_BY_ZONE para o cluster B. Para uma explicação mais detalhada dos back-ends preferidos, consulte Visão geral do balanceamento de carga avançado.
    • Esse comportamento é definido principalmente pela GCPTrafficDistributionPolicy, que define o algoritmo, no cluster A e na GCPBackendPolicy, que definem a capacidade do back-end, nos clusters A e B.

Malha de serviço de vários clusters com balanceamento de carga avançado

No Istio, os serviços Kubernetes regulares se tornam implicitamente "multicluster" quando há vários clusters na malha de serviço e o serviço é criado em fronteiras de cluster. Embora a GCPTrafficDistributionPolicy a seguir seja destinada ao serviço Kubernetes foo normal, ela se aplica ao serviço foo de vários clusters composto de cargas de trabalho correspondentes em dois clusters.

  1. Crie a GCPTrafficDistributionPolicy para o cluster A:

    kubectl apply --context cluster-a-context -f - <<EOF
    kind: GCPTrafficDistributionPolicy
    apiVersion: networking.gke.io/v1
    metadata:
    name: foo-traffic-distribution-policy
    namespace: foo
    spec:
      targetRefs:
      - kind: Service
        group: ""
        name: foo-service
      default:
        serviceLbAlgorithm: WATERFALL_BY_ZONE
    
    EOF
    
  2. Crie a GCPBackendPolicy para o cluster A:

    kubectl apply --context cluster-a-context -f - <<EOF
    kind: GCPBackendPolicy
    apiVersion: networking.gke.io/v1
    metadata:
    name: foo-backend-policy
    namespace: foo
    spec:
      default:
        maxRatePerEndpoint: 100
        backendPreference: PREFERRED
      targetRef:
        group: ""
        kind: Service
        name: foo-service
    EOF
    
  3. Crie a GCPBackendPolicy para o cluster B:

    kubectl apply --context cluster-b-context -f - <<EOF
    kind: GCPBackendPolicy
    apiVersion: networking.gke.io/v1
    metadata:
    name: foo-backend-policy
    namespace: foo
    spec:
      default:
        maxRatePerEndpoint: 10
      targetRef:
        group: ""
        kind: Service
        name: foo-service
    EOF
    

A seguir