Introduction
Déboguer un pod en cours d'exécution dans Kubernetes commence souvent par un message d'erreur tel que ImagePullBackOff, CrashLoopBackOff ou OOMKilled. Ces erreurs courantes peuvent interrompre un déploiement, mais avec une approche systématique, vous pouvez diagnostiquer la cause profonde et appliquer rapidement un correctif ciblé.
Cet article est un guide pratique destiné aux développeurs, ingénieurs DevOps et équipes techniques de startups qui doivent résoudre les problèmes de pods Kubernetes dans des clusters de développement, de préproduction ou de production. Nous couvrons les erreurs de pod les plus fréquentes, expliquons leur signification et fournissons des commandes kubectl concrètes et des extraits de configuration pour les identifier et les résoudre.
Vous apprendrez à :
- Inspecter l'état du pod et les événements avec
kubectl getetkubectl describe - Récupérer les journaux des instances de conteneurs actuelles et précédentes
- Corriger les erreurs liées aux images, les boucles de crash, les limites de ressources et les échecs de sondes
- Vérifier un correctif en contrôlant l'état du déploiement et la santé du pod
- Utiliser une liste de contrôle opérationnelle pour éviter les pièges courants
Tous les exemples utilisent Kubernetes 1.25+ et supposent un kubectl opérationnel configuré pour accéder à votre cluster. L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'action, utiliser des espaces réservés plutôt que des secrets, vérifier le résultat et documenter les étapes de récupération.
Inventaire des versions et de l'environnement
Avant de déboguer, établissez une image claire de votre environnement Kubernetes. Exécutez les commandes suivantes pour capturer l'état actuel et les versions pertinentes :
kubectl version --short
kubectl cluster-info
kubectl get nodes
kubectl get pods -o wide -n <namespace>
Par exemple, si vous dépannez un pod nommé web-app-7d5c6f8b9-xyz dans le namespace default, la sortie pourrait ressembler à :
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-app-7d5c6f8b9-xyz 0/1 CrashLoopBackOff 5 10m 10.244.1.5 worker-01 <none> <none>
Cela vous indique déjà que le pod redémarre de façon répétée (RESTARTS = 5) et se trouve dans un état CrashLoopBackOff. Ensuite, collectez des informations détaillées sur le pod :
kubectl describe pod web-app-7d5c6f8b9-xyz -n default
La section Events en bas de la sortie de describe est souvent le moyen le plus rapide de repérer le problème. Voici une séquence d'événements typique d'une boucle de crash :
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2m default-scheduler Successfully assigned default/web-app-7d5c6f8b9-xyz to worker-01
Normal Pulled 105s kubelet Successfully pulled image "myapp:1.0" in 3.2s
Normal Created 105s kubelet Created container app
Normal Started 105s kubelet Started container app
Warning BackOff 104s kubelet Back-off restarting failed container
Pour voir les journaux des instances de conteneurs actuelles et précédentes, utilisez :
kubectl logs web-app-7d5c6f8b9-xyz -n default
kubectl logs web-app-7d5c6f8b9-xyz -n default --previous
Capturez toujours la sortie de ces commandes avant d'effectuer toute modification. Cette observation en lecture seule constitue votre base de référence et vous aide à vérifier si un correctif a réellement fonctionné.
Chemin de configuration sûr
Lorsqu'un pod ne parvient pas à s'exécuter, résistez à l'envie de le supprimer et de le recréer immédiatement. Suivez plutôt un chemin de configuration sûr : comprenez la configuration du pod, repérez la mauvaise configuration et appliquez le plus petit changement qui traite la cause profonde.
Une source courante d'erreurs est une spécification de pod incorrecte. Récupérez la définition du pod au format YAML :
kubectl get pod web-app-7d5c6f8b9-xyz -n default -o yaml
Examinez les sections clés :
spec.containers[].image– le nom et l'étiquette de l'image sont-ils corrects ?spec.containers[].resources– les requêtes et limites sont-elles raisonnables ?spec.containers[].readinessProbe/livenessProbe– les sondes sont-elles correctement configurées ?spec.containers[].env– les variables d'environnement sont-elles correctement définies ?
Par exemple, un pod peut échouer parce que la livenessProbe a un initialDelaySeconds beaucoup plus court que le temps de démarrage de l'application. Cela amène le kubelet à tuer le conteneur avant qu'il ne soit prêt.
Exemple de sonde de vivacité problématique :
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
Si l'application a besoin de 30 secondes pour démarrer, la sonde échouera pendant les 25 premières secondes et déclenchera un redémarrage. Une configuration plus sûre serait :
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 5
Cela donne à l'application suffisamment de temps pour démarrer et tolère les échecs transitoires.
Pour modifier la configuration d'un pod en direct, vous ne pouvez généralement pas changer directement la plupart des champs. Modifiez plutôt le déploiement qui gère le pod :
kubectl edit deployment web-app -n default
Effectuez votre modification, enregistrez et surveillez le déploiement :
kubectl rollout status deployment/web-app -n default
Si le déploiement échoue, vous pouvez revenir à la révision précédente :
kubectl rollout undo deployment/web-app -n default
Pour tester les modifications de configuration localement avant de les appliquer au cluster, utilisez kubectl apply --dry-run=client ou kubectl diff :
kubectl apply -f web-app.yaml --dry-run=client
kubectl diff -f web-app.yaml
Ce chemin sûr minimise les risques et vous donne un plan de retour arrière clair.
Vérification et diagnostics
Après avoir appliqué un correctif, vous devez vérifier que le pod récupère réellement. Utilisez les commandes suivantes pour confirmer la santé :
- Vérifiez l'état du pod :
kubectl get pods -n default -l app=web-app
Recherchez le statut Running et un faible nombre de redémarrages.
- Vérifiez l'état du déploiement :
kubectl rollout status deployment/web-app -n default
Un déploiement réussi affiche : deployment "web-app" successfully rolled out.
- Inspectez les événements du pod pour tout nouvel avertissement :
kubectl describe pod <nouveau-nom-de-pod> -n default | tail -20
- Vérifiez que l'application sert réellement le trafic. Utilisez le transfert de port pour tester localement :
kubectl port-forward pod/<nouveau-nom-de-pod> 8080:8080 -n default
Ouvrez ensuite http://localhost:8080 dans un navigateur ou utilisez curl :
curl -I http://localhost:8080/health
Vous devriez voir une réponse HTTP 200 si l'application est saine.
- Pour des diagnostics plus approfondis, exécutez des commandes à l'intérieur du conteneur à l'aide de
kubectl exec:
kubectl exec -it <nouveau-nom-de-pod> -n default -- /bin/sh
Dans le shell, vous pouvez vérifier les processus, la connectivité réseau ou les montages de fichiers.
N'oubliez pas de capturer la sortie attendue à chaque étape. Par exemple, une vérification de pod sain devrait montrer :
NAME READY STATUS RESTARTS AGE
web-app-6c9f7b8f-abcde 1/1 Running 0 2m
Si le pod reste en CrashLoopBackOff, ne supposez pas que le correctif a fonctionné. Continuez vers la section des modes de défaillance.
Modes de défaillance et récupération
Les pods Kubernetes échouent de nombreuses façons. Voici les types d'erreurs les plus courants, leurs causes probables et des correctifs spécifiques.
1. ImagePullBackOff ou ErrImagePull
Symptôme : L'état du pod affiche ImagePullBackOff ou ErrImagePull. Décrivez le pod et vous verrez des événements comme :
Warning Failed 2m (x4 over 3m) kubelet Failed to pull image "myapp:latest": rpc error: code = NotFound desc = failed to pull and unpack image
Causes :
- Nom d'image ou étiquette incorrect
- L'image n'existe pas dans le registre
- Échec d'authentification auprès d'un registre privé
- Problèmes de réseau entre le nœud et le registre
Diagnostic :
kubectl describe pod <nom-du-pod> | grep -A 5 Events
Vérifiez la référence exacte de l'image. Vérifiez qu'elle existe dans le registre. Pour les registres privés, assurez-vous que les imagePullSecrets sont configurés.
Correctif :
- Corrigez le nom/étiquette de l'image dans votre YAML de déploiement.
- Si vous utilisez un registre privé, créez et référencez un secret :
apiVersion: v1
kind: Secret
metadata:
name: regcred
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: <base64-encoded-docker-config>
Ensuite, dans votre spécification de pod :
spec:
imagePullSecrets:
- name: regcred
containers:
- name: app
image: myregistry.com/myapp:1.0
- Pour les problèmes de réseau, vérifiez la connectivité du nœud vers le registre.
2. CrashLoopBackOff
Symptôme : Le pod redémarre de façon répétée. Le conteneur démarre puis se termine avec un code non nul.
Causes :
- Erreur d'application à l'intérieur du conteneur (par exemple, mauvaise configuration, dépendance manquante)
- La sonde de vivacité échoue et tue le conteneur
- Mémoire insuffisante (OOMKilled)
- Commande ou arguments incorrects
Diagnostic :
Vérifiez les journaux du conteneur précédent pour voir l'erreur à la sortie :
kubectl logs <nom-du-pod> --previous
Pour une terminaison OOM, l'état du pod affichera :
State: Terminated
Reason: OOMKilled
Exit Code: 137
Correctif :
- Corrigez l'erreur d'application en fonction des journaux.
- Pour OOM, augmentez la limite de mémoire ou réduisez l'utilisation mémoire de l'application. Exemple de bloc de ressources :
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
- Ajustez les paramètres de la sonde de vivacité comme indiqué dans le chemin de configuration sûr.
- Assurez-vous que la commande et les arguments sont corrects dans la spécification du pod.
3. Pods en attente (Pending)
Symptôme : Le pod reste dans l'état Pending.
Causes :
- CPU ou mémoire insuffisants sur les nœuds
- Aucun nœud ne correspond aux sélecteurs de nœuds ou aux règles d'affinité
- La PersistentVolumeClaim ne peut pas être liée
Diagnostic :
kubectl describe pod <nom-du-pod> | grep -A 10 Events
Recherchez des messages comme :
Warning FailedScheduling 10s (x2 over 20s) default-scheduler 0/3 nodes are available: 1 Insufficient memory, 2 node(s) didn't match node selector.
Correctif :
- Réduisez les requêtes de ressources ou ajoutez plus de nœuds au cluster.
- Ajustez les sélecteurs de nœuds ou les affinités pour correspondre aux nœuds disponibles.
- Assurez-vous que les classes de stockage et les PVC sont correctement définies.
4. Échecs des sondes de préparation ou de vivacité
Symptôme : Le pod est Running mais pas Ready, ou est tué par la sonde de vivacité.
Causes :
- L'endpoint de la sonde renvoie un statut non-200 ou expire
- Le chemin ou le port de la sonde est incorrect
initialDelaySecondstrop court
Diagnostic :
Vérifiez les événements du pod et la configuration de la sonde :
kubectl describe pod <nom-du-pod> | grep -E 'Readiness|Liveness'
Correctif :
- Corrigez l'endpoint, le chemin et le port de la sonde.
- Augmentez
initialDelaySecondspour tenir compte du démarrage de l'application. - Pour les sondes HTTP, assurez-vous que l'application écoute sur le port spécifié.
5. CreateContainerConfigError
Symptôme : Le pod ne peut pas démarrer car la configuration du conteneur est invalide.
Causes :
- ConfigMap ou Secret manquant référencé dans la spécification du pod
- Montages de volume invalides
- Définitions de variables d'environnement invalides
Diagnostic :
kubectl describe pod <nom-du-pod> | grep -A 10 Events
Recherchez des messages comme :
Warning Failed 5m kubelet Error: configmap "app-config" not found
Correctif :
- Créez la ConfigMap ou le Secret manquant, ou corrigez le nom de référence.
- Corrigez les montages de volume ou la syntaxe des variables d'environnement.
Meilleures pratiques de récupération
Après avoir appliqué un correctif, déployez toujours et vérifiez :
kubectl apply -f fixed-deployment.yaml
kubectl rollout status deployment/<nom>
Si le nouveau pod échoue toujours, revenez en arrière :
kubectl rollout undo deployment/<nom>
Documentez l'erreur, le correctif et le résultat de la vérification dans le runbook de votre équipe pour référence future.
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle pour déboguer systématiquement un problème de pod. Remplacez les valeurs d'exemple par vos propres noms de ressources et paramètres.
- Identifier le pod en échec
- Commande :
kubectl get pods -n default -l app=web-app - Sortie attendue : liste des pods ; notez celui avec un statut non-Running.
- Recueillir des informations détaillées sur le pod
- Commande :
kubectl describe pod web-app-7d5c6f8b9-xyz -n default - Rechercher : événements, états du conteneur, dernier état (par exemple, Terminated avec OOMKilled), détails des sondes de préparation/vivacité.
- Récupérer les journaux d'application
- Journaux actuels :
kubectl logs web-app-7d5c6f8b9-xyz -n default - Journaux précédents :
kubectl logs web-app-7d5c6f8b9-xyz -n default --previous - Sortie attendue : trace de pile d'erreur d'application ou message de sortie.
- Vérifier les contraintes de ressources
- Commande :
kubectl top pod web-app-7d5c6f8b9-xyz -n default - Comparez l'utilisation mémoire/CPU par rapport aux limites dans
kubectl get pod -o yaml.
- Vérifier les références de configuration
- Assurez-vous que toutes les ConfigMaps, Secrets et PersistentVolumeClaims référencés existent et sont correctement nommés.
- Appliquer le plus petit correctif
- Exemple : changer l'étiquette d'image de
latestà une version spécifique, augmenter la limite mémoire de 256Mi à 512Mi, ou corriger le chemin de la sonde. - Mettez à jour le YAML de déploiement et appliquez via
kubectl apply -f deployment.yaml.
- Surveiller le déploiement
- Commande :
kubectl rollout status deployment/web-app -n default - Sortie attendue :
deployment "web-app" successfully rolled out.
- Vérifier la santé du pod
- Commande :
kubectl get pods -n default -l app=web-app - Sortie attendue : le pod affiche
RunningetReady 1/1.
- Tester la fonctionnalité de l'application
- Utilisez
kubectl port-forwardpour accéder à l'application localement et confirmer la réponse attendue (par exemple, HTTP 200 depuis/health).
- Documenter l'incident
- Enregistrez l'erreur, la cause profonde, le correctif et les étapes de vérification dans votre runbook ou système de tickets.
Cette liste de contrôle garantit que vous ne sautez pas d'étapes de diagnostic critiques et réduit le risque d'introduire de nouveaux problèmes.
Conclusion
Déboguer un pod en cours d'exécution dans Kubernetes est un processus méthodique. En commençant par kubectl get et kubectl describe, en examinant les journaux et en comprenant les motifs d'erreur courants, vous pouvez rapidement identifier la cause profonde et appliquer un correctif ciblé.
N'oubliez pas de toujours observer d'abord l'état actuel, d'effectuer des changements minimaux et de vérifier chaque correctif. Utilisez les commandes et les exemples de cet article comme référence, mais adaptez-les à votre environnement et à votre application spécifiques.
Comme prochaine étape, choisissez une vérification à faible risque pour une erreur de pod que vous avez rencontrée ou anticipée. Pratiquez le flux de diagnostic : capturez les événements du pod, inspectez les journaux, identifiez la raison de l'échec et appliquez un correctif documenté. Ensuite, assurez-vous que votre équipe dispose d'une entrée de runbook pour cette erreur afin que les incidents futurs soient résolus plus rapidement.
Un flux de travail de dépannage fiable rend la défaillance visible, protège les valeurs sensibles, limite les modifications à la ressource prévue et définit la vérification de récupération avant qu'un incident ne force la décision. Avec ces pratiques, vous pouvez transformer le débogage de pods Kubernetes d'une lutte contre l'incendie en un processus structuré.