troubleshooting7 min de lecture

Déboguer un pod en CrashLoopBackOff sur Kubernetes : causes et solutions

SFEIR Institute

Points clés

  • 23% des incidents Kubernetes en production sont liés à CrashLoopBackOff (Komodor 2024)
  • kubectl logs --previous affiche les logs du conteneur crashé précédent
  • 'Backoff exponentiel: délais croissants entre tentatives de redémarrage'

Le debug pod CrashLoopBackOff Kubernetes est l'une des compétences de dépannage les plus demandées. Selon Komodor State of Kubernetes 2024, CrashLoopBackOff représente 23% des incidents en production. Ce guide détaille les causes, la méthodologie de diagnostic, et les solutions pour chaque scénario. Un développeur Backend Kubernetes ou un ingénieur logiciel doit maîtriser ces techniques pour maintenir des applications stables.

TL;DR : CrashLoopBackOff signifie que le container démarre, crash, et Kubernetes tente de le redémarrer avec un backoff exponentiel. Les causes principales sont : erreur applicative, configuration manquante, ressources insuffisantes, ou problème d'image. Utilisez kubectl describe et kubectl logs --previous pour diagnostiquer.

Pour maîtriser le dépannage Kubernetes, suivez la formation LFS458 Administration Kubernetes.

Qu'est-ce que CrashLoopBackOff exactement ?

CrashLoopBackOff est un état du pod indiquant que le container principal crash de manière répétée. Kubernetes applique un délai de redémarrage exponentiel (backoff) entre les tentatives : 10s, 20s, 40s, jusqu'à un maximum de 5 minutes.

Cette définition technique cache une réalité opérationnelle frustrante : le pod ne fonctionne jamais assez longtemps pour être débogué de l'intérieur.

# Identifier les pods en CrashLoopBackOff
kubectl get pods -A | grep CrashLoopBackOff

# Exemple de sortie
NAMESPACE   NAME                      READY   STATUS             RESTARTS   AGE
production  checkout-7d4b5c6f9-x2k4n  0/1     CrashLoopBackOff   15         12m
À retenir : Le compteur RESTARTS indique le nombre de redémarrages. Un nombre élevé (>10) suggère un problème persistant nécessitant une investigation approfondie.

Comment debug pod CrashLoopBackOff Kubernetes : méthodologie

La méthodologie de dépannage pod erreur restart Kubernetes suit une approche systématique en 5 étapes.

Étape 1 : Collecter les informations de base

# Détails complets du pod
kubectl describe pod checkout-7d4b5c6f9-x2k4n -n production

# Points clés à examiner dans la sortie :
# - Events (fin de la sortie)
# - State / Last State
# - Exit Code
# - Reason

L'exit code révèle souvent la cause :

Exit CodeSignificationCause probable
0SuccèsContainer terminé normalement (pas prévu pour un serveur)
1Erreur applicationException non gérée, erreur de config
137SIGKILL (OOM)Limite mémoire dépassée
139SIGSEGVSegmentation fault
143SIGTERMTerminaison gracieuse échouée

Étape 2 : Examiner les logs du container précédent

# Logs du crash précédent
kubectl logs checkout-7d4b5c6f9-x2k4n -n production --previous

# Si plusieurs containers
kubectl logs checkout-7d4b5c6f9-x2k4n -n production -c main --previous

Cette commande récupère les logs du container avant son crash, essentiels pour comprendre l'erreur.

Étape 3 : Analyser les événements du namespace

# Événements triés par timestamp
kubectl get events -n production --sort-by='.lastTimestamp' | tail -20

Les événements révèlent des problèmes de scheduling, de pull d'image, ou de montage de volumes.

Pour une vision globale du monitoring, consultez le module Monitoring et dépannage Kubernetes.

Causes principales et solutions pour debug pod CrashLoopBackOff Kubernetes

Cause 1 : Erreur applicative au démarrage

Le container démarre mais l'application crash immédiatement. C'est la cause la plus fréquente (45% des cas selon Komodor).

Symptômes :

Exit Code: 1
Reason: Error

Diagnostic :

# Logs de l'application
kubectl logs checkout-7d4b5c6f9-x2k4n --previous

# Exemple de sortie
Error: Cannot connect to database at postgres:5432

Solutions :

# 1. Ajouter des init containers pour les dépendances
initContainers:
  - name: wait-for-db
    image: busybox:1.36
    command: ['sh', '-c', 'until nc -z postgres 5432; do sleep 2; done']

# 2. Configurer les readiness/liveness probes correctement
readinessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 10
  periodSeconds: 5

Cause 2 : Configuration manquante (ConfigMap/Secret)

Le container essaie de lire une variable d'environnement ou un fichier de configuration qui n'existe pas.

Symptômes :

State: Waiting
Reason: CreateContainerConfigError

Diagnostic :

# Vérifier les ConfigMaps référencés
kubectl describe pod checkout-7d4b5c6f9-x2k4n | grep -A5 "Environment"

# Vérifier que le ConfigMap existe
kubectl get configmap checkout-config -n production

Solutions :

# Rendre la variable optionnelle
env:
  - name: DATABASE_URL
    valueFrom:
      configMapKeyRef:
        name: checkout-config
        key: database-url
        optional: true  # Le pod démarre même si absent
À retenir : Utilisez optional: true pour les configurations non critiques. Validez les configurations requises dans un init container.

Cause 3 : OOMKilled (dépassement mémoire)

Le container dépasse sa limite mémoire et est tué par le kernel.

Symptômes :

Exit Code: 137
Reason: OOMKilled
Last State: Terminated

Diagnostic :

# Vérifier la consommation mémoire avant le crash
kubectl top pod checkout-7d4b5c6f9-x2k4n --containers

# Comparer avec les limits
kubectl get pod checkout-7d4b5c6f9-x2k4n -o jsonpath='{.spec.containers[0].resources}'

Solutions :

resources:
  requests:
    memory: "512Mi"
  limits:
    memory: "1Gi"  # Augmenter si nécessaire

Pour un guide détaillé, consultez Résoudre les erreurs OOMKilled.

Cause 4 : Problème d'image container

L'image ne peut pas être tirée ou le entrypoint est incorrect.

Symptômes :

State: Waiting
Reason: ImagePullBackOff
# ou
Reason: CrashLoopBackOff avec Exit Code: 127 (command not found)

Diagnostic :

# Vérifier les événements de pull
kubectl describe pod checkout-7d4b5c6f9-x2k4n | grep -A3 "Events"

# Tester localement
docker run --rm myregistry/checkout:v1.2.3 /bin/sh -c "echo test"

Solutions :

# Vérifier le imagePullSecret
imagePullSecrets:
  - name: registry-credentials

# Corriger le command/entrypoint
command: ["/app/checkout"]  # Chemin absolu
args: ["--port=8080"]

Cause 5 : Probes mal configurées

Les liveness probes tuent le container avant qu'il soit prêt.

Symptômes :

Events:
  Liveness probe failed: connection refused
  Container checkout-container failed liveness probe, will be restarted

Diagnostic : Si votre application met 30 secondes à démarrer, votre liveness probe doit commencer à 30 secondes. Les probes agressives sont la première cause de CrashLoopBackOff auto-infligé.

# Vérifier le timing des probes
kubectl get pod checkout-7d4b5c6f9-x2k4n -o yaml | grep -A10 livenessProbe

Solutions :

livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 60  # Attendre le démarrage
  periodSeconds: 10
  failureThreshold: 3      # 3 échecs avant restart

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5   # Plus rapide que liveness
  periodSeconds: 5
À retenir : La readinessProbe doit être plus rapide que la livenessProbe. Commencez avec des valeurs conservatrices puis optimisez.

Techniques avancées de debugging Kubernetes

Utiliser kubectl debug (Kubernetes 1.25+)

Les ephemeral containers permettent d'attacher un container de debug à un pod en cours d'exécution ou crashé.

# Attacher un container debug
kubectl debug -it checkout-7d4b5c6f9-x2k4n --image=busybox:1.36 --target=checkout

# Debug avec des outils réseau
kubectl debug -it checkout-7d4b5c6f9-x2k4n --image=nicolaka/netshoot

Copier le pod pour debugging

# Créer une copie avec command modifié
kubectl debug checkout-7d4b5c6f9-x2k4n -it --copy-to=checkout-debug \
  --container=checkout -- /bin/sh

# Le pod debug reste actif pour investigation

Cette technique est enseignée dans la formation Kubernetes administrateur système.

Examiner les logs du runtime container

# Sur le nœud (nécessite accès SSH)
crictl logs <container-id>

# Trouver le container ID
kubectl get pod checkout-7d4b5c6f9-x2k4n -o jsonpath='{.status.containerStatuses[0].containerID}'

Checklist de dépannage rapide

Utilisez cette checklist pour un diagnostic systématique :

#!/bin/bash
# debug-crashloop.sh <pod-name> <namespace>

POD=$1
NS=${2:-default}

echo "=== 1. État du pod ==="
kubectl get pod $POD -n $NS

echo "=== 2. Description ==="
kubectl describe pod $POD -n $NS | tail -30

echo "=== 3. Logs précédents ==="
kubectl logs $POD -n $NS --previous --tail=50 2>/dev/null || echo "Pas de logs précédents"

echo "=== 4. Événements ==="
kubectl get events -n $NS --field-selector involvedObject.name=$POD

echo "=== 5. Ressources ==="
kubectl top pod $POD -n $NS --containers 2>/dev/null || echo "Metrics non disponibles"

Consultez également le guide Résoudre les échecs de déploiement Kubernetes pour une approche complémentaire.

Prévenir les CrashLoopBackOff en production

Bonnes pratiques de configuration

apiVersion: apps/v1
kind: Deployment
metadata:
  name: checkout
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    spec:
      terminationGracePeriodSeconds: 30
      containers:
        - name: checkout
          image: myregistry/checkout:v1.2.3
          
          # Ressources explicites
          resources:
            requests:
              cpu: 100m
              memory: 256Mi
            limits:
              cpu: 500m
              memory: 512Mi
          
          # Probes bien calibrées
          startupProbe:
            httpGet:
              path: /health
              port: 8080
            failureThreshold: 30
            periodSeconds: 10
          
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            periodSeconds: 10
            failureThreshold: 3
          
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            periodSeconds: 5
            failureThreshold: 3
À retenir : La startupProbe (K8s 1.20+) remplace initialDelaySeconds pour les applications à démarrage lent. Elle empêche liveness de tuer le container pendant le démarrage.

Monitoring proactif

Configurez des alertes avant que le problème n'affecte les utilisateurs :

# PrometheusRule
- alert: PodCrashLooping
  expr: |
    increase(kube_pod_container_status_restarts_total[1h]) > 5
  for: 5m
  labels:
    severity: warning
  annotations:
    summary: "Pod {{ $labels.pod }} en CrashLoop"

La checklist observabilité Kubernetes en production détaille ces configurations.

Problèmes réseau causant des crashes

Les problèmes réseau peuvent provoquer des CrashLoopBackOff indirects (application qui timeout et crash).

Symptômes :

  • Logs montrant des timeouts de connexion
  • Exit code 1 après délai

Diagnostic :

# Depuis un pod de debug
kubectl run debug --rm -it --image=nicolaka/netshoot -- /bin/bash

# Tests réseau
nslookup kubernetes.default
curl -v http://checkout-service.production.svc.cluster.local:8080/health

Consultez le guide Diagnostic et résolution des problèmes réseau pour approfondir.

Quand escalader et demander de l'aide

Certains CrashLoopBackOff nécessitent une expertise avancée :

  • Exit code 139 (SIGSEGV) : bug mémoire dans l'application, nécessite profiling
  • Problèmes intermittents : peuvent indiquer des race conditions ou des problèmes de nœud
  • Après mise à jour cluster : possibles incompatibilités API

Le déploiement et mise en production Kubernetes couvre les stratégies de rollback pour les déploiements problématiques.

Formations pour maîtriser le troubleshooting Kubernetes

Le dépannage pod erreur restart Kubernetes est une compétence clé évaluée dans les certifications CKA et CKAD.

Pour développer votre expertise en debugging :

Consultez les prochaines sessions ou contactez-nous pour un parcours sur mesure.