Introduction
Les pods mal configurés sont l'une des causes les plus fréquentes d'incidents de production dans Kubernetes. Les symptômes sont familiers : pods bloqués en état Pending, bouclant en CrashLoopBackOff, échouant aux sondes de disponibilité ou consommant plus de ressources que prévu. Pourtant, de nombreuses équipes dépannent encore en supprimant et recréant des ressources, en espérant que le prochain déploiement se comportera différemment.
Ce guide remplace les suppositions par une approche systématique de la configuration des pods Kubernetes. Il est destiné aux développeurs, consultants DevOps et équipes techniques de startups qui exploitent des clusters au quotidien. Il se concentre sur quatre domaines pratiques : les erreurs de configuration des pods, la validation des pods, le retour en arrière des pods et le dépannage des pods. Pour chacun, vous trouverez des commandes kubectl concrètes, les sorties attendues, les signaux de défaillance et les décisions de récupération adaptées au scénario.
Le principe directeur tout au long de ce guide est la sécurité : observer avant de modifier, limiter le rayon d'impact, utiliser des valeurs factices au lieu de secrets, vérifier les résultats et documenter les chemins de récupération avant qu'un incident ne force une décision précipitée.
Inventaire des versions et de l'environnement
Avant de toucher à un pod, vous devez savoir avec quoi vous travaillez. L'inventaire des versions et de l'environnement signifie identifier le composant concerné (pod, Deployment, ReplicaSet), la plage de versions prises en charge, les prérequis, une observation en lecture seule, le plus petit changement justifié et la commande ou le signal qui vérifie le résultat.
Commencez par capturer l'état actuel sans rien modifier. Enregistrez la version du serveur Kubernetes, l'espace de noms dans lequel le pod s'exécute et les balises d'image exactes utilisées. Cela établit une base de référence et évite toute confusion lors de la comparaison des états avant et après.
kubectl version --short
kubectl get pods -n payments -o wide
kubectl get deployment -n payments -o yaml | grep -A 2 image:
Exemple de sortie d'une base de référence saine :
Client Version: v1.28.2
Server Version: v1.28.4
NAME READY STATUS RESTARTS AGE IP NODE
checkout-7d9f8c5b6d-abcde 1/1 Running 0 2m 10.244.1.5 node-1
checkout-7d9f8c5b6d-fghij 1/1 Running 0 2m 10.244.2.7 node-2
Pour voir les événements, les détails de planification et les avertissements récents, décrivez le pod :
kubectl describe pod checkout-7d9f8c5b6d-abcde -n payments
Portez attention à la section Events en bas. Un pod bloqué en état Pending parce qu'aucun nœud n'a suffisamment de ressources affichera des événements comme FailedScheduling avec des messages tels que 0/3 nodes are available: 3 Insufficient memory.
Séparez l'observation de l'intervention. Ne supprimez pas et ne modifiez pas encore le pod. Capturez l'état actuel et les horodatages, protégez les informations d'identification et le matériel privé, puis planifiez un changement ciblé à la fois.
Les ressources associées telles que Deployment, ReplicaSet et Node ne doivent être incluses que lorsqu'elles affectent les prérequis, la compatibilité, la sécurité, l'observabilité ou la récupération. Par exemple, si un pod est toujours planifié sur le même nœud, vérifiez les teintes et les étiquettes du nœud, car cela peut révéler une tolérance manquante dans la spécification du pod.
Gardez le test local petit. Appliquez un manifeste, inspectez les ressources générées et vérifiez le trafic avec kubectl port-forward ou un Service local de type NodePort avant de passer à un équilibreur de charge cloud ou à un contrôleur d'entrée.
Erreurs courantes de configuration des pods
Les erreurs de configuration les plus fréquentes se répartissent en quelques catégories récurrentes. Chaque erreur ci-dessous inclut une commande réelle pour la reproduire, une description de la défaillance et une correction qui a été vérifiée en pratique.
Déclaration de port de conteneur manquante ou incorrecte
Un conteneur peut écouter sur le port 8080 à l'intérieur, mais si la spécification du pod ne déclare pas containerPort, les Services ne peuvent pas acheminer le trafic correctement. Pire, si le mauvais port est déclaré, le trafic ne va nulle part.
apiVersion: v1
kind: Pod
metadata:
name: webapp
spec:
containers:
- name: webapp
image: myapp:1.2.3
ports:
- containerPort: 8080 # l'application écoute réellement sur 8080, donc c'est correct
Pour vérifier à l'intérieur du conteneur, exécutez :
kubectl exec -it webapp -- sh -c 'netstat -tulpn | grep LISTEN'
Sortie attendue si l'application écoute sur 8080 :
tcp 0 0 :::8080 :::* LISTEN -
Si la sortie montre un autre port ou aucun écouteur, corrigez la déclaration containerPort dans le manifeste.
Limites de ressources manquantes ou trop strictes
Sans demandes et limites de ressources, un pod peut être évincé lorsqu'un nœud manque de mémoire, ou il peut affamer d'autres charges de travail. À l'inverse, des limites trop basses provoquent des OOMKilled ou un étranglement du processeur.
Définissez des valeurs réalistes basées sur l'utilisation observée :
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
Pour vérifier l'utilisation actuelle, utilisez kubectl top :
kubectl top pod -n payments
Exemple de sortie :
NAME CPU(cores) MEMORY(bytes)
checkout-7d9f8c5b6d-abcde 120m 150Mi
checkout-7d9f8c5b6d-fghij 98m 142Mi
Si l'utilisation de la mémoire est constamment proche de 256Mi, augmentez la limite à 512Mi et mettez à jour la demande en conséquence. Si un pod a été tué par OOM, vérifiez la raison de l'arrêt :
kubectl describe pod checkout-7d9f8c5b6d-abcde -n payments | grep -A 5 'Last State'
Recherchez Reason: OOMKilled. La correction consiste à augmenter la limite de mémoire ou à réduire l'empreinte de la charge de travail.
Sondes mal configurées
Les sondes de vivacité et de disponibilité sont essentielles, mais de mauvaises configurations provoquent des redémarrages ou des pertes de trafic. Une erreur courante consiste à utiliser une sonde TCP sur un point de terminaison HTTP, ou à définir initialDelaySeconds trop bas pour les applications à démarrage lent.
Exemple de sonde HTTP problématique :
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 5 # trop court pour une app qui met 15 secondes à démarrer
periodSeconds: 10
Avec cette sonde, le conteneur peut ne jamais devenir prêt avant que la sonde de vivacité ne commence à échouer, provoquant un CrashLoopBackOff. Augmentez initialDelaySeconds à 30 et periodSeconds à 20.
Pour observer les échecs de sonde, décrivez le pod et recherchez les événements Unhealthy :
kubectl describe pod webapp -n payments | grep -A 10 Events
Si vous voyez Liveness probe failed: HTTP probe failed with statuscode: 500, l'application elle-même échoue ; s'il s'agit de connection refused, la sonde atteint le mauvais port.
Variables d'environnement codées en dur ou secrets en texte clair
Mettre des mots de passe de base de données ou des clés API directement dans la spécification du pod est une erreur grave. Utilisez les Secrets Kubernetes et référencez-les via valueFrom.
Mauvaise approche :
env:
- name: DB_PASSWORD
value: "Sup3rSecret!" # ne faites jamais cela
Bonne approche :
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: app-secrets
key: db-password
Créez d'abord le Secret avec une valeur factice, puis injectez la valeur réelle via un gestionnaire de secrets externe ou un secret scellé.
kubectl create secret generic app-secrets --from-literal=db-password='CHANGE_ME'
Vérifiez que le pod peut lire le Secret sans l'imprimer :
kubectl exec webapp -- printenv DB_PASSWORD
Ne faites pas écho à la valeur dans les journaux ou les commandes qui se retrouvent dans l'historique du shell. Utilisez une valeur masquée si vous devez confirmer l'existence.
Politique de tirage d'image incorrecte ou authentification de registre manquante
Si votre image est privée, un pod peut échouer avec ImagePullBackOff parce que le cluster ne peut pas s'authentifier. La politique de tirage d'image compte également : Always tire à chaque fois, ce qui est sûr pour les balises mutables mais lent ; IfNotPresent est plus rapide pour les balises immuables.
imagePullPolicy: IfNotPresent # à utiliser avec des balises immuables
imagePullSecrets:
- name: regcred
Créez le secret de tirage :
kubectl create secret docker-registry regcred \
--docker-server=registry.example.com \
--docker-username=deploy \
--docker-password=xxxx \
[email protected]
Si un pod est en ImagePullBackOff, vérifiez les événements :
kubectl describe pod webapp | grep -A 5 Events
Recherchez des messages comme failed to authorize: failed to fetch anonymous token ou pull access denied. Corrigez le secret ou la balise d'image, puis supprimez le pod pour forcer un nouveau tirage.
Chemin de configuration sûr
Le chemin de configuration sûr est une séquence qui réduit le risque à chaque étape. Il se compose de cinq phases : observer, planifier, modifier, vérifier et documenter. Pour la configuration des pods Kubernetes, cela signifie nommer le composant concerné, la version prise en charge, les prérequis, une observation en lecture seule, le plus petit changement justifié et la commande de vérification.
Phase 1 : Observer
Ne changez encore rien. Collectez l'état actuel :
kubectl get pods -n payments -o wide
kubectl describe pod <pod-name> -n payments
kubectl logs <pod-name> --previous -n payments # si le conteneur a redémarré
kubectl rollout status deployment/checkout -n payments
Exemple de sortie lorsqu'un déploiement est bloqué :
Waiting for deployment "checkout" rollout to finish: 1 old replicas are pending termination...
Phase 2 : Planifier
Identifiez le champ exact à modifier. Si un pod est en CrashLoopBackOff, inspectez d'abord les journaux précédents :
kubectl logs checkout-7d9f8c5b6d-abcde --previous -n payments
Supposons que le journal affiche :
panic: runtime error: invalid memory address or nil pointer dereference
Cela indique un bogue d'application, pas un problème de configuration. Mais si le journal affiche Error: could not connect to database at postgres:5432, la configuration est probablement erronée : le nom d'hôte de la base de données ou les informations d'identification peuvent être incorrects.
Choisissez le plus petit changement qui répond à la défaillance observée. S'il s'agit d'une erreur de configuration, modifiez le Deployment (pas directement le pod, car les pods sont éphémères) :
kubectl edit deployment checkout -n payments
Phase 3 : Modifier
Appliquez la modification via un patch de fusion pour éviter d'écraser des champs non liés :
kubectl patch deployment checkout -n payments -p '{"spec":{"template":{"spec":{"containers":[{"name":"checkout","env":[{"name":"DB_HOST","value":"postgres.internal"}]}]}}}}'
Puis surveillez le déploiement :
kubectl rollout status deployment/checkout -n payments
Sortie attendue en cas de succès :
deployment "checkout" successfully rolled out
Phase 4 : Vérifier
Confirmez que le nouveau pod est en cours d'exécution et prêt, et que le trafic circule. Utilisez le transfert de port pour tester localement :
kubectl port-forward deployment/checkout 8080:8080 -n payments
curl http://localhost:8080/healthz
Attendu :
{"status":"ok"}
Phase 5 : Documenter
Enregistrez ce qui a changé, pourquoi et comment revenir en arrière. Par exemple, notez dans votre runbook : "Augmentation de initialDelaySeconds de la sonde de vivacité de 5 à 30 pour le déploiement checkout en raison d'un démarrage lent. Commande de retour en arrière : kubectl rollout undo deployment/checkout -n payments"
Vérification et diagnostics
La vérification n'est pas un simple kubectl get après un déploiement. C'est une séquence de contrôles qui confirment que le pod est sain de l'intérieur vers l'extérieur : processus, utilisation des ressources, accessibilité réseau et réponse au niveau de l'application.
Vérifier le statut et la disponibilité du pod
Commencez par les bases :
kubectl get pods -n payments -o wide
Tous les pods doivent être Running et READY 1/1. Si un pod est Running mais 0/1, la disponibilité échoue. Décrivez pour voir pourquoi :
kubectl describe pod checkout-7d9f8c5b6d-xyz -n payments
Recherchez des événements comme Readiness probe failed: Get "http://10.244.1.6:8080/ready": dial tcp 10.244.1.6:8080: connect: connection refused.
Inspecter les journaux pour les erreurs
kubectl logs checkout-7d9f8c5b6d-xyz -n payments --tail=50
Si le conteneur a redémarré, incluez l'instance précédente :
kubectl logs checkout-7d9f8c5b6d-xyz -n payments --previous
Filtrez les erreurs avec grep :
kubectl logs checkout-7d9f8c5b6d-xyz -n payments --previous | grep -i error
Tester la connectivité réseau depuis l'intérieur du pod
kubectl exec -it checkout-7d9f8c5b6d-xyz -n payments -- sh
# à l'intérieur du pod
ping -c 3 postgres.internal # si ping est installé
nc -zv postgres.internal 5432
Si le pod peut résoudre le nom DNS mais ne peut pas se connecter au port, il peut y avoir une NetworkPolicy bloquant le trafic.
Valider l'utilisation des ressources par rapport aux limites
kubectl top pod checkout-7d9f8c5b6d-xyz -n payments --containers
Exemple de sortie :
POD NAME CPU(cores) MEMORY(bytes)
checkout-7d9f8c5b6d-xyz checkout 75m 198Mi
Si la mémoire est proche de la limite (par exemple, limite de 256Mi, utilisation de 198Mi), envisagez d'augmenter la limite avant le prochain pic de trafic.
Vérifier l'historique des déploiements
kubectl rollout history deployment/checkout -n payments
Exemple :
deployment.apps/checkout
REVISION CHANGE-CAUSE
1 <none>
2 kubectl set image deployment/checkout checkout=myapp:1.2.4
Cet historique est essentiel pour les décisions de retour en arrière.
Modes de défaillance et récupération
Chaque configuration de pod peut échouer de manière prévisible. Connaître les modes de défaillance typiques et leurs commandes de récupération réduit le temps d'incident.
CrashLoopBackOff
Symptôme : le pod redémarre à plusieurs reprises, STATUS affiche CrashLoopBackOff et le nombre de RESTARTS augmente.
Diagnostic :
kubectl describe pod webapp -n payments | grep -A 10 'Last State'
kubectl logs webapp --previous -n payments
Causes courantes : plantage de l'application au démarrage, fichier de configuration manquant, commande ou arguments incorrects, OOMKilled.
Récupération : corrigez la cause racine (par exemple, ajoutez la ConfigMap manquante, augmentez la limite de mémoire), puis supprimez le pod pour redémarrer proprement :
kubectl delete pod webapp -n payments
Si le pod est géré par un Deployment, il sera recréé automatiquement.
ImagePullBackOff
Symptôme : le pod ne peut pas extraire l'image, statut ImagePullBackOff ou ErrImagePull.
Diagnostic :
kubectl describe pod webapp -n payments | grep -A 10 Events
Recherchez des messages comme failed to pull image "myapp:latest": pull access denied ou repository does not exist.
Récupération : corrigez le nom ou la balise de l'image, assurez-vous que le secret de tirage existe et est référencé par la spécification du pod. Ensuite, supprimez le pod.
En attente en raison de ressources insuffisantes
Symptôme : le pod reste en Pending, READY est 0/1, et les événements affichent FailedScheduling.
Diagnostic :
kubectl describe pod bigdata -n analytics | grep -A 5 Events
Exemple de message : 0/3 nodes are available: 3 Insufficient cpu.
Récupération : réduisez les demandes de ressources, réduisez d'autres charges de travail ou ajoutez des nœuds au cluster. Si la demande est justifiée, augmentez la capacité du cluster.
Échec de la sonde de disponibilité
Symptôme : le pod est Running mais pas Ready ; le Service ne route pas le trafic vers lui.
Diagnostic :
kubectl get pods -n payments
kubectl describe pod webapp -n payments | grep -A 10 Events
Recherchez Readiness probe failed: HTTP probe failed with statuscode: 503.
Récupération : corrigez le chemin, le port ou le délai de la sonde. Pour une application qui met 30 secondes à devenir prête, définissez initialDelaySeconds: 30 et periodSeconds: 10.
OOMKilled
Symptôme : le pod se termine avec la raison OOMKilled, code de sortie 137.
Diagnostic :
kubectl describe pod webapp -n payments | grep -A 5 'Last State'
La sortie affiche Reason: OOMKilled.
Récupération : augmentez la limite de mémoire ou réduisez l'utilisation de la mémoire. Utilisez un outil de mise à l'échelle verticale ou ajustez les paramètres de mémoire de l'application. Ensuite, déployez une nouvelle révision.
Récupération par retour en arrière
Si un changement récent a provoqué la défaillance, revenez à une révision précédente :
kubectl rollout undo deployment/checkout -n payments
kubectl rollout status deployment/checkout -n payments
Pour revenir à une révision spécifique :
kubectl rollout undo deployment/checkout --to-revision=1 -n payments
Vérifiez toujours après le retour en arrière :
kubectl get pods -n payments -o wide
kubectl logs deployment/checkout --tail=20 -n payments
Liste de contrôle opérationnelle
Utilisez cette liste de contrôle pour standardiser le dépannage et les modifications de configuration des pods. Chaque élément inclut un exemple concret et le résultat attendu.
- Enregistrez le contexte du cluster et de l'espace de noms.
- Commande :
kubectl config current-context && kubectl get ns payments - Attendu : le nom du contexte est affiché et l'espace de noms existe.
- Capturez la base de référence du pod.
- Commande :
kubectl get pods -n payments -o wide --show-labels - Attendu : tous les pods sont répertoriés avec les étiquettes et les adresses IP.
- Décrivez le pod défaillant et enregistrez les événements dans un fichier.
- Commande :
kubectl describe pod webapp-abc123 -n payments > /tmp/webapp-events.txt - Attendu : le fichier contient des événements récents comme des échecs de sonde ou des erreurs de planification.
- Vérifiez les journaux du conteneur précédent s'il a redémarré.
- Commande :
kubectl logs webapp-abc123 --previous -n payments | tail -50 - Attendu : les erreurs de démarrage ou les traces de pile de plantage sont visibles.
- Validez la spécification du pod par rapport à la configuration souhaitée.
- Comparez la spécification en cours d'exécution avec votre manifeste source :
kubectl get pod webapp-abc123 -n payments -o yaml | diff - desired-pod.yaml - Attendu : uniquement des différences attendues (par exemple, des champs par défaut).
- Appliquez le plus petit changement via un patch, pas un remplacement complet.
- Exemple :
kubectl patch deployment webapp -n payments -p '{"spec":{"template":{"spec":{"containers":[{"name":"webapp","resources":{"limits":{"memory":"512Mi"}}}]}}}}' - Attendu : le patch réussit avec
deployment.apps/webapp patched.
- Surveillez le statut du déploiement.
- Commande :
kubectl rollout status deployment/webapp -n payments - Attendu :
deployment "webapp" successfully rolled outdans le délai imparti.
- Vérifiez la disponibilité du pod et la santé de l'application.
- Commandes :
kubectl get pods -n payments, puiskubectl port-forward deployment/webapp 8080:8080 -n paymentsetcurl localhost:8080/healthz. - Attendu : pods
1/1 Running, le point de terminaison de santé renvoie 200 OK.
- Confirmez que l'utilisation des ressources est dans les limites.
- Commande :
kubectl top pod -n payments - Attendu : mémoire et CPU inférieurs aux limites, avec une marge.
- Documentez le changement et la commande de retour en arrière.
- Exemple de note : "Augmentation de la limite de mémoire de webapp de 256Mi à 512Mi pour éviter OOMKilled. Retour en arrière :
kubectl rollout undo deployment/webapp -n payments." - Attendu : entrée dans le runbook de l'équipe ou le journal des incidents.
Conclusion
Les erreurs de configuration des pods Kubernetes sont inévitables, mais elles ne doivent pas provoquer de longues interruptions. Les exemples pratiques de ce guide ont montré comment observer l'état du pod avant de changer quoi que ce soit, diagnostiquer les modes de défaillance courants avec des commandes kubectl spécifiques, appliquer le plus petit changement sûr et vérifier le résultat avant de déclarer victoire.
Chaque recommandation ici est limitée à une version, observable et réversible lorsque Kubernetes le permet. Copier une commande sans vérifier les prérequis et la sortie attendue n'est pas une procédure opérationnelle ; c'est un pari.
Comme prochaine étape, choisissez une vérification à faible risque de la liste de contrôle opérationnelle, enregistrez l'état actuel, exécutez la vérification documentée, comparez le résultat avec le signal attendu et examinez les dépendances telles que Deployment, ReplicaSet et Node dans votre propre cluster. Ensuite, identifiez l'erreur de configuration de pod la plus fréquente dans votre environnement et créez une entrée de runbook pour celle-ci en utilisant les phases du chemin de configuration sûr.
Un flux de travail technique fiable rend la défaillance visible, protège les valeurs sensibles, limite les modifications à la ressource prévue et définit la vérification de récupération avant qu'un incident ne force la décision. Votre futur moi d'astreinte vous remerciera.