Sondas de vida em Kubernetes podem ser perigosas

Nota perev. : O engenheiro líder de Zalando, Henning Jacobs, notou repetidamente problemas com os usuários do Kubernetes no entendimento do objetivo das sondas de vivacidade (e prontidão) e sua aplicação correta. Portanto, ele reuniu seus pensamentos neste artigo amplo, que com o tempo se tornará parte da documentação do K8.



As verificações de saúde, conhecidas no Kubernetes como sondas de vivacidade (isto é, literalmente, "testes de viabilidade" - aprox. Transl.) , Podem ser bastante perigosas. Recomendo evitá-las sempre que possível: as únicas exceções são os casos em que são realmente necessárias e você está totalmente ciente das especificidades e conseqüências de seu uso. Esta publicação se concentrará nas verificações de prontidão e prontidão e também explicará em que casos vale a pena e não vale a pena usá-las.

Meu colega Sandor recentemente compartilhou no Twitter os erros mais comuns que ele encontra, incluindo aqueles relacionados ao uso de testes de prontidão / vivacidade:



Um livenessProbe configurado incorretamente pode agravar situações com alta carga (desligamento de avalanche + lançamento potencialmente longo do contêiner / aplicativo) e levar a outras consequências negativas, como uma queda nas dependências (consulte também meu artigo recente sobre limitação do número de solicitações no pacote K3s + ACME) . Pior ainda, quando um probe animado é combinado com uma verificação de integridade, que atua como um banco de dados externo: a única falha no banco de dados reiniciará todos os seus contêineres !

A mensagem geral “Não use sondas de vivacidade” neste caso ajuda um pouco, portanto, consideraremos para que servem as verificações de prontidão e vivacidade.

Nota: A maior parte do teste abaixo foi originalmente incluída na documentação interna dos desenvolvedores do Zalando.

Verificações de prontidão e vida


O Kubernetes fornece dois mecanismos importantes chamados testes de vivacidade e testes de prontidão . Eles executam periodicamente alguma ação - por exemplo, envia uma solicitação HTTP, abre uma conexão TCP ou executa um comando em um contêiner - para confirmar que o aplicativo está funcionando corretamente.

O Kubernetes usa testes de prontidão para entender quando um contêiner está pronto para receber tráfego. Um pod é considerado pronto para uso, se todos os seus contêineres estiverem prontos. Uma aplicação desse mecanismo é controlar quais pods são usados ​​como back-end para serviços Kubernetes (e especialmente o Ingress).

As análises de vida útil ajudam o Kubernetes a entender quando é hora de reiniciar o contêiner. Por exemplo, essa verificação permite interceptar o impasse quando o aplicativo está "preso" em um só lugar. Reiniciar o contêiner nesse estado ajuda a mover o aplicativo do chão, apesar dos erros, mas também pode levar a falhas em cascata (veja abaixo).

Se você tentar implantar uma atualização em um aplicativo que falhe nas verificações de disponibilidade / prontidão, a implantação será interrompida porque o Kubernetes aguardará o status de Ready em todos os pods.

Exemplo


Aqui está um exemplo de análise de prontidão que verifica o caminho /health através do HTTP com configurações padrão ( intervalo : 10 segundos, tempo limite : 1 segundo, limite de sucesso : 1, limite de falha : 3):

 #    deployment'/ podTemplate: spec: containers: - name: my-container # ... readinessProbe: httpGet: path: /health port: 8080 

Recomendações


  1. Para microsserviços com um ponto de extremidade HTTP (REST, etc.), defina sempre uma análise de prontidão que verifique se o aplicativo (pod) está pronto para receber tráfego.
  2. Verifique se o probe de prontidão cobre a disponibilidade da porta real do servidor da web :
    • Usando portas para necessidades administrativas denominadas “admin” ou “management” (por exemplo, 9090) para readinessProbe , verifique se o endpoint retorna OK somente se a porta HTTP principal (como 8080) estiver pronta para aceitar tráfego *;

      * Conheço pelo menos um caso em Zalando quando isso não aconteceu, ou seja, o readinessProbe verificou a porta de "gerenciamento", mas o próprio servidor não foi iniciado devido a problemas ao carregar o cache.
    • uma detecção de prontidão suspensa em uma porta separada pode levar ao fato de que o congestionamento na porta principal não será refletido na verificação de integridade (ou seja, o pool de threads no servidor está cheio, mas a verificação de integridade ainda mostra que está tudo bem).
  3. Garantir a detecção de prontidão permite a inicialização / migração do banco de dados ;
    • a maneira mais fácil de conseguir isso é acessar o servidor HTTP somente após a conclusão da inicialização (por exemplo, migração de banco de dados do Flyway , etc.); ou seja, em vez de alterar o status da verificação de integridade, simplesmente não inicie o servidor da web até que a migração do banco de dados * seja concluída.

      * Você também pode executar migrações de banco de dados a partir de containers init fora do pod. Ainda sou fã de aplicativos independentes, ou seja, aqueles em que o contêiner de aplicativos, sem coordenação externa, sabe como levar o banco de dados ao estado desejado.
  4. Use httpGet para verificações de prontidão através de pontos de extremidade típicos de verificações de saúde (por exemplo, /health ).
  5. successThreshold: 1 configurações successThreshold: 1 ( interval: 10s , timeout: 1s , successThreshold: 1 , failureThreshold: 3 ):
    • os parâmetros padrão significam que o pod ficará indisponível após cerca de 30 segundos (três falhas nas verificações de integridade).
  6. Use uma porta separada para "admin" ou "management" se a pilha de tecnologia (por exemplo, Java / Spring) permitir que isso separe o gerenciamento de integridade e métricas do tráfego normal:
    • mas não se esqueça do parágrafo 2.
  7. Se necessário, a sonda de prontidão pode ser usada para aquecer / carregar o cache e retornar o código de status 503 até que o contêiner seja "aquecido":
    • Também recomendo que você se familiarize com a nova verificação startupProbe , que apareceu na versão 1.16 (escrevemos sobre isso em russo aqui - aprox. Trad.) .

Advertências


  1. Não confie em dependências externas (como armazenamento de dados) ao realizar testes de disponibilidade / disponibilidade - isso pode levar a falhas em cascata:
    • como exemplo, vamos usar um serviço REST com estado com 10 pods, dependendo de um banco de dados do Postgres: quando a verificação depende de uma conexão de trabalho com o banco de dados, todos os 10 pods podem cair se houver um atraso na rede / no lado do banco de dados - geralmente tudo termina pior do que poderia;
    • observe que o Spring Data, por padrão, verifica a conexão com o banco de dados *;

      * Esse é o comportamento padrão do Spring Data Redis (pelo menos era como quando verifiquei pela última vez), o que levou a uma falha "catastrófica": quando o Redis ficou indisponível por um curto período de tempo, todos os pods "caíram".
    • “Externo” nesse sentido também pode significar outros pods do mesmo aplicativo, ou seja, idealmente, a verificação não deve depender do estado de outros pods do mesmo cluster para evitar falhas em cascata:
      • os resultados podem variar para aplicativos de estado distribuído (por exemplo, armazenamento em cache na memória em pods).
  2. Não use o probe liveness para pods (as exceções são casos em que são realmente necessárias e você está totalmente ciente das especificidades e conseqüências de seu uso):
    • o probe liveness pode ajudar a recuperar contêineres “travados”, mas como você tem controle total sobre seu aplicativo, idealmente, processos e travamentos “travados” não devem acontecer: a melhor alternativa é interromper o aplicativo intencionalmente e retorná-lo ao estado estacionário anterior;
    • uma falha no probe liveness reiniciará o contêiner, exacerbando potencialmente as conseqüências dos erros de carregamento: reiniciar o contêiner resultará em tempo de inatividade (pelo menos durante o tempo de inicialização do aplicativo, digamos, por mais de 30 segundos), causando novos erros, aumentando a carga outros recipientes e aumentando a probabilidade de falha, etc.;
    • as verificações de integridade em combinação com uma dependência externa são as piores combinações possíveis, o que pode levar a falhas em cascata: um pequeno atraso no lado do banco de dados fará com que todos os seus contêineres sejam reiniciados!
  3. Os parâmetros para verificações de disponibilidade e disponibilidade devem ser diferentes :
    • você pode usar o probe liveness com a mesma verificação de integridade, mas um limite mais alto ( failureThreshold ), por exemplo, atribui o status de não pronto após 3 tentativas e assume que o probe falhou após 10 tentativas;
  4. Não use verificações de exec , pois elas estão associadas a problemas conhecidos que levam ao aparecimento de processos zumbis:

Sumário


  • Use sondas de prontidão para determinar quando um pod está pronto para receber tráfego.
  • Use sondas de vivacidade somente quando forem realmente necessárias.
  • O uso incorreto de testes de prontidão / disponibilidade pode levar a disponibilidade reduzida e falhas em cascata.



Materiais adicionais sobre o tópico



Atualização No1 de 29/09/2019


Sobre contêineres init para migração de banco de dados : nota de rodapé adicionada.

EJ me lembrou o PDB: um dos problemas das verificações de vivacidade é a falta de coordenação entre os pods. O Kubernetes possui Orçamentos de interrupção de pod (PDBs) para limitar o número de falhas simultâneas que um aplicativo pode enfrentar, mas as verificações não levam em consideração os PDBs. Idealmente, podemos solicitar K8s: "Reinicie um pod se a verificação falhar, mas não os reinicie todos para não piorar".

Bryan formulou perfeitamente : “Use um som de animação quando tiver certeza de que a melhor coisa a fazer é“ matar ”o aplicativo ” (novamente, não se deixe levar).



Atualização No.2 de 29/09/2019


Sobre a leitura da documentação antes do uso : Criei uma solicitação de recurso para suplementar a documentação das análises de vitalidade.

PS do tradutor


Leia também em nosso blog:

Source: https://habr.com/ru/post/pt470958/


All Articles