
CrashLoopBackOff signifie qu'un conteneur plante, redémarre, puis replante
en boucle. Kubernetes augmente le délai entre chaque redémarrage
(10 s → 20 s → 40 s → ... → 5 min max) pour éviter de surcharger le nœud.
Ce guide vous donne une méthodologie en 4 étapes pour identifier la cause
et corriger le problème.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre le mécanisme du backoff exponentiel et pourquoi Kubernetes augmente le délai entre les redémarrages
- Identifier les 6 causes principales d'un CrashLoopBackOff
- Appliquer une méthodologie de diagnostic reproductible en 4 étapes
- Utiliser
kubectl logs --previousetkubectl describe podpour trouver la cause réelle - Reproduire et corriger un CrashLoopBackOff sur un cluster de test
Prérequis
Section intitulée « Prérequis »- Un cluster Kubernetes fonctionnel (v1.28+)
kubectlconfiguré et connecté au cluster- Des droits de lecture sur les pods, événements et logs
- Connaissances de base sur les Pods et les probes
Qu'est-ce qu'un CrashLoopBackOff ?
Section intitulée « Qu'est-ce qu'un CrashLoopBackOff ? »CrashLoopBackOff n'est pas une phase du Pod. C'est un état d'attente
visible dans la colonne STATUS de kubectl get pods lorsqu'un conteneur
échoue puis redémarre en boucle avec backoff. Selon le moment où vous
observez le Pod, sa phase peut rester Running, mais ce n'est pas
systématique, le point clé est qu'un conteneur redémarre en boucle.
Le backoff exponentiel
Section intitulée « Le backoff exponentiel »Quand un conteneur plante, le kubelet applique un délai croissant avant chaque nouveau redémarrage :
| Tentative | Délai avant redémarrage | Temps total écoulé |
|---|---|---|
| 1re | 10 secondes | 10 s |
| 2e | 20 secondes | 30 s |
| 3e | 40 secondes | 1 min 10 s |
| 4e | 80 secondes | 2 min 30 s |
| 5e | 160 secondes | 5 min 10 s |
| 6e+ | 300 secondes (maximum) | +5 min par tentative |
Si le conteneur reste stable pendant 10 minutes, le compteur de backoff est réinitialisé.
Ces valeurs sont celles d'un cluster par défaut. Depuis Kubernetes 1.35, un
administrateur peut abaisser le plafond de 5 minutes via
crashLoopBackOff.maxContainerRestartPeriod dans la configuration du kubelet.
Si les délais que vous observez ne correspondent pas au tableau, c'est la
première chose à vérifier auprès de l'équipe qui exploite le cluster.
Les 6 causes principales
Section intitulée « Les 6 causes principales »Voici les causes les plus fréquentes rencontrées en pratique :
| # | Cause | Symptôme typique | Où chercher |
|---|---|---|---|
| 1 | Erreur applicative | Exception, panic, segfault dans les logs | kubectl logs |
| 2 | Configuration manquante | Variable d'env absente, fichier de config introuvable | kubectl describe pod (env, volumes) |
| 3 | OOMKilled | Le conteneur dépasse sa limite mémoire | kubectl describe pod → Last State: OOMKilled |
| 4 | Probe mal configurée (liveness ou startup) | Unhealthy, Killing, redémarrages répétés | kubectl describe pod → Events, définition des probes |
| 5 | Commande ou entrypoint invalide | Le conteneur s'arrête immédiatement, en StartError ou avec exit code 126/127 | kubectl describe pod, kubectl logs --previous |
| 6 | Dépendance externe indisponible | La base de données ou l'API n'est pas accessible | kubectl logs (timeout, connection refused) |
Méthodologie de diagnostic en 4 étapes
Section intitulée « Méthodologie de diagnostic en 4 étapes »-
Identifier le pod en CrashLoopBackOff
Listez les pods et repérez ceux dont le STATUS est
CrashLoopBackOffou dont le compteurRESTARTSaugmente :Fenêtre de terminal kubectl get pods -A | grep -E 'CrashLoop|Error|BackOff'Notez le nom du pod, son namespace et le nombre de RESTARTS.
-
Lire les logs du conteneur crashé
La commande la plus importante est
kubectl logs --previous, qui affiche les logs de l'exécution précédente (celle qui a planté) :Fenêtre de terminal kubectl logs <pod> -n <namespace> --previousSi le pod contient plusieurs conteneurs, précisez le conteneur :
Fenêtre de terminal kubectl logs <pod> -n <namespace> -c <conteneur> --previousCherchez des indices :
Exception,Error,panic,Traceback,connection refused,OOM,permission denied. -
Inspecter la description du pod
Fenêtre de terminal kubectl describe pod <pod> -n <namespace>Les sections à regarder en priorité :
- Last State : la raison de l'arrêt précédent (
OOMKilled,Error,Completed) - Exit Code :
0= arrêt normal,1= erreur applicative,137= OOMKilled ou SIGKILL,139= segfault,128= le conteneur n'a même pas démarré - Events :
Unhealthy(probe échouée),BackOff,Pulling - Containers → Args/Command : la commande de démarrage est-elle correcte ?
- Containers → Env : les variables d'environnement sont-elles présentes ?
- Containers → Mounts : les volumes sont-ils montés correctement ?
- Last State : la raison de l'arrêt précédent (
-
Corriger et vérifier
Selon la cause identifiée :
Cause Action corrective Erreur applicative Corriger le code ou la config, redéployer Config manquante Ajouter le ConfigMap/Secret, vérifier les noms OOMKilled Augmenter resources.limits.memoryProbe mal configurée Augmenter initialDelaySeconds,timeoutSeconds, ou ajouter une startup probeCommande/entrypoint invalide Vérifier command:etargs:dans le manifesteDépendance externe Vérifier la connectivité, ajouter un init container Après correction, vérifiez que le pod est stable :
Fenêtre de terminal kubectl get pods -n <namespace> -wLe drapeau
-wsuit l'évolution en direct. Le Pod doit passer àRunning, et le compteurRESTARTSne doit plus augmenter : c'est cette seconde condition qui prouve la correction.
Exemple pratique : reproduire un CrashLoopBackOff
Section intitulée « Exemple pratique : reproduire un CrashLoopBackOff »Pour bien comprendre le mécanisme, créons volontairement un pod qui crashe.
Cas 1 : erreur applicative (exit code 1)
Section intitulée « Cas 1 : erreur applicative (exit code 1) »kubectl apply -f- <<'EOF'apiVersion: v1kind: Podmetadata: name: crash-exit-error namespace: defaultspec: restartPolicy: Always containers: - name: app image: busybox:1.37@sha256:9db7b59979c38555a39def84a31fb98b5296952f9e3afd4f6f11f05b07adfab0 command: ["sh", "-c", "echo 'Application démarrée'; sleep 2; echo 'Erreur fatale!'; exit 1"]EOFAttendez 30 secondes puis observez :
kubectl get pods crash-exit-error -wVous verrez le STATUS passer de Running à Error puis à
CrashLoopBackOff, avec le compteur RESTARTS qui augmente.
Diagnostic :
# Logs de l'exécution qui a crashékubectl logs crash-exit-error --previous
# Description avec exit codekubectl describe pod crash-exit-error | grep -A5 "Last State"Cas 2 : OOMKilled (dépassement mémoire)
Section intitulée « Cas 2 : OOMKilled (dépassement mémoire) »Pour provoquer un vrai OOMKill, le conteneur doit allouer de la mémoire
au-delà de sa limite. Un simple dd vers /dev/null consomme du CPU, pas de
la RAM. Voici un exemple qui alloue réellement de la mémoire avec un tail
grossier :
kubectl apply -f- <<'EOF'apiVersion: v1kind: Podmetadata: name: crash-oom namespace: defaultspec: restartPolicy: Always containers: - name: app image: python:3.13-slim@sha256:6771159cd4fa5d9bba1258caf0b82e6b73458c694d178ad97c5e925c2d0e1a91 command: ["python3", "-c", "data = []; [data.append('x' * 10**6) for _ in range(500)]"] resources: limits: memory: "50Mi"EOFLe script Python alloue des blocs de 1 Mo en boucle jusqu'à dépasser la limite de 50 Mi, ce qui déclenche un OOMKill.
Diagnostic :
kubectl describe pod crash-oom | grep -A5 "Last State"Vous verrez Reason: OOMKilled et Exit Code: 137.
Nettoyage
Section intitulée « Nettoyage »Un Pod en CrashLoopBackOff peut mettre du temps à disparaître : le
kubelet attend la fin du délai en cours avant de traiter la suppression. Les
deux options ci-dessous coupent court à cette attente, et n'ont rien de
dangereux ici : ces Pods ne portent aucune donnée.
kubectl delete pod crash-exit-error crash-oom --force --grace-period=0Les exit codes essentiels
Section intitulée « Les exit codes essentiels »Les exit codes aident à identifier rapidement la nature du crash :
| Exit code | Signification | Cause probable |
|---|---|---|
0 | Arrêt normal | Le conteneur s'est terminé volontairement, si restartPolicy: Always, il sera relancé |
1 | Erreur générique | Bug applicatif, exception non gérée |
2 | Mauvais usage de commande shell | Commande ou argument invalide dans command: |
126 | Permission denied | Un shell a refusé d'exécuter un fichier non exécutable |
127 | Command not found | Un shell n'a pas trouvé le binaire demandé |
128 | StartError | Le conteneur n'a jamais démarré : c'est le runtime qui a échoué, pas un programme |
137 | SIGKILL (128 + 9) | Processus tué par SIGKILL, souvent un OOMKill, mais pas exclusivement |
139 | SIGSEGV (128 + 11) | Segmentation fault dans l'application |
143 | SIGTERM (128 + 15) | Arrêt gracieux demandé par Kubernetes |
Cas particuliers
Section intitulée « Cas particuliers »Trois situations produisent un CrashLoopBackOff sans que la méthode en
quatre étapes suffise, parce que l'information attendue n'est pas là où on
la cherche : les journaux sont vides, le conteneur fonctionne pourtant
très bien, ou le coupable n'est pas le conteneur applicatif. Les
reconnaître évite de relire dix fois une sortie qui ne dira jamais rien.
CrashLoopBackOff avec logs vides
Section intitulée « CrashLoopBackOff avec logs vides »Si kubectl logs --previous ne retourne rien, c'est que le conteneur a planté
avant de produire quoi que ce soit, ou qu'il n'a jamais démarré. La
distinction se lit dans l'exit code, et elle change complètement l'endroit où
chercher.
Les codes 126 et 127 viennent d'un shell : ils supposent qu'un shell a
bien démarré, puis n'a pas trouvé ou pas pu exécuter ce que vous lui demandiez.
Le message est alors dans les logs.
kubectl logs mon-pod --previoussh: binaire-absent: not foundQuand le manifeste appelle le binaire directement, sans shell, il n'y a
personne pour produire ce message : le runtime échoue à créer le conteneur, et
Kubernetes rend un StartError avec l'exit code 128. Les logs sont alors
définitivement vides, et la cause vit dans un champ que peu de gens pensent à
lire :
kubectl get pod mon-pod \ -o jsonpath='{.status.containerStatuses[0].state.terminated.message}'failed to create containerd task: failed to create shim task:OCI runtime create failed: runc create failed: unable to start container processRetenez la règle : 126 ou 127, regardez les logs ; 128, regardez le
message. Un 137 immédiat, lui, désigne un OOMKill au démarrage.
CrashLoopBackOff causé par une liveness probe
Section intitulée « CrashLoopBackOff causé par une liveness probe »Si les événements montrent Unhealthy suivi de Killing, le conteneur
fonctionne mais la liveness probe considère qu'il est mort :
Warning Unhealthy 10s kubelet Liveness probe failed: HTTP probe failed with statuscode: 503Normal Killing 10s kubelet Container app failed liveness probe, will be restartedLa solution est de revoir la configuration de la probe :
- Augmenter
initialDelaySecondssi l'application met du temps à démarrer - Augmenter
timeoutSecondssi le endpoint est lent - Utiliser une startup probe pour les démarrages longs
Consultez le guide sur les probes Kubernetes pour les bonnes pratiques de configuration.
CrashLoopBackOff sur un init container
Section intitulée « CrashLoopBackOff sur un init container »Un init container s'exécute une fois, avant le conteneur principal. S'il
échoue, le Pod n'atteint jamais Running, et la colonne STATUS affiche
Init:CrashLoopBackOff : le préfixe Init: est ce qui vous met sur la
piste.
Diagnostic identique, en précisant le conteneur :
kubectl logs <pod> -c <init-container> --previousDépannage rapide
Section intitulée « Dépannage rapide »Ce tableau se lit par la colonne de gauche, celle du symptôme observé. Chaque ligne donne la première action à mener, celle qui écarte ou confirme une famille de causes avant d'aller plus loin. Si aucune ne correspond, revenez à la méthode en quatre étapes plutôt que d'essayer des commandes au hasard.
| Symptôme | Première action | Commande |
|---|---|---|
CrashLoopBackOff avec RESTARTS élevés | Lire les logs précédents | kubectl logs <pod> --previous |
| Exit code 137, pas de logs | Vérifier la mémoire | kubectl describe pod <pod> → chercher OOMKilled |
| Exit code 127 | Vérifier l'image et la commande | kubectl describe pod <pod> → section Containers |
Events Unhealthy + Killing | La probe tue le conteneur | Revoir livenessProbe dans le manifeste |
Init:CrashLoopBackOff | L'init container crashe | kubectl logs <pod> -c <init-container> --previous |
| Logs montrent "connection refused" | Dépendance externe absente | Vérifier le Service/Endpoint cible |
À retenir
Section intitulée « À retenir »CrashLoopBackOffn'est pas une phase du Pod, c'est un état d'attente entre deux redémarrages, avec un délai qui double à chaque crash (10 s → 300 s max)kubectl logs --previousest votre commande principale : elle affiche les logs de l'exécution qui a plantékubectl describe podrévèle l'exit code, les événements et la configuration, indispensable quand les logs sont vides- Exit code 137 = processus tué par
SIGKILL, souvent un OOMKill (mais pas exclusivement), vérifiez aveckubectl describe podpuis augmentezresources.limits.memorysi c'est confirmé - Exit code 127 = un shell n'a pas trouvé le binaire, le message est
dans les logs ;
StartErroret 128 = le conteneur n'a jamais démarré, les logs sont vides et la cause est dansterminated.message - Si les events montrent
Unhealthy→Killing, c'est la liveness probe qui tue le conteneur, pas un crash applicatif - Après correction, surveillez le pod avec
kubectl get pods -wet vérifiez que les RESTARTS ne reprennent pas
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Sept questions sur ce qui fait perdre le plus de temps en incident : la distinction entre une phase et un état d'attente, le champ où lire la cause quand les journaux sont vides, et la signature d'une sonde de vivacité trop agressive.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Diagnostiquer un ImagePullBackOff : L'autre panne de démarrage fréquente, dont les symptômes se confondent parfois avec le CrashLoop.
- Garantir la disponibilité applicative : Les garde-fous qui évitent qu'un redémarrage en boucle coupe le service.
- Routine d'exploitation : Les contrôles réguliers qui repèrent ces boucles avant l'alerte utilisateur.