Introduction
Les conteneurs d'initialisation Kubernetes échouent souvent pour des raisons qui ne sont pas évidentes à partir du seul statut du pod. Un opérateur voit Init:0/1 ou Init:Error et a besoin d'un chemin fiable du symptôme à la résolution. Ce guide fournit des étapes de dépannage pratiques, pilotées par commandes, pour les conteneurs d'initialisation Kubernetes, avec des exemples concrets, des sorties attendues et une vérification de la récupération. Il s'adresse aux développeurs, ingénieurs DevOps et équipes plateforme qui exécutent Kubernetes en production ou en préproduction. Nous couvrons l'inventaire des versions et de l'environnement, la configuration sûre, la vérification et le diagnostic, les modes de défaillance et la récupération, ainsi qu'une liste de contrôle opérationnelle. L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets, vérifier le résultat et documenter la récupération avant qu'un incident ne force une décision.
Inventaire des versions et de l'environnement
Avant de dépanner une défaillance de conteneur d'initialisation, rassemblez des informations précises sur votre cluster Kubernetes et le pod affecté. Cela réduit les fausses hypothèses et circonscrit l'espace du problème.
Vérifier la version du cluster et les dépréciations d'API
kubectl version --short
Sortie attendue (exemple) :
Client Version: v1.28.2
Server Version: v1.28.2
Si le conteneur d'initialisation utilise une API bêta qui a été supprimée dans la version du serveur (par exemple, extensions/v1beta1 supprimée en 1.16), le pod ne pourra pas être créé. Confirmez avec :
kubectl explain pod.spec.initContainers | head -20
Si la commande renvoie error: the server doesn't have a resource type "pod" ou similaire, vérifiez la connectivité au cluster et les informations d'identification.
Identifier le pod, l'espace de noms et les noms des conteneurs d'initialisation
kubectl get pods -n <namespace> -o wide
Exemple de sortie :
NAME READY STATUS RESTARTS AGE IP NODE
web-app-6d4b8c-abc 0/1 Init:0/2 0 5m 10.244.2.5 node-1
La colonne STATUS montre l'état du conteneur d'initialisation : Init:0/2 signifie que 0 conteneur d'initialisation sur 2 est terminé. Pour lister les noms des conteneurs d'initialisation dans un pod :
kubectl get pod web-app-6d4b8c-abc -n <namespace> -o jsonpath='{.spec.initContainers[*].name}'
Sortie attendue :
init-db init-migrate
Inspecter les événements du pod pour un premier signal
kubectl describe pod web-app-6d4b8c-abc -n <namespace>
Recherchez les événements en bas. Exemple :
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 5m default-scheduler Successfully assigned default/web-app-6d4b8c-abc to node-1
Warning Failed 4m kubelet Error: failed to create containerd task: failed to create shim: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "bootstrap.sh": executable file not found in $PATH: unknown
Cet événement pointe immédiatement vers un exécutable manquant dans l'image du conteneur d'initialisation.
Chemin de configuration sûr
Lorsque vous modifiez une configuration, capturez toujours l'état actuel avec horodatage, puis appliquez le plus petit changement réversible. Ne mettez jamais de secrets directement dans les manifestes ; utilisez les Secrets Kubernetes ou des stockages de secrets externes.
Capturer le manifeste actuel et la somme de contrôle
kubectl get pod web-app-6d4b8c-abc -n <namespace> -o yaml > pod-before.yaml
shasum -a 256 pod-before.yaml
Exemple de sortie :
e1c7f8f2b6a4d... pod-before.yaml
Mauvaise configuration courante : commande ou arguments incorrects
De nombreux conteneurs d'initialisation échouent parce que la command ou les args remplacent incorrectement le point d'entrée par défaut de l'image. Par exemple, ce manifeste vise à attendre une base de données mais utilise incorrectement une commande shell :
initContainers:
- name: init-mysql
image: busybox:1.36
command: ["until nc -z mysql 3306; do sleep 2; done"]
La commande est une chaîne unique, mais command attend un tableau. Il faudrait :
initContainers:
- name: init-mysql
image: busybox:1.36
command: ['sh', '-c', 'until nc -z mysql 3306; do echo waiting for mysql; sleep 2; done']
Après correction, appliquez le changement :
kubectl apply -f deployment.yaml
kubectl rollout status deployment/web-app -n <namespace> --timeout=120s
Sortie attendue en cas de succès :
deployment "web-app" successfully rolled out
Variables d'environnement et secrets
Utilisez des références de secret plutôt que des valeurs littérales :
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
Vérifiez que le secret existe avant la création du pod :
kubectl get secret db-secret -n <namespace>
S'il manque, le conteneur d'initialisation peut échouer avec CreateContainerConfigError. Voir Modes de défaillance.
Notes de compatibilité de version
- Kubernetes 1.20+ prend en charge les conteneurs éphémères pour le débogage, mais les conteneurs d'initialisation sont standard.
- Si vous utilisez
restartPolicy: Alwaysdans un pod avec des conteneurs d'initialisation, les conteneurs d'initialisation en échec redémarrent selon la politique.
Vérification et diagnostic
Cette section montre des commandes de diagnostic pas à pas pour identifier la défaillance exacte.
Obtenir les journaux du conteneur d'initialisation
kubectl logs web-app-6d4b8c-abc -n <namespace> -c init-mysql --tail=50
Si le conteneur d'initialisation a planté et redémarré, utilisez --previous :
kubectl logs web-app-6d4b8c-abc -n <namespace> -c init-mysql --previous
Exemple de journal pour un refus de connexion :
/bin/sh: nc: not found
Cela indique que nc est manquant dans busybox. Utilisez busybox:1.36 avec nc via busybox-extras ou une autre image comme alpine/socat.
Vérifier les codes de sortie et la raison de terminaison
kubectl get pod web-app-6d4b8c-abc -n <namespace> -o jsonpath='{.status.initContainerStatuses[?(@.name=="init-mysql")].state}'
Exemple de sortie :
{"terminated":{"exitCode":127,"reason":"ContainerCannotRun","message":"exec: \"nc\": executable file not found in $PATH","startedAt":"...","finishedAt":"...","containerID":"..."}}
Codes de sortie courants :
126: permission refusée ou commande non exécutable127: commande introuvable137: SIGKILL (OOM ou échec de sonde de vie)1: erreur applicative générale
Inspecter les limites de ressources et l'état du nœud
Si le conteneur d'initialisation reste bloqué dans Init:0/1 pendant longtemps, vérifiez s'il est OOMKilled :
kubectl describe pod web-app-6d4b8c-abc -n <namespace> | grep -A5 'State'
Exemple :
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: OOMKilled
Exit Code: 137
Augmentez la limite de mémoire ou optimisez le conteneur d'initialisation.
Déboguer avec des conteneurs éphémères (K8s 1.23+)
Si le conteneur d'initialisation ne peut pas démarrer du tout, vous pouvez exécuter un conteneur de débogage éphémère pour inspecter l'environnement :
kubectl debug -it web-app-6d4b8c-abc -n <namespace> --image=busybox:1.36 --target=init-mysql
Testez ensuite la connectivité manuellement.
Modes de défaillance et récupération
Cette section couvre des modes de défaillance spécifiques, leurs causes et les étapes de récupération.
Défaillance : Init:Error ou Init:CrashLoopBackOff
Cause : le processus du conteneur d'initialisation se termine avec un code non nul à plusieurs reprises. Récupération :
- Obtenez les journaux et le code de sortie comme ci-dessus.
- Corrigez la commande, le bogue de script ou la dépendance manquante.
- Appliquez le correctif et forcez un nouveau déploiement si nécessaire :
kubectl rollout restart deployment/web-app -n <namespace>
- Surveillez :
kubectl get pods -n <namespace> -w
Défaillance : Init:CreateContainerConfigError
Cause : la ConfigMap ou le Secret référencé n'existe pas, ou problème de permissions. Exemple d'événement :
Warning Failed 4s kubelet Error: secret "db-secret" not found
Récupération :
kubectl create secret generic db-secret --from-literal=password='S3cureP@ss' -n <namespace>
# ou appliquez le manifeste du secret
kubectl apply -f db-secret.yaml
Supprimez ensuite le pod pour redémarrer les conteneurs d'initialisation :
kubectl delete pod web-app-6d4b8c-abc -n <namespace>
Défaillance : Init:ImagePullBackOff
Cause : nom d'image incorrect, balise, authentification ou politique réseau. Vérifiez les événements :
kubectl describe pod web-app-6d4b8c-abc -n <namespace> | grep -A5 'Events'
Exemple :
Warning Failed 10s kubelet Failed to pull image "myregistry/init:v2": rpc error: code = NotFound desc = failed to pull and unpack image "myregistry/init:v2": failed to resolve reference "myregistry/init:v2": not found
Récupération : corrigez le nom/la balise de l'image, créez un imagePullSecret :
kubectl create secret docker-registry regcred --docker-server=myregistry --docker-username=user --docker-password=pass [email protected]
Ajoutez imagePullSecrets à la spécification du pod.
Défaillance : le conteneur d'initialisation se termine mais le conteneur d'application échoue
Ce n'est pas une défaillance du conteneur d'initialisation en soi, mais vérifiez que le conteneur d'initialisation a réussi :
kubectl get pod web-app-6d4b8c-abc -n <namespace> -o jsonpath='{.status.initContainerStatuses[*].state.terminated.exitCode}'
Si la sortie est 0, les conteneurs d'initialisation ont réussi ; dépannez le conteneur d'application séparément.
Liste de contrôle opérationnelle
Utilisez cette liste avant et après tout changement sur les conteneurs d'initialisation.
Avant le changement
- [ ] Confirmer la version du cluster et la compatibilité de l'API.
- [ ] Capturer le manifeste actuel du pod avec horodatage :
kubectl get pod <name> -o yaml > pod-$(date +%Y%m%d%H%M%S).yaml - [ ] Identifier les noms des conteneurs d'initialisation :
kubectl get pod <name> -o jsonpath='{.spec.initContainers[*].name}' - [ ] Noter l'état actuel :
kubectl get pods -n <namespace> - [ ] Vérifier que tous les secrets/configmaps référencés existent.
Après le changement
- [ ] Appliquer le changement :
kubectl apply -f updated-manifest.yaml - [ ] Surveiller le déploiement :
kubectl rollout status deployment/<deployment> --timeout=120s - [ ] Vérifier que le nouveau pod est passé à
Runningavec tous les conteneurs d'initialisation terminés :
kubectl wait --for=condition=Initialized pod/web-app-6d4b8c-abc -n <namespace> --timeout=60s
Attendu : pod/web-app-6d4b8c-abc condition met
- [ ] Tester le point de terminaison de l'application ou sa fonctionnalité.
- [ ] Documenter le mode de défaillance, la cause et le correctif dans le runbook.
Exemple d'entrée de runbook
Date : 2025-03-15
Problème : Le conteneur d'initialisation init-mysql a quitté avec le code 127, nc introuvable.
Correctif : Changement de l'image de busybox:1.35 à alpine/socat:1.7.4.3 et ajustement de la commande.
Vérification : le pod est passé à Running en 45 s, le journal montre "waiting for mysql" puis succès.
Conclusion
Le dépannage des conteneurs d'initialisation Kubernetes nécessite une approche méthodique : rassembler les détails de version et d'environnement, inspecter les événements et les journaux, vérifier les codes de sortie et appliquer des correctifs minimaux avec vérification. Les exemples de ce guide fournissent un modèle pour les défaillances courantes telles que les binaires manquants, les mauvaises commandes, les secrets absents et les erreurs d'extraction d'image. Observez toujours avant de modifier, protégez les informations d'identification et définissez la vérification de la récupération avant un incident. Choisissez une vérification à faible risque de ce guide, enregistrez l'état actuel, exécutez le contrôle documenté, comparez le résultat et examinez les dépendances telles que le cycle de vie du pod et la configuration. Un flux de travail fiable rend la défaillance visible et limite les changements à la ressource prévue.