Introduction
Les pannes Kubernetes peuvent être bruyantes et déroutantes sous la pression. Cet article vous propose un flux de travail pratique, orienté sécurité d'abord, avec des exemples concrets, les commandes exactes à exécuter et des correctifs ciblés que vous pouvez vérifier rapidement. Vous apprendrez à :
- Trier l'impact et localiser le composant en échec rapidement
- Lire les événements, les journaux de pod et de nœud, et les champs de statut
- Classer les pannes et lancer des vérifications de cause racine ciblées
- Appliquer des remédiations sûres et valider les résultats
- Répéter le tout localement avant de toucher à la production
Outils présents dans les exemples : images Docker et registres, releases Helm, pipelines GitLab CI/CD, Ingress Nginx, StorageClasses basées sur Ceph, et métriques Prometheus.
Vue d'ensemble du workflow
Suivez ce parcours de bout en bout. Chaque étape privilégie l'inspection en lecture seule avant toute modification.
1. Définir le périmètre et localiser le problème
Confirmez le contexte et l'espace de noms :
kubectl config current-context
kubectl get ns
kubectl get pods -A -o wide
Identifiez la charge de travail et le composant en échec (pod, deployment, statefulset, daemonset, job, cronjob, service, ingress).
2. Collecter les signaux rapides (lecture seule)
Santé globale :
kubectl get nodes -o wide
kubectl get pods -A --field-selector=status.phase!=Running
kubectl get deploy,sts,ds -A
Les événements racontent l'histoire dans l'ordre :
kubectl get events -A --sort-by=.metadata.creationTimestamp
describe ajoute le contexte de décision du scheduler et des contrôleurs :
kubectl -n <ns> describe pod <pod>
Journaux pour la tentative courante et la précédente du conteneur :
kubectl -n <ns> logs <pod> -c <container> --tail=200
kubectl -n <ns> logs <pod> -c <container> --previous --tail=200
Câblage service et endpoints :
kubectl -n <ns> get svc,ep
kubectl -n <ns> describe svc <name>
Signaux de stockage :
kubectl -n <ns> get pvc
kubectl -n <ns> describe pvc <pvc>
kubectl get storageclass
Pression sur le nœud et kubelet :
kubectl describe node <node>
# Si vous avez un accès SSH au nœud
sudo journalctl -u kubelet -n 200 --no-pager
3. Classer la panne rapidement
Statuts de pod courants et ce qu'ils suggèrent :
- Pending : le scheduler ne peut pas placer le pod (ressources, nodeSelector, taints, tolerations, affinity, PVC Pending)
- ContainerCreating : latence de pull d'image, problèmes de montage de volume, initialisation CNI (Container Network Interface) : interface réseau de conteneur, montage de secrets/config
- ImagePullBackOff : mauvaise référence d'image ou identifiants incorrects
- CrashLoopBackOff : l'application échoue répétitivement au démarrage
- OOMKilled : limite mémoire trop basse ou fuite mémoire
- RunContainerError : problème d'entrée (entrypoint) ou de permissions
- 0/1 ready (ou similaire) : sonde de readiness en échec
- NodeNotReady : santé du nœud, réseau, kubelet ou problèmes cloud
4. Vérifications de cause racine et remédiations sûres
Voici des playbooks ciblés avec des commandes à risque minimal en premier.
A. ImagePullBackOff
Vérifications :
kubectl -n <ns> describe pod <pod> | sed -n '/Events/,$p'
kubectl -n <ns> get sa <sa> -o yaml
kubectl -n <ns> get secret
Correctifs :
# Corriger le nom ou le tag de l'image
kubectl -n <ns> set image deploy/<name> <container>=<repo>/<image>:<tag>
kubectl -n <ns> rollout status deploy/<name>
# Ajouter ou corriger le secret de registre
kubectl -n <ns> create secret docker-registry regcred \
--docker-server=<registry> --docker-username=<user> \
--docker-password=<pass> --docker-email=<email>
# Le référencer dans le spec du pod sous imagePullSecrets
B. CrashLoopBackOff
Vérifications :
kubectl -n <ns> logs <pod> -c <container> --previous --tail=200
kubectl -n <ns> get pod <pod> -o yaml
Causes typiques et correctifs :
- Mauvaise configuration ou clé d'env/secret manquante : corriger la ConfigMap/Secret et redémarrer le rollout.
kubectl -n <ns> rollout restart deploy/<name>
kubectl -n <ns> rollout status deploy/<name>
- L'application a besoin de temps au démarrage : augmenter
readinessProbe.initialDelaySecondsoutimeoutSeconds. - Mauvais entrypoint : corriger
commandetargsvers le binaire ou script attendu.
C. OOMKilled
Vérifications :
kubectl -n <ns> describe pod <pod> | grep -i -E 'oom|memory'
kubectl top pod -n <ns> <pod>
Correctifs :
- Augmenter la limite mémoire ou réduire l'utilisation. S'assurer que les requests reflètent les besoins réels pour éviter l'éviction ou le churn de scheduling.
- Pour les pics mémoire, ajouter des plafonds de heap (ex.
-Xmxpour JVM), limiter les workers, ou activer des limites mémoire au niveau de l'application.
D. Pod Pending (Non planifiable)
Vérifications :
kubectl -n <ns> describe pod <pod> | sed -n '/Events/,$p'
kubectl get nodes
Correctifs :
- Baisser des requests gonflées ou les ajuster selon l'usage réel via
kubectl top. - Supprimer un
nodeSelectortrop strict ou ajuster les labels. - Ajouter un pool de nœuds compatible si la charge de travail a légitimement besoin de plus de ressources.
E. Sonde Readiness ou Liveness en échec
Vérifications :
kubectl -n <ns> describe pod <pod>
kubectl -n <ns> logs <pod> -c <container> --tail=200
Correctifs :
- Corriger le chemin, le port ou la commande. Ajouter
initialDelaySecondspour les démarrages à froid. - S'assurer que l'application écoute sur
0.0.0.0, pas sur127.0.0.1. - Pour les sondes HTTP, vérifier que le chemin renvoie 2xx dans
timeoutSeconds.
F. Service sans endpoints (trou noir de trafic)
Vérifications :
kubectl -n <ns> get svc <name> -o yaml
kubectl -n <ns> get pods -l <selector> -o wide --show-labels
kubectl -n <ns> get ep <name> -o yaml
Correctifs :
- Aligner labels et selectors. Si vous utilisez Helm, vérifier que les values génèrent des labels cohérents sur Service et Deployment.
G. PVC Pending ou échecs de montage
Vérifications :
kubectl -n <ns> describe pvc <pvc>
kubectl get storageclass
Correctifs :
- Définir le bon
storageClassName. Adapter le mode d'accès à la charge (ReadWriteOnce pour la plupart des cas mono-écrivain). Demander une taille réaliste. - Si vous utilisez Ceph, vérifier que la StorageClass choisie existe et que le cluster peut provisionner des volumes (regarder
ceph statuset les logs du provisioner).
H. Problèmes DNS ou add-on Cluster DNS
Vérifications :
kubectl -n <ns> run dnsutils --rm -it --image=busybox:1.36 -- nslookup kubernetes.default
kubectl -n kube-system get pods -l k8s-app=kube-dns
kubectl -n kube-system logs deploy/coredns --tail=200
Correctifs :
- Corriger la ConfigMap CoreDNS si mal configurée (ex. stub domains, forward zones).
- Assouplir les NetworkPolicies pour autoriser UDP/TCP 53 vers CoreDNS depuis vos namespaces.
I. Node NotReady ou sous pression
Vérifications :
kubectl describe node <node>
Problèmes courants : DiskPressure, MemoryPressure, PIDPressure, ou soucis d'agent réseau.
Correctifs (ordre sûr) :
# Cordon le nœud pour arrêter le nouveau scheduling, puis drain si vous devez déplacer les pods
kubectl cordon <node>
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
# Après remédiation, uncordon
kubectl uncordon <node>
5. Vérifier, puis annuler si nécessaire
- Contrôler le rollout et la santé :
kubectl -n <ns> rollout status deploy/<name>
kubectl -n <ns> get pods,svc,ep
kubectl -n <ns> get events --sort-by=.metadata.creationTimestamp | tail -n 20
- Si le changement n'a pas aidé, annuler rapidement :
kubectl -n <ns> rollout undo deploy/<name>
- Avec des applications gérées par Helm, préférer un dry-run avant les modifications réelles :
helm -n <ns> upgrade <rel> <chart> --dry-run --values values.yaml
Mini-playbooks pratiques
CrashLoopBackOff dû à une clé ConfigMap manquante
Symptôme :
kubectl -n app describe pod api-xyz | sed -n '/Events/,$p'
kubectl -n app logs api-xyz -c api --previous --tail=200
# affiche : KeyError: 'MISSING_URL'
Correctif : Ajouter la clé manquante à la ConfigMap ou mettre à jour envFrom vers le bon nom, puis redémarrer le rollout.
kubectl -n app apply -f configmap.yaml
kubectl -n app rollout restart deploy/api
kubectl -n app rollout status deploy/api
Service sans endpoints à cause d'un désaccord de label
Symptôme :
kubectl -n web get svc nginx
kubectl -n web get ep nginx -o yaml # subsets vide
kubectl -n web get deploy nginx -o yaml | grep labels -A5
Correctif : Aligner le selector du Service avec les labels du template de pod du Deployment, puis appliquer.
kubectl -n web apply -f svc.yaml -f deploy.yaml
kubectl -n web get ep nginx -o yaml # endpoints maintenant peuplés
PVC Pending avec mauvaise StorageClass
Symptôme :
kubectl -n data describe pvc db-data | sed -n '/Events/,$p'
# ProvisioningFailed: storageclass "ceph-block" not found
Correctif : Définir storageClassName sur une classe existante (par exemple ceph-rbd exposée par votre cluster), puis réappliquer.
kubectl -n data apply -f pvc.yaml
kubectl -n data get pvc db-data
ImagePullBackOff dû à des identifiants manquants
Symptôme :
kubectl -n ci describe pod runner-abc | sed -n '/Events/,$p'
# error: unauthorized: authentication required
Correctif : Créer un secret docker-registry et le référencer via imagePullSecrets.
kubectl -n ci create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=ci-user --docker-password='$TOKEN' [email protected]
kubectl -n ci patch sa default -p '{"imagePullSecrets":[{"name":"regcred"}]}'
kubectl -n ci rollout restart deploy/runner
Plan pilote local
Entraînez-vous dans un cluster bac à sable pour observer chaque signal de bout en bout.
Périmètre
- Objectif : détecter, diagnostiquer, corriger et valider 4 pannes en moins de 30 minutes au total.
- Environnement : un cluster local (par exemple kind ou minikube) et kubectl.
Préparation
- Déployer une application simple (Déploiement Nginx + Service ClusterIP + Ingress optionnel) et un petit déploiement API avec ConfigMap et Secret.
- Installer metrics-server si vous souhaitez
kubectl top.
Exercices (Provoquer, puis corriger)
- Désaccord de label
- Casser : changer le selector du Service vers un label non correspondant.
- Détecter : endpoints vides. Corriger : aligner labels et selectors.
- Échec de la sonde Readiness
- Casser : définir le chemin de readiness sur
/bad. - Détecter : erreurs de sonde dans describe. Corriger : corriger le chemin et ajuster
initialDelaySeconds.
- ImagePullBackOff
- Casser : changer le tag d'image vers un tag inexistant.
- Détecter : événements montrent une erreur de pull. Corriger : corriger le tag ou ajouter
imagePullSecret.
- PVC Pending
- Casser : demander une StorageClass inexistante.
- Détecter : événements PVC affichent
ProvisioningFailed. Corriger : définir une classe existante.
Mesure
Pour chaque exercice, noter : temps au premier signal, cause racine, correctif appliqué, et sortie de la commande de vérification.
Critères de succès : statut de rollout vert et endpoints/pods sains après chaque correctif.
Sécurité
- Utiliser uniquement des commandes non destructives tant que la panne n'est pas comprise.
- Privilégier les redémarrages de rollout et les corrections de spec plutôt que la suppression de pods. Si suppression, s'assurer qu'un contrôleur possède le pod pour qu'il soit recréé.
Conclusion
Vous disposez désormais d'un flux de travail de dépannage pratique, par étapes, et de playbooks répétables pour les erreurs Kubernetes les plus courantes. Prochaines étapes :
- Transformer ce workflow en runbook d'équipe avec commandes copier-coller
- Répéter l'exercice chaque trimestre dans un bac à sable pour garder la mémoire musculaire fraîche
- Ajouter des pré-vérifications rapides dans vos pipelines GitLab CI/CD ou Helm (par exemple
kubectl apply --dry-run=server,helm --dry-run) pour attraper tôt les erreurs de label, de sonde et de stockage - Instrumenter avec Prometheus et des alertes sur la readiness, les pics de redémarrage et les échecs de provisionnement PVC
Lorsqu'un incident survient, commencez par l'inspection en lecture seule, classez vite, appliquez le plus petit correctif sûr, et vérifiez. La constance bat l'improvisation sous pression.