Pular para o conteúdo principal

Health Checks

O que é um Health Check?​

Um Health Check é um mecanismo automático que verifica regularmente se seus servidores estão funcionando corretamente. O Load Balancer utiliza essas informações para direcionar o tráfego apenas para os servidores saudáveis.

┌─────────────────────────────────────────────────────────────┐
│ HEALTH CHECK - CONCEITO │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ ALB │ │
│ │ │ │
│ │ A cada 30 segundos, verifica: │ │
│ │ "O /health responde 200 OK?" │ │
│ │ │ │
│ └─────────────────────┬───────────────────────────────┘ │
│ │ │
│ ┌─────────────┼─────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ Server │ │ Server │ │ Server │ │
│ │ 1 │ │ 2 │ │ 3 │ │
│ │ │ │ │ │ │ │
│ │ 200✓ │ │ 200✓ │ │ 503✗ │ │
│ │ HEALTHY│ │ HEALTHY│ │UNHEALTHY│ │
│ └────────┘ └────────┘ └────────┘ │
│ ↑ ↑ ✗ │
│ │ │ │ │
│ Recebe Recebe NÃO recebe │
│ tráfego tráfego tráfego │
│ │
└─────────────────────────────────────────────────────────────┘

Parâmetros de Health Check​

Configuração​

┌─────────────────────────────────────────────────────────────┐
│ PARÂMETROS HEALTH CHECK │
├─────────────────────────────────────────────────────────────┤
│ │
│ PARÂMETRO │ DESCRIÇÃO │ PADRÃO │
│ ───────────────────────┼─────────────────────┼──────────│
│ Protocol │ HTTP, HTTPS, TCP │ HTTP │
│ Port │ Porta a verificar │ traffic │
│ Path │ URL a testar │ / │
│ Interval │ Frequência (seg) │ 30 │
│ Timeout │ Tempo máx (seg) │ 5 │
│ Healthy Threshold │ Sucessos para healthy│ 3 │
│ Unhealthy Threshold │ Falhas para unhealthy│ 2 │
│ Success Codes │ Códigos HTTP OK │ 200 │
│ │
│ Exemplo: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Protocol: HTTP │ │
│ │ Port: 80 │ │
│ │ Path: /health │ │
│ │ Interval: 30s │ │
│ │ Timeout: 5s │ │
│ │ Healthy Threshold: 2 │ │
│ │ Unhealthy Threshold: 3 │ │
│ │ Success Codes: 200-299 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

Ciclo de Vida de um Target​

┌─────────────────────────────────────────────────────────────┐
│ ESTADOS DE UM TARGET │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ │
│ │ initial │ Target acabou de ser registrado │
│ └────┬─────┘ │
│ │ │
│ │ Health checks iniciam │
│ ▼ │
│ ┌──────────┐ N falhas consecutivas ┌──────────┐ │
│ │ healthy │ ────────────────────────────►│ unhealthy│ │
│ │ │ │ │ │
│ │ Recebe │◄──────────────────────────── │ NÃO │ │
│ │ tráfego │ N sucessos consecutivos │ recebe │ │
│ └──────────┘ └──────────┘ │
│ │
│ Outros estados: │
│ • draining : Target em processo de remoção │
│ • unused : Target não utilizado (sem tráfego para ele) │
│ │
└─────────────────────────────────────────────────────────────┘

Endpoint /health​

Implementação Recomendada​

┌─────────────────────────────────────────────────────────────┐
│ ENDPOINT /health │
├─────────────────────────────────────────────────────────────┤
│ │
│ SIMPLES (básico) │
│ ──────────────── │
│ GET /health │
│ Response: 200 OK │
│ Body: {"status": "ok"} │
│ │
│ AVANÇADO (verifica dependências) │
│ ───────────────────────────────── │
│ GET /health │
│ Response: 200 OK (se tudo ok) │
│ Body: │
│ { │
│ "status": "healthy", │
│ "timestamp": "2024-01-15T10:30:00Z", │
│ "checks": { │
│ "database": "connected", │
│ "cache": "connected", │
│ "disk": "ok (75% free)" │
│ } │
│ } │
│ │
│ Response: 503 Service Unavailable (se problema) │
│ Body: │
│ { │
│ "status": "unhealthy", │
│ "checks": { │
│ "database": "connection failed", │
│ "cache": "connected", │
│ "disk": "ok" │
│ } │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘

Exemplos de Código​

Python (Flask):

from flask import Flask, jsonify
import psycopg2

app = Flask(__name__)

@app.route('/health')
def health_check():
checks = {}
is_healthy = True

# Verificar o banco de dados
try:
conn = psycopg2.connect(DATABASE_URL)
conn.close()
checks['database'] = 'connected'
except Exception as e:
checks['database'] = f'failed: {str(e)}'
is_healthy = False

# Verificar o cache Redis
try:
redis_client.ping()
checks['redis'] = 'connected'
except:
checks['redis'] = 'failed'
is_healthy = False

status_code = 200 if is_healthy else 503
return jsonify({
'status': 'healthy' if is_healthy else 'unhealthy',
'checks': checks
}), status_code

Node.js (Express):

app.get('/health', async (req, res) => {
const checks = {};
let isHealthy = true;

// Verificar a DB
try {
await db.query('SELECT 1');
checks.database = 'connected';
} catch (e) {
checks.database = 'failed';
isHealthy = false;
}

const statusCode = isHealthy ? 200 : 503;
res.status(statusCode).json({
status: isHealthy ? 'healthy' : 'unhealthy',
checks
});
});

Boas Práticas​

Configuração Recomendada​

┌─────────────────────────────────────────────────────────────┐
│ BOAS PRÁTICAS HEALTH CHECK │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ FAÇA │
│ ────────── │
│ • Use um endpoint dedicado (/health, /healthz) │
│ • Verifique dependências críticas (DB, cache) │
│ • Retorne 200 apenas se realmente saudável │
│ • Mantenha o health check leve e rápido │
│ • Documente o que o health check verifica │
│ │
│ ❌ EVITE │
│ ────────── │
│ • Usar a página inicial (/) como health check │
│ • Health check que faz operações pesadas │
│ • Sempre retornar 200 (mesmo com problema) │
│ • Intervalo muito curto (sobrecarga) │
│ • Timeout muito longo (detecção lenta) │
│ │
│ CONFIGURAÇÃO RECOMENDADA: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Interval: 30 segundos │ │
│ │ Timeout: 5 segundos │ │
│ │ Healthy Threshold: 2 │ │
│ │ Unhealthy Threshold: 3 │ │
│ │ Path: /health │ │
│ │ │ │
│ │ Tempo para detectar uma falha: │ │
│ │ 3 falhas × 30s = 90 segundos máx │ │
│ │ │ │
│ │ Tempo para voltar a healthy: │ │
│ │ 2 sucessos × 30s = 60 segundos mín │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

Tipos de Health Checks​

TipoO que verificaQuando usar
ShallowApp responde (200 OK)Mínimo necessário
DeepApp + dependências (DB, cache)Produção
LivenessApp está vivaKubernetes
ReadinessApp pode receber tráfegoKubernetes

Configuração CLI​

# Criar um Target Group com health check personalizado
aws elbv2 create-target-group \
--name tg-web-healthy \
--protocol HTTP \
--port 80 \
--vpc-id vpc-xxx \
--health-check-protocol HTTP \
--health-check-port 80 \
--health-check-path /health \
--health-check-interval-seconds 30 \
--health-check-timeout-seconds 5 \
--healthy-threshold-count 2 \
--unhealthy-threshold-count 3 \
--matcher HttpCode=200-299

# Modificar um health check existente
aws elbv2 modify-target-group \
--target-group-arn arn:aws:...:tg-web \
--health-check-path /api/health \
--health-check-interval-seconds 15

# Verificar o estado dos targets
aws elbv2 describe-target-health \
--target-group-arn arn:aws:...:tg-web

Troubleshooting Health Checks​

┌─────────────────────────────────────────────────────────────┐
│ TROUBLESHOOTING HEALTH CHECK │
├─────────────────────────────────────────────────────────────┤
│ │
│ SINTOMA: Target permanece "unhealthy" │
│ │
│ Checklist: │
│ │
│ ☐ 1. Security Group permite o tráfego do LB? │
│ → SG do EC2 deve autorizar a porta a partir do sg-alb│
│ │
│ ☐ 2. O aplicativo está ouvindo na porta correta? │
│ → Verifique com netstat -tlnp na instância │
│ │
│ ☐ 3. O path /health existe e retorna 200? │
│ → Teste com curl http://localhost/health │
│ │
│ ☐ 4. O timeout não está muito curto? │
│ → Se /health for lento, aumente o timeout │
│ │
│ ☐ 5. Os códigos de sucesso estão corretos? │
│ → Se o app retorna 204, adicione aos success │
│ │
│ Comandos úteis: │
│ # Na instância EC2 │
│ curl -v http://localhost/health │
│ netstat -tlnp | grep :80 │
│ │
│ # Via AWS CLI │
│ aws elbv2 describe-target-health --target-group-arn ... │
│ │
└─────────────────────────────────────────────────────────────┘

Resumo​

ParâmetroValor RecomendadoImpacto
Interval30sFrequência de verificação
Timeout5sTempo máx de resposta
Healthy Threshold2Retorno rápido ao serviço
Unhealthy Threshold3Evita falsos positivos
Path/healthEndpoint dedicado

Próxima seção: Lab Architecture HA