Introduction
Kubernetes est devenu la norme de facto pour l'orchestration de conteneurs, mais une grande puissance s'accompagne d'une grande complexité. Si les configurations de base des pods sont simples, des fonctionnalités avancées comme les sondes de démarrage, les conteneurs d'initialisation, les contextes de sécurité et les limites de ressources peuvent introduire des problèmes subtils difficiles à diagnostiquer. Ce guide propose une approche systématique pour dépanner les problèmes de configuration avancée des pods, avec des exemples pratiques, des commandes et des étapes de vérification. Que vous soyez développeur, consultant DevOps ou membre d'une équipe de startup technique, vous apprendrez à identifier les causes profondes et à mettre en œuvre des correctifs sûrs.
Inventaire des versions et de l'environnement
Avant de plonger dans le dépannage, établissez une image claire de votre environnement. Connaître les versions exactes et la topologie aide à réduire les causes possibles et garantit la compatibilité des solutions.
Documenter les versions de Kubernetes et du runtime de conteneurs
Commencez par vérifier la version du serveur Kubernetes :
kubectl version --short
Sortie attendue (exemple) :
Client Version: v1.27.3
Kustomize Version: v5.0.1
Server Version: v1.27.3
Remarque : le drapeau --short est déprécié dans les versions plus récentes ; s'il échoue, utilisez kubectl version pour une sortie complète.
Vérifiez également la version du runtime de conteneurs sur vos nœuds si vous y avez accès (en utilisant crictl ou docker selon le runtime) :
crictl version
Sortie typique :
Version: 0.1.0
RuntimeName: containerd
RuntimeVersion: 1.7.2
RuntimeApiVersion: v1
Inventorier la topologie du cluster et les détails des pods
Identifiez les nœuds et l'emplacement du pod :
kubectl get nodes -o wide
kubectl get pod <nom-du-pod> -n <namespace> -o wide
Pour le pod, notez son nœud, son IP et son statut. Consultez également les événements du pod pour des indices initiaux :
kubectl describe pod <nom-du-pod> -n <namespace>
Prérequis pour le dépannage
- Accès au cluster avec les autorisations RBAC appropriées (au moins
get,list,describe,logsetexecsur les pods). - Une compréhension claire du comportement attendu du pod à partir de sa spécification.
- Outils :
kubectl, un éditeur de texte et éventuellementjqpour analyser les sorties JSON.
Chemin de configuration sûr
Lors de la mise en œuvre de modifications sur des configurations avancées de pods, adoptez une approche limitée et réversible. Évitez les changements radicaux ; modifiez plutôt un paramètre à la fois et vérifiez son effet.
Étape 1 : Extraire la configuration actuelle du pod
Pour comprendre la configuration existante, exportez la spécification du pod en YAML :
kubectl get pod <nom-du-pod> -n <namespace> -o yaml > pod-backup.yaml
Ce fichier sert à la fois de référence et de point de restauration. Inspectez les sections avancées clés :
grep -A 20 'startupProbe\|readinessProbe\|livenessProbe\|initContainers\|securityContext\|resources' pod-backup.yaml
Étape 2 : Tester les modifications de configuration dans un environnement de préproduction
Si possible, reproduisez le pod dans un namespace ou un cluster de préproduction. Pour des tests locaux, vous pouvez utiliser un outil comme kind ou minikube pour créer un environnement similaire. Appliquez d'abord les modifications là-bas et observez le comportement.
Étape 3 : Appliquer les modifications de manière incrémentale
Utilisez kubectl apply avec un manifeste modifié. Par exemple, si vous ajustez les limites de ressources, créez un fichier de correctif :
# patch-resources.yaml
spec:
template:
spec:
containers:
- name: myapp
resources:
limits:
cpu: "500m"
memory: "512Mi"
Appliquez le correctif :
kubectl patch deployment myapp -n <namespace> --patch "$(cat patch-resources.yaml)"
Vous pouvez également modifier l'objet en direct avec kubectl edit pour un changement interactif rapide, mais effectuez toujours une sauvegarde au préalable.
Étape 4 : Surveiller l'état du déploiement
Après l'application, vérifiez l'état du déploiement pour les ressources de type Deployment :
kubectl rollout status deployment/myapp -n <namespace>
Sortie attendue :
Waiting for deployment "myapp" rollout to finish: 1 out of 2 new replicas have been updated...
deployment "myapp" successfully rolled out
Si le déploiement se bloque, investiguez avec kubectl describe et kubectl logs.
Vérification et diagnostics
Une fois les modifications appliquées, vérifiez que le pod fonctionne correctement et que les configurations avancées se comportent comme prévu.
Vérifier le statut du pod et les événements
Commencez par les bases :
kubectl get pods -n <namespace>
kubectl describe pod <nom-du-pod> -n <namespace>
Recherchez des événements comme Started container, Readiness probe failed ou Back-off restarting failed container. Ces événements fournissent une orientation immédiate.
Inspecter les journaux des conteneurs
Pour les conteneurs qui plantent ou fonctionnent mal, consultez les journaux :
kubectl logs <nom-du-pod> -n <namespace> -c <nom-du-conteneur> --previous
L'option --previous affiche les journaux de l'instance précédente, ce qui est utile si le conteneur redémarre.
Déboguer les sondes de démarrage
Les sondes de démarrage sont essentielles pour les applications à démarrage lent. Si une sonde de démarrage échoue, le conteneur peut être tué avant d'être prêt. Vérifiez la configuration de la sonde :
kubectl get pod <nom-du-pod> -n <namespace> -o jsonpath='{.spec.containers[*].startupProbe}' | jq .
Exemple de sortie (si configuré) :
{
"httpGet": {
"path": "/healthz",
"port": 8080
},
"initialDelaySeconds": 0,
"periodSeconds": 10,
"failureThreshold": 30
}
Pour tester manuellement le point de terminaison de la sonde, exécutez une commande dans le conteneur (s'il est toujours en cours d'exécution) et utilisez curl ou wget :
kubectl exec -it <nom-du-pod> -n <namespace> -- wget -qO- http://localhost:8080/healthz
Si le point de terminaison renvoie une erreur, la sonde identifie correctement un problème, et vous devez corriger l'application ou ajuster les seuils de la sonde.
Déboguer les conteneurs d'initialisation
Les conteneurs d'initialisation s'exécutent avant les conteneurs principaux. Si un conteneur d'initialisation échoue, le pod reste bloqué dans l'état Init:Error ou Init:CrashLoopBackOff. Consultez les journaux du conteneur d'initialisation :
kubectl logs <nom-du-pod> -n <namespace> -c <nom-du-conteneur-init>
Inspectez également la commande et l'environnement du conteneur d'initialisation :
kubectl get pod <nom-du-pod> -n <namespace> -o jsonpath='{.spec.initContainers[0].command}'; echo
Les problèmes courants incluent des commandes incorrectes, des montages de volumes manquants ou des autorisations insuffisantes.
Déboguer le contexte de sécurité
Les problèmes de contexte de sécurité se manifestent souvent par des erreurs de permission refusée. Vérifiez le contexte de sécurité du pod :
kubectl get pod <nom-du-pod> -n <namespace> -o yaml | grep -A 10 securityContext
Testez en essayant d'exécuter une commande en tant qu'utilisateur spécifié dans le conteneur :
kubectl exec <nom-du-pod> -n <namespace> -- id
Sortie attendue si exécuté en tant que non-root :
uid=1000(appuser) gid=1000(appuser) groups=1000(appuser)
Si le conteneur ne peut pas démarrer en raison d'un utilisateur ou d'un groupe manquant, ajustez les paramètres runAsUser ou fsGroup.
Déboguer les limites et les demandes de ressources
Des limites de ressources incorrectes peuvent provoquer des erreurs OOMKilled ou une limitation du CPU. Vérifiez les allocations de ressources actuelles :
kubectl get pod <nom-du-pod> -n <namespace> -o jsonpath='{.spec.containers[*].resources}' | jq .
Exemple de sortie :
{
"limits": {
"cpu": "500m",
"memory": "512Mi"
},
"requests": {
"cpu": "250m",
"memory": "256Mi"
}
}
Si un conteneur a été tué par OOM (Out of Memory), vérifiez le statut du pod :
kubectl get pod <nom-du-pod> -n <namespace> -o jsonpath='{.status.containerStatuses[0].lastState.terminated.reason}'
Si la sortie est OOMKilled, augmentez la limite de mémoire ou optimisez l'utilisation de la mémoire de l'application.
Modes de défaillance et récupération
Malgré une planification minutieuse, des défaillances peuvent survenir. Comprendre les modes de défaillance courants et disposer d'un plan de restauration est essentiel.
Modes de défaillance courants
| Mode de défaillance | Symptômes | Cause probable |
|---|---|---|
| Échec de la sonde de démarrage | Le pod redémarre avant d'être prêt ; les événements affichent Startup probe failed | Le point de terminaison de la sonde n'est pas prêt à temps, mauvais port/chemin, ou failureThreshold insuffisant |
| Échec du conteneur d'initialisation | Le pod est bloqué dans Init:CrashLoopBackOff ; les journaux du conteneur d'initialisation affichent des erreurs | Commande incorrecte, dépendances manquantes ou problèmes de permission |
| Inadéquation du contexte de sécurité | Le conteneur se termine avec Permission denied ou ne peut pas écrire sur le volume | runAsUser, fsGroup ou capabilities mal configurés |
| Limite de ressources dépassée | Conteneur tué avec OOMKilled ou limité ; le statut du pod affiche Terminated | Limite de mémoire/CPU trop basse pour la charge de travail |
| Problèmes de montage de volume | Le pod ne démarre pas avec MountVolume.SetUp failed | Définition de volume incorrecte, PVC manquant ou le nœud ne dispose pas du pilote de stockage |
Stratégies de restauration
Restaurer un déploiement : si vous avez modifié un déploiement, utilisez kubectl rollout undo :
kubectl rollout undo deployment/myapp -n <namespace>
Cela revient à la révision précédente. Vérifiez avec :
kubectl rollout status deployment/myapp -n <namespace>
Restaurer un pod à partir d'une sauvegarde : si vous avez modifié un pod autonome (non recommandé en production), supprimez-le et recréez-le à partir de la sauvegarde :
kubectl delete pod <nom-du-pod> -n <namespace>
kubectl apply -f pod-backup.yaml
Récupération après CrashLoopBackOff : si un conteneur est en état CrashLoopBackOff, il redémarre automatiquement, mais vous pouvez le mettre en pause temporairement pour déboguer :
kubectl scale deployment myapp --replicas=0 -n <namespace>
Ensuite, investiguez et corrigez, puis remettez à l'échelle.
Vérification post-récupération
Après une restauration ou une correction, vérifiez que le pod est sain :
kubectl get pods -n <namespace>
kubectl describe pod <nom-du-pod> -n <namespace> | grep -A 5 'Conditions:'
Vérifiez que tous les conteneurs sont prêts et que les événements ne montrent aucune défaillance.
Pièges courants et comment les éviter
Même les utilisateurs expérimentés de Kubernetes rencontrent des erreurs de configuration récurrentes. Voici les pièges les plus courants, leurs causes et comment les prévenir ou s'en remettre.
1. Sondes mal configurées avec des seuils irréalistes
Pourquoi cela arrive : les développeurs définissent souvent un failureThreshold trop bas ou un initialDelaySeconds trop court, ce qui fait échouer les sondes avant que l'application ne soit prête. Par exemple, une application Java peut nécessiter 60 secondes pour démarrer, mais la sonde de démarrage est configurée pour échouer après 30 secondes.
Comment l'éviter : observez le temps de démarrage réel de votre conteneur dans un environnement de test et définissez initialDelaySeconds et failureThreshold en conséquence. Utilisez une sonde de démarrage (startupProbe) pour protéger les conteneurs à démarrage lent. Surveillez toujours les journaux des sondes pour confirmer qu'elles réussissent comme prévu.
Récupération : augmentez temporairement le seuil pour permettre au conteneur de démarrer, puis optimisez le temps de démarrage de l'application ou ajustez la sonde de façon permanente.
2. Commandes de conteneurs d'initialisation manquantes ou incorrectes
Pourquoi cela arrive : les conteneurs d'initialisation exécutent souvent des commandes shell ou des scripts, et une faute de frappe ou une dépendance manquante peut les faire échouer. Par exemple, un conteneur d'initialisation qui exécute une migration de base de données peut échouer parce que la base de données n'est pas prête.
Comment l'éviter : testez les commandes des conteneurs d'initialisation localement avec Docker ou un outil similaire. Assurez-vous que les services requis (comme les bases de données) sont joignables et correctement configurés. Utilisez une logique de nouvelle tentative dans la commande si nécessaire.
Récupération : corrigez la commande et redémarrez le pod. Si le conteneur d'initialisation est bloqué dans CrashLoopBackOff, supprimez le pod et recréez-le pour déclencher une exécution propre.
3. Contexte de sécurité trop restrictif
Pourquoi cela arrive : définir runAsUser sur un utilisateur non-root sans s'assurer que l'utilisateur existe dans l'image du conteneur conduit à des erreurs Permission denied. De même, un fsGroup manquant peut empêcher l'écriture sur les volumes.
Comment l'éviter : vérifiez toujours que l'utilisateur et le groupe existent dans l'image. Utilisez runAsNonRoot: true pour imposer une exécution non-root, et définissez fsGroup pour correspondre au groupe qui a besoin d'un accès en écriture aux volumes. Testez en préproduction avant la production.
Récupération : modifiez le contexte de sécurité pour utiliser un utilisateur/groupe valide, ou ajustez le Dockerfile de l'image pour créer l'utilisateur nécessaire.
4. Limites de ressources trop strictes ou manquantes
Pourquoi cela arrive : sous-estimer les besoins en mémoire ou en CPU conduit à des erreurs OOMKilled, tandis que des limites manquantes peuvent faire consommer toutes les ressources du nœud par un conteneur, affectant d'autres charges de travail.
Comment l'éviter : utilisez des outils de surveillance comme Prometheus et Grafana pour observer l'utilisation réelle des ressources au fil du temps. Définissez des demandes et des limites avec une marge (par exemple, 20 % de marge). Utilisez le Vertical Pod Autoscaler (VPA) en mode recommandation pour obtenir des suggestions.
Récupération : augmentez temporairement les limites pour arrêter les plantages, puis optimisez l'application ou ajustez de façon permanente.
5. Mauvaises configurations de montage de volume
Pourquoi cela arrive : des définitions de volume incorrectes, comme référencer un PVC inexistant ou utiliser de mauvais chemins de montage, empêchent le pod de démarrer. Cela se produit souvent lors de la copie de YAML depuis un autre environnement sans l'adapter.
Comment l'éviter : validez les définitions de volume par rapport aux classes de stockage de votre cluster et aux PVC existants. Utilisez kubectl get pvc pour confirmer l'existence du PVC. Gardez les manifestes spécifiques à l'environnement.
Récupération : corrigez la définition du volume et recréez le pod. Si les pilotes de stockage sont manquants sur un nœud, drainez le nœud ou installez le pilote.
Liste de contrôle opérationnelle
Pour prévenir et gérer efficacement les problèmes avancés de configuration des pods, établissez une liste de contrôle opérationnelle reproductible. Chaque élément doit avoir un responsable et une fréquence de révision.
- Audit des versions et de l'environnement (Responsable : Ingénieur DevOps, Fréquence : Mensuelle) : Enregistrez la version de Kubernetes, le runtime et le système d'exploitation des nœuds pour chaque session de dépannage.
- Configuration de base (Responsable : Responsable d'ingénierie, Fréquence : À chaque modification) : Conservez des manifestes sous contrôle de version pour toutes les charges de travail ; ne modifiez jamais les pods en direct directement.
- Revue de la configuration des sondes (Responsable : Développeur d'application, Fréquence : Avant chaque version) : Assurez-vous que les sondes de démarrage, de préparation et de vivacité sont correctement définies avec des seuils réalistes.
- Validation des conteneurs d'initialisation (Responsable : Développeur d'application, Fréquence : Avant chaque version) : Testez les commandes des conteneurs d'initialisation localement ou dans un environnement de préproduction avant de déployer.
- Audit du contexte de sécurité (Responsable : Ingénieur en sécurité, Fréquence : Trimestrielle) : Confirmez que
runAsUser,fsGroupet les capacités correspondent aux exigences de l'application. - Dimensionnement des ressources (Responsable : SRE, Fréquence : Mensuelle) : Surveillez l'utilisation réelle avec des outils comme
kubectl topet ajustez les demandes/limites en conséquence. - Journalisation et surveillance (Responsable : SRE, Fréquence : Continue) : Centralisez les journaux et configurez des alertes pour les redémarrages de pods, les OOMKills et les échecs de sonde.
- Plan de restauration (Responsable : Ingénieur DevOps, Fréquence : À chaque modification) : Ayez toujours une version précédente connue comme bonne ou un manifeste de sauvegarde prêt.
- Vérification après modification (Responsable : Développeur d'application, Fréquence : Après chaque modification de configuration) : Attendez la fin du déploiement et vérifiez l'état de préparation des pods et les événements.
- Documentation (Responsable : Chef d'équipe, Fréquence : Après chaque incident) : Enregistrez le problème, la cause profonde et la correction pour référence future.
Utilisez le tableau suivant pour suivre vos vérifications :
| Élément de vérification | Commande | Résultat attendu |
|---|---|---|
| Statut du pod | kubectl get pods | Tous les pods sont en cours d'exécution et prêts |
| Événements | kubectl describe pod <nom> | Aucun événement d'erreur récent |
| Journaux | kubectl logs <pod> -c <conteneur> | Aucune erreur fatale ni trace de pile |
| Utilisation des ressources | kubectl top pod <nom> | Utilisation inférieure aux limites |
| Points de terminaison des sondes | kubectl exec <pod> -- curl -f http://localhost:<port>/health | Réponse HTTP 200 |
Conclusion
Le dépannage des configurations avancées des pods Kubernetes nécessite une approche méthodique : inventorier votre environnement, appliquer les modifications en toute sécurité, vérifier avec des diagnostics ciblés et être prêt à récupérer des défaillances. En suivant les étapes pratiques de ce guide, vous pouvez réduire les temps d'arrêt et construire des applications plus résilientes. Commencez par un changement pilote étroit et mesurable, observez ses effets et gagnez en confiance. N'oubliez pas de documenter vos processus et de maintenir des manifestes à jour pour rationaliser le dépannage futur.
Maintenant, choisissez un domaine de la liste de contrôle opérationnelle, comme la validation des sondes de démarrage, et appliquez-le à une charge de travail non critique dans votre cluster. Mesurez l'impact et utilisez les résultats pour améliorer vos pratiques globales de configuration.