Aller au contenu
English
Conteneurs & Orchestration medium

Méthode de diagnostic d'un incident Kubernetes

40 min de lecture

logo kubernetes

Face à un incident Kubernetes, commencez toujours par le même réflexe : qualifier le niveau du problème, cluster, nœud, pod ou réseau, puis descendez méthodiquement. Ce guide vous donne une approche systématique en 4 niveaux avec les commandes kubectl adaptées à chaque situation. Vous pourrez localiser la cause d'un incident en quelques minutes au lieu de chercher au hasard.

  • Appliquer une méthode de triage en 4 niveaux : cluster → nœud → pod → réseau
  • Maîtriser les 4 commandes de diagnostic essentielles : get, describe, logs, events
  • Utiliser kubectl debug avec les conteneurs éphémères pour inspecter un pod en cours d'exécution
  • Diagnostiquer les problèmes de Service : DNS, EndpointSlices, kube-proxy

Sous pression, le réflexe naturel est d'aller droit aux journaux du Pod suspect. C'est souvent une perte de temps : si le problème vient du nœud, disque plein ou kubelet en panne, ou du réseau, Service mal configuré ou DNS cassé, ces journaux ne montreront rien d'utile.

Une méthode structurée permet de :

  • Éliminer rapidement les niveaux qui fonctionnent
  • Localiser la couche responsable avant de creuser
  • Communiquer clairement l'état du diagnostic à l'équipe
  • Reproduire la même démarche à chaque incident
NiveauQuestion à se poserCommandes principales
1. ClusterLe cluster est-il accessible et sain ?kubectl cluster-info, kubectl get nodes
2. NœudUn nœud est-il en difficulté ?kubectl describe node, kubectl top nodes
3. PodPourquoi ce pod ne fonctionne pas ?kubectl describe pod, kubectl logs, kubectl debug
4. RéseauLe trafic arrive-t-il au bon endroit ?kubectl get svc, kubectl get endpointslices, DNS check

La règle : commencer par le haut et descendre. Si le niveau 1 est sain, passer au 2. Si le 2 est sain, passer au 3, etc.

Avant toute chose, vérifiez que vous pouvez communiquer avec l'API server et que les nœuds sont opérationnels.

Fenêtre de terminal
kubectl cluster-info

Résultat attendu :

Kubernetes control plane is running at https://192.168.122.50:6443
CoreDNS is running at https://192.168.122.50:6443/api/v1/namespaces/kube-system/services/coredns:dns/proxy

Si cette commande échoue, le problème est en amont de Kubernetes : réseau, kubeconfig, VPN, certificat expiré. Vérifiez votre fichier ~/.kube/config et la connectivité réseau vers l'API server.

Un seul nœud NotReady suffit à expliquer des Pods en Pending ou des applications injoignables, et c'est la vérification la moins chère du niveau 1 : une commande, une colonne à lire. Si tous les nœuds sont Ready, vous venez d'écarter toute une famille de causes en deux secondes.

Fenêtre de terminal
kubectl get nodes
StatusSignificationAction
Tous ReadyLe cluster reste globalement accessible, mais cela ne suffit pas à exclure un problème control plane, kube-system ou réseau. Continuer le triage selon le symptômeVérifier kube-system et /readyz
Un nœud NotReadyProblème sur ce nœud → passer au niveau 2Inspecter le nœud
Un nœud SchedulingDisabledMaintenance en cours (cordon)Normal si planifié
Aucune réponseAPI server injoignableVérifier le plan de contrôle
Fenêtre de terminal
kubectl get pods -n kube-system -o wide

Vérifiez que etcd, kube-apiserver, kube-controller-manager et kube-scheduler sont en état Running avec RESTARTS à 0 (ou très faible).

Pour un diagnostic plus fin :

Fenêtre de terminal
kubectl get --raw='/readyz?verbose' | grep -E '\[(\+|\-)\]'

Chaque ligne [+] confirme un sous-système fonctionnel. Une ligne [-] signale un composant en échec.

Un kubectl qui répond ne prouve qu'une chose : l'API server est joignable et votre kubeconfig est valide. Les nœuds peuvent tous être NotReady, le scheduler à l'arrêt et les applications mortes, la commande répondra quand même. C'est pour cela que le niveau 1 ne s'arrête pas là.

Si un nœud est NotReady ou SchedulingDisabled de manière inattendue, inspectez-le en détail.

Fenêtre de terminal
kubectl describe node <nom-du-noeud>

La section Conditions révèle la cause. Voici les signaux d'alerte :

ConditionValeur anormaleCause probable
ReadyFalse ou UnknownKubelet arrêté, réseau coupé, nœud surchargé
MemoryPressureTrueMémoire insuffisante, pods trop gourmands
DiskPressureTrueDisque plein (nodefs, imagefs ou inodes)
PIDPressureTrueTrop de processus sur le nœud
NetworkUnavailableTruePlugin CNI non fonctionnel
Fenêtre de terminal
kubectl top nodes

Si un nœud affiche CPU ou mémoire proches de 100 %, les pods peuvent être en train d'être évincés ou incapables de démarrer.

Fenêtre de terminal
kubectl events --for node/<nom-du-noeud> --types=Warning

Les événements Warning sur un nœud peuvent révéler des problèmes de disque, de kubelet ou de réseau que les conditions ne montrent pas encore.

C'est le niveau le plus fréquent. Le triage commence par identifier l'état du pod, puis on choisit la bonne commande selon le symptôme.

Fenêtre de terminal
kubectl get pods -n <namespace> -o wide
Status observéSignificationProchaine action
PendingLe pod n'est pas encore planifié ou pas encore prêt à démarrerkubectl describe pod → voir Events (scheduling)
ContainerCreatingLe conteneur est en cours de créationAttendre, puis kubectl describe pod si ça persiste
RunningAu moins un conteneur tourneVérifier si l'application répond réellement
CrashLoopBackOffUn conteneur échoue puis redémarre en bouclekubectl logs --previous, kubectl describe pod
ImagePullBackOffL'image ne peut pas être téléchargéekubectl describe pod → Events (pull errors)
ErrorUn conteneur s'est arrêté avec une erreurkubectl logs --previous, kubectl describe pod

OOMKilled n'apparaît pas dans ce tableau car ce n'est pas un statut de pod au même titre que Pending ou Running. C'est une raison de terminaison du conteneur, visible dans kubectl describe pod sous Last State. Si vous voyez des redémarrages fréquents avec OOMKilled, augmentez limits.memory.

Quatre commandes couvrent la majorité des diagnostics : kubectl get, describe, logs et events. kubectl exec et kubectl debug ne viennent qu'ensuite, pour l'inspection interactive.

  1. kubectl describe pod, la vue complète

    Fenêtre de terminal
    kubectl describe pod <pod> -n <namespace>

    Sections à lire en priorité :

    • Events : messages du scheduler, du kubelet, des probes
    • Last State : raison de l'arrêt précédent (OOMKilled, Error, etc.)
    • Exit Code : indice sur la nature du crash
    • Containers → Env / Mounts : configuration du conteneur
    • Conditions : PodScheduled, Initialized, ContainersReady, Ready
  2. kubectl logs, les logs applicatifs

    Fenêtre de terminal
    # Logs du conteneur actuel
    kubectl logs <pod> -n <namespace>
    # Logs de l'exécution précédente (celle qui a crashé)
    kubectl logs <pod> -n <namespace> --previous
    # Pod multi-conteneur : préciser le conteneur
    kubectl logs <pod> -n <namespace> -c <conteneur> --previous
    # Les 50 dernières lignes seulement
    kubectl logs <pod> -n <namespace> --tail=50

    Cherchez : Exception, Error, panic, Traceback, connection refused, permission denied, OOM.

  3. kubectl events, les événements filtrés

    Fenêtre de terminal
    # Événements d'un pod spécifique
    kubectl events --for pod/<pod> -n <namespace>
    # Événements Warning du namespace
    kubectl events -n <namespace> --types=Warning

    Les événements complètent les logs en montrant ce que Kubernetes a fait (scheduling, pull d'image, kill par une probe, éviction).

  4. kubectl exec, entrer dans le conteneur

    Fenêtre de terminal
    kubectl exec -it <pod> -n <namespace> -- /bin/sh

    De l'intérieur du conteneur, quatre choses se vérifient qu'aucune commande extérieure ne montre :

    • La connectivité réseau : wget, curl, nslookup
    • La présence des fichiers de configuration attendus
    • Les variables d'environnement réellement injectées : env
    • Les processus en cours : ps aux

    Si le conteneur n'a pas de shell (image distroless), utilisez kubectl debug (voir ci-dessous).

Depuis Kubernetes v1.25, les conteneurs éphémères sont stables. Ils permettent d'inspecter un pod sans modifier son manifeste, même si l'image est minimaliste (distroless, scratch).

Fenêtre de terminal
kubectl debug -it <pod> -n <namespace> --image=busybox:1.37@sha256:9db7b59979c38555a39def84a31fb98b5296952f9e3afd4f6f11f05b07adfab0 --target=<conteneur>

Cette commande lance un conteneur busybox attaché au Pod existant. Il rejoint le Pod et partage au minimum son contexte réseau ; l'accès à l'espace de processus dépend du mode utilisé, de --target et du support effectif du runtime.

Profils disponibles avec --profile :

ProfilCe qu'il permetCas d'usage
generalConteneur isolé dans le podDiagnostic réseau basique
baselineComme general, plus contraintEnvironnements restrictifs
restrictedTrès limitéClusters avec politique stricte
netadminAjoute les capacités NET_ADMIN et NET_RAWDiagnostic réseau avancé (tcpdump)
sysadminAccès complet (root, hostPID)Diagnostic système poussé
Fenêtre de terminal
# Diagnostic réseau avancé avec tcpdump
kubectl debug -it <pod> -n <namespace> \
--image=nicolaka/netshoot:v0.16@sha256:b09d9b21381f47a79b3cbcb30da25266dc17186ea00ae65e99fdc51396f48e70 --profile=netadmin --target=<conteneur>
# Diagnostic d'un nœud directement
kubectl debug node/<nom-du-noeud> -it --image=busybox:1.37@sha256:9db7b59979c38555a39def84a31fb98b5296952f9e3afd4f6f11f05b07adfab0

Niveau 4 : diagnostiquer le réseau (Services et DNS)

Section intitulée « Niveau 4 : diagnostiquer le réseau (Services et DNS) »

Si le pod tourne (Running) mais que l'application n'est pas joignable, le problème est souvent au niveau du Service, du DNS ou des Network Policies.

Fenêtre de terminal
kubectl get svc <service> -n <namespace>

Vérifiez que le TYPE, le CLUSTER-IP et le PORT correspondent à ce que vous attendez.

Fenêtre de terminal
kubectl get endpointslices -n <namespace> -l kubernetes.io/service-name=<service>

Si la liste des endpoints est vide, le Service ne trouve aucun pod correspondant. Causes possibles :

  • Le sélecteur (spec.selector) du Service ne correspond pas aux labels des pods
  • Les pods ne sont pas Ready (probe échouée)
  • Les pods sont dans un autre namespace

Depuis un pod de test :

Fenêtre de terminal
kubectl run dnstest --image=busybox:1.37@sha256:9db7b59979c38555a39def84a31fb98b5296952f9e3afd4f6f11f05b07adfab0 --rm -it --restart=Never -- \
nslookup <service>.<namespace>.svc.cluster.local

Résultat attendu : le nom est résolu vers l'IP du Service (CLUSTER-IP).

Si la résolution échoue :

Fenêtre de terminal
# Vérifier que CoreDNS fonctionne
kubectl get pods -n kube-system -l k8s-app=kube-dns
# Vérifier les logs de CoreDNS
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=20
Fenêtre de terminal
kubectl run curltest --image=curlimages/curl:8.21.0@sha256:7c12af72ceb38b7432ab85e1a265cff6ae58e06f95539d539b654f2cfa64bb13 --rm -it --restart=Never -- \
curl -v http://<service>.<namespace>.svc.cluster.local:<port>/

Si le DNS fonctionne mais la connexion échoue, vérifiez :

  • Le port cible (targetPort) dans la définition du Service
  • Les Network Policies qui pourraient bloquer le trafic
  • Le kube-proxy (mode iptables/IPVS) sur les nœuds

Un dernier suspect, et le plus discret : les Network Policies bloquent le trafic sans aucun message d'erreur, ni côté émetteur ni côté destinataire. Une connexion qui expire sans explication dans un namespace qui en contient mérite donc un kubectl get networkpolicies -n <namespace>, suivi d'une lecture des règles ingress et egress.

Utilisez ce tableau quand vous êtes face à un symptôme et que vous ne savez pas par quel niveau commencer :

SymptômeNiveau probablePremière commande
kubectl ne répond pas1, ClusterVérifier kubeconfig, réseau, VPN
Nœud NotReady2, Nœudkubectl describe node <noeud>
Pod Pending3, Podkubectl describe pod <pod> (Events)
Pod CrashLoopBackOff3, Podkubectl logs <pod> --previous
Pod ImagePullBackOff3, Podkubectl describe pod <pod> (Events)
Pod Running mais application inaccessible4, Réseaukubectl get svc, kubectl get endpointslices
Timeout intermittent4, RéseauDNS check + Network Policies
Pods évincés sans raison apparente2, Nœudkubectl describe node (conditions, pression)

Ce tableau ne remplace pas les quatre niveaux : il sert quand vous reconnaissez le symptôme et voulez sauter directement au bon endroit. En cas de doute, reprenez au niveau 1 : sauter une étape coûte plus cher que de la parcourir.

SymptômeCause probableSolution
kubectl timeoutAPI server inaccessibleVérifier kubeconfig et connectivité réseau
Nœud NotReady persistantKubelet arrêté ou disque pleinSSH sur le nœud, systemctl status kubelet
Pod Pending longue duréePas de nœud avec assez de ressourceskubectl describe pod → Events → ajuster requests ou ajouter un nœud
Logs vides + exit code 137OOMKill (visible dans Last State de describe)kubectl describe pod → augmenter limits.memory
Logs vides + exit code 127Binaire introuvable dans l'imageVérifier command: et le tag de l'image
Pod Running mais connexion refuséeService mal configuré ou pod pas ReadyVérifier le sélecteur du Service et les probes
DNS ne résout pasCoreDNS en pannekubectl get pods -n kube-system -l k8s-app=kube-dns
Trafic bloqué sans erreurNetwork Policy restrictivekubectl get networkpolicies -n <namespace>
  • Toujours commencer par le haut : cluster → nœud → pod → réseau. Cela évite de perdre du temps à lire des logs quand le problème est un nœud en panne
  • Les 4 commandes de base sont kubectl get, describe, logs et events. kubectl exec et kubectl debug complètent ensuite pour l'inspection interactive
  • kubectl logs --previous est la commande la plus sous-utilisée : elle affiche les logs de l'exécution qui a planté, pas celle en cours
  • kubectl debug avec les conteneurs éphémères permet d'inspecter un pod sans le redémarrer, même sur une image distroless
  • Les problèmes réseau sont souvent des problèmes de configuration : sélecteur de Service incorrect, probe qui échoue, Network Policy qui bloque
  • Documentez votre diagnostic : notez les commandes exécutées et leurs résultats, cela aide à communiquer avec l'équipe et à créer des runbooks

Sept questions sur la discipline de la méthode : ce qu'une commande qui répond prouve vraiment, ce qu'un EndpointSlice vide veut dire, et pourquoi une NetworkPolicy ne se signale jamais.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

7 questions
5 min.
80% requis

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

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn