Health Checks
Qu'est-ce qu'un Health Check ?
Un Health Check est un mécanisme automatique qui vérifie régulièrement si vos serveurs fonctionnent correctement. Le Load Balancer utilise ces informations pour ne diriger le trafic que vers les serveurs sains.
┌─────────────────────────────────────────────────────────────┐
│ HEALTH CHECK - CONCEPT │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ ALB │ │
│ │ │ │
│ │ Toutes les 30 secondes, vérifie : │ │
│ │ "Est-ce que /health répond 200 OK ?" │ │
│ │ │ │
│ └─────────────────────┬───────────────────────────────┘ │
│ │ │
│ ┌─────────────┼─────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ Server │ │ Server │ │ Server │ │
│ │ 1 │ │ 2 │ │ 3 │ │
│ │ │ │ │ │ │ │
│ │ 200✓ │ │ 200✓ │ │ 503✗ │ │
│ │ HEALTHY│ │ HEALTHY│ │UNHEALTHY│ │
│ └────────┘ └────────┘ └────────┘ │
│ ↑ ↑ ✗ │
│ │ │ │ │
│ Reçoit Reçoit NE reçoit │
│ trafic trafic PAS de trafic │
│ │
└─────────────────────────────────────────────────────────────┘
Paramètres de Health Check
Configuration
┌─────────────────────────────────────────────────────────────┐
│ PARAMÈTRES HEALTH CHECK │
├─────────────────────────────────────────────────────────────┤
│ │
│ PARAMÈTRE │ DESCRIPTION │ DÉFAUT │
│ ───────────────────────┼──────────────────────┼──────────│
│ Protocol │ HTTP, HTTPS, TCP │ HTTP │
│ Port │ Port à vérifier │ traffic │
│ Path │ URL à tester │ / │
│ Interval │ Fréquence (sec) │ 30 │
│ Timeout │ Délai max (sec) │ 5 │
│ Healthy Threshold │ Succès pour healthy │ 3 │
│ Unhealthy Threshold │ Échecs pour unhealthy│ 2 │
│ Success Codes │ Codes HTTP OK │ 200 │
│ │
│ Exemple : │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Protocol: HTTP │ │
│ │ Port: 80 │ │
│ │ Path: /health │ │
│ │ Interval: 30s │ │
│ │ Timeout: 5s │ │
│ │ Healthy Threshold: 2 │ │
│ │ Unhealthy Threshold: 3 │ │
│ │ Success Codes: 200-299 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Cycle de Vie d'un Target
┌─────────────────────────────────────────────────────────────┐
│ ÉTATS D'UN TARGET │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ │
│ │ initial │ Target vient d'être enregistré │
│ └────┬─────┘ │
│ │ │
│ │ Health checks démarrent │
│ ▼ │
│ ┌──────────┐ N échecs consécutifs ┌──────────┐ │
│ │ healthy │ ────────────────────────────►│ unhealthy│ │
│ │ │ │ │ │
│ │ Reçoit │◄──────────────────────────── │ NE reçoit│ │
│ │ trafic │ N succès consécutifs │ PAS │ │
│ └──────────┘ └──────────┘ │
│ │
│ Autres états : │
│ • draining : Target en cours de désinscription │
│ • unused : Target non utilisé (pas de trafic vers lui) │
│ │
└─────────────────────────────────────────────────────────────┘
Endpoint /health
Implémentation Recommandée
┌─────────────────────────────────────────────────────────────┐
│ ENDPOINT /health │
├─────────────────────────────────────────────────────────────┤
│ │
│ SIMPLE (basique) │
│ ──────────────── │
│ GET /health │
│ Response: 200 OK │
│ Body: {"status": "ok"} │
│ │
│ AVANCÉ (vérifie les dépendances) │
│ ───────────────────────────────── │
│ GET /health │
│ Response: 200 OK (si tout va bien) │
│ Body: │
│ { │
│ "status": "healthy", │
│ "timestamp": "2024-01-15T10:30:00Z", │
│ "checks": { │
│ "database": "connected", │
│ "cache": "connected", │
│ "disk": "ok (75% free)" │
│ } │
│ } │
│ │
│ Response: 503 Service Unavailable (si problème) │
│ Body: │
│ { │
│ "status": "unhealthy", │
│ "checks": { │
│ "database": "connection failed", │
│ "cache": "connected", │
│ "disk": "ok" │
│ } │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
Exemples de Code
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
});
});
Bonnes Pratiques
Configuration Recommandée
┌─────────────────────────────────────────────────────────────┐
│ BONNES PRATIQUES HEALTH CHECK │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ À FAIRE │
│ ────────── │
│ • Utiliser un endpoint dédié (/health, /healthz) │
│ • Vérifier les dépendances critiques (DB, cache) │
│ • Retourner 200 seulement si vraiment healthy │
│ • Garder le health check léger et rapide │
│ • Documenter ce que le health check vérifie │
│ │
│ ❌ À ÉVITER │
│ ────────── │
│ • Utiliser la page d'accueil (/) comme health check │
│ • Health check qui fait des opérations lourdes │
│ • Toujours retourner 200 (même si problème) │
│ • Interval trop court (surcharge) │
│ • Timeout trop long (détection lente) │
│ │
│ CONFIGURATION RECOMMANDÉE : │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Interval: 30 secondes │ │
│ │ Timeout: 5 secondes │ │
│ │ Healthy Threshold: 2 │ │
│ │ Unhealthy Threshold: 3 │ │
│ │ Path: /health │ │
│ │ │ │
│ │ Temps pour détecter une panne : │ │
│ │ 3 échecs × 30s = 90 secondes max │ │
│ │ │ │
│ │ Temps pour revenir healthy : │ │
│ │ 2 succès × 30s = 60 secondes min │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Types de Health Checks
| Type | Ce qu'il vérifie | Quand l'utiliser |
|---|---|---|
| Shallow | L'app répond (200 OK) | Minimum vital |
| Deep | App + dépendances (DB, cache) | Production |
| Liveness | L'app est vivante | Kubernetes |
| Readiness | L'app peut recevoir du trafic | Kubernetes |
Configuration CLI
# Créer un Target Group avec health check personnalisé
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
# Modifier un health check existant
aws elbv2 modify-target-group \
--target-group-arn arn:aws:...:tg-web \
--health-check-path /api/health \
--health-check-interval-seconds 15
# Vérifier l'état des targets
aws elbv2 describe-target-health \
--target-group-arn arn:aws:...:tg-web
Dépannage Health Checks
┌─────────────────────────────────────────────────────────────┐
│ DÉPANNAGE HEALTH CHECK │
├─────────────────────────────────────────────────────────────┤
│ │
│ SYMPTÔME : Target reste "unhealthy" │
│ │
│ Checklist : │
│ │
│ ☐ 1. Security Group permet le trafic du LB ? │
│ → EC2 SG doit autoriser le port depuis sg-alb │
│ │
│ ☐ 2. L'application écoute sur le bon port ? │
│ → Vérifier avec netstat -tlnp sur l'instance │
│ │
│ ☐ 3. Le path /health existe et retourne 200 ? │
│ → Tester avec curl http://localhost/health │
│ │
│ ☐ 4. Le timeout n'est pas trop court ? │
│ → Si /health est lent, augmenter timeout │
│ │
│ ☐ 5. Les codes de succès sont corrects ? │
│ → Si l'app retourne 204, l'ajouter aux success │
│ │
│ Commandes utiles : │
│ # Sur l'instance EC2 │
│ curl -v http://localhost/health │
│ netstat -tlnp | grep :80 │
│ │
│ # Depuis AWS CLI │
│ aws elbv2 describe-target-health --target-group-arn ... │
│ │
└─────────────────────────────────────────────────────────────┘
Résumé
| Paramètre | Valeur Recommandée | Impact |
|---|---|---|
| Interval | 30s | Fréquence de vérification |
| Timeout | 5s | Délai max de réponse |
| Healthy Threshold | 2 | Retour en service rapide |
| Unhealthy Threshold | 3 | Évite faux positifs |
| Path | /health | Endpoint dédié |
Prochaine section : Lab Architecture HA