Sondes et cycle de vie - ii02735/learn-k8 GitHub Wiki
Les sondes et le cycle de vie d'un Pod
Un Pod naît, démarre, travaille, puis meurt — et il est presque toujours remplacé plutôt que réparé. Comprendre son cycle de vie et savoir sonder ses containers, c'est savoir quand Kubernetes considère une application comme prête, et comment il réagit quand elle ne l'est plus.
Le cycle de vie d'un Pod
Les phases (status.phase)
À tout moment, un Pod se trouve dans une phase :
Pending: le Pod est accepté par l'API, mais les containers ne sont pas encore tous démarrés (planification en cours, image en cours de téléchargement, volume pas encore prêt…).Running: le Pod est planifié sur un noeud et au moins un container tourne (ou est en cours de démarrage).Succeeded: tous les containers se sont terminés avec succès — typique d'un Job mené à bien.Failed: au moins un container s'est terminé en erreur.Unknown: l'état ne peut pas être déterminé (problème de communication avec le noeud).
Un Pod est Running longtemps avant d'être Ready : ces deux états ne disent pas la même chose.
Les conditions (status.conditions)
À côté des phases, chaque Pod expose des conditions — plus fines, elles décrivent sa progression :
PodScheduled: le Pod a été affecté à un noeud (le scheduler a fait son travail).Initialized: tous les init containers ont réussi.ContainersReady: tous les containers sont prêts (leursreadinessProbepassent).Ready: le Pod peut servir du trafic — c'est la condition qui compte pour les Services.
[!NOTE] Un Pod n'est
Readyque lorsque tous ses containers le sont. Un seul container dont lareadinessProbeéchoue suffit à retirer le Pod des endpoints d'un Service.
Les états d'un container (status.containerStatuses)
Chaque container possède son propre état :
Waiting: le container attend (téléchargement de l'image, attente d'un volume…). Le champreasonest parlant :ImagePullBackOff,CrashLoopBackOff…Running: le container s'exécute.Terminated: le container s'est arrêté, avec unexitCodeet unereason(Completed,Error,OOMKilled…).
C'est là que se cachent la plupart des diagnostics : un Pod Running dont un container est en CrashLoopBackOff ne sert aucun trafic.
La politique de redémarrage (restartPolicy)
Elle définit si et quand un container est relancé :
Always(défaut) : le container est toujours redémarré. C'est le comportement attendu pour un service.OnFailure: redémarré uniquement en cas d'échec — adapté aux Jobs.Never: jamais redémarré.
:warning: Le restartPolicy s'applique au niveau du Pod, mais concerne le redémarrage des containers : le Pod lui-même n'est pas ressuscité, il reste sur le même noeud.
Les containers d'initialisation (init containers)
Un init container s'exécute avant les containers applicatifs. Il doit se terminer avec succès pour que le Pod poursuive son démarrage.
- Ils tournent séquentiellement, dans l'ordre de déclaration.
- Si l'un échoue, le Pod le relance (selon le
restartPolicy) et ne passe jamais à l'étape suivante. - Ils ont leurs propres images et peuvent monter les mêmes volumes que les containers applicatifs.
Ils servent à préparer l'environnement : attendre qu'une dépendance soit disponible, télécharger des données, appliquer des permissions, initialiser un volume…
[!IMPORTANT] Un init container n'est pas un sidecar : il finit avant le démarrage de l'application, alors qu'un sidecar tourne en même temps que le container principal.
Les sondes (probes)
Les sondes sont des vérifications périodiques de l'état d'un container. Petite précision : elles se définissent au niveau de chaque container (spec.containers[].livenessProbe, etc.), et non au niveau du Pod. C'est le kubelet du noeud qui les exécute.
Trois sondes répondent à trois questions différentes :
livenessProbe(vitalité) : « le container est-il encore vivant ? ». Après plusieurs échecs, le kubelet redémarre le container. À réserver aux blocages (deadlock) qu'un redémarrage peut résoudre.readinessProbe(disponibilité) : « le container est-il prêt à recevoir du trafic ? ». En cas d'échec, le Pod est retiré des endpoints des Services mais n'est pas redémarré. Pratique pendant un démarrage lent ou une surcharge temporaire.startupProbe(démarrage) : pour les applications lentes à démarrer. Tant qu'elle n'a pas réussi, les sondeslivenessetreadinesssont désactivées, ce qui évite un redémarrage prématuré.
Comment sonder un container ?
httpGet: une requête HTTPGETsur unpathet unport; un code 200 à 399 est un succès.tcpSocket: tente d'ouvrir une connexion TCP sur un port.exec: exécute une commande dans le container ; un code de sortie 0 est un succès.grpc: appelle un endpoint gRPC de health checking.
Les paramètres de réglage
initialDelaySeconds: délai avant la première sonde (défaut :0).periodSeconds: intervalle entre deux sondes (défaut :10).timeoutSeconds: délai maximal d'une sonde (défaut :1).successThreshold: nombre de succès consécutifs pour repasser àReady(défaut :1; forcé à1pourlivenessetstartup).failureThreshold: nombre d'échecs consécutifs avant de considérer la sonde en échec (défaut :3).
Un manifeste complet
containers:
- name: app
image: nginx:1.27
ports:
- name: http
containerPort: 80
startupProbe: # le temps du démarrage lent
httpGet:
path: /
port: http
failureThreshold: 30
periodSeconds: 5
livenessProbe: # « es-tu encore vivant ? »
httpGet:
path: /healthz
port: http
periodSeconds: 10
readinessProbe: # « peux-tu recevoir du trafic ? »
httpGet:
path: /ready
port: http
periodSeconds: 5
failureThreshold: 2
Les bonnes pratiques
- Toujours définir une
readinessProbepour une application exposée par un Service. - Ne jamais mettre une dépendance externe (base de données, API tierce) dans une
livenessProbe: une panne externe ferait redémarrer tous les Pods en boucle. Utiliser unereadinessProbeà la place. - Utiliser une
startupProbepour les applications lentes, afin de réserver lalivenessaux containers réellement bloqués. - Éviter les seuils trop agressifs (
timeoutSecondstrop court,failureThresholdtrop bas) qui provoquent des redémarrages inutiles.
:warning: Une livenessProbe mal réglée peut provoquer une boucle de redémarrage (CrashLoopBackOff).
Le démarrage et l'arrêt d'un container
Les hooks de cycle de vie
Deux hooks permettent d'exécuter du code à des moments précis :
postStart: lancé juste après la création du container. Attention, il n'est pas garanti de s'exécuter avant l'ENTRYPOINT— il ne faut pas en dépendre pour initialiser l'application.preStop: appelé avant l'arrêt du container, pour un arrêt propre (vider les files, fermer les connexions, signaler à un load balancer…). Le kubelet attend la fin du hook.
L'arrêt gracieux
Quand un Pod est supprimé, Kubernetes orchestre un arrêt ordonné :
- Le Pod est retiré des endpoints des Services (il ne reçoit plus de nouveau trafic).
- Le hook
preStopest exécuté, s'il existe. - Le kubelet envoie
SIGTERMau processus principal (PID 1). - L'application dispose de
terminationGracePeriodSeconds(défaut : 30 s) pour se terminer proprement. - Passé ce délai, le kubelet envoie
SIGKILL: le container est tué de force.
[!NOTE] Une application bien élevée doit intercepter
SIGTERMet finir les requêtes en cours avant de s'arrêter. UnpreStopqui attend quelques secondes est aussi un moyen simple de laisser le temps au load balancer de retirer le Pod.
Les commandes principales
- Suivre l'évolution des Pods en direct :
kubectl get pods -w - Voir les conditions, les états et les événements d'un Pod :
kubectl describe pod app - Consulter les logs du container précédent (celui qui a planté) :
kubectl logs app --previous - Ouvrir un shell dans un container :
kubectl exec -it app -- sh - Simuler une suppression et observer l'arrêt gracieux :
kubectl delete pod app - Lire la phase courante :
kubectl get pod app -o jsonpath='{.status.phase}' - Filtrer les événements d'un Pod :
kubectl get events --field-selector involvedObject.name=app
Pour aller plus loin
- Les fondations sur les Pods (réseau, volumes, multi-container) : Les pods.
- Le redémarrage automatique des Pods et leur remplacement : Les ReplicaSets.
- L'exposition du trafic vers les Pods seulement lorsqu'ils sont
Ready: Les Services.