Boas práticas de health checks e readiness probes em serviços

1. Fundamentos de Health Checks e Readiness Probes

Health checks e readiness probes são mecanismos fundamentais para garantir a resiliência e disponibilidade de serviços em ambientes modernos. Embora frequentemente confundidos, eles servem a propósitos distintos e complementares.

Liveness probes (health checks) determinam se um serviço está vivo ou em estado de falha irreversível. Quando uma liveness probe falha, o orquestrador reinicia o container, buscando restaurar o serviço. Readiness probes indicam se o serviço está pronto para receber tráfego. Quando falham, o serviço é removido do balanceamento de carga, mas não é reiniciado.

Em Kubernetes, esses probes permitem:
- Detecção automática de falhas (deadlocks, memory leaks)
- Roteamento inteligente de tráfego apenas para instâncias saudáveis
- Auto-recuperação sem intervenção manual

# Exemplo conceitual de comportamento
Liveness:  Falha → Reinicia container
Readiness: Falha → Remove do Service/Ingress

2. Tipos de Probes e Mecanismos de Implementação

Probes HTTP

São os mais comuns. O orquestrador faz requisições HTTP a um endpoint específico e avalia o código de status.

livenessProbe:
  httpGet:
    path: /health
    port: 8080
    httpHeaders:
    - name: Custom-Header
      value: health-check
  initialDelaySeconds: 5
  periodSeconds: 10

Probes TCP

Verificam se uma porta TCP está aceitando conexões. Úteis para serviços que não expõem HTTP.

readinessProbe:
  tcpSocket:
    port: 3306
  initialDelaySeconds: 10
  periodSeconds: 5

Probes de Comando

Executam scripts dentro do container para validações mais complexas.

livenessProbe:
  exec:
    command:
    - /bin/sh
    - -c
    - "pgrep -f meu-servico || exit 1"
  initialDelaySeconds: 15
  periodSeconds: 30

3. Boas Práticas para Liveness Probes (Vitalidade)

Evitar Loops de Reinicialização

Configure timeouts realistas e implemente falhas graduais. Uma probe muito agressiva pode causar reinicializações desnecessárias.

livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30  # Tempo para inicialização
  periodSeconds: 15        # Intervalo entre checks
  timeoutSeconds: 5        # Timeout individual
  failureThreshold: 3      # Falhas antes de reiniciar

Checks Internos

A liveness probe deve verificar apenas o estado interno do serviço, sem depender de serviços externos.

# Bom: verifica apenas o serviço local
path: /health
# Retorna 200 se o serviço está rodando internamente

# Ruim: depende de banco de dados externo
path: /health?check=db  # Pode causar cascading failures

Estratégias de Backoff

Use initialDelaySeconds generoso para serviços com inicialização lenta. Considere startups probes para aplicações que demoram a ficar prontas.

4. Boas Práticas para Readiness Probes (Prontidão)

Verificação de Dependências

Diferente da liveness, a readiness probe pode e deve verificar dependências externas.

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5
  failureThreshold: 2

Endpoints Específicos

Mantenha endpoints separados: /health para liveness (check interno) e /ready para readiness (check completo).

# Endpoint /ready - Exemplo de implementação
def ready_endpoint():
    if db_connected() and queue_available() and cache_ok():
        return 200, {"status": "ready"}
    return 503, {"status": "not ready"}

Tratamento de Degradação

Em cenários de alta carga, a readiness probe pode falhar temporariamente para evitar sobrecarga.

5. Configuração de Parâmetros Cruciais

Ajuste Fino de Parâmetros

apiVersion: v1
kind: Pod
metadata:
  name: meu-servico
spec:
  containers:
  - name: app
    image: minha-app:1.0
    livenessProbe:
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 30
      periodSeconds: 15
      timeoutSeconds: 5
      successThreshold: 1
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 10
      periodSeconds: 5
      timeoutSeconds: 3
      successThreshold: 1
      failureThreshold: 2

Parâmetros Recomendados

Parâmetro Liveness Readiness
initialDelaySeconds 30-60 5-15
periodSeconds 15-30 5-10
timeoutSeconds 3-5 2-3
failureThreshold 3-5 2-3
successThreshold 1 1

6. Monitoramento e Logging de Probes

Métricas Essenciais

  • Latência de cada probe
  • Taxa de sucesso/falha
  • Número de reinicializações
  • Tempo médio de recuperação

Integração com Prometheus

# Métricas exportadas pelo kubelet
kubelet_http_requests_duration_seconds{path="/health"}
kubelet_http_requests_total{path="/ready", status="200"}

Exemplo de Alerta (Prometheus)

- alert: HighProbeFailureRate
  expr: |
    rate(kubelet_http_requests_total{status=~"5.."}[5m]) 
    / 
    rate(kubelet_http_requests_total[5m]) > 0.1
  for: 5m
  labels:
    severity: warning
  annotations:
    summary: "Taxa de falha de probes elevada"

7. Casos Especiais e Anti-Padrões

Anti-Padrão: Dependências Externas em Liveness

# ❌ Ruim - Liveness depende de banco externo
livenessProbe:
  httpGet:
    path: /health?check=db  # Se DB cair, container reinicia

# ✅ Bom - Liveness verifica apenas o processo
livenessProbe:
  httpGet:
    path: /health  # Retorna 200 se o servidor está rodando

Probes Agressivas vs. Lenientes

# ❌ Muito agressiva: causa reinicializações desnecessárias
periodSeconds: 1
failureThreshold: 1
timeoutSeconds: 1

# ❌ Muito leniente: atrasa detecção de falhas
periodSeconds: 60
failureThreshold: 10
timeoutSeconds: 30

Estratégias para Serviços Stateful

Para bancos de dados e serviços com estado, considere:
- Usar readiness probes mais conservadoras
- Implementar graceful shutdown
- Considerar StatefulSets com probes específicas

8. Testes e Validação de Probes em Cenários Reais

Simulação de Falhas

# Teste 1: Injeção de latência
# Simular lentidão no endpoint /health
kubectl exec pod -- /bin/sh -c "while true; do sleep 5; done"

# Teste 2: Queda de dependência
# Bloquear acesso ao banco de dados
kubectl exec pod -- iptables -A OUTPUT -p tcp --dport 5432 -j DROP

# Teste 3: Sobrecarga de CPU
kubectl exec pod -- stress --cpu 4 --timeout 60

Script de Teste Automatizado

#!/bin/bash
# Teste de probes em cenário real

echo "Testando liveness probe..."
for i in {1..10}; do
  response=$(kubectl exec pod -- curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/health)
  if [ "$response" != "200" ]; then
    echo "Falha na liveness probe (tentativa $i)"
  fi
  sleep 1
done

echo "Testando readiness probe..."
kubectl exec pod -- /bin/sh -c "kill -STOP 1"  # Simular pausa
sleep 5
kubectl describe pod | grep -A5 "Readiness"

Validação Contínua

Implemente testes regulares:
- Testes de carga com probes ativas
- Monitoramento de métricas de probes
- Revisão periódica dos thresholds
- Ajuste baseado em observabilidade

Lembre-se: probes são ferramentas de resiliência, não de monitoramento. Use-as para auto-recuperação, e métricas/alertas para observabilidade.

Referências