Resolver problemas de balanceamento de carga no GKE


Nesta página, mostramos como resolver problemas relacionados ao balanceamento de carga em clusters do Google Kubernetes Engine (GKE) usando recursos de Serviço, Entrada ou Gateway.

Se precisar de mais ajuda, entre em contato com o Cloud Customer Care.

BackendConfig não encontrado

Esse erro ocorre quando um BackendConfig de uma porta de serviço é especificado na anotação de serviço, mas o recurso BackendConfig real não é encontrado.

Para avaliar um evento do Kubernetes, execute o seguinte comando:

kubectl get event

O exemplo de saída a seguir indica que seu BackendConfig não foi encontrado:

KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: error getting BackendConfig for port 80 on service "default/my-service":
no BackendConfig for service port exists

Para resolver esse problema, verifique se você não criou o recurso BackendConfig no namespace errado ou se digitou incorretamente a referência na anotação do serviço.

Política de segurança de entrada não encontrada

Depois que o objeto de Entrada é criado, se a política de segurança não estiver adequadamente associada ao serviço LoadBalancer, avalie o evento do Kubernetes para ver se há um erro de configuração. Se o BackendConfig especificar uma política de segurança que não existe, um evento de aviso vai ser emitido periodicamente.

Para avaliar um evento do Kubernetes, execute o seguinte comando:

kubectl get event

O exemplo de saída a seguir indica que sua política de segurança não foi encontrada:

KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: The given security policy "my-policy" does not exist.

Para resolver esse problema, especifique o nome correto da política de segurança no BackendConfig.

Como solucionar erros da série 500 com NEGs durante o escalonamento de cargas de trabalho no GKE

Sintoma:

Ao usar NEGs provisionados pelo GKE para o balanceamento de carga, podem ocorrer erros 502 ou 503 nos serviços durante a redução da escala vertical das cargas de trabalho. Os erros 502 ocorrem quando os pods são encerrados antes do encerramento das conexões atuais, enquanto os erros 503 ocorrem quando o tráfego é direcionado para pods excluídos.

Esse problema pode afetar os clusters ao empregar produtos de balanceamento de carga gerenciado do GKE que usam NEGs, como NEGs de gateway, de entrada e independentes. Se você escalona as cargas de trabalho com frequência, seu cluster corre mais risco de ser afetado.

Diagnóstico:

Remover um pod no Kubernetes sem diminuir a conexão do endpoint dele e removê-lo do NEG primeiro resulta em erros da série 500. Para evitar problemas durante o encerramento do pod, considere a ordem das operações. As imagens a seguir mostram cenários em que BackendService Drain Timeout não está definido e BackendService Drain Timeout está definido com BackendConfig.

Cenário 1: BackendService Drain Timeout não está definido.

A imagem a seguir exibe um cenário em que BackendService Drain Timeout não está configurado.

O tempo limite de diminuição da conexão do BackendService não está definido.

Cenário 2: BackendService Drain Timeout está definido.

A imagem a seguir exibe um cenário em que BackendService Drain Timeout está definido.

O tempo limite de diminuição da conexão do BackendService está definido.

O momento exato em que os erros da série 500 ocorrem depende dos seguintes fatores:

  • Latência de remoção da API NEG: representa o tempo atual necessário para finalizar a operação de remoção no Google Cloud. Isso é afetado por vários fatores externos ao Kubernetes, como o tipo de balanceador de carga e a zona específica.

  • Latência de diminuição da conexão: representa o tempo que o balanceador de carga leva a fim de começar a direcionar o tráfego para longe de uma parte específica do sistema. Depois que a diminuição da conexão é iniciada, o balanceador de carga para de enviar novas solicitações ao endpoint. No entanto, ainda há uma latência no acionamento dessa diminuição (latência de diminuição da conexão), que pode causar erros 503 temporários caso o pod não exista mais.

  • Configuração da verificação de integridade: limites de verificação de integridade mais precisos reduzem a duração dos erros 503, porque podem sinalizar ao balanceador de carga que ele deve interromper o envio de solicitações aos endpoints, mesmo que a operação de remoção não tenha sido concluída.

  • Período de carência para o encerramento: determina o tempo máximo que um pod tem para ser encerrado. No entanto, lembre-se de que um pod pode ser encerrado antes do término desse período. Se um pod demorar mais do que isso para ser encerrado, o encerramento ocorrerá de modo forçado ao final do período. Essa configuração é feita no pod e precisa ser realizada na definição da carga de trabalho.

Possível resolução:

Para evitar erros 5XX, aplique as configurações a seguir. Os valores de tempo limite são sugestões, e talvez seja necessário ajustá-los para aplicativos específicos. Na seção a seguir, você encontra instruções sobre o processo de personalização.

A seguinte imagem mostra como manter o pod ativo com preStopHook:

O tempo limite de diminuição da conexão do BackendService está definido.

Para evitar erros da série 500, siga estas etapas:

  1. Defina BackendService Drain Timeout para o serviço como 1 minuto.

  2. Estenda terminationGracePeriod no pod.

    Defina terminationGracePeriodSeconds no pod como 3,5 minutos. Quando combinado com as configurações recomendadas, isso permite que os pods tenham uma janela de 30 a 45 segundos para realizar um encerramento normal depois da remoção do endpoint associado do NEG. Se você precisar de mais tempo para o encerramento normal, estenda o período de carência ou siga as instruções na seção Personalizar tempos limite.

    O seguinte Pod manifesto especifica um tempo limite de diminuição da conexão de 210 segundos (3,5 minutos):

    spec:
      terminationGracePeriodSeconds: 210
      containers:
      - name: my-app
        ...
      ...
    
  3. Aplique um preStopHook a todos os contêineres.

    Aplique um preStopHook que garanta que o pod fique ativo por mais 120 segundos enquanto ocorre a diminuição da conexão do endpoint dele no balanceador de carga e a remoção desse endpoint do NEG.

    spec:
      containers:
      - name: my-app
        ...
        lifecycle:
          preStopHook:
            exec:
              command: ["/bin/sh", "-c", "sleep 120s"]
      ...
    

Personalizar tempos limite

Para que você possa garantir a continuidade do pod e evitar erros da série 500, ele precisa estar ativo até que o endpoint seja removido do NEG. Especialmente para evitar os erros 502 e 503, considere a implementação de uma combinação de tempos limite e de preStopHook.

Para manter o pod ativo por mais tempo durante o processo de encerramento, adicione preStopHook a ele. Execute preStopHook antes que o encerramento de um pod seja solicitado. Assim, preStopHook pode ser usado para mantê-lo ativo até que o endpoint associado seja removido do NEG.

Para manter um pod ativo por mais tempo durante o processo de encerramento, insira preStopHook na configuração dele, da seguinte maneira:

spec:
  containers:
  - name: my-app
    ...
    lifecycle:
      preStopHook:
        exec:
          command: ["/bin/sh", "-c", "sleep <latency time>"]

É possível definir tempos limite e configurações relacionadas para gerenciar o encerramento normal de pods durante as reduções de escala vertical das cargas de trabalho. Você pode ajustar os tempos limites com base em casos de uso específicos. Recomendamos que você comece com tempos limite mais longos e reduza a duração conforme necessário. É possível personalizar os tempos limite configurando parâmetros relacionados a eles e preStopHook das seguintes maneiras:

Tempo limite de diminuição da conexão do serviço de back-end

O parâmetro Backend Service Drain Timeout não é definido por padrão e não tem efeito. Se você definir o parâmetro Backend Service Drain Timeout e ativá-lo, o balanceador de carga deixará de encaminhar novas solicitações ao endpoint e aguardará o tempo limite antes de encerrar as conexões atuais.

É possível definir o parâmetro Backend Service Drain Timeout usando BackendConfig com o Ingress, GCPBackendPolicy com o gateway ou de modo manual em BackendService, no caso de NEGs independentes. O tempo limite precisa ser de 1,5 a 2 vezes maior que o tempo necessário para processar uma solicitação. Isso garante que uma solicitação que tenha chegado antes do início da diminuição da conexão seja concluída antes do tempo limite. Definir o parâmetro Backend Service Drain Timeout como um valor maior que 0 ajuda a reduzir erros 503, porque nenhuma nova solicitação é enviada aos endpoints programados para remoção. Para que esse tempo limite seja eficaz, é preciso usá-lo com preStopHook, a fim de garantir que o pod permaneça ativo enquanto ocorre a diminuição da conexão. Sem essa combinação, as solicitações atuais que não foram concluídas vão receber um erro 502.

Tempo em preStopHook

Ao configurar preStopHook, é preciso atrasar o encerramento do pod o suficiente para que haja tempo de concluir a latência de diminuição da conexão e o tempo limite de diminuição da conexão do serviço de back-end. Com isso, você garante a diminuição adequada da conexão e a remoção do endpoint do NEG antes do encerramento do pod.

Para resultados ideais, verifique se o tempo de execução de preStopHook é menor ou igual à soma de Backend Service Drain Timeout e da latência de diminuição da conexão.

Isso pode ser calculado com a seguinte fórmula:

preStopHook >= Backend Service Drain Timeout + Drain Latency

Recomendamos definir a latência de diminuição da conexão para 1 minuto. Se erros 500 continuarem acontecendo, estime a duração total da ocorrência e adicione o dobro desse tempo à latência. Isso garante que haja tempo suficiente para a diminuição adequada da conexão do pod antes da remoção dele do serviço. É possível ajustar esse valor se ele for muito grande para seu caso de uso específico.

Também é possível estimar esse tempo analisando o carimbo de data/hora da exclusão do pod e o carimbo de data/hora de quando o endpoint foi removido do NEG nos Registros de auditoria do Cloud.

Parâmetro do período de carência para o encerramento

Configure o parâmetro terminationGracePeriod a fim de que haja tempo suficiente para que preStopHook seja concluído e o pod realize um encerramento normal.

Por padrão, quando terminationGracePeriod não é definido de modo explícito, a duração é de 30 segundos. É possível calcular o terminationGracePeriod ideal usando a seguinte fórmula:

terminationGracePeriod >= preStopHook Time + Pod shutdown time

Defina terminationGracePeriod na configuração do pod da seguinte maneira:

  spec:
    terminationGracePeriodSeconds: <terminationGracePeriod>
    containers:
    - name: my-app
      ...
    ...

NEG não encontrado ao criar um recurso de Entrada interna

O seguinte erro pode ocorrer ao criar uma entrada interna no GKE:

Error syncing: error running backend syncing routine: googleapi: Error 404: The resource 'projects/PROJECT_ID/zones/ZONE/networkEndpointGroups/NEG' was not found, notFound

Esse erro ocorre porque o Ingress para balanceadores de carga internos de aplicativos requer grupos de endpoints de rede (NEGs, na sigla em inglês) como back-ends.

Em ambientes de VPC compartilhada ou clusters com políticas de rede ativadas, adicione a anotação cloud.google.com/neg: '{"ingress": true}' ao manifesto de serviço.

504 tempo limite do gateway: tempo limite da solicitação upstream

O seguinte erro pode ocorrer quando você acessa um serviço de uma entrada interna no GKE:

HTTP/1.1 504 Gateway Timeout
content-length: 24
content-type: text/plain

upsteam request timeout

Esse erro ocorre porque o tráfego enviado para balanceadores de carga de aplicativo internos é enviado por proxies Envoy no intervalo de sub-redes somente proxy.

Para permitir o tráfego do intervalo de sub-rede somente proxy, crie uma regra de firewall no targetPort do serviço.

Erro 400: valor inválido para o campo "resource.target"

O seguinte erro pode ocorrer quando você acessa um serviço de uma entrada interna no GKE:

Error syncing:LB_NAME does not exist: googleapi: Error 400: Invalid value for field 'resource.target': 'https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION_NAME/targetHttpProxies/LB_NAME. A reserved and active subnetwork is required in the same region and VPC as the forwarding rule.

Para resolver esse problema, implante uma sub-rede apenas de proxy.

Erro durante a sincronização: erro ao executar a rotina de sincronização do balanceador de carga: o balanceador de carga não existe

Um dos seguintes erros pode ocorrer quando o plano de controle do GKE é atualizado ou quando você modifica um objeto de Entrada:

"Error during sync: error running load balancer syncing routine: loadbalancer
INGRESS_NAME does not exist: invalid ingress frontend configuration, please
check your usage of the 'kubernetes.io/ingress.allow-http' annotation."

Ou:

Error during sync: error running load balancer syncing routine: loadbalancer LOAD_BALANCER_NAME does not exist:
googleapi: Error 400: Invalid value for field 'resource.IPAddress':'INGRESS_VIP'. Specified IP address is in-use and would result in a conflict., invalid

Para resolver esses problemas, siga estas etapas:

  • Adicione o campo hosts na seção tls do manifesto de entrada e exclua o Ingress. Aguarde cinco minutos para que o GKE exclua os recursos de Entrada não utilizados. Em seguida, recrie a Entrada. Para mais informações, consulte Campo "Hosts" de um objeto de Entrada.
  • Reverta as alterações feitas no Ingress. Em seguida, adicione um certificado usando uma anotação ou secret do Kubernetes.

A Entrada externa produz erros HTTP 502

Use as orientações a seguir para solucionar erros HTTP 502 com recursos de Entrada externa:

  1. Ative os registros para cada serviço de back-end associado a cada serviço do GKE referenciado pela Entrada.
  2. Use os detalhes do status para identificar as causas das respostas HTTP 502. Os detalhes do status que indicam a resposta HTTP 502 originada do back-end exigem solução de problemas nos pods de exibição, não no balanceador de carga.

Grupos de instâncias não gerenciadas

É possível que ocorram erros HTTP 502 com os recursos de Entrada externos se sua Entrada externa usar back-ends de grupos de instâncias não gerenciados. Esse problema ocorre quando todas as condições a seguir são atendidas:

  • O cluster tem um grande número total de nós em todos os pools.
  • Os pods de exibição para um ou mais serviços que são referenciados pela Entrada estão localizados em apenas alguns nós.
  • Os serviços referenciados pela Entrada usam externalTrafficPolicy: Local.

Para determinar se a Entrada externa usa back-ends de grupos de instâncias não gerenciadas, faça o seguinte:

  1. Acesse a página do Entrada no console do Google Cloud.

    Acessar o Ingress

  2. Clique no nome do Ingress externo.

  3. Clique no nome do balanceador de carga. A página Detalhes do balanceamento de carga é exibida.

  4. Verifique a tabela na seção Serviços de back-end para determinar se a Entrada externa usa NEGs ou grupos de instâncias.

Para resolver esse problema, use um dos métodos a seguir.

  • Use um cluster nativo de VPC.
  • Use externalTrafficPolicy: Cluster para cada Serviço referenciado pelo Ingress externo. Essa solução faz com que você perca o endereço IP original do cliente nas origens do pacote.
  • Use a anotação node.kubernetes.io/exclude-from-external-load-balancers=true: Adicione a anotação aos nós ou pools de nós que não executam qualquer pod de veiculação para qualquer serviço referenciado por qualquer entrada externa ou serviço LoadBalancer no cluster.

Usar registros do balanceador de carga para resolver problemas

É possível usar registros do balanceador de carga de rede de passagem interna e registros do balanceador de carga de rede de passagem externa para solucionar problemas com balanceadores de carga e correlacionar tráfego de balanceadores de carga para recursos do GKE.

Os registros são agregados por conexão e exportados quase em tempo real. Os registros são gerados para cada nó do GKE envolvido no caminho de dados de um serviço LoadBalancer, para o tráfego de entrada e saída. As entradas de registro incluem campos adicionais para recursos do GKE, como: - Nome do cluster - Local do cluster - Nome do serviço - Namespace do serviço - Nome do pod - Pod namespace

Preços

Não há cobranças extras pelo uso de registros. Dependendo da maneira como você ingere registros, são aplicados os preços padrão ao Cloud Logging, BigQuery ou Pub/Sub. A ativação de registros não afeta o desempenho do balanceador de carga.

Usar ferramentas de diagnóstico para resolver problemas

A ferramenta de diagnóstico check-gke-ingress inspeciona os recursos do Ingress em busca de erros de configuração comuns. É possível usar a ferramenta check-gke-ingress das seguintes maneiras:

A seguir

Se precisar de mais ajuda, entre em contato com o Cloud Customer Care.