Health Checks
¿Qué es un Health Check?
Un Health Check es un mecanismo automático que verifica regularmente si sus servidores funcionan correctamente. El Load Balancer utiliza esta información para dirigir el tráfico solo a los servidores saludables.
┌─────────────────────────────────────────────────────────────┐
│ HEALTH CHECK - CONCEPTO │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ ALB │ │
│ │ │ │
│ │ Cada 30 segundos, verifica: │ │
│ │ "¿Responde /health con 200 OK?" │ │
│ │ │ │
│ └─────────────────────┬───────────────────────────────┘ │
│ │ │
│ ┌─────────────┼─────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ Server │ │ Server │ │ Server │ │
│ │ 1 │ │ 2 │ │ 3 │ │
│ │ │ │ │ │ │ │
│ │ 200✓ │ │ 200✓ │ │ 503✗ │ │
│ │ HEALTHY│ │ HEALTHY│ │UNHEALTHY│ │
│ └────────┘ └────────┘ └────────┘ │
│ ↑ ↑ ✗ │
│ │ │ │ │
│ Recibe Recibe NO recibe │
│ tráfico tráfico tráfico │
│ │
└─────────────────────────────────────────────────────────────┘
Parámetros de Health Check
Configuración
┌─────────────────────────────────────────────────────────────┐
│ PARÁMETROS HEALTH CHECK │
├─────────────────────────────────────────────────────────────┤
│ │
│ PARÁMETRO │ DESCRIPCIÓN │ POR DEFECTO│
│ ───────────────────────┼─────────────────────┼───────────│
│ Protocol │ HTTP, HTTPS, TCP │ HTTP │
│ Port │ Puerto a verificar │ traffic │
│ Path │ URL a probar │ / │
│ Interval │ Frecuencia (seg) │ 30 │
│ Timeout │ Tiempo máx (seg) │ 5 │
│ Healthy Threshold │ Éxitos para healthy │ 3 │
│ Unhealthy Threshold │ Fallos para unhealthy│ 2 │
│ Success Codes │ Códigos HTTP OK │ 200 │
│ │
│ Ejemplo: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Protocol: HTTP │ │
│ │ Port: 80 │ │
│ │ Path: /health │ │
│ │ Interval: 30s │ │
│ │ Timeout: 5s │ │
│ │ Healthy Threshold: 2 │ │
│ │ Unhealthy Threshold: 3 │ │
│ │ Success Codes: 200-299 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Ciclo de Vida de un Target
┌─────────────────────────────────────────────────────────────┐
│ ESTADOS DE UN TARGET │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ │
│ │ initial │ Target acaba de ser registrado │
│ └────┬─────┘ │
│ │ │
│ │ Inician los health checks │
│ ▼ │
│ ┌──────────┐ N fallos consecutivos ┌──────────┐ │
│ │ healthy │ ────────────────────────────►│ unhealthy│ │
│ │ │ │ │ │
│ │ Recibe │◄──────────────────────────── │ NO recibe│ │
│ │ tráfico │ N éxitos consecutivos │ │ │
│ └──────────┘ └──────────┘ │
│ │
│ Otros estados: │
│ • draining : Target en proceso de desregistro │
│ • unused : Target no usado (sin tráfico dirigido a él) │
│ │
└─────────────────────────────────────────────────────────────┘
Endpoint /health
Implementación Recomendada
┌─────────────────────────────────────────────────────────────┐
│ ENDPOINT /health │
├─────────────────────────────────────────────────────────────┤
│ │
│ SIMPLE (básico) │
│ ──────────────── │
│ GET /health │
│ Response: 200 OK │
│ Body: {"status": "ok"} │
│ │
│ AVANZADO (verifica dependencias) │
│ ───────────────────────────────── │
│ GET /health │
│ Response: 200 OK (si todo está bien) │
│ Body: │
│ { │
│ "status": "healthy", │
│ "timestamp": "2024-01-15T10:30:00Z", │
│ "checks": { │
│ "database": "connected", │
│ "cache": "connected", │
│ "disk": "ok (75% free)" │
│ } │
│ } │
│ │
│ Response: 503 Service Unavailable (si hay problema) │
│ Body: │
│ { │
│ "status": "unhealthy", │
│ "checks": { │
│ "database": "connection failed", │
│ "cache": "connected", │
│ "disk": "ok" │
│ } │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
Ejemplos 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
# Vérifier la base de données
try:
conn = psycopg2.connect(DATABASE_URL)
conn.close()
checks['database'] = 'connected'
except Exception as e:
checks['database'] = f'failed: {str(e)}'
is_healthy = False
# Vérifier le 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;
// Vérifier la 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
});
});
Buenas Prácticas
Configuración Recomendada
┌─────────────────────────────────────────────────────────────┐
│ BUENAS PRÁCTICAS HEALTH CHECK │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ QUÉ HACER │
│ ────────── │
│ • Usar un endpoint dedicado (/health, /healthz) │
│ • Verificar dependencias críticas (DB, cache) │
│ • Retornar 200 solo si realmente está healthy │
│ • Mantener el health check ligero y rápido │
│ • Documentar lo que verifica el health check │
│ │
│ ❌ QUÉ EVITAR │
│ ────────── │
│ • Usar la página principal (/) como health check │
│ • Health check que realiza operaciones pesadas │
│ • Retornar siempre 200 (aunque haya problema) │
│ • Intervalo demasiado corto (sobrecarga) │
│ • Timeout demasiado largo (detección lenta) │
│ │
│ CONFIGURACIÓN RECOMENDADA: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Interval: 30 segundos │ │
│ │ Timeout: 5 segundos │ │
│ │ Healthy Threshold: 2 │ │
│ │ Unhealthy Threshold: 3 │ │
│ │ Path: /health │ │
│ │ │ │
│ │ Tiempo para detectar una falla: │ │
│ │ 3 fallos × 30s = 90 segundos máx │ │
│ │ │ │
│ │ Tiempo para volver a healthy: │ │
│ │ 2 éxitos × 30s = 60 segundos mín │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Tipos de Health Checks
| Tipo | Qué verifica | Cuándo usarlo |
|---|---|---|
| Shallow | La app responde (200 OK) | Mínimo vital |
| Deep | App + dependencias (DB, cache) | Producción |
| Liveness | La app está viva | Kubernetes |
| Readiness | La app puede recibir tráfico | Kubernetes |
Configuración CLI
# Crear un Target Group con 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 un 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 el estado de los targets
aws elbv2 describe-target-health \
--target-group-arn arn:aws:...:tg-web
Resolución de Problemas Health Checks
┌─────────────────────────────────────────────────────────────┐
│ RESOLUCIÓN DE PROBLEMAS HEALTH CHECK │
├─────────────────────────────────────────────────────────────┤
│ │
│ SÍNTOMA: Target permanece "unhealthy" │
│ │
│ Checklist: │
│ │
│ ☐ 1. ¿El Security Group permite tráfico del LB? │
│ → El SG de EC2 debe autorizar el puerto desde sg-alb│
│ │
│ ☐ 2. ¿La aplicación escucha en el puerto correcto? │
│ → Verificar con netstat -tlnp en la instancia │
│ │
│ ☐ 3. ¿El path /health existe y retorna 200? │
│ → Probar con curl http://localhost/health │
│ │
│ ☐ 4. ¿El timeout no es demasiado corto? │
│ → Si /health es lento, aumentar el timeout │
│ │
│ ☐ 5. ¿Los códigos de éxito son correctos? │
│ → Si la app retorna 204, añadirlo a los success │
│ │
│ Comandos útiles: │
│ # En la instancia EC2 │
│ curl -v http://localhost/health │
│ netstat -tlnp | grep :80 │
│ │
│ # Desde AWS CLI │
│ aws elbv2 describe-target-health --target-group-arn ... │
│ │
└─────────────────────────────────────────────────────────────┘
Resumen
| Parámetro | Valor Recomendado | Impacto |
|---|---|---|
| Interval | 30s | Frecuencia de verificación |
| Timeout | 5s | Tiempo máx de respuesta |
| Healthy Threshold | 2 | Retorno rápido a servicio |
| Unhealthy Threshold | 3 | Evita falsos positivos |
| Path | /health | Endpoint dedicado |
Próxima sección: Lab Arquitectura HA