Health checks¶
Signaler l'état de sante des services à l'orchestrateur — liveness, readiness, startup et stratégies de déploiement.
Trois types, trois rôles¶
Les health checks permettent à l'orchestrateur (Kubernetes, load balancer) de savoir si un service peut recevoir du trafic. Il existe trois types avec des rôles très différents — les confondre crée des comportements contre-intuitifs et dangereux.
| Type | Question posee | Exemple de check | Action si échec |
|---|---|---|---|
| Liveness | Le processus est-il vivant ? | Répondre 200 sur /healthz | Redémarrer le conteneur |
| Readiness | Le service peut-il traiter des requêtes ? | Vérifier DB + cache accessibles | Retirer du load balancer |
| Startup | Le service a-t-il fini de démarrer ? | Migrations terminees, warm-up effectue | Attendre avant d'activer liveness/readiness |
Liveness¶
Détecté un processus bloque (deadlock, OOM, boucle infinie). Le check doit être minimal — une simple réponse HTTP 200 sur /healthz. Kubernetes redemarrera le pod si ce check échoué repetitivement.
Le liveness ne doit PAS vérifier les dépendances externes. Si la base de données est lente, le processus est vivant — il ne faut pas le redémarrer. Le redémarrage creerait une boucle : le pod redemarrerait, tenterait de se reconnecter a une DB déjà saturee, echouerait au liveness, serait redémarrer à nouveau.
Readiness¶
Détecté un service temporairement incapable de traiter des requêtes. La DB est en maintenance, le cache est en cours de warm-up, une migration est en cours. Le pod reste vivant mais sort de la rotation du load balancer.
Le readiness peut vérifier les dépendances critiques. Il répond à la question : "si je recois une requête maintenant, est-ce que je suis capable de la traiter correctement ?"
Startup¶
Désactivé liveness et readiness pendant le démarrage pour éviter de tuer un pod qui n'a pas encore eu le temps de s'initialiser. Utile pour les services avec des démarrages longs :
- Chargement de modèles ML (parfois plusieurs minutes)
- Migrations de schéma de base de données
- Precalcul de cache ou warm-up d'index
- Téléchargement de fichiers de configuration volumineux
Deep vs shallow¶
La profondeur du health check détermine ce qu'il vérifié et les risques associes.
Shallow — le processus répond. Rapide (< 5ms), peu coûteux. Utilisé pour le liveness. Ne vérifié que l'état interne du process.
Deep — les dépendances critiques sont aussi accessibles. Vérifié que la DB répond en moins de X ms, que le cache est joignable, que les APIs externes clés sont disponibles. Réservé au readiness.
// GET /ready — deep
{
"status": "ok",
"checks": {
"database": {"status": "ok", "latency_ms": 12},
"redis": {"status": "ok", "latency_ms": 3},
"payment-api": {"status": "ok", "latency_ms": 45}
}
}
Tip
Les liveness checks doivent être shallow. Un check deep qui inclut la DB fera redémarrer votre service quand la DB est lente, aggravant la situation. La distinction est simple : Liveness = le processus respire. Readiness = le processus est prêt à travailler.
Checklist des dépendances a inclure dans le readiness¶
| Dépendance | Inclure ? | Justification |
|---|---|---|
| Base de données | Oui | Sans DB, le service ne peut pas traiter les requêtes |
| Cache (Redis) | Depends | Oui si critique pour la performance, non si fallback local |
| API externe critique | Oui | Si le service ne peut pas fonctionner sans |
| API externe secondaire | Non | Le service peut fonctionner en mode dégradé |
| File system local | Rarement | Sauf si le service écrit des fichiers critiques |
| Message broker | Oui | Si le service est un consumer Kafka/RabbitMQ |
Configuration Kubernetes¶
apiVersion: v1
kind: Pod
spec:
containers:
- name: api
image: api:1.2.0
ports:
- containerPort: 8080
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 2
# Le pod a 60s pour demarrer (30 * 2s)
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 0
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 2
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 3
successThreshold: 1
timeoutSeconds: 3
Parametres critiques¶
| Parametre | Liveness recommande | Readiness recommande | Explication |
|---|---|---|---|
| periodSeconds | 10s | 5s | Readiness doit reagir plus vite |
| failureThreshold | 3 | 3 | 3 échecs consecutifs avant action |
| timeoutSeconds | 2s | 3s | Readiness peut tolérer un peu plus (deep check) |
| successThreshold | 1 | 1 | 1 succès suffit pour revenir en rotation |
Graceful shutdown¶
Le health check ne suffit pas si le service ne sait pas s'arrêter proprement. Quand Kubernetes envoie un signal SIGTERM, le service doit :
- Cesser d'accepter de nouvelles requêtes — le readiness doit retourner un échec immédiatement
- Terminer les requêtes en cours — laisser les requêtes actives se terminer normalement
- Fermer les connexions proprement — libérer les connexions DB, fermer les consumers Kafka, flusher les buffers
- S'arrêter — quitter le processus avec un code 0
sequenceDiagram
participant K as Kubernetes
participant LB as Load Balancer
participant P as Pod
participant R as Requetes en cours
K->>P: SIGTERM
P->>P: readiness = false
K->>LB: Retirer du endpoint
Note over LB: Nouveau trafic\nvers autres pods
P->>R: Terminer requetes en cours
R-->>P: Toutes terminees
P->>P: Fermer connexions
P->>K: Exit 0
Note over K: Si timeout (30s par defaut)\nSIGKILL force Le terminationGracePeriodSeconds (défaut 30s) est le délai maximal entre SIGTERM et SIGKILL. Si le service n'a pas termine en 30 secondes, Kubernetes le tue de force. Ajuster cette valeur pour les services avec des traitements longs.
Readiness gates et déploiement¶
Readiness gates¶
Les readiness gates sont des conditions supplémentaires que Kubernetes vérifié avant de considérer un pod comme "ready". Elles sont utiles quand le readiness probe standard ne suffit pas :
- Le service doit être enregistre dans un service mesh avant de recevoir du trafic
- Un warm-up externe est nécessaire (precharger un CDN, invalider un cache)
- Une vérification humaine est requise (pour les déploiements critiques)
apiVersion: v1
kind: Pod
spec:
readinessGates:
- conditionType: "custom.io/mesh-registered"
- conditionType: "custom.io/cache-warm"
Le pod ne recevra du trafic que quand toutes les conditions de readiness (probes + gates) sont satisfaites.
Stratégies de déploiement et health checks¶
Les health checks sont le pilier de toute stratégie de déploiement progressive. Sans eux, l'orchestrateur n'a aucun moyen de savoir si la nouvelle version fonctionne.
Rolling update¶
Déployer les nouveaux pods un par un. Chaque nouveau pod doit passer son readiness probe avant que le suivant soit déployé et qu'un ancien pod soit arrêté.
graph LR
subgraph Etape1["Etape 1"]
V1a["v1"]
V1b["v1"]
V1c["v1"]
end
subgraph Etape2["Etape 2"]
V1d["v1"]
V1e["v1"]
V2a["v2 — readiness OK"]
end
subgraph Etape3["Etape 3"]
V1f["v1"]
V2b["v2"]
V2c["v2"]
end
Etape1 -->|deploy| Etape2
Etape2 -->|readiness OK| Etape3
style V2a fill:#2a9d8f,color:#fff
style V2b fill:#2a9d8f,color:#fff
style V2c fill:#2a9d8f,color:#fff Configuration Kubernetes :
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 1 pod supplementaire pendant le deploiement
maxUnavailable: 0 # 0 pod indisponible — zero downtime
maxUnavailable: 0 garantit qu'aucun ancien pod n'est retire tant que le nouveau n'est pas ready. C'est le reglage le plus conservateur — plus lent mais sans perte de capacité.
Blue-green¶
Deux environnements complets existent en parallèle. Le trafic est bascule integralement de l'ancien (blue) vers le nouveau (green) quand tous les health checks du green sont valides.
| Aspect | Rolling update | Blue-green |
|---|---|---|
| Rollback | Lent (re-déployer) | Instantané (rebascule) |
| Ressources | N + 1 pods | 2N pods |
| Risque | Versions mixtes | Tout ou rien |
| Health check rôle | Par pod progressif | Validation globale avant switch |
Canary¶
Envoyer un pourcentage faible du trafic (1-5%) vers la nouvelle version. Monitorer les métriques (latence, erreurs, SLI). Si les health checks et les métriques sont bons, augmenter progressivement le pourcentage.
graph LR
LB["Load Balancer"]
LB -->|95%| V1["v1 — 3 pods"]
LB -->|5%| V2["v2 — 1 pod canary"]
V2 -->|metriques| Mon["Monitoring"]
Mon -->|OK| Inc["Augmenter %"]
Mon -->|KO| Roll["Rollback"]
style V2 fill:#e9c46a,color:#000 Le canary est la stratégie la plus sure pour les services a fort trafic. L'impact d'un bug est limite a 5% des utilisateurs, et le rollback est immédiat.
Matrice de choix¶
| Critère | Rolling | Blue-green | Canary |
|---|---|---|---|
| Vitesse de rollback | Lente | Instantanée | Instantanée |
| Coût en ressources | Faible | Double | Faible |
| Détection de régression | Tardive | Pre-switch | Progressive |
| Complexité | Faible | Moyenne | Élevée |
| Convient pour | Standard | Critique | Fort trafic |
Warning
Un déploiement canary sans health checks et sans métriques automatisees est un déploiement à l'aveugle avec un nom elegant. Le canary n'a de valeur que si on compare activement les SLI de la version canary avec ceux de la version stable. Sans cette comparaison, on ne détecté rien.
Chapitre suivant : SLI, SLO, SLA — mesurer et formaliser la fiabilité.