Introduction
Les pods Kubernetes sont les plus petites unités déployables, mais leur cycle de vie est truffé de pièges : images qui ne se téléchargent jamais, sondes qui échouent, nœuds qui ne peuvent pas planifier et conteneurs qui plantent au démarrage. Lorsqu'un pod est bloqué, savoir dans quel état il se trouve et pourquoi est le chemin le plus rapide vers la récupération.
Cet article est un guide de terrain destiné aux développeurs, ingénieurs DevOps et SRE qui doivent passer d'un symptôme signalé à un correctif vérifié sans deviner. Il passe en revue les états de défaillance courants, les commandes exactes pour les inspecter, les journaux et événements qui révèlent la cause racine, et les plus petits changements sûrs qui rétablissent le service.
Nous couvrirons :
- Comment inventorier votre cluster et l'état des pods avant de faire des changements
- Le cycle de vie des pods, de Pending à Running jusqu'à Terminated
- Cinq modes de défaillance courants : Pending, ImagePullBackOff, CrashLoopBackOff, échecs de sondes et OOMKilled
- Comment utiliser
kubectl describe,kubectl logs, les événements et les métriques - Procédures de récupération avec exemples et sorties attendues
- Une liste de contrôle opérationnelle pour éviter d'aggraver les choses
Tous les exemples supposent Kubernetes 1.24 ou ultérieur et un contexte kubectl fonctionnel. Remplacez les noms de ressources selon vos besoins.
Inventaire de version et d'environnement
Avant de modifier quoi que ce soit, capturez l'état actuel. L'objectif est d'observer sans muter. Considérez cela comme une passe de diagnostic en lecture seule.
1. Confirmer la version du cluster et la disponibilité de l'API
kubectl version --short
# Client Version: v1.27.3
# Server Version: v1.27.1
Si le client et le serveur diffèrent de plus d'une version mineure, mettez à niveau le client pour qu'il corresponde avant de déboguer ; certains drapeaux kubectl peuvent ne pas exister sur les serveurs plus anciens.
2. Obtenir une vue d'ensemble des pods
kubectl get pods -n default -o wide
Exemple de sortie :
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-6d4cf56db6-8z7wv 0/1 ImagePullBackOff 1 5m <none> minikube <none> <none>
api-85f9b8c7f-4k9s2 1/1 Running 0 2d 10.244.0.5 worker-01 <none> <none>
Regardez les colonnes STATUS, RESTARTS et NODE. Un nombre élevé de redémarrages suggère une boucle de crash ; une IP manquante signifie souvent que le pod n'est pas planifié.
3. Vérifier les événements au niveau du cluster
kubectl get events -n default --sort-by=.lastTimestamp
Les événements sont éphémères (1 heure par défaut). Si le pod échoue depuis longtemps, vous devrez peut-être vous fier à describe ou aux journaux pour l'historique plus ancien.
4. Inspecter les conditions des nœuds
kubectl get nodes -o custom-columns='NAME:.metadata.name,READY:.status.conditions[?(@.type=="Ready")].status,MEMORY_PRESSURE:.status.conditions[?(@.type=="MemoryPressure")].status,DISK_PRESSURE:.status.conditions[?(@.type=="DiskPressure")].status'
Si un nœud est NotReady, les pods qui s'y trouvent resteront Pending ou seront évincés.
5. Vérifier le contrôleur du pod
kubectl get deploy,rs,sts,ds -n default
Si un pod est géré par un Deployment, le nom du ReplicaSet dans kubectl describe pod indique quel contrôleur l'a créé. Cela importe car vous devrez peut-être revenir en arrière sur un Deployment plutôt que de modifier directement un pod.
Liste de contrôle avant intervention :
- Version du cluster confirmée
- Liste des pods capturée
- Événements examinés
- Santé des nœuds vérifiée
- Contrôleur identifié
Ce n'est qu'après cet inventaire que vous devez passer au diagnostic et au changement.
Chemin de configuration sûr
Traitez chaque changement comme un incident de production potentiel. Utilisez d'abord un cluster local ou de staging, puis promouvez.
1. Reproduire localement
Utilisez un outil comme kind ou minikube pour créer un cluster jetable :
kind create cluster --name debug
Appliquez le même manifeste (après avoir supprimé ou remplacé les secrets) :
kubectl apply -f pod.yaml
Si l'échec se reproduit, vous pouvez expérimenter en toute sécurité. Sinon, le problème peut être environnemental (capacité du nœud, politique réseau, accès au registre).
2. Utiliser dry-run et diff
Prévisualisez toujours les changements :
kubectl apply -f pod.yaml --dry-run=client
Pour les modifications d'objets existants :
kubectl diff -f pod.yaml
kubectl diff montre ce qui changerait sans l'appliquer.
3. Changer une chose à la fois
Si vous mettez à jour à la fois une étiquette d'image et une limite de ressources simultanément, vous ne saurez pas lequel a résolu le problème. Appliquez un patch minimal :
kubectl set image deployment/nginx nginx=nginx:1.25.1
Puis attendez et observez avant le prochain changement.
4. Protéger les secrets
Ne mettez jamais de secrets dans des manifestes que vous validez. Utilisez des espaces réservés :
env:
- name: DB_PASSWORD
value: REPLACE_ME
Injectez ensuite la valeur réelle via un Secret :
kubectl create secret generic db-secret --from-literal=password='actual-password'
Référencez-le dans le pod :
valueFrom:
secretKeyRef:
name: db-secret
key: password
5. Vérifier après chaque changement
Utilisez kubectl rollout status pour les Deployments :
kubectl rollout status deployment/nginx
Sortie attendue lorsqu'il est sain :
Waiting for deployment "nginx" rollout to finish: 0 of 1 updated replicas are available...
deployment "nginx" successfully rolled out
S'il expire, revenez en arrière :
kubectl rollout undo deployment/nginx
6. Tester le trafic localement avant d'exposer
Utilisez le transfert de port au lieu de créer immédiatement un LoadBalancer :
kubectl port-forward pod/nginx-6d4cf56db6-8z7wv 8080:80
Puis curl :
curl localhost:8080
Si cela fonctionne, créez d'abord un Service de type ClusterIP, puis NodePort ou Ingress selon les besoins.
Vérification et diagnostics
Cette section est le cœur du dépannage : comment identifier pourquoi un pod est bloqué.
Le cycle de vie des pods dans Kubernetes
Un pod passe par ces phases :
- Pending : Planifié mais les conteneurs ne sont pas encore créés (téléchargement d'image, délai de planification).
- Running : Tous les conteneurs ont démarré, mais peuvent encore échouer aux contrôles de préparation.
- Succeeded/Terminated : Tous les conteneurs se sont terminés avec succès (pour les Jobs) ou ont été terminés.
- Failed : Au moins un conteneur s'est terminé avec un statut non nul.
- Unknown : L'état ne peut pas être déterminé (généralement un problème de communication avec le nœud).
Au sein de Running, les statuts des conteneurs incluent :
Waiting(avec une raison commeCrashLoopBackOffouImagePullBackOff)RunningTerminated(avec code de sortie)
Commandes de diagnostic
kubectl describe pod
C'est la première commande détaillée à exécuter.
kubectl describe pod nginx-6d4cf56db6-8z7wv
Sections clés :
- Events en bas : contiennent souvent le message d'erreur direct.
- Conditions :
PodScheduled,Initialized,ContainersReady,Ready. - Container statuses :
State,Reason,Exit Code.
Exemple d'événement :
Warning Failed 4m (x5 over 5m) kubelet Failed to pull image "nginx:latest": rpc error: code = Unknown desc = Error response from daemon: manifest for nginx:latest not found: manifest unknown: manifest unknown
kubectl logs
Pour un conteneur en cours d'exécution :
kubectl logs pod-name -c container-name
Pour un conteneur qui a planté, utilisez --previous :
kubectl logs pod-name --previous
Cela montre la sortie standard/erreur avant la dernière terminaison.
kubectl get events
Déjà montré, mais combinez avec une surveillance :
kubectl get events -n default --watch &
kubectl apply -f pod.yaml
Observez les événements au fur et à mesure qu'ils arrivent.
kubectl top
Si metrics-server est installé :
kubectl top pod
kubectl top node
Cela révèle l'utilisation CPU/mémoire causant des évictions ou des OOM.
Interprétation des codes de sortie courants
| Code de sortie | Signification | Cause typique |
|---|---|---|
| 0 | Succès | Arrêt normal |
| 1 | Erreur générale | Plantage d'application |
| 2 | Mauvais usage des commandes shell intégrées | Syntaxe de commande incorrecte |
| 126 | La commande ne peut pas s'exécuter | Problème de permission |
| 127 | Commande introuvable | Binaire manquant ou PATH incorrect |
| 128+n | Signal n | Par exemple, 137 = SIGKILL (OOM ou sonde de vivacité tuant le conteneur) |
Exemple : déboguer un CrashLoopBackOff
- Obtenez les détails du pod :
kubectl get pod crashpod -o yaml
- Vérifiez le dernier état et le code de sortie :
lastState:
terminated:
exitCode: 1
reason: Error
- Consultez les journaux précédents :
kubectl logs crashpod --previous
- Si les journaux montrent un fichier de configuration manquant, corrigez le montage ou la variable d'environnement.
Modes de défaillance et récupération
Voici les cinq états de défaillance de pod les plus courants, chacun avec diagnostic et étapes de récupération.
1. Pod bloqué en Pending
Symptômes : kubectl get pods affiche Pending, aucun nœud attribué (colonne NODE vide).
Causes :
- Ressources insuffisantes sur un nœud (CPU, mémoire, GPU)
- Taints de nœud non tolérés
- Sélecteurs de nœud/règles d'affinité non satisfaits
- PersistentVolumeClaim lié à un stockage indisponible
Diagnostic :
kubectl describe pod pending-pod
Regardez les événements pour des messages comme :
0/3 nodes are available: 3 Insufficient memory.
Ou vérifiez les taints des nœuds :
kubectl get nodes -o json | jq '.items[].spec.taints'
Récupération :
- Si insuffisance de ressources, réduisez les requêtes ou ajoutez des nœuds.
- Si taints, ajoutez une tolérance dans la spécification du pod :
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
- Si le sélecteur de nœud ne correspond pas, ajustez le sélecteur ou étiquetez un nœud.
2. ImagePullBackOff
Symptômes : Statut du pod ImagePullBackOff ou ErrImagePull.
Causes :
- L'étiquette d'image n'existe pas
- Échec d'authentification auprès du registre
- Politique réseau bloquant le registre
- Limites de taux de Docker Hub
Diagnostic :
kubectl describe pod imagepull-pod | grep -A5 Events
Événement typique :
Failed to pull image "myrepo/myapp:v1.2": rpc error: code = Unknown desc = Error response from daemon: pull access denied for myrepo/myapp, repository does not exist or may require 'docker login'
Vérifiez si l'image existe localement :
docker pull myrepo/myapp:v1.2
Récupération :
- Corrigez l'étiquette d'image.
- Si registre privé, créez un Secret et définissez
imagePullSecrets:
kubectl create secret docker-registry regcred \
--docker-server=myregistry.com \
--docker-username=user \
--docker-password=pass
Puis dans la spécification du pod :
imagePullSecrets:
- name: regcred
- Si limité par le taux, utilisez un cache pull-through ou un autre registre.
3. CrashLoopBackOff
Symptômes : Le pod redémarre à plusieurs reprises, statut CrashLoopBackOff, nombre élevé de RESTARTS.
Causes :
- L'application se termine immédiatement en raison d'une mauvaise configuration
- Dépendance manquante (base de données, fichier de configuration)
- Sonde de vivacité tuant le conteneur
- Arrêt pour mémoire insuffisante (OOM)
Diagnostic :
kubectl logs crashpod --previous
Erreurs courantes :
Error: Cannot find module '/app/index.js'(Node.js)panic: runtime error: invalid memory address or nil pointer dereference(Go)Exception in thread "main" java.lang.IllegalStateException: No database connection(Java)
Vérifiez si OOM :
kubectl describe pod crashpod | grep -i oom
Si OOM, vous pouvez voir :
Last State: Terminated
Reason: OOMKilled
Exit Code: 137
Récupération :
- Corrigez l'erreur sous-jacente de l'application.
- Si OOM, augmentez la limite de mémoire ou réduisez l'utilisation de la mémoire de l'application.
- Si la sonde de vivacité est trop agressive, ajustez
initialDelaySeconds,periodSecondsou la commande de la sonde.
4. Échecs de sondes (readiness/liveness)
Symptômes : Le pod est Running mais pas Ready ; le trafic n'est pas envoyé (readiness) ou le conteneur est redémarré (liveness).
Diagnostic :
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# web-6d4cf56db6-8z7wv 0/1 Running 1 10m
Échec de readiness : RESTARTS reste faible. Échec de liveness : RESTARTS augmente.
Vérifiez la configuration des sondes :
kubectl get pod web-6d4cf56db6-8z7wv -o yaml | less
Trouvez les sections readinessProbe et livenessProbe.
Échecs de sondes courants :
- Le point de terminaison HTTP renvoie 4xx/5xx
- Le port TCP n'est pas ouvert
- La commande se termine avec un code non nul
Récupération :
- Testez le point de terminaison manuellement à l'intérieur du pod :
kubectl exec -it pod-name -- curl localhost:8080/healthz
- Ajustez le chemin, le port ou les seuils de la sonde.
- Augmentez
timeoutSecondssi l'application est lente à démarrer. - Envisagez une
startupProbepour les applications à démarrage lent.
5. Pod évincé ou terminé de manière inattendue
Symptômes : Le pod disparaît du nœud, ou entre dans Failed avec le statut Evicted.
Causes :
- Pression sur les ressources du nœud (mémoire, disque)
- Nœud cordonné/drainé
- Préemption par des pods de priorité supérieure
Diagnostic :
kubectl describe pod evicted-pod | grep -A10 Events
Cherchez :
The node was low on resource: memory.
Ou vérifiez les conditions du nœud :
kubectl describe node worker-01
Récupération :
- Libérez des ressources sur le nœud (supprimez les pods inutilisés, redimensionnez les requêtes)
- Ajoutez plus de nœuds
- Définissez des classes de priorité appropriées pour éviter la préemption des pods critiques
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle après toute défaillance pour vous assurer d'avoir une vue complète et une récupération sûre.
Réponse immédiate
- [ ] Capturer la liste des pods avec horodatage :
kubectl get pods -o wide > pods-$(date +%s).txt - [ ] Capturer la sortie de describe :
kubectl describe pod <name> > describe-<name>.txt - [ ] Capturer les journaux (actuels et précédents) :
kubectl logs <name> --previous > logs-<name>-prev.txt - [ ] Capturer les événements :
kubectl get events > events.txt - [ ] Noter l'heure exacte et tout changement récent (déploiements, mises à jour de configuration)
Diagnostic
- [ ] Déterminer la phase et la raison du pod à partir de
describe - [ ] Vérifier le dernier état et le code de sortie du conteneur
- [ ] Examiner les journaux pour les erreurs d'application
- [ ] Vérifier l'utilisation des ressources (
kubectl topsi disponible) - [ ] Vérifier la santé et les taints des nœuds
- [ ] Si échec de sonde, tester le point de terminaison manuellement
Récupération
- [ ] Décider du changement minimal (image, configuration, ressource, sonde)
- [ ] Appliquer le changement en staging d'abord si possible
- [ ] Utiliser
kubectl applyoukubectl setpour le changement - [ ] Surveiller le déploiement avec
kubectl rollout status - [ ] Vérifier la préparation du pod et le trafic (test de transfert de port)
- [ ] Revenir en arrière si ce n'est pas sain :
kubectl rollout undo - [ ] Documenter la cause racine et le correctif
Prévention
- [ ] Ajouter des sondes de vivacité et de préparation à tous les pods à longue durée de vie
- [ ] Définir des requêtes et limites de ressources appropriées
- [ ] Utiliser des étiquettes d'image explicites au lieu de
latest - [ ] Mettre en œuvre des PodDisruptionBudgets pour les services critiques
- [ ] Configurer des alertes de surveillance sur les redémarrages et échecs de pods
- [ ] Examiner régulièrement la capacité des nœuds et les politiques de mise à l'échelle automatique
Conclusion
Le dépannage du cycle de vie des pods Kubernetes est systématique : observer d'abord, puis diagnostiquer, puis appliquer un correctif minimal, et toujours vérifier. Se précipiter vers kubectl delete pod peut apporter un soulagement temporaire mais masque la cause racine.
Cet article a couvert les techniques essentielles :
- Capturer l'état de l'environnement et des pods avant les changements
- Comprendre les phases et statuts des pods
- Utiliser
kubectl describe,logset les événements pour trouver les causes racines - Cinq modes de défaillance courants et leurs procédures de récupération
- Une liste de contrôle opérationnelle pour assurer une réponse aux incidents complète
Comme prochaine étape, choisissez un pod en échec dans votre cluster et suivez le processus de diagnostic décrit ici. Enregistrez l'état observé, identifiez la cause, appliquez le plus petit correctif et vérifiez le résultat. Avec le temps, ces habitudes transformeront le débogage des pods d'une corvée stressante en une procédure calme et reproductible.
Rappelez-vous : l'objectif n'est pas seulement de redémarrer un pod, mais de comprendre pourquoi il a échoué et d'empêcher la récurrence.