Guide complet de dépannage des échecs de Pods Kubernetes
Naviguez dans les complexités des échecs de Pods Kubernetes avec ce guide complet. Apprenez le processus structuré pour diagnostiquer les problèmes courants comme CrashLoopBackOff, ImagePullBackOff et l'épuisement des ressources. Nous détaillons comment utiliser des outils cruciaux comme `kubectl describe` et `kubectl logs --previous` pour identifier la cause racine, interpréter les états de sortie des conteneurs et mettre en œuvre des correctifs pratiques pour maintenir la disponibilité et la stabilité fiables des applications.
Guide complet de dépannage des échecs de Pods Kubernetes
Le dépannage des échecs de pods Kubernetes consiste moins à mémoriser chaque statut qu'à apprendre où Kubernetes laisse des indices. Un pod échoue presque jamais "silencieusement". Le planificateur, le kubelet, l'exécution du conteneur, le registre d'images, le plugin de volume et votre application laissent tous des traces à différents endroits. L'astuce est de les vérifier dans le bon ordre pour ne pas passer vingt minutes à lire les logs d'application pour un pod qui n'a jamais tiré son image.
Je commence généralement par une question : le pod a-t-il échoué avant le démarrage du conteneur, pendant le démarrage du conteneur, ou après le début de l'exécution de l'application ? Cette simple division maintient l'investigation ancrée. Pending indique généralement un problème de planification, de stockage ou de configuration d'image. ImagePullBackOff indique un problème de chemin de registre, de tag, d'identifiants ou de sortie de nœud. CrashLoopBackOff signifie généralement que le processus démarre puis se termine, bien que la raison puisse être une configuration, un fichier manquant, une mauvaise commande, une dépendance défaillante ou une pression mémoire.
Les trois piliers du diagnostic de Pod
Le dépannage commence par l'utilisation de trois commandes kubectl principales pour recueillir toutes les informations disponibles sur le Pod défaillant.
1. Vérification initiale du statut (kubectl get pods)
La première étape consiste toujours à déterminer l'état actuel du Pod et de ses conteneurs. Portez une attention particulière aux colonnes STATUS et READY.
kubectl get pods -n my-namespace
Interprétation du statut du Pod
| Statut | Signification | Action initiale |
|---|---|---|
| Running | Au moins un conteneur est en cours d'exécution ; cela ne signifie pas toujours que l'application sert du trafic. | Vérifier READY, les redémarrages et les événements de readiness. |
| Pending | Le Pod a été accepté par Kubernetes mais les conteneurs ne sont pas encore créés. | Vérifier les événements de planification ou le statut de tirage d'image. |
| CrashLoopBackOff | Le conteneur démarre, plante, et Kubelet tente de le redémarrer à plusieurs reprises. | Vérifier les logs d'application (kubectl logs --previous). |
| ImagePullBackOff | Kubelet ne peut pas tirer l'image conteneur requise. | Vérifier le nom de l'image, le tag et les identifiants du registre. |
| Error | Le Pod s'est terminé en raison d'une erreur d'exécution ou d'une commande de démarrage échouée. | Vérifier les logs et les événements describe. |
| Terminating/Unknown | Le Pod est en cours d'arrêt ou l'hôte Kubelet est injoignable. | Vérifier la santé du nœud. |
2. Inspection approfondie (kubectl describe pod)
Si le statut est autre que Running, la commande describe fournit un contexte crucial, détaillant les décisions de planification, l'allocation des ressources et les états des conteneurs.
kubectl describe pod [POD_NAME] -n my-namespace
Concentrez-vous sur ces sections dans la sortie :
- Containers/Init Containers : Vérifiez l'
State(en particulierWaitingouTerminated) et leLast State(où la raison de l'échec est souvent enregistrée, par exempleReason: OOMKilled). - Resource Limits : Vérifiez que les
LimitsetRequestssont correctement définis. - Events : C'est la section la plus critique. Les événements montrent l'historique du cycle de vie, y compris les échecs de planification, les problèmes de montage de volume et les tentatives de tirage d'image.
Astuce : Si la section
Eventsaffiche un message comme "0/N nodes available", le Pod échoue probablement à se planifier en raison de ressources insuffisantes (CPU, mémoire) ou de règles d'affinité non satisfaites.
Lisez les événements de bas en haut lorsque vous voulez l'indice le plus récent, mais n'ignorez pas les événements plus anciens. Un pod peut avoir plus d'un problème. Par exemple, un déploiement peut commencer par FailedScheduling parce que la mémoire demandée est trop élevée, puis passer à ImagePullBackOff après l'ajout d'un nœud. Si vous ne regardez que le statut final, vous risquez de manquer le changement qui a fait avancer le problème.
3. Examen des logs (kubectl logs)
Pour les problèmes d'exécution d'application, les logs fournissent la trace de la pile ou les messages d'erreur expliquant pourquoi le processus s'est terminé.
# Vérifier les logs actuels du conteneur
kubectl logs [POD_NAME] -n my-namespace
# Vérifier les logs pour un conteneur spécifique dans le Pod
kubectl logs [POD_NAME] -c [CONTAINER_NAME] -n my-namespace
# Crucial pour CrashLoopBackOff : Vérifier les logs de l'exécution *précédente* qui a échoué
kubectl logs [POD_NAME] --previous -n my-namespace
Si le pod a des sidecars, incluez toujours -c. De nombreuses enquêtes frustrantes proviennent de la lecture des logs du sidecar sain au lieu du conteneur d'application défaillant. Pour les échecs de conteneurs init, utilisez également le nom du conteneur init avec -c :
kubectl logs [POD_NAME] -c [INIT_CONTAINER_NAME] -n my-namespace
Scénarios courants d'échec de Pod et solutions
La plupart des échecs de Pod tombent dans quelques modèles reconnaissables, chacun nécessitant une approche de diagnostic ciblée.
Scénario 1 : CrashLoopBackOff
C'est l'échec de Pod le plus fréquent. Il signifie que le conteneur démarre avec succès, mais que l'application à l'intérieur du conteneur se termine immédiatement (avec un code de sortie non nul).
Diagnostic :
- Utilisez
kubectl logs --previouspour voir la trace ou la raison de la sortie. - Utilisez
kubectl describepour vérifier leExit Codedans la sectionLast State.
Causes courantes et correctifs :
- Code de sortie 1/2 : Erreur générale de l'application, fichier de configuration manquant, échec de connectivité à la base de données, ou plantage de l'application dû à une mauvaise entrée.
- Correctif : Déboguez le code de l'application ou vérifiez les ConfigMaps/Secrets montés.
- Dépendances manquantes : Le script de point d'entrée nécessite des fichiers ou des environnements qui ne sont pas présents.
- Correctif : Vérifiez le Dockerfile et le processus de construction de l'image.
- Mauvaise commande ou arguments : L'image conteneur est valide, mais la commande dans la spécification du Pod remplace incorrectement le point d'entrée de l'image.
- Correctif : Comparez la
commandet lesargsdu Déploiement avec la commande de démarrage attendue de l'image. Testez la même image localement si possible.
- Correctif : Comparez la
- Redémarrages induits par les sondes : Une sonde de liveness peut tuer une application à démarrage lent avant qu'elle ne finisse de chauffer.
- Correctif : Augmentez
initialDelaySeconds, utilisez unestartupProbe, ou pointez la sonde vers un point de terminaison de santé moins coûteux.
- Correctif : Augmentez
Un modèle pratique consiste à déployer une copie temporaire avec la même image mais une commande inoffensive, puis à inspecter le système de fichiers et l'environnement :
kubectl run debug-image \
--image=registry.example.com/app:tag \
--restart=Never \
--command -- sleep 3600
kubectl exec -it debug-image -- /bin/sh
Cela ne remplace pas la correction du Déploiement, mais cela aide à répondre rapidement à des questions simples : le fichier de configuration est-il réellement dans l'image, le binaire existe-t-il, le conteneur a-t-il le shell attendu, et les variables d'environnement sont-elles présentes ?
Scénario 2 : ImagePullBackOff / ErrImagePull
Cela se produit lorsque le Kubelet ne peut pas récupérer l'image conteneur spécifiée dans la définition du Pod.
Diagnostic :
- Vérifiez la section
Eventsdekubectl describepour le message d'erreur spécifique (par exemple,404 Not Foundouauthentication required).
Causes courantes et correctifs :
- Faute de frappe ou mauvais tag : Le nom de l'image ou le tag est incorrect.
- Correctif : Corrigez le nom de l'image dans la spécification du Déploiement ou du Pod.
- Accès au registre privé : Le cluster n'a pas les identifiants pour tirer depuis un registre privé (comme Docker Hub, GCR, ECR).
- Correctif : Assurez-vous qu'un
imagePullSecretapproprié est référencé dans la spécification du Pod et que le Secret existe dans l'espace de noms.
- Correctif : Assurez-vous qu'un
# Exemple d'extrait de spécification de Pod pour utiliser un secret de tirage
spec:
containers:
...
imagePullSecrets:
- name: my-registry-secret
Vérifiez également où se trouve le secret de tirage. Les secrets Kubernetes sont limités aux espaces de noms. Un secret nommé regcred dans default n'aidera pas un pod dans payments. Si la même image fonctionne dans un espace de noms mais échoue dans un autre, comparez les comptes de service et les secrets de tirage d'image avant de supposer que le registre est cassé :
kubectl get serviceaccount default -n payments -o yaml
kubectl get secret regcred -n payments
Scénario 3 : Statut Pending (Bloqué)
Un Pod reste en statut Pending, indiquant généralement qu'il ne peut pas être planifié sur un Nœud ou qu'il attend des ressources (comme un PersistentVolume).
Diagnostic :
- Exécutez
kubectl describeet regardez la sectionEvents.
Causes courantes et correctifs :
- Épuisement des ressources : Le cluster manque de Nœuds avec suffisamment de CPU ou de Mémoire disponibles pour satisfaire les
requestsdu Pod.- Correctif : Augmentez la taille du cluster, ou réduisez les demandes de ressources du Pod (si possible).
- Exemple de message d'événement :
0/4 nodes are available: 4 Insufficient cpu.
- Problèmes de liaison de volume : Le Pod nécessite un
PersistentVolumeClaim(PVC) qui ne peut pas être lié à unPersistentVolume(PV) sous-jacent.- Correctif : Vérifiez le statut du PVC (
kubectl get pvc) et assurez-vous que la StorageClass fonctionne.
- Correctif : Vérifiez le statut du PVC (
- Inadéquation de sélecteur ou d'affinité : Le pod demande une étiquette de nœud qui n'existe pas, ou une règle d'affinité requise exclut chaque nœud.
- Correctif : Comparez
nodeSelector,nodeAffinity, et les étiquettes de nœud aveckubectl get nodes --show-labels.
- Correctif : Comparez
- Taints non tolérées : Les nœuds sont disponibles, mais ils repoussent ce pod car il manque une tolérance correspondante.
- Correctif : Ajoutez la tolérance prévue au pod, ou supprimez la taint si elle ne représente plus une règle de placement réelle.
Scénario 4 : OOMKilled (Tué par manque de mémoire)
Bien que cela aboutisse généralement à un statut CrashLoopBackOff, la cause sous-jacente est spécifique : le conteneur a utilisé plus de mémoire que la limite définie dans sa spécification, ce qui a provoqué sa terminaison forcée par le système d'exploitation hôte (via le Kubelet).
Diagnostic :
- Vérifiez
kubectl describe->Last State->Reason: OOMKilled.
Correctifs :
- Augmenter les limites : Augmentez la
limitde mémoire dans la spécification du Pod, offrant plus de marge. - Optimiser l'application : Profilez l'application pour réduire son empreinte mémoire.
- Définir les requests : Assurez-vous que les
requestssont proches de l'utilisation réelle en régime permanent pour améliorer la fiabilité de la planification.
resources:
limits:
memory: "512Mi" # Augmentez cette valeur
requests:
memory: "256Mi"
Soyez prudent avec les "correctifs" de mémoire qui ne font qu'augmenter la limite. Si l'application a une fuite, une limite plus élevée peut seulement retarder le prochain échec et faire porter plus de risque au nœud. Examinez la mémoire au fil du temps dans votre système de métriques. Un motif en dents de scie qui revient à la ligne de base après le garbage collection est différent d'une montée régulière jusqu'à OOM.
Scénario 5 : CreateContainerConfigError et CreateContainerError
Ces statuts sont faciles à négliger car ils ne ressemblent pas à des échecs d'application. Ils signifient généralement que le kubelet n'a pas pu assembler la configuration du conteneur.
Les causes courantes incluent :
- Un ConfigMap ou Secret référencé n'existe pas dans l'espace de noms.
- Une clé dans un ConfigMap ou Secret est mal orthographiée.
- Un chemin de montage de volume entre en conflit avec un autre montage.
- Le conteneur référence un contexte de sécurité invalide.
La vérification la plus rapide reste describe :
kubectl describe pod [POD_NAME] -n my-namespace
Recherchez des messages d'événement tels que secret "app-config" not found ou configmap "settings" not found. Ensuite, vérifiez l'objet :
kubectl get secret app-config -n my-namespace
kubectl get configmap settings -n my-namespace -o yaml
C'est une erreur courante de pipeline de déploiement. Le manifeste de l'application est appliqué, mais l'étape de création du secret a échoué ou a été exécutée dans le mauvais espace de noms.
Scénario 6 : Running mais pas Prêt
Un pod peut afficher Running tout en étant inutilisable. La colonne READY vous indique combien de conteneurs sont prêts selon leurs sondes de readiness. Un pod avec 1/2 ou 0/1 peut être vivant mais retiré des points de terminaison du Service.
Vérifiez les points de terminaison lorsque le trafic échoue mais que les pods semblent vivants :
kubectl get endpoints [SERVICE_NAME] -n my-namespace
kubectl describe pod [POD_NAME] -n my-namespace
Si la liste des points de terminaison est vide, le problème peut être une sonde de readiness, une inadéquation du sélecteur de Service, ou l'application qui écoute sur un port différent de celui attendu par le Service. Dans les incidents réels, c'est là que les gens perdent du temps : ils continuent à redémarrer les pods même si les pods ne sont pas la raison pour laquelle le trafic est manquant.
Prévenir les échecs futurs : Bonnes pratiques
Des applications robustes nécessitent une configuration minutieuse pour éviter les pièges de déploiement courants.
Utiliser des sondes de Liveness et Readiness
Une mise en œuvre correcte des sondes permet à Kubernetes de gérer intelligemment la santé des conteneurs :
- Sondes de Liveness : Déterminent si le conteneur est suffisamment sain pour continuer à s'exécuter. Si la sonde de liveness échoue, Kubelet redémarrera le conteneur (résolvant les verrous logiciels).
- Sondes de Readiness : Déterminent si le conteneur est prêt à servir du trafic. Si la sonde de readiness échoue, le Pod est retiré des points de terminaison du service, empêchant les requêtes échouées pendant que le conteneur récupère.
Ne pointez pas les sondes de liveness vers des vérifications de dépendances profondes à moins que vous ne vouliez vraiment que Kubernetes redémarre le conteneur chaque fois que cette dépendance a une courte panne. Une base de données indisponible pendant trente secondes n'est généralement pas la preuve que le processus est mort. Readiness est le meilleur endroit pour dire "n'envoyez pas de trafic à ce pod pour le moment".
Appliquer les limites et les demandes de ressources
Définissez toujours les exigences de ressources pour les conteneurs. Cela empêche les Pods de consommer des ressources excessives (conduisant à l'instabilité du nœud) et garantit que le planificateur peut placer le Pod sur un Nœud avec une capacité suffisante.
Utiliser des conteneurs Init pour la configuration
Si un Pod nécessite une vérification de dépendance ou une configuration de données avant le démarrage de l'application principale (par exemple, attendre la fin d'une migration de base de données), utilisez un conteneur Init. Si le conteneur Init échoue, le Pod le redémarrera à plusieurs reprises, isolant proprement les erreurs de configuration des erreurs d'exécution de l'application.
Un flux de triage pratique
Lorsque vous êtes de garde, utilisez un chemin reproductible :
- Vérifiez
kubectl get pods -n <namespace> -o widepour voir le statut, les redémarrages, l'âge et le placement du nœud. - Exécutez
kubectl describe podet lisez les événements, l'état, le dernier état, les montages et les paramètres de ressources. - Tirez les logs avec
kubectl logs, en ajoutant--previouspour les conteneurs redémarrés et-cpour les pods multi-conteneurs. - Si le pod est
Pending, inspectez la planification, les taints, les étiquettes de nœud et les PVC avant de lire les logs d'application. - Si le pod est
Runningmais ne reçoit pas de trafic, inspectez les sondes de readiness, les sélecteurs de Service et les points de terminaison. - Si le pod a été OOMKilled, comparez les limites avec les graphiques de mémoire réels avant d'augmenter simplement le nombre.
Cet ordre vous empêche de sauter directement à l'application alors que Kubernetes ne l'a même pas encore démarrée.
Vérification finale
L'habitude la plus utile est de séparer les symptômes des causes. CrashLoopBackOff est un symptôme. La cause peut être un secret manquant, une mauvaise migration, une sonde de liveness ou une limite de mémoire. Pending est un symptôme. La cause peut être des demandes de CPU, un PVC, une taint ou un sélecteur de nœud. Laissez le statut du pod vous dire où regarder, puis laissez les événements et les logs vous dire ce qui a changé.