Como usar balanceamento de carga nativo de contêiner

Nesta página, explicamos como usar o balanceamento de carga nativo de contêiner no Google Kubernetes Engine (GKE). O balanceamento de carga nativo de contêiner permite que os balanceadores de carga segmentem os pods do Kubernetes diretamente e distribuam o tráfego aos pods por igual.

Consulte Balanceamento de carga nativo de contêiner para informações sobre os benefícios, os requisitos e as limitações desse recurso.

Como usar balanceamento de carga nativo de contêiner

Nas seções a seguir, você será orientado por uma configuração de balanceamento de carga nativo de contêiner no GKE.

Como criar um cluster nativo de VPC

Para usar o balanceamento de carga nativo de contêiner, é preciso criar um cluster com IPs de alias ativados.

Por exemplo, o comando a seguir cria um cluster, neg-demo-cluster, com uma sub-rede provisionada automaticamente na zona us-central1-a:

    gcloud container clusters create neg-demo-cluster \
        --enable-ip-alias \
        --create-subnetwork="" \
        --network=default \
        --zone=us-central1-a
    

Como criar uma implantação

Em seguida, implante uma carga de trabalho no cluster.

Na amostra de implantação a seguir, neg-demo-app executa uma única instância de um servidor HTTP em contêiner. Recomendamos o uso de cargas de trabalho que apliquem o feedback de prontidão do pod, se ele estiver disponível na sua versão do GKE. Consulte Prontidão do pod para mais informações e requisitos da versão do GKE. Avalie a possibilidade de fazer upgrade do cluster para usar o feedback de prontidão do pod.

Como usar o feedback de prontidão do pod

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        run: neg-demo-app # Label for the Deployment
      name: neg-demo-app # Name of Deployment
    spec:
      selector:
        matchLabels:
          run: neg-demo-app
      template: # Pod template
        metadata:
          labels:
            run: neg-demo-app # Labels Pods from this Deployment
        spec: # Pod specification; each Pod created by this Deployment has this specification
          containers:
          - image: k8s.gcr.io/serve_hostname:v1.4 # Application to run in Deployment's Pods
            name: hostname # Container name
      

Como usar o atraso fixado no código

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        run: neg-demo-app # Label for the Deployment
      name: neg-demo-app # Name of Deployment
    spec:
      minReadySeconds: 60 # Number of seconds to wait after a Pod is created and its status is Ready
      selector:
        matchLabels:
          run: neg-demo-app
      template: # Pod template
        metadata:
          labels:
            run: neg-demo-app # Labels Pods from this Deployment
        spec: # Pod specification; each Pod created by this Deployment has this specification
          containers:
          - image: k8s.gcr.io/serve_hostname:v1.4 # Application to run in Deployment's Pods
            name: hostname # Container name
          # Note: The following line is necessary only on clusters running GKE v1.11 and lower.
          # For details, see https://cloud.google.com/kubernetes-engine/docs/how-to/container-native-load-balancing#align_rollouts
          terminationGracePeriodSeconds: 60 # Number of seconds to wait for connections to terminate before shutting down Pods
      

Nesta implantação, cada contêiner executa um servidor HTTP. O servidor HTTP simplesmente retorna o nome do host do servidor de aplicativos (nome do pod em que o servidor é executado) como resposta.

Salve este manifesto como neg-demo-app.yaml e, em seguida, crie a implantação executando o seguinte comando:

kubectl apply -f neg-demo-app.yaml

Como criar um serviço para um balanceador de carga nativo de contêiner

Depois de criar uma implantação, é preciso agrupar os pods correspondentes em um serviço (em inglês).

No serviço de exemplo a seguir, neg-demo-svc segmenta a implantação de amostra criada na seção anterior:

apiVersion: v1
    kind: Service
    metadata:
      name: neg-demo-svc # Name of Service
      annotations:
        cloud.google.com/neg: '{"ingress": true}' # Creates a NEG after an Ingress is created
    spec: # Service's specification
      type: NodePort
      selector:
        run: neg-demo-app # Selects Pods labelled run: neg-demo-app
      ports:
      - port: 80 # Service's port
        protocol: TCP
        targetPort: 9376
    

A anotação do serviço, cloud.google.com/neg: '{"ingress": true}', ativa o balanceamento de carga nativo de contêiner. No entanto, o balanceador de carga não será criado até você gerar um Ingress para o serviço.

Salve este manifesto como neg-demo-svc.yaml e, em seguida, crie o serviço executando o seguinte comando:

kubectl apply -f neg-demo-svc.yaml

Como criar um Ingress para o serviço

No seguinte Ingress (em inglês) de amostra, neg-demo-ing segmenta o serviço criado:

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: neg-demo-ing
    spec:
      backend:
        serviceName: neg-demo-svc # Name of the Service targeted by the Ingress
        servicePort: 80 # Should match the port used by the Service

Salve este manifesto como neg-demo-ing.yaml e, em seguida, crie o Ingress executando o seguinte comando:

kubectl apply -f neg-demo-ing.yaml

Ao criar o Ingress, um balanceador de carga HTTP(S) é gerado no projeto, e os NEGs são criados em cada zona em que o cluster é executado. Os endpoints no NEG e os do serviço são mantidos em sincronia.

Como verificar o Ingress

Depois de implantar uma carga de trabalho, agrupar os respectivos pods em um serviço e criar um Ingress para o serviço, é preciso verificar se o Ingress provisionou o balanceador de carga nativo de contêiner.

Para recuperar o status do Ingress, execute o seguinte comando:

kubectl describe ingress neg-demo-ing

Na saída do comando, procure os eventos ADD e CREATE:

Events:
    Type     Reason   Age                From                     Message
    ----     ------   ----               ----                     -------
    Normal   ADD      16m                loadbalancer-controller  default/neg-demo-ing
    Normal   Service  4s                 loadbalancer-controller  default backend set to neg-demo-svc:32524
    Normal   CREATE   2s                 loadbalancer-controller  ip: 192.0.2.0

Como testar a funcionalidade do balanceador de carga

Nas seções a seguir, explicaremos como testar a funcionalidade de um balanceador de carga nativo de contêiner.

Acessar o endereço IP do Ingress

Aguarde alguns minutos para que o balanceador de carga HTTP(S) seja configurado.

É possível verificar se o balanceador de carga nativo de contêiner está funcionando acessando o endereço IP do Ingress.

Para conseguir o endereço IP do Ingress, execute o seguinte comando:

kubectl get ingress neg-demo-ing

Na resposta ao comando, o endereço IP do Ingress é exibido na coluna ADDRESS. Visite o endereço IP em um navegador da Web.

Verificar status de integridade do serviço de back-end

Também é possível receber o status de integridade do serviço de back-end do balanceador de carga.

Primeiro, consiga uma lista dos serviços de back-end em execução no projeto:

    gcloud compute backend-services list
    

Copie o nome do back-end que inclui o nome do serviço, como neg-demo-svc. Em seguida, detecte o status de integridade do serviço de back-end:

    gcloud compute backend-services get-health [BACKEND_SERVICE_NAME] --global
    

Como verificar a funcionalidade do Ingress

Outra maneira de testar se o balanceador de carga funciona conforme o esperado é dimensionar a implantação de amostra. Para isso, basta enviar solicitações de teste para o Ingress e verificar se o número correto de réplicas é retornado.

Com o comando a seguir, a implantação de neg-demo-app é dimensionada de uma para duas instâncias:

kubectl scale deployment neg-demo-app --replicas 2

Aguarde alguns minutos até que o lançamento seja concluído. Para verificar se o lançamento foi concluído, execute o seguinte comando:

kubectl get deployment neg-demo-app

Na resposta ao comando, verifique se há duas réplicas disponíveis:

NAME           DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    neg-demo-app   2         2         2            2           26m

Em seguida, execute o seguinte comando para contar o número de respostas distintas provenientes do balanceador de carga:

    for i in `seq 1 100`; do \
      curl --connect-timeout 1 -s [IP_ADDRESS] && echo; \
    done  | sort | uniq -c

em que [IP_ADDRESS] é o endereço IP do Ingress. É possível conseguir o endereço IP do Ingress executando o comando kubectl describe ingress neg-demo-ing.

Na resposta ao comando, observe que o número de respostas distintas é igual ao número de réplicas, indicando que todos os pods de back-end estão processando tráfego:

44 neg-demo-app-7f7dfd7bc6-dcn95
    56 neg-demo-app-7f7dfd7bc6-jrmzf

Limpeza

Depois de concluir as tarefas nesta página, siga estas etapas para remover os recursos e evitar cobranças indesejadas na sua conta:

Excluir o cluster

gcloud

gcloud container clusters delete neg-demo-cluster

Console

  1. Acesse o menu do Google Kubernetes Engine no Console do Cloud.

    Acessar o menu do Google Kubernetes Engine

  2. Selecione neg-demo-cluster.

  3. Clique em Excluir.

Resolver problemas

Use as técnicas abaixo para verificar a configuração de rede. Nas seções a seguir, você verá como resolver problemas comuns relacionados ao balanceamento de carga nativo de contêiner.

  • Consulte a documentação de balanceamento de carga para saber como listar grupos de endpoints de rede.

  • É possível encontrar o nome e as zonas do NEG correspondente a um serviço na anotação neg-status do serviço. Veja a especificação do serviço com o comando:

    kubectl get svc svc-name -o yaml

    A anotação metadata:annotations:cloud.google.com/neg-status lista as zonas e o nome do NEG correspondente ao serviço.

  • É possível verificar a integridade do serviço de back-end correspondente a um NEG com o seguinte comando:

        gcloud compute backend-services [--project PROJECT_NAME] \
          get-health BACKEND_SERVICE_NAME --global
        

    O serviço de back-end tem o mesmo nome que o NEG.

  • Para imprimir os logs de eventos de um serviço:

        kubectl describe svc [SERVICE_NAME]
        

    A string do nome do serviço inclui o nome e o namespace do serviço correspondente do GKE.

Não é possível criar um cluster com IPs de alias

Sintomas
Ao tentar criar um cluster com IPs de alias, talvez aconteça o seguinte erro:
ResponseError: code=400, message=IP aliases cannot be used with a legacy network.
Causas possíveis
Esse erro aparecerá se você tentar criar um cluster com IPs de alias que também usa uma rede legada.
Resolução
Não crie um cluster com IPs de alias e uma rede legada ativada simultaneamente. Para mais informações sobre como usar IPs de alias, consulte Como criar clusters nativos de VPC usando IPs de alias.

O tráfego não alcança os endpoints

Sintomas
Erros 502 ou conexões rejeitadas.
Causas possíveis

Novos endpoints geralmente se tornam acessíveis depois de anexados ao balanceador de carga, desde que respondam às verificações de integridade. Poderão ocorrer erros 502 ou conexões rejeitadas se o tráfego não conseguir alcançar os endpoints.

Erros 502 e conexões rejeitadas também podem ser causados por um contêiner que não processa SIGTERM. Se um contêiner não processar SIGTERM de maneira explícita, ele será encerrado imediatamente e parará de processar as solicitações. O balanceador de carga continua a enviar tráfego de entrada para esse contêiner encerrado, causando erros.

Resolução

Configure os contêineres para processar SIGTERM e continuar a responder às solicitações durante o período de carência do encerramento (30 segundos por padrão). Configure os pods para começar a falhar nas verificações de integridade ao receber SIGTERM. Isso envia um sinal para que o balanceador de carga pare de enviar tráfego ao pod enquanto a desprogramação do endpoint está em andamento.

Para mais informações, consulte a documentação sobre encerramento de pod e esta postagem sobre práticas recomendadas de encerramento de pods (links em inglês).

Para solucionar problemas de tráfego que não alcança os endpoints, verifique se as regras de firewall permitem o tráfego TCP de entrada para os endpoints nos intervalos 130.211.0.0/22 e 35.191.0.0/16. Para saber mais, consulte Como adicionar verificações de integridade na documentação do Cloud Load Balancing.

Veja os serviços de back-end no seu projeto. A string de nome do serviço de back-end relevante inclui o nome e o namespace do serviço do Google Kubernetes Engine correspondente:

gcloud compute backend-services list

Recupere o status de integridade do back-end do serviço correspondente:

gcloud compute backend-services get-health [BACKEND_SERVICE_NAME]

Se nenhum back-end estiver íntegro, significa que pode haver problemas na configuração do firewall, do Ingress ou do serviço.

Se alguns back-ends não estiverem íntegros por um curto período, a causa poderá ser a latência da programação de rede.

Se alguns back-ends não aparecerem na lista de serviços, a causa poderá ser a latência da programação. Para verificar isso, execute o seguinte comando, em que [NEG] é o nome do serviço de back-end. NEGs e serviços de back-end compartilham o mesmo nome:

gcloud compute network-endpoint-groups list-network-endpoints [NEG]

Verifique se todos os endpoints esperados estão no NEG.

Lançamento interrompido

Sintomas
O lançamento de uma implantação atualizada é interrompido, e o número de réplicas atualizadas não corresponde ao esperado.
Causas possíveis

As verificações de integridade da implantação estão falhando. A imagem do contêiner pode estar corrompida ou a verificação de integridade pode estar mal configurada. O substituição gradual dos pods aguarda até que o pod recém-iniciado passe pelo portão de prontidão do pod (em inglês). Isso só ocorrerá se o pod estiver respondendo às verificações de integridade do balanceador de carga. Se o pod não estiver respondendo ou se a verificação de integridade estiver configurada incorretamente, as condições do portão de prontidão não serão cumpridas e o lançamento não poderá continuar.

Se você usa o kubectl 1.13 ou posterior, é possível verificar o status dos portões de prontidão de um pod com o seguinte comando:

kubectl get my-Pod -o wide

Verifique a coluna READINESS GATES.

Essa coluna não existe no kubectl 1.12 ou anterior. Um pod marcado com o estado READY pode ter um portão de prontidão com falha. Para verificar isso, use o seguinte comando:

kubectl get my-pod -o yaml

Os portões de prontidão e os status deles são listados na resposta.

Resolução

Verifique se a imagem do contêiner na especificação do pod da implantação está funcionando corretamente e se pode responder às verificações de integridade. Verifique se as verificações de integridade estão configuradas corretamente.

Problemas conhecidos

O balanceamento de carga nativo de contêiner no Google Kubernetes Engine apresenta os seguintes problemas conhecidos:

Coleta de lixo incompleta

O Google Kubernetes Engine coleta lixo de balanceadores de carga nativos de contêiner a cada dois minutos. Se um cluster for excluído antes que os balanceadores de carga sejam totalmente removidos, você precisará excluir manualmente os NEGs do balanceador de carga.

Veja os NEGs do seu projeto executando o seguinte comando:

gcloud compute network-endpoint-groups list

Na resposta ao comando, procure os NEGs relevantes.

Para excluir um NEG, execute o seguinte comando, em que [NEG] é o nome do NEG:

gcloud compute network-endpoint-groups delete [NEG]

Como alinhar lançamentos de carga de trabalho com propagação de endpoint

Ao implantar uma carga de trabalho no cluster ou atualizar uma carga de trabalho atual, o balanceador de carga nativo de contêiner pode levar mais tempo para propagar novos endpoints do que para concluir o lançamento da carga de trabalho. A implantação de amostra realizada neste guia usa dois campos para alinhar o lançamento com a propagação dos endpoints: terminationGracePeriodSeconds e minReadySeconds.

terminationGracePeriodSeconds (em inglês) permite que o pod seja encerrado normalmente ao esperar o término das conexões após um pod ser programado para exclusão.

minReadySeconds (em inglês) adiciona um período de latência depois que um pod é criado. Especifique um número mínimo de segundos para que um novo pod entre no status Ready (em inglês) sem que nenhum contêiner apresente falhas, de modo que o pod seja considerado disponível.

Configure os valores minReadySeconds e terminationGracePeriodSeconds das cargas de trabalho como 60 segundos ou mais para garantir que o serviço não seja interrompido devido às implantações das cargas de trabalho.

terminationGracePeriodSeconds está disponível em todas as especificações do pod e minReadySeconds está disponível para Deployments e DaemonSets.

Para saber mais sobre o ajuste detalhado de lançamentos, consulte RollingUpdateStrategy (em inglês).

A seguir