Introduction
Les événements Kubernetes sont l'un des premiers endroits où les opérateurs regardent quand quelque chose ne va pas, mais ils sont aussi l'un des plus mal compris. Un événement n'est pas une erreur en soi ; c'est un enregistrement horodaté de ce qui est arrivé à un objet du cluster, comme un pod planifié, un conteneur qui plante ou un volume qui échoue à se monter. Des erreurs courantes comme CrashLoopBackOff, ImagePullBackOff, FailedScheduling ou FailedMount apparaissent comme événements, et chacune pointe vers un problème sous-jacent différent. Cet article couvre les erreurs d'événements Kubernetes les plus fréquentes, comment les lire, comment les corriger avec des commandes pratiques et comment les empêcher de se reproduire.
Nous nous concentrons sur les opérations réelles pour les développeurs, les ingénieurs DevOps et les équipes de startups qui exécutent Kubernetes en production ou en préproduction. L'objectif est de vous donner un chemin clair depuis l'observation d'un événement jusqu'à la vérification de la correction, sans conjectures dangereuses. Chaque recommandation inclut des commandes kubectl concrètes, le résultat attendu et les étapes de récupération. Avant de changer quoi que ce soit, capturez l'état actuel et comprenez le rayon d'impact. Ensuite, faites un changement ciblé et vérifiez le résultat. Ce modèle de sécurité opérationnelle traverse tout l'article.
Gardez à l'esprit que les versions et distributions Kubernetes (vanilla, EKS, GKE, AKS, OpenShift) peuvent différer dans la formulation des événements ou les valeurs par défaut. Les commandes montrées ici fonctionnent sur Kubernetes 1.24 et ultérieur sauf indication contraire. Vérifiez toujours la version de votre cluster avec kubectl version avant d'appliquer des correctifs.
Inventaire de la version et de l'environnement
Avant de diagnostiquer les erreurs d'événements, sachez exactement avec quoi vous travaillez. Exécutez ces commandes pour établir une base de référence :
kubectl version --short
kubectl cluster-info
kubectl get nodes -o wide
Exemple de sortie (tronquée) pour un cluster sain :
Client Version: v1.27.3
K8s Master: https://192.168.49.2:8443
NAME STATUS ROLES AGE VERSION INTERNAL-IP
minikube Ready control-plane 10d v1.26.1 192.168.49.2
worker1 Ready <none> 10d v1.26.1 192.168.49.3
Cela vous indique l'adresse du serveur API, les versions des nœuds et l'état de santé général. Si un nœud est NotReady, les événements sur les pods planifiés sur ce nœud vont s'enchaîner. Traitez d'abord les problèmes de nœud.
Ensuite, identifiez l'espace de noms et les ressources qui vous intéressent. Utilisez kubectl get all -n <namespace> pour voir les pods, services, déploiements, etc. Pour un pod spécifique, obtenez des informations détaillées :
kubectl get pods -n myapp -o wide
NAME READY STATUS RESTARTS AGE
web-5db6d9c8f4-abcde 0/1 CrashLoopBackOff 5 10m
web-5db6d9c8f4-fghij 1/1 Running 0 5m
Ici, un pod est en boucle de plantage. Pour voir les événements de ce pod :
kubectl describe pod web-5db6d9c8f4-abcde -n myapp
Regardez la section Events en bas. Elle affichera les horodatages, la raison et le message. Exemple :
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 10m default-scheduler Successfully assigned myapp/web-5db6d9c8f4-abcde to worker1
Normal Pulled 9m kubelet Container image "nginx:latest" already present on machine
Normal Created 9m kubelet Created container web
Normal Started 9m kubelet Started container web
Warning BackOff 8m kubelet Back-off restarting failed container
Cela montre que le conteneur a démarré mais a ensuite échoué, déclenchant un backoff. Pour voir pourquoi il a échoué, récupérez les journaux :
kubectl logs web-5db6d9c8f4-abcde -n myapp --previous
L'option --previous est cruciale pour CrashLoopBackOff car elle obtient les journaux de l'instance précédente du conteneur, qui contient l'erreur ayant causé le redémarrage. Sans elle, vous ne verrez peut-être que les journaux de démarrage actuels (probablement en échec).
Si le pod est en attente en raison de problèmes de planification, regardez les événements pour FailedScheduling et les conditions des nœuds. Enregistrez toujours ces sorties dans vos notes d'incident. L'inventaire de l'environnement n'est pas une étape ponctuelle ; répétez-la après tout changement pour comparer les états.
Chemin de configuration sûr
La façon la plus sûre de corriger les erreurs d'événements est de d'abord les reproduire dans un environnement contrôlé. Évitez de modifier directement les manifestes de production sans les tester. Utilisez un cluster local comme minikube, kind ou k3s pour des expériences rapides. Par exemple, pour tester un manifeste avant de l'appliquer en production :
kubectl apply --dry-run=client -f deployment.yaml
# ou pour une validation côté serveur sans persistance :
kubectl apply --dry-run=server -f deployment.yaml
Si le manifeste passe, vous pouvez l'appliquer à un espace de noms de préproduction. Gardez toujours les manifestes versionnés dans Git et utilisez une stratégie de déploiement comme la mise à jour progressive pour limiter le rayon d'impact.
Quand un pod redémarre continuellement, inspectez l'état du déploiement :
kubectl rollout status deployment/web -n myapp
S'il est bloqué, vous pouvez mettre en pause le déploiement :
kubectl rollout pause deployment/web -n myapp
Ensuite, faites des modifications et reprenez ou annulez :
kubectl rollout undo deployment/web -n myapp
Pour les erreurs de configuration comme une ConfigMap ou un Secret manquant, le pod peut échouer à démarrer. Utilisez kubectl describe pour voir l'événement, puis vérifiez si les ressources existent :
kubectl get configmap,secret -n myapp
Si elles sont manquantes, créez-les à partir des bons fichiers ou valeurs. Évitez d'intégrer des secrets dans les manifestes ; utilisez les Secrets Kubernetes et référencez-les.
Après avoir corrigé la configuration, vérifiez que le pod est sain :
kubectl get pods -n myapp -w
# Ctrl+C pour arrêter de surveiller
Surveillez que le statut devienne Running et prêt 1/1 sans redémarrages. Un chemin de configuration sûr inclut toujours un plan de retour en arrière.
Vérification et diagnostics
Une fois que vous avez appliqué un correctif, vous devez vérifier qu'il fonctionne comme prévu. Ne supposez pas ; vérifiez avec des commandes et des journaux.
Pour un pod qui fonctionne maintenant, testez la connectivité depuis l'intérieur du cluster ou via le transfert de port :
kubectl port-forward pod/web-5db6d9c8f4-abcde 8080:80 -n myapp
Puis dans un autre terminal :
curl -I http://localhost:8080
La sortie attendue doit inclure HTTP/1.1 200 OK si le conteneur sert du HTTP. Sinon, examinez à nouveau les journaux.
Pour diagnostiquer les plantages de conteneurs, obtenez le code de sortie :
kubectl get pods -n myapp -o jsonpath='{.items[0].status.containerStatuses[0].lastState.terminated.exitCode}'
Codes de sortie courants :
0: sortie normale (mais s'il sort immédiatement, peut-être que le conteneur n'a pas de processus au premier plan)1: erreur d'application2: mauvaise utilisation des commandes internes du shell126: la commande invoquée ne peut pas s'exécuter127: commande introuvable137: SIGKILL (souvent une terminaison OOM ou un arrêt du pod)139: SIGSEGV (erreur de segmentation)143: SIGTERM (arrêt gracieux)
Par exemple, le code de sortie 137 indique que le conteneur a été tué, probablement en raison de limites de mémoire. Vérifiez l'utilisation des ressources et les limites du pod :
kubectl top pod -n myapp
kubectl describe pod web-5db6d9c8f4-abcde -n myapp | grep -A5 Limits
Si le conteneur a dépassé la mémoire, augmentez la limite ou réduisez l'utilisation de la mémoire.
Les erreurs d'événements nécessitent souvent de vérifier les événements au niveau du cluster :
kubectl get events -n myapp --sort-by=.lastTimestamp
Vous pouvez filtrer les événements par sélecteur de champ, par exemple, pour ne voir que les avertissements :
kubectl get events -n myapp --field-selector type=Warning
Cela vous aide à vous concentrer sur les problèmes. Si vous utilisez des outils de surveillance comme Prometheus ou Loki, corrélez les horodatages des événements avec les métriques et les journaux pour une image complète.
Modes de défaillance et récupération
Plongeons dans des erreurs d'événements courantes spécifiques et comment s'en remettre.
CrashLoopBackOff
À quoi cela ressemble : Statut du pod CrashLoopBackOff, les événements montrent un avertissement BackOff. Pourquoi cela arrive : Le conteneur démarre puis sort avec un code non nul, de façon répétée. Causes courantes et correctifs :
- Erreur d'application : Vérifiez les journaux avec
kubectl logs <pod> --previous. Corrigez le code ou la configuration. Par exemple, si une application Python échoue parce qu'un module est manquant, ajoutez la dépendance à l'image ou aux exigences. - Fichier ou configuration manquant : Le conteneur attend un fichier de configuration mais il n'est pas monté. Assurez-vous que la ConfigMap ou le Secret est monté correctement.
- Mauvaise configuration de la sonde de vivacité : Si la sonde de vivacité est trop stricte, le conteneur peut être tué même s'il est sain. Ajustez
initialDelaySeconds,periodSeconds,timeoutSecondsetfailureThreshold. - Commande ou arguments incorrects : La
commandou lesargsdu pod peuvent être incorrects. Vérifiez le point d'entrée de l'image. Si l'image s'attend à s'exécuter en tant que non-root, définissezsecurityContext.runAsUser.
Récupération : Corrigez la cause racine, puis redémarrez le pod en le supprimant (le déploiement le recréera) ou en déployant une nouvelle version.
ImagePullBackOff
À quoi cela ressemble : Statut du pod ImagePullBackOff ou ErrImagePull, les événements montrent Failed to pull image. Pourquoi cela arrive : L'image du conteneur ne peut pas être extraite du registre. Causes courantes et correctifs :
- Nom ou étiquette d'image incorrect : Vérifiez l'orthographe, le registre et l'étiquette. Utilisez
docker pull <image>localement pour tester. - Identifiants de registre privé manquants : Créez un Secret avec les identifiants du registre et référencez-le dans
imagePullSecrets. - Registre inaccessible : Vérifiez la connectivité réseau des nœuds au registre.
- Limitation de débit : Docker Hub limite les tirages anonymes. Utilisez des tirages authentifiés ou un miroir.
Récupération : Corrigez la référence de l'image ou les identifiants, puis supprimez le pod pour forcer un nouveau tirage, ou mettez à jour le déploiement.
FailedScheduling
À quoi cela ressemble : Pod bloqué en Pending, les événements montrent FailedScheduling avec des raisons comme 0/3 nodes are available: 3 Insufficient cpu. Pourquoi cela arrive : Aucun nœud n'a assez de ressources, ou il y a des teintures/tolérances, ou les sélecteurs de nœud/règles d'affinité ne peuvent pas être satisfaits. Causes courantes et correctifs :
- Demandes de ressources trop élevées : Réduisez
resources.requestsou augmentez la taille des nœuds. - Teintures et tolérances : Les nœuds peuvent avoir des teintures ; les pods ont besoin de tolérances correspondantes.
- Incompatibilité du sélecteur de nœud : Le
nodeSelectordu pod peut ne correspondre à aucune étiquette de nœud. - Anti-affinité de pod : Les règles peuvent empêcher la planification.
Récupération : Ajustez la spécification du pod ou la capacité du cluster. Utilisez kubectl describe pod pour voir la raison exacte.
FailedMount
À quoi cela ressemble : Le conteneur ne peut pas démarrer, les événements montrent FailedMount ou MountVolume.SetUp failed. Pourquoi cela arrive : Le volume ne peut pas être monté, souvent en raison d'un PersistentVolume (PV) ou d'un PersistentVolumeClaim (PVC) manquant, ou d'un nom de secret/configmap incorrect. Causes courantes et correctifs :
- PVC non lié : Vérifiez
kubectl get pvc -n <ns>. S'il est en attente, il n'y a peut-être pas de PV ou de StorageClass correspondant. - Secret/ConfigMap manquant : Créez la ressource requise ou corrigez la référence.
- Problèmes de NFS ou de volume cloud : Vérifiez la connectivité et les autorisations du backend de stockage.
Récupération : Corrigez le stockage sous-jacent ou la référence, puis recréez le pod.
Diagnostics avancés avec les événements
Pour un dépannage plus approfondi, utilisez la sortie JSON et jq pour filtrer les événements :
kubectl get events -n myapp -o json | jq '.items[] | select(.reason=="FailedScheduling") | .message'
Vous pouvez également surveiller les événements en temps réel avec kubectl get events -w dans un terminal séparé pendant que vous appliquez des modifications. Cela donne un retour immédiat.
Si les événements ne fournissent pas assez de détails, vérifiez les journaux du kubelet sur le nœud où le pod est planifié :
journalctl -u kubelet -f
# ou si kubelet s'exécute comme conteneur :
docker logs kubelet
Ces journaux contiennent souvent des messages d'erreur plus détaillés, en particulier pour les problèmes de montage ou les problèmes d'exécution de conteneurs.
Pour les événements anciens et purgés (la rétention par défaut est de 1 heure), vous devrez peut-être vous appuyer sur les journaux des systèmes de surveillance ou augmenter le TTL des événements dans kube-apiserver si nécessaire pour l'analyse forensique.
Pièges courants et comment les éviter
De nombreuses erreurs d'événements Kubernetes partagent des pièges évitables. Voici les plus fréquents que nous voyons sur le terrain.
Ignorer l'option --previous
Quand un conteneur est en boucle de plantage, kubectl logs <pod> montre les journaux du conteneur actuel (souvent juste en train de démarrer). L'erreur réelle est dans les journaux du conteneur précédent. Utilisez toujours --previous pour CrashLoopBackOff. Sans cela, vous manquez la cause racine et perdez du temps.
Comment éviter : Faites de kubectl logs <pod> --previous votre première commande pour tout pod qui redémarre.
Supposer que les événements sont des erreurs
Tous les événements ne sont pas mauvais. Les événements Normal comme Scheduled, Pulled, Created et Started sont attendus. Seuls les événements Warning indiquent des problèmes. Le filtrage par type vous aide à vous concentrer.
Comment éviter : Utilisez kubectl get events --field-selector type=Warning pour ne voir que les avertissements.
Changer trop de choses à la fois
Dans la panique, les équipes modifient souvent plusieurs configurations simultanément. Si le pod se met à fonctionner, elles ne savent pas quel changement l'a corrigé ; s'il échoue, elles ont un gâchis. Cela viole le principe d'un changement à la fois.
Comment éviter : Faites un changement ciblé, vérifiez, puis continuez. Gardez un plan de retour en arrière.
Ne pas vérifier les limites de ressources
De nombreux problèmes de CrashLoopBackOff sont dus à OOMKilled parce que les limites de mémoire sont trop basses. Le pod montre le code de sortie 137. Augmenter les limites ou optimiser l'utilisation de la mémoire est souvent le correctif.
Comment éviter : Définissez des demandes et limites de ressources raisonnables, surveillez l'utilisation avec kubectl top et ajustez avant que les limites ne soient atteintes.
Oublier imagePullSecrets pour les registres privés
Lors du passage d'images publiques à privées, les pods échouent avec ImagePullBackOff parce que les identifiants sont manquants. C'est un oubli de configuration classique.
Comment éviter : Incluez toujours imagePullSecrets dans la spécification de votre pod lorsque vous utilisez des registres privés. Testez le tirage de l'image manuellement sur un nœud pour confirmer les identifiants.
Ne pas utiliser assez kubectl describe
kubectl describe pod montre l'historique des événements que kubectl get events pourrait manquer ou qui a été purgé. Il montre aussi les états des conteneurs, les sondes et les informations de montage en un seul endroit. De nombreux opérateurs sautent directement aux journaux et manquent les indices des événements.
Comment éviter : Faites de kubectl describe pod <name> une partie de votre triage initial, juste après kubectl get pods.
Propriétaires et cadence de revue
Dans un cadre d'équipe, le dépannage des événements Kubernetes devrait avoir une propriété claire. Nous recommandons d'attribuer une rotation d'ingénieurs d'astreinte responsables du triage initial. Par exemple, Priya Shah, responsable de l'ingénierie, possède le processus de réponse aux incidents et examine les tendances des erreurs d'événements chaque semaine. L'ingénieur d'astreinte enquête sur chaque erreur d'événement, documente la cause racine et met à jour le manuel. Une revue post-incident est tenue pour toute erreur d'événement qui cause plus de 10 minutes d'indisponibilité ou des occurrences répétées. Cela garantit que les correctifs ne sont pas de simples pansements mais mènent à des améliorations à long terme.
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle lorsque vous rencontrez une erreur d'événement Kubernetes. C'est une version compacte des flux de travail décrits ci-dessus, avec des commandes concrètes.
| Étape | Action | Commande / Exemple | Propriétaire | Fréquence |
|---|---|---|---|---|
| 1 | Identifier la ressource en échec | kubectl get pods -n myapp -o wide | Ingénieur d'astreinte | Chaque incident |
| 2 | Obtenir les événements détaillés et l'état | kubectl describe pod <pod-name> -n myapp | Ingénieur d'astreinte | Chaque incident |
| 3 | Vérifier les journaux précédents pour le plantage | kubectl logs <pod-name> -n myapp --previous | Ingénieur d'astreinte | Chaque incident |
| 4 | Examiner les avertissements du cluster | kubectl get events -n myapp --field-selector type=Warning | Ingénieur d'astreinte | Chaque incident |
| 5 | Diagnostiquer la cause racine | Basé sur la raison de l'événement et les journaux | Ingénieur d'astreinte | Chaque incident |
| 6 | Appliquer un correctif minimal en préproduction d'abord | kubectl apply --dry-run=server -f fix.yaml | Développeur | Avant le changement en production |
| 7 | Vérifier le correctif en préproduction | kubectl port-forward et curl | Développeur | Après chaque correctif |
| 8 | Déployer en production avec un plan de retour en arrière | kubectl apply -f fix.yaml (déploiement) | Responsable de l'ingénierie | Après vérification en préproduction |
| 9 | Surveiller la récurrence | kubectl get pods -w et alertes | Ingénieur d'astreinte | 24 heures après le correctif |
| 10 | Mettre à jour le manuel et partager les apprentissages | Documentation dans le wiki | Ingénieur d'astreinte | Revue hebdomadaire |
Conclusion
Les erreurs d'événements Kubernetes sont gérables si vous les abordez systématiquement. Commencez par l'inventaire de l'environnement, utilisez kubectl describe et kubectl logs --previous pour lire l'histoire des événements, appliquez un correctif ciblé à la fois et vérifiez soigneusement. Les erreurs courantes comme CrashLoopBackOff, ImagePullBackOff, FailedScheduling et FailedMount ont des causes et des correctifs bien connus décrits ci-dessus. Évitez les pièges d'ignorer les journaux précédents, de mélanger les changements et de négliger les limites de ressources. Attribuez une propriété claire et examinez régulièrement les incidents pour améliorer les processus.
Comme prochaine étape, choisissez une vérification à faible risque de cet article, enregistrez l'état actuel de votre cluster, exécutez les commandes documentées, comparez le résultat avec le signal attendu et notez toute divergence. Prenez l'habitude de vérifier les événements avant et après chaque changement.
Un flux de travail opérationnel fiable rend les défaillances visibles, protège les valeurs sensibles, limite les changements à la ressource prévue et définit la vérification de la récupération avant qu'un incident ne force la décision. Avec la pratique, vous transformerez les événements Kubernetes d'une source de confusion en un outil de diagnostic puissant.