Desligamento gracioso
Quando o Kubernetes tira um pod do ar, ele manda SIGTERM e espera. O que o seu serviço faz entre o sinal e o fim do processo decide se uma requisição em curso é concluída ou se o cliente vê um erro.
O orçamento é do chart:
terminationGracePeriodSeconds: 30
Trinta segundos. Se o processo não terminar até lá, o kubelet mata.
A sequência
/readypassa a negar. O pod sai do balanceamento antes de fechar qualquer coisa — nenhuma requisição nova chega.- Espera de drenagem: 3 s em produção,
0em desenvolvimento. Nesse tempo o serviço continua atendendo normalmente: é a janela para o balanceador perceber que o pod saiu. - O listener fecha e as requisições em curso terminam.
- O trabalho de fundo é cancelado e esperado.
- Os beans são destruídos, o pool por último.
- O processo termina com 0.
Os prazos, e o que acontece quando estouram
| etapa | prazo |
|---|---|
| espera de drenagem | 3 s (produção) |
| listeners + workers | um orçamento único de 20 s, contado do fim da espera |
| fechamento do contexto depois do prazo | +3 s |
terminationGracePeriodSeconds | 30 s |
Listeners e workers dividem os 20 s. Se o orçamento estourar, o registro é
nns: desligamento incompleto (com nns: workers não terminaram no prazo em error) e o código de
saída é 1 — sinal para quem observa que aquele pod não saiu limpo, mesmo tendo saído.
Se o contexto não acabar de fechar até 3 s depois do prazo, o processo é encerrado com 1. Todo o
caminho cabe nos 30 s do terminationGracePeriodSeconds.
O que isso vale na prática
Medido no laboratório: uma requisição presa em curso terminou com 201, o pod saiu em 15,8 s
e houve 0 erro em 528 mil requisições durante o desligamento. É o comportamento que você deve
esperar de um NNS que não inventa o próprio desligamento.
As duas armadilhas
Não use @Scheduled para trabalho periódico. Ele não conhece o papel da release e para de
disparar no início do desligamento — mas uma rodada em curso não é tratada como parte do
desligamento. O caminho do SDK é a tarefa periódica da release ativa, que o runtime cancela e espera
junto com o resto:
@NnsPeriodic(name = "items-sync", every = "1h")
void run(Ctx ctx) {
// só roda na release ATIVA; o runtime cuida do agendamento e do desligamento
}
Um bean que encerra algo por conta própria precisa se declarar. Se o seu serviço fecha um recurso próprio (uma conexão de longa duração, um cliente externo) e não consegue terminar dentro do orçamento, marque:
NnsShutdown.incomplete("cliente externo não fechou no prazo");
Sem isso, o desligamento é declarado limpo mesmo tendo deixado algo pela metade — e o código de saída mente para o operador.
O que o seu handler pode contar
Um handler em curso recebe um Ctx com o prazo da rota. O desligamento não cancela esse prazo
antes da hora: a requisição já aceita termina. O que muda é o /ready, que a partir do SIGTERM
responde negando para que nada novo entre.
Operação longa já respondida como 202 não depende do desligamento: ela é executada pelo runner da
Action, e a release ativa adota e fecha o que ficou pendente.
Como conferir
./nnconsolew chart check --values nns/helm/testdata/injected-values.yaml --namespace <ns> \
--runtime jvm --runtime-user 1002 nns/helm/chart
O chart check confere o terminationGracePeriodSeconds do manifesto. Uma execução local que
exercite o desligamento é papel dos testes do serviço (./mvnw verify), que sobem a aplicação e
mandam o sinal.
Esta página ajudou?
Reportar um problema nesta páginaNão envie senhas, chaves, tokens ou dados de clientes.