Visão Geral do Ciclo de Vida de um Pod
O ciclo de vida de um Pod refere-se ao período desde sua criação até sua terminação. Durante esse intervalo, o Pod passa por vários estados e pode executar operações configuráveis. A operação principal é a execução do contêiner, mas outras como contêineres de inicialização, ganchos de ciclo de vida, e sondagens de saúde são opcionais e dependem da especificação do Pod.
Fases do Pod (Pod Phases)
Indepenedntemente de ser criado manualmente ou por controladores como Deployments, um Pod sempre se ancontra em uma das seguintes fases:
- Pending: O objeto Pod foi criado e persistido no etcd, mas ainda não foi agendado ou está baixando a imagem do contêiner.
- Running: O Pod foi agendado em um nó, e todos os seus contêineres foram criados pelo kubelet.
- Succeeded: Todos os contêineres no Pod terminaram com sucesso e não serão reiniciados.
- Failed: Todos os contêineres terminaram, mas pelo menos um terminou com falha (código de saída diferente de zero ou foi encerrado pelo sistema).
- Unknown: O estado do Pod não pôde ser obtido, geralmente devido a uma falha de comunicação entre o kubelet e o API Server.
Diagnóstico Rápido de Problemas
Problemas comuns e suas verificações prioritárias:
- Pod preso em Pending: Verifique os recursos do nó e tolerâncias com
kubectl describe node <nome-do-no>. - CrashLoopBackOff: Inspecione os logs do contêiner anterior com
kubectl logs --previous <nome-do-pod>. - Indisponibilidade intermitente: Valide a configuração da sonda de prontidão (
readinessProbe) e os endpoints do serviço comkubectl get endpoints. - Terminação demorada: Observe os eventos em tempo real para verificar ganchos
preStopcomkubectl get events -w. - Falha ao montar volume: Verifique o estado do PersistentVolumeClaim com
kubectl get pvc -o wide.
Criação do Pod
O fluxo de criação segue estas etapas principais:
- O cliente (ex:
kubectl apply) envia uma requisição para o API Server, autenticado com certificados. - O API Server valida a requisição e persiste a especificação do Pod no etcd.
- O Controller Manager observa (watch) a discrepância entre o estado desejado (ex: réplicas de um Deployment) e o atual, solicitando a criação de novos Pods.
- O Scheduler obtém Pods pendentes, avalia os recursos do cluster e os agendam em nós adequados.
- O agendamento é registrado no etcd via API Server.
- O kubelet no nó agendado recebe a tarefa, baixa as imagens e cria os contêineres do Pod.
- O kubelet reporta periodicamente o status do Pod e do nó de volta ao API Server.
Ganchos de Ciclo de Vida (Lifecycle Hooks)
Os ganchos permitem executar código customizado em eventos específicos do ciclo de vida do contêiner principal. Dois são fornecidos:
- postStart: Executado imediatamente após a criação do contêiner.
- preStop: Executado antes do contêiner ser encerrado.
Definição dos Ganchos
Os ganchos podem definir ações de duas maneiras:
Modo exec
Executa um comando diretamente dentro do contêiner. Sucesso é um código de saída 0.
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo 'Contêiner inicializado' > /tmp/status.log"]
Modo httpGet
Realiza uma requisição HTTP GET. Sucesso é uma resposta com código de status entre 200 e 399.
lifecycle:
postStart:
httpGet:
path: /health/startup
port: 8080
scheme: HTTP
host: localhost
Sondas de Contêiner (Container Probes)
Existem três tipos de sondas que o kubelet pode executar para verificar a saúde do contêiner. A falha em uma sonda pode levar a reinicializações ou remoção do endpoint do serviço.
Sonda de Inicialização (Startup Probe)
Verifica se o contêiner completou sua inicialização. Enquanto esta sonda não for bem-sucedida, as outras sondas (liveness, readiness) ficam desabilitadas. É uma verificação única no início.
Sonda de Atividade (Liveness Probe)
Determina se o contêiner está em execução. Se falhar, o kubelet matará o contêiner, e a política de reinício definirá o que acontecerá em seguida.
Sonda de Prontidão (Readiness Probe)
Determina se o contêiner está pronto para aceitar tráfego de rede. Se falhar, o endereço IP do Pod será removido dos endpoints do(s) Service(s) associado(s), impedindo que ele receba requisições.
Parâmetros Comuns das Sondas
initialDelaySeconds: Tempo de espera após a inicialização do contêiner antes de iniciar as sondas.periodSeconds: Intervalo entre execuções da sonda.timeoutSeconds: Tempo máximo de espera por uma resposta da sonda.successThreshold: Número de sucessos consecutivos após uma falha para considerar o contêiner saudável novamente.failureThreshold: Número de falhas consecutivas para considerar o contêiner não saudável.
Exemplos de Configuração
Sonda HTTP
apiVersion: v1
kind: Pod
metadata:
name: web-app-probe
spec:
containers:
- name: app
image: httpd:latest
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /status
port: 80
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 2
periodSeconds: 5
Sonda TCP
apiVersion: v1
kind: Pod
metadata:
name: cache-service-probe
spec:
containers:
- name: memcached
image: memcached:latest
ports:
- containerPort: 11211
readinessProbe:
tcpSocket:
port: 11211
initialDelaySeconds: 5
periodSeconds: 10
Sonda Exec
apiVersion: v1
kind: Pod
metadata:
name: data-sync-probe
spec:
containers:
- name: sync-agent
image: busybox
command: ["/bin/sh", "-c", "while true; do echo alive; sleep 60; done"]
livenessProbe:
exec:
command: ["grep", "alive", "/tmp/heartbeat.log"]
initialDelaySeconds: 10
periodSeconds: 5
Diretrizes de Implementação
- Sonda de Inicialização: Use para aplicações com tempo de inicialização longo ou variável. Defina um
failureThresholdalto eperiodSecondsadequado para dar tempo suficiente. - Sonda de Atividade: Essencial para detectar travamentos (ex: deadlock). Certifique-se de que a aplicação termine limpa quando a sonda falhar.
- Sonda de Prontidão: Use para aplicações que dependem de recursos externos (banco de dados, cache) antes de estarem prontas. Isso evita erros 502 ou timeouts para os clientes.
As sondas de prontidão e atividade podem e devem ser combinadas no mesmo Pod para uma gestão robusta do tráfego e da saúde.
Política de Reinício (restartPolicy)
A política determina se o kubelet deve reiniciar um contêiner encerrado. É definida por Pod:
- Always: Reinicia o contêiner sempre que ele encerrar. É o padrão.
- OnFailure: Reinicia apenas se o contêinar terminar com um código de erro (diferente de 0).
- Never: Nunca reinicia o contêiner, independentemente do motivo do encerramento.
Reinicializações subsequentes após a primeira falha têm um backoff exponencial (10s, 20s, 40s, ... até 300s).
Encerramento e Encerramento Gracioso
Ao deletar um Pod, segue-se este processo:
- O Pod recebe o sinal
SIGTERMe é marcado como "Terminating". - Simultaneamente, o Pod é removido da lista de endpoints dos Services.
- O gancho
preStop(se definido) é executado. - O contêiner tem o tempo de encerramento gracioso (
terminationGracePeriodSeconds, padrão 30s) para encerrar suas aplicações. - Se o processo não terminar dentro do período de graça, o kubelet enviará um sinal
SIGKILLpara forçar o encerramento. - Finalmente, o kubelet solicita ao API Server a remoção definitiva do recurso do Pod.
Configurando um Encerramento Gracioso
Dois campos são críticos:
apiVersion: v1
kind: Pod
metadata:
name: graceful-app
spec:
terminationGracePeriodSeconds: 45 # Tempo total para encerramento
containers:
- name: main-app
image: my-app:latest
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 15 && /app/shutdown.sh"]
Neste exemplo, o contêiner tem 45 segundos no total. Ao receber SIGTERM, primeiro executará o gancho preStop (que dorme por 15 segundos e executa um script de encerramento). Após o gancho, o contêiner principal tem os 30 segundos restantes para encerrar. Isso é útil para conexões de drenagem, salvamento de estado, etc.