Aller au contenu
Conteneurs & Orchestration medium
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

Débugger une application Kubernetes

18 min de lecture

logo kubernetes

Kubernetes offre plusieurs outils de diagnostic intégrés. Vous utiliserez principalement kubectl logs pour les erreurs applicatives, kubectl describe et kubectl get events pour les problèmes d’orchestration, et kubectl exec ou kubectl debug pour l’investigation interactive. Ce guide vous montre comment combiner ces outils efficacement.

  • Diagnostiquer avec kubectl get, kubectl describe et kubectl get events
  • Analyser les logs avec kubectl logs
  • Exécuter des commandes avec kubectl exec
  • Utiliser les conteneurs éphémères (kubectl debug)
  • Investiguer les problèmes réseau et de service
  • Résoudre les erreurs courantes (CrashLoopBackOff, ImagePullBackOff, OOMKilled, Pending)

Le debugging suit une progression logique :

  1. Observer — Quel est l’état actuel du Pod, des événements ?
  2. Comprendre — Pourquoi cet état ? Logs, conditions, exit codes
  3. Investiguer — Plonger dans le conteneur si nécessaire
  4. Corriger — Appliquer la solution et vérifier
SymptômePremière commandeDeuxième commande
Pod en CrashLoopBackOffkubectl logs --previouskubectl describe pod
Pod en Pendingkubectl describe podkubectl get events
Pod Running mais application KOkubectl logskubectl port-forward / debug réseau
Image minimale sans shellkubectl debug --image=busyboxps, ss, nslookup, curl
Suspicion OOMkubectl describe podkubectl top pod
Problème de Servicekubectl get endpointskubectl port-forward pod

Première commande pour voir l’état de vos ressources :

Fenêtre de terminal
# État des Pods dans un namespace
kubectl get pods -n mon-namespace
# État de TOUS les Pods du cluster
kubectl get pods -A
# Plus de détails (node, IP)
kubectl get pods -o wide
# Rafraîchissement continu
kubectl get pods -w

Exemple de sortie :

NAME READY STATUS RESTARTS AGE
app-healthy 1/1 Running 0 2h
app-crashloop 0/1 CrashLoopBackOff 5 (30s ago) 3m
app-pending 0/1 Pending 0 5m

Commande sous-estimée mais extrêmement utile. Les événements donnent une vue chronologique de ce qui s’est passé :

Fenêtre de terminal
# Événements du namespace courant, triés par date
kubectl get events --sort-by=.lastTimestamp
# Événements de tous les namespaces
kubectl get events -A --sort-by=.lastTimestamp
# Événements d'un namespace spécifique
kubectl get events -n mon-namespace --sort-by=.lastTimestamp

Exemple de sortie :

LAST SEEN TYPE REASON OBJECT MESSAGE
2m Warning FailedScheduling pod/app-pending 0/3 nodes are available: 3 Insufficient memory
3m Normal Pulling pod/app-new Pulling image "nginx:1.25"
5m Warning BackOff pod/app-crashloop Back-off restarting failed container

Pour comprendre pourquoi un Pod est dans un état donné :

Fenêtre de terminal
kubectl describe pod mon-pod

Sections clés à examiner :

SectionInformation
StatusÉtat actuel du Pod
ConditionsReady, Initialized, ContainersReady, PodScheduled
ContainersÉtat de chaque conteneur, codes de sortie, raison
EventsHistorique chronologique des actions sur ce Pod

kubectl logs lit les logs via le kubelet sur le nœud, à partir des fichiers de logs du conteneur. C’est pourquoi votre application doit écrire vers stdout et stderr.

Fenêtre de terminal
# Logs d'un Pod (conteneur unique)
kubectl logs mon-pod
# Logs d'un conteneur spécifique (Pod multi-conteneurs)
kubectl logs mon-pod -c mon-conteneur
# Dernières 100 lignes
kubectl logs mon-pod --tail=100
# Logs en temps réel
kubectl logs mon-pod -f
# Logs de l'instance précédente du conteneur (après crash)
kubectl logs mon-pod --previous

Pour exécuter des commandes dans un conteneur en cours d’exécution :

Fenêtre de terminal
# Commande unique
kubectl exec mon-pod -- ls -la /app
# Shell interactif
kubectl exec -it mon-pod -- /bin/sh
# Avec conteneur spécifique (Pod multi-conteneurs)
kubectl exec -it mon-pod -c sidecar -- /bin/bash

Les conteneurs éphémères sont stables depuis Kubernetes v1.25. Ils permettent d’injecter un conteneur de debug temporaire dans un Pod existant :

Fenêtre de terminal
# Ajouter un conteneur éphémère basique
kubectl debug mon-pod -it --image=busybox:1.36 --target=app
# Avec des outils réseau complets
kubectl debug mon-pod -it --image=nicolaka/netshoot --target=app

Exemple pratique dans le conteneur de debug :

Fenêtre de terminal
# Voir les processus du conteneur cible
ps aux
# Variables d'environnement du processus principal
cat /proc/1/environ | tr '\0' '\n'
# Ports en écoute
ss -tlnp
# Test de connectivité réseau
curl -v http://mon-service:8080/health
Fenêtre de terminal
# Pod → Local
kubectl cp mon-pod:/app/logs/error.log ./error.log
# Local → Pod
kubectl cp ./config.yaml mon-pod:/app/config.yaml
# Avec conteneur spécifique
kubectl cp mon-pod:/app/dump.txt ./dump.txt -c app

Voir la consommation CPU/mémoire (nécessite metrics-server installé) :

Fenêtre de terminal
# Pods du namespace courant
kubectl top pods
# Tous les Pods
kubectl top pods -A
# Nœuds
kubectl top nodes
# Tri par mémoire
kubectl top pods --sort-by=memory
# Un Pod spécifique avec ses conteneurs
kubectl top pod mon-pod --containers

Accédez à un Pod ou Service sans exposition externe :

Fenêtre de terminal
# Vers un Pod
kubectl port-forward mon-pod 8080:80
# Vers un Service
kubectl port-forward svc/mon-service 8080:80
# En arrière-plan
kubectl port-forward mon-pod 8080:80 &

Utile pour tester si le Pod répond indépendamment du Service.

Symptôme : Le conteneur démarre, crash, redémarre en boucle.

  1. Vérifiez les logs du crash précédent

    Fenêtre de terminal
    kubectl logs mon-pod --previous
  2. Examinez le code de sortie et la raison

    Fenêtre de terminal
    kubectl describe pod mon-pod | grep -A10 "Last State"
  3. Interprétez le code de sortie

    CodeSignification
    0Sortie normale (mais Pod censé tourner → vérifiez la commande)
    1Erreur applicative générique
    137Processus tué par SIGKILL (souvent OOM — confirmez avec describe)
    143SIGTERM reçu (arrêt propre demandé)
  4. Appliquez la solution

    • Code 1 : Corrigez le bug applicatif (voir logs)
    • Code 137 + OOMKilled : Augmentez resources.limits.memory
    • Sortie immédiate (code 0) : Vérifiez la commande/entrypoint

Symptôme : Kubernetes ne peut pas télécharger l’image.

Fenêtre de terminal
kubectl describe pod mon-pod | grep -A10 Events
kubectl get events --field-selector involvedObject.name=mon-pod
CauseSolution
Image inexistanteVérifiez le nom et le tag exact
Registry privéCréez un imagePullSecret et référencez-le
Quota Docker HubAuthentifiez-vous ou utilisez un registry privé
Erreur réseauVérifiez la connectivité du nœud vers le registry

Symptôme : Le Pod reste en Pending indéfiniment.

Fenêtre de terminal
kubectl describe pod mon-pod | grep -A20 Events
kubectl get events -A --sort-by=.lastTimestamp | grep -i scheduling
CauseSolution
Insufficient cpu/memoryRéduisez les requests ou ajoutez des nœuds
No nodes match nodeSelectorVérifiez les labels des nœuds
Taints not toleratedAjoutez les tolerations nécessaires
PVC pendingVérifiez le PVC et le StorageClass

Symptôme : Conteneur tué pour surconsommation mémoire.

Fenêtre de terminal
# Vérifier l'état du conteneur
kubectl describe pod mon-pod | grep -A5 "Last State"
# Chercher OOMKilled explicitement
kubectl describe pod mon-pod | grep -i oom
# Voir la consommation actuelle
kubectl top pod mon-pod --containers

Solutions :

  1. Augmentez resources.limits.memory
  2. Analysez les fuites mémoire de l’application
  3. Ajoutez du monitoring pour détecter la tendance avant le crash

C’est un cas très fréquent : le Pod est Running, mais l’application ne répond pas.

Étape 1 : Vérifiez que le Pod répond directement

Section intitulée « Étape 1 : Vérifiez que le Pod répond directement »
Fenêtre de terminal
# Accès direct au Pod, contournant le Service
kubectl port-forward mon-pod 8080:80
# Dans un autre terminal
curl http://localhost:8080/health

Si le Pod répond : le problème vient du Service ou du réseau. Si le Pod ne répond pas : le problème est applicatif.

Fenêtre de terminal
# Voir le Service
kubectl get svc mon-service -o wide
# Vérifier que le Service a des endpoints
kubectl get endpoints mon-service
# Ou avec EndpointSlices (Kubernetes moderne)
kubectl get endpointslices -l kubernetes.io/service-name=mon-service

Endpoints vides ? Le selector du Service ne matche aucun Pod. Vérifiez les labels :

Fenêtre de terminal
# Labels du Service (selector)
kubectl get svc mon-service -o jsonpath='{.spec.selector}'
# Labels des Pods
kubectl get pods --show-labels

Étape 3 : Testez la connectivité depuis un autre Pod

Section intitulée « Étape 3 : Testez la connectivité depuis un autre Pod »
Fenêtre de terminal
# Lancer un Pod de debug avec des outils réseau
kubectl run debug-net --rm -it --image=nicolaka/netshoot -- /bin/bash
# Dans le Pod de debug
nslookup mon-service
curl -v http://mon-service:80/health
nc -zv mon-service 80

Quand kubectl exec échoue faute de shell (distroless, scratch), voici le workflow :

  1. Lancez un conteneur éphémère avec une image de debug

    Fenêtre de terminal
    kubectl debug mon-pod -it --image=nicolaka/netshoot --target=app
  2. Explorez le conteneur cible

    Fenêtre de terminal
    # Processus
    ps aux
    # Variables d'environnement
    cat /proc/1/environ | tr '\0' '\n'
    # Fichiers ouverts
    ls -la /proc/1/fd/
  3. Testez le réseau

    Fenêtre de terminal
    # Résolution DNS
    nslookup kubernetes.default
    nslookup mon-service.mon-namespace.svc.cluster.local
    # Connectivité TCP
    nc -zv mon-service 80
    # Test HTTP
    curl -v http://mon-service:80/health
    # Ports en écoute dans le conteneur cible
    ss -tlnp
    # Routes réseau
    ip route
  4. Vérifiez les volumes montés

    Fenêtre de terminal
    mount | grep -v "cgroup\|proc\|sys"
    cat /etc/resolv.conf
  1. Vue globale

    Fenêtre de terminal
    kubectl get pods -A | grep -v Running
    kubectl get events -A --sort-by=.lastTimestamp | head -20
  2. Cibler le Pod problématique

    Fenêtre de terminal
    kubectl describe pod mon-pod
  3. Logs applicatifs

    Fenêtre de terminal
    kubectl logs mon-pod --tail=100
    # Si crash récent
    kubectl logs mon-pod --previous
  4. Investigation interactive

    Fenêtre de terminal
    # Si shell disponible
    kubectl exec -it mon-pod -- /bin/sh
    # Sinon
    kubectl debug mon-pod -it --image=nicolaka/netshoot --target=app
  5. Vérification réseau/service

    Fenêtre de terminal
    kubectl port-forward mon-pod 8080:80
    kubectl get endpoints mon-service
  6. Métriques

    Fenêtre de terminal
    kubectl top pod mon-pod --containers
  1. Loguez vers stdout/stderr — Kubernetes capture automatiquement via le kubelet
  2. Implémentez des health endpoints/health, /ready pour les probes
  3. Définissez des ressources — Évite les OOMKilled silencieux et les Pending
  4. Utilisez des labels cohérents — Facilite le filtrage (kubectl get pods -l app=api)
  5. Gérez SIGTERM proprement — Arrêt gracieux pour les rolling updates
  1. Commencez par get events — Vue chronologique de ce qui s’est passé
  2. Utilisez -A / --all-namespaces — Quand vous ne savez pas où est le problème
  3. Gardez une image de debugnicolaka/netshoot ou busybox pour les cas difficiles
  4. Centralisez les logs — Loki, Elasticsearch, CloudWatch pour l’historique
  1. Vue globale rapide

    Fenêtre de terminal
    kubectl get pods -A
    kubectl get events -A --sort-by=.lastTimestamp
  2. Diagnostic d’un Pod

    Fenêtre de terminal
    kubectl describe pod <pod>
    kubectl logs <pod> --previous
  3. Investigation interactive

    Fenêtre de terminal
    kubectl exec -it <pod> -- /bin/sh
  4. Test de connectivité

    Fenêtre de terminal
    kubectl port-forward <pod> 8080:80
  5. Debug avancé (images minimales)

    Fenêtre de terminal
    kubectl debug <pod> -it --image=busybox --target=<container>
  6. Vérifier les endpoints d’un Service

    Fenêtre de terminal
    kubectl get endpoints <service>
SituationCommande
Vue globale tous namespaceskubectl get pods -A
Événements chronologiqueskubectl get events --sort-by=.lastTimestamp
Détails d’un Podkubectl describe pod
Logs applicatifskubectl logs [--previous]
Shell interactifkubectl exec -it -- /bin/sh
Images minimaleskubectl debug --image=busybox --target=app
Test direct Podkubectl port-forward pod 8080:80
Vérifier Servicekubectl get endpoints
Métriques instantanéeskubectl top pods
Copier des fichierskubectl cp (nécessite tar dans le conteneur)

Le debugging Kubernetes suit toujours le même pattern : observer l’état global, lire les événements, analyser les logs, vérifier le réseau/service, investiguer interactivement si nécessaire.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn