Dépannage : Pourquoi mon Pod Kubernetes est-il bloqué en état Pending ou CrashLoopBackOff ?
Les Pods Kubernetes bloqués en état `Pending` ou `CrashLoopBackOff` peuvent interrompre les déploiements. Ce guide complet démystifie ces états courants, en proposant un dépannage pratique et étape par étape. Apprenez à diagnostiquer des problèmes tels que les contraintes de ressources, les erreurs de tirage d'image, les échecs d'application et les mauvaises configurations de sonde à l'aide des commandes `kubectl`. Donnez-vous les moyens d'agir avec des informations exploitables et des bonnes pratiques pour résoudre rapidement les problèmes de Pod et maintenir un environnement Kubernetes robuste et fiable, garantissant que vos applications sont toujours opérationnelles.
Dépannage : Pourquoi mon Pod Kubernetes est-il bloqué en état Pending ou CrashLoopBackOff ?
Pending et CrashLoopBackOff se ressemblent lorsque vous attendez un déploiement, mais ils signifient des choses très différentes. Pending signifie généralement que Kubernetes n'a pas pu placer ou préparer le pod. CrashLoopBackOff signifie que le conteneur a démarré, puis s'est arrêté, et que Kubernetes retarde le prochain redémarrage.
Cette différence est importante. Un pod en attente est souvent un problème de planificateur, d'image ou de stockage. Un pod qui plante est généralement un problème d'application, de commande, de sonde, d'autorisation ou de mémoire. Commencez par cette distinction et le chemin de dépannage sera beaucoup plus court.
Comprendre les états des Pods : Pending vs. CrashLoopBackOff
Avant de plonger dans le dépannage, il est essentiel de comprendre ce que signifient ces deux états.
Statut du Pod : Pending
Un Pod dans l'état Pending signifie que Kubernetes a accepté l'objet Pod, mais qu'il n'est pas encore passé à l'état de conteneur en cours d'exécution. Parfois, il n'a pas été programmé sur un nœud. Parfois, un nœud lui a été attribué, mais le tirage de l'image, l'attachement du volume ou la configuration du bac à sable n'est pas terminé.
Statut du Pod : CrashLoopBackOff
Un Pod dans l'état CrashLoopBackOff signifie qu'un conteneur dans le Pod démarre, plante et redémarre de manière répétée. Kubernetes implémente un délai de back-off exponentiel entre les redémarrages pour éviter de submerger le nœud. Cet état indique presque toujours un problème avec l'application s'exécutant dans le conteneur lui-même ou son environnement immédiat.
Un cas subtil : un conteneur peut se terminer avec le code 0 et entrer tout de même dans une boucle de redémarrage si la charge de travail est censée être un serveur de longue durée. Cela se produit souvent lorsqu'un Déploiement exécute par erreur une commande unique, comme un script de migration ou une commande shell qui se termine immédiatement.
Dépannage des Pods en état Pending
Lorsqu'un Pod est Pending, le premier endroit à regarder est le planificateur et le nœud sur lequel il essaie d'atterrir. Voici les causes courantes et les étapes de diagnostic.
1. Ressources insuffisantes sur les nœuds
L'une des raisons les plus fréquentes pour lesquelles un Pod est Pending est qu'aucun nœud du cluster ne dispose de suffisamment de ressources disponibles (CPU, mémoire) pour satisfaire les requests du Pod. Le planificateur ne peut pas trouver de nœud approprié.
Étapes de diagnostic :
Décrire le Pod : La commande
kubectl describe podest votre meilleure amie ici. Elle montrera souvent des événements détaillant pourquoi le Pod ne peut pas être programmé.kubectl describe pod <nom-du-pod> -n <namespace>Recherchez des événements comme "
FailedScheduling" et des messages tels que "0/3 nodes are available: 3 Insufficient cpu" ou "memory".Vérifier les ressources des nœuds : Consultez l'utilisation actuelle des ressources et la capacité de vos nœuds.
kubectl get nodes kubectl top nodes # (nécessite metrics-server)
Solution :
- Augmenter la capacité du cluster : Ajoutez plus de nœuds à votre cluster Kubernetes.
- Ajuster les demandes de ressources du Pod : Réduisez les
requestspour le CPU et la mémoire dans le manifeste de votre Pod si elles sont trop élevées.resources: requests: memory: "128Mi" cpu: "250m" - Évacuer d'autres Pods : Évacuez manuellement les Pods de priorité inférieure des nœuds pour libérer des ressources (à utiliser avec prudence).
2. Erreurs de tirage d'image
Si Kubernetes peut programmer le Pod sur un nœud, mais que le nœud ne parvient pas à tirer l'image du conteneur, le Pod restera Pending.
Causes courantes :
- Nom/Étiquette d'image incorrect : Fautes de frappe dans le nom de l'image ou utilisation d'une étiquette inexistante.
- Authentification de registre privé :
ImagePullSecretsmanquants ou incorrects pour les registres privés. - Problèmes réseau : Le nœud ne peut pas atteindre le registre d'images.
Étapes de diagnostic :
Décrire le Pod : Encore une fois,
kubectl describe podest essentiel. Recherchez des événements comme "Failed" ou "ErrImagePull" ou "ImagePullBackOff".kubectl describe pod <nom-du-pod> -n <namespace>Exemple d'événement de sortie :
Failed to pull image "my-private-registry/my-app:v1.0": rpc error: code = Unknown desc = Error response from daemon: pull access denied for my-private-registry/my-app, repository does not exist or may require 'docker login'Vérifier ImagePullSecrets : Vérifiez que
imagePullSecretsest correctement configuré dans votre Pod ou ServiceAccount.kubectl get secret <votre-secret-image-pull> -o yaml -n <namespace>
Solution :
- Corriger le nom/étiquette de l'image : Revérifiez le nom et l'étiquette de l'image dans votre manifeste de déploiement.
- Configurer ImagePullSecrets : Assurez-vous d'avoir créé un secret
docker-registryet de l'avoir lié à votre Pod ou ServiceAccount.
Ensuite, ajoutez-le à la spécification de votre Pod :kubectl create secret docker-registry mon-secret-registry \ --docker-server=votre-registry.com \ --docker-username=votre-utilisateur \ --docker-password=votre-mot-de-passe \ --docker-email=votre-email -n <namespace>spec: imagePullSecrets: - name: mon-secret-registry containers: ... - Connectivité réseau : Vérifiez la connectivité réseau du nœud au registre d'images.
Si vous utilisez un registre privé, vérifiez également le ServiceAccount. De nombreuses équipes attachent imagePullSecrets au ServiceAccount par défaut du namespace plutôt qu'à chaque Déploiement :
kubectl get serviceaccount default -n <namespace> -o yaml
Si le secret existe mais que le tirage échoue toujours, confirmez que le nom d'hôte du registre dans le secret correspond exactement au nom d'hôte dans la référence de l'image. registry.example.com/app:v1 et https://registry.example.com/app:v1 ne sont pas la même référence.
3. Problèmes liés aux volumes
Si votre Pod nécessite un PersistentVolumeClaim (PVC) et que le PersistentVolume (PV) correspondant ne peut pas être provisionné ou lié, le Pod restera Pending.
Étapes de diagnostic :
Décrire le Pod : Recherchez des événements liés aux volumes.
kubectl describe pod <nom-du-pod> -n <namespace>Les événements peuvent montrer
FailedAttachVolume,FailedMount, ou des messages similaires.Vérifier le statut PVC et PV : Inspectez le statut du PVC et du PV.
kubectl get pvc <nom-du-pvc> -n <namespace> kubectl get pvRecherchez les PVC bloqués en
Pendingou les PV non liés.
Solution :
- S'assurer de la StorageClass : Assurez-vous qu'une
StorageClassest définie et disponible, surtout si vous utilisez le provisionnement dynamique. - Vérifier la disponibilité du PV : Si vous utilisez le provisionnement statique, assurez-vous que le PV existe et correspond aux critères du PVC.
- Vérifier les modes d'accès : Assurez-vous que les modes d'accès (par exemple,
ReadWriteOnce,ReadWriteMany) sont compatibles.
Vérifiez également si le pod est programmé dans une zone où le volume peut être attaché. Dans les clusters cloud, un disque créé dans une zone de disponibilité peut ne pas s'attacher à un nœud dans une autre. L'événement mentionne généralement l'affinité du nœud de volume ou l'échec d'attachement. Dans ce cas, la correction peut être des contraintes de planification, une StorageClass différente, ou la recréation du volume dans la bonne zone.
4. Taints, Tolerations et Node Selectors
Un pod peut rester Pending même lorsque le cluster a beaucoup de CPU et de mémoire. Le planificateur doit également respecter les règles de placement.
Exemples courants :
- Le pod a un
nodeSelectorqui ne correspond à aucun nœud. - Le pod nécessite une affinité de nœud trop stricte.
- Les seuls nœuds correspondants ont des taints, et le pod n'a pas de toleration correspondante.
- Le namespace a un quota qui bloque les ressources demandées.
Vérifiez d'abord les événements de planification :
kubectl describe pod <nom-du-pod> -n <namespace>
Ensuite, comparez les règles de placement du pod avec les étiquettes des nœuds :
kubectl get pod <nom-du-pod> -n <namespace> -o yaml
kubectl get nodes --show-labels
kubectl describe node <nom-du-noeud>
Si l'événement indique qu'une taint n'a pas été tolérée, planifiez le pod ailleurs ou ajoutez une toleration uniquement si cette charge de travail appartient vraiment à ces nœuds. Ne tolérez pas aveuglément chaque taint. Les taints protègent souvent les nœuds spéciaux, les nœuds GPU, les nœuds d'infrastructure ou les nœuds sous pression.
Dépannage des Pods en état CrashLoopBackOff
Un état CrashLoopBackOff indique un problème au niveau de l'application. Le conteneur a démarré avec succès mais s'est ensuite arrêté avec une erreur, incitant Kubernetes à le redémarrer de manière répétée.
1. Erreurs d'application
La cause la plus courante est que l'application elle-même ne parvient pas à démarrer ou rencontre une erreur fatale peu après le démarrage.
Causes courantes :
- Dépendances/Configuration manquantes : L'application ne trouve pas les fichiers de configuration, les variables d'environnement ou les services externes critiques dont elle dépend.
- Commande/Arguments incorrects : La
commandou lesargsspécifiés dans la spécification du conteneur sont incorrects ou conduisent à une sortie immédiate. - Erreurs de logique applicative : Bogues dans le code de l'application qui provoquent un crash au démarrage.
Étapes de diagnostic :
Consulter les logs du Pod : C'est l'étape la plus critique. Les logs montreront souvent le message d'erreur exact qui a provoqué le crash de l'application.
kubectl logs <nom-du-pod> -n <namespace>Si le Pod plante de manière répétée, les logs peuvent montrer la sortie de la tentative échouée la plus récente. Pour voir les logs d'une instance précédente d'un conteneur qui plante, utilisez le drapeau
-p(previous) :kubectl logs <nom-du-pod> -p -n <namespace>Décrire le Pod : Recherchez
Restart Countdans la sectionContainers, qui indique combien de fois le conteneur a planté. Vérifiez égalementLast StatepourExit Code.kubectl describe pod <nom-du-pod> -n <namespace>Un code de sortie de
0signifie généralement un arrêt gracieux, mais tout code de sortie non nul signifie une erreur. Les codes de sortie non nuls courants incluent1(erreur générale),137(SIGKILL, souvent OOMKilled),139(SIGSEGV, erreur de segmentation).
Solution :
- Examiner les logs de l'application : Sur la base des logs, déboguez votre code d'application ou votre configuration. Assurez-vous que toutes les variables d'environnement,
ConfigMapsetSecretsrequis sont correctement montés/injectés. - Tester localement : Essayez d'exécuter l'image du conteneur localement avec les mêmes variables d'environnement et commandes pour reproduire et déboguer le problème.
Si le pod a plusieurs conteneurs, spécifiez toujours le nom du conteneur :
kubectl logs <nom-du-pod> -c <nom-du-conteneur> -n <namespace>
kubectl logs <nom-du-pod> -c <nom-du-conteneur> -p -n <namespace>
Sans -c, vous lisez peut-être les logs du sidecar alors que l'application principale est celle qui plante.
2. Échec des sondes Liveness et Readiness
Kubernetes utilise les sondes Liveness et Readiness pour déterminer la santé et la disponibilité de votre application. Si une sonde liveness échoue continuellement, Kubernetes redémarrera le conteneur, conduisant à CrashLoopBackOff.
Étapes de diagnostic :
Décrire le Pod : Vérifiez les définitions des sondes
LivenessetReadinesset leurLast Statedans la sectionContainers.kubectl describe pod <nom-du-pod> -n <namespace>Recherchez des messages indiquant des échecs de sonde, comme "
Liveness probe failed: HTTP probe failed with statuscode: 500".Consulter les logs de l'application : Parfois, les logs de l'application fourniront un contexte expliquant pourquoi le point de terminaison de la sonde échoue.
Solution :
- Ajuster la configuration de la sonde : Corrigez le
path,port,command,initialDelaySeconds,periodSeconds, oufailureThresholdde la sonde. - Assurer la santé du point de terminaison de la sonde : Vérifiez que le point de terminaison de l'application ciblé par la sonde est réellement sain et répond comme prévu. L'application peut prendre trop de temps à démarrer, nécessitant un
initialDelaySecondsplus grand.
Pour les applications à démarrage lent, envisagez une startupProbe. Elle donne à l'application plus de temps pour s'initialiser avant que la sonde liveness ne commence à l'évaluer. C'est plus propre que de définir un initialDelaySeconds énorme pour chaque redémarrage.
3. Dépassement des limites de ressources
Si un conteneur tente constamment d'utiliser plus de mémoire que sa memory.limit ou est limité en CPU en raison du dépassement de sa cpu.limit, le noyau peut terminer le processus, souvent avec un événement OOMKilled (Out Of Memory Killed).
Étapes de diagnostic :
Décrire le Pod : Recherchez
OOMKilleddans la sectionLast StateouEvents. UnExit Code: 137indique souvent un événementOOMKilled.kubectl describe pod <nom-du-pod> -n <namespace>Vérifier avec
kubectl top: Simetrics-serverest installé, utilisezkubectl top podpour voir l'utilisation réelle des ressources de vos Pods.kubectl top pod <nom-du-pod> -n <namespace>
Solution :
- Augmenter les limites de ressources : Si votre application a vraiment besoin de plus de ressources, augmentez les
limitsdememoryet/oucpudans le manifeste de votre Pod. Cela peut nécessiter plus de capacité sur vos nœuds.resources: requests: memory: "256Mi" cpu: "500m" limits: memory: "512Mi" # Augmentez ceci cpu: "1000m" # Augmentez ceci - Optimiser l'application : Profilez votre application pour identifier et réduire sa consommation de ressources.
4. Problèmes d'autorisations
Les conteneurs peuvent planter s'ils manquent des autorisations nécessaires pour accéder aux fichiers, répertoires ou ressources réseau dont ils ont besoin.
Étapes de diagnostic :
- Consulter les logs : Les logs de l'application peuvent montrer des erreurs d'autorisation refusée (
EACCES). - Décrire le Pod : Vérifiez le
ServiceAccountutilisé et les paramètressecurityContextmontés.
Solution :
- Ajuster
securityContext: DéfinissezrunAsUser,fsGroup, ouallowPrivilegeEscalationselon les besoins. - Autorisations du ServiceAccount : Assurez-vous que le
ServiceAccountassocié au Pod dispose desRolesetClusterRolesnécessaires liés via desRoleBindingsetClusterRoleBindings. - Autorisations des volumes : Assurez-vous que les volumes montés (par exemple,
emptyDir,hostPath,ConfigMap,Secret) ont les autorisations correctes pour l'utilisateur du conteneur.
Un arbre de décision rapide
Quand quelqu'un dit "le pod est cassé", exécutez-les dans l'ordre :
kubectl get pod <nom-du-pod> -n <namespace> -o wide
kubectl describe pod <nom-du-pod> -n <namespace>
kubectl logs <nom-du-pod> -n <namespace> --all-containers=true --tail=100
kubectl logs <nom-du-pod> -n <namespace> --all-containers=true -p --tail=100
Ensuite, bifurquez :
- S'il n'y a pas de nœud dans
kubectl get pod -o wide, concentrez-vous sur la planification : requests, taints, affinité, quota et disponibilité des nœuds. - S'il y a un nœud mais que l'événement mentionne le tirage d'image, concentrez-vous sur le nom de l'image, l'étiquette, l'authentification du registre et l'accès réseau nœud-vers-registre.
- Si l'événement mentionne le montage ou l'attachement, concentrez-vous sur les PVC, PV, StorageClass, modes d'accès et placement de zone.
- Si le pod démarre puis redémarre, concentrez-vous sur les logs, le code de sortie, les sondes, la commande/args, la configuration, les secrets et les limites de mémoire.
Cet ordre évite une erreur courante : lire les logs d'application pour un pod qui n'a jamais réellement démarré un conteneur d'application.
Lire les codes de sortie sans réagir de manière excessive
Les codes de sortie sont des indices, pas des explications complètes.
1signifie généralement que l'application a renvoyé une erreur générale. Les logs sont plus importants que le nombre.2peut indiquer des erreurs d'utilisation de la ligne de commande dans de nombreux programmes.126signifie souvent que la commande existe mais ne peut pas être exécutée.127signifie souvent que la commande n'a pas été trouvée.137apparaît couramment lorsque le processus reçoitSIGKILL; dans Kubernetes, cela est souvent, mais pas toujours, lié à OOMKilled.143signifie que le processus a reçuSIGTERM, ce qui peut se produire lors d'une terminaison normale.
Si le code de sortie est 137, vérifiez Last State du pod et les événements avant de supposer une fuite de mémoire. Un drain de nœud, une éviction ou un kill manuel peuvent également terminer un conteneur.
Étapes de diagnostic générales et outils
Voici une liste de contrôle rapide des commandes à exécuter face à des problèmes de Pod :
- Obtenir un aperçu rapide : Vérifiez le statut de vos Pods.
kubectl get pods -n <namespace> kubectl get pods -n <namespace> -o wide - Informations détaillées sur le Pod : La commande la plus cruciale pour comprendre les événements, les états et les conditions du Pod.
kubectl describe pod <nom-du-pod> -n <namespace> - Logs du conteneur : Voyez ce que votre application rapporte.
kubectl logs <nom-du-pod> -n <namespace> kubectl logs <nom-du-pod> -p -n <namespace> # Instance précédente kubectl logs <nom-du-pod> -f -n <namespace> # Suivre les logs - Événements à l'échelle du cluster : Parfois, le problème ne vient pas d'un Pod spécifique mais d'un événement à l'échelle du cluster (par exemple, pression sur le nœud).
kubectl get events -n <namespace> - Débogage interactif : Si votre conteneur démarre mais plante rapidement, vous pouvez peut-être utiliser
execpour y accéder brièvement ou dans un conteneur de débogage séparé s'il est configuré.
(Remarque : Cela fonctionne uniquement si le conteneur reste en vie assez longtemps pour s'attacher.)kubectl exec -it <nom-du-pod> -n <namespace> -- bash
Bonnes pratiques pour éviter les problèmes de Pod
Mieux vaut prévenir que guérir. Suivre ces bonnes pratiques peut réduire considérablement les incidents Pending et CrashLoopBackOff :
- Définir des demandes et limites de ressources réalistes : Commencez avec des
requestsetlimitsraisonnables, puis affinez-les en fonction du profilage et de la surveillance de l'application. - Utiliser des étiquettes d'image spécifiques : Évitez les étiquettes
latesten production. Utilisez des étiquettes immuables (par exemple,v1.2.3,commit-sha) pour la reproductibilité. - Implémenter des sondes robustes : Configurez des sondes
livenessetreadinessqui reflètent avec précision la santé de votre application. Tenez compte des temps de démarrage avecinitialDelaySeconds. - Journalisation et surveillance centralisées : Utilisez des outils comme Prometheus, Grafana, la pile ELK ou des services de journalisation natifs du cloud pour collecter et analyser les logs et métriques des Pods.
- Contrôle de version pour les manifestes : Stockez vos manifestes Kubernetes dans un système de contrôle de version (par exemple, Git) pour suivre les modifications et faciliter les retours en arrière.
- Tests approfondis : Testez vos images de conteneur et vos déploiements Kubernetes dans des environnements de développement et de staging avant de déployer en production.
- Arrêts gracieux : Assurez-vous que vos applications gèrent les signaux
SIGTERMpour des arrêts gracieux, leur permettant de libérer des ressources avant la terminaison.
Ce qui le répare généralement le plus rapidement
Pour Pending, kubectl describe pod est généralement le chemin le plus rapide car les événements du planificateur et du kubelet expliquent ce que Kubernetes n'a pas pu faire. Pour CrashLoopBackOff, les logs précédents sont généralement le chemin le plus rapide car le conteneur actuel peut être trop récent pour montrer le crash qui a provoqué la boucle.
Après avoir résolu le problème immédiat, recherchez l'étape de prévention : des requests bien dimensionnées, de meilleures étiquettes d'image, une sonde de démarrage, une vérification de secret manquant dans CI, ou un runbook plus clair. Le meilleur incident de pod est celui qui devient plus facile à reconnaître la prochaine fois.