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

Troubleshooting du cluster Kubernetes

35 min de lecture

logo kubernetes

Le domaine Troubleshooting pèse 30% de la CKA et inclut souvent des pannes d’infrastructure à diagnostiquer puis corriger rapidement. Ce guide cible principalement les clusters déployés avec kubeadm : control plane en static Pods, certificats gérés par kubeadm, et diagnostic local via kubelet et le runtime CRI. Il couvre le dépannage du control plane (kube-apiserver, scheduler, controller-manager), d’etcd, des nœuds workers, des certificats et des composants réseau du cluster.

Face à une panne d’infrastructure, appliquez cette séquence systématique :

  1. État global — Le cluster répond-il ? (kubectl cluster-info, kubectl get nodes)
  2. Composants système — Les Pods kube-system tournent-ils ? (kubectl get pods -n kube-system)
  3. Nœuds — Tous les nœuds sont-ils Ready ? (kubectl get nodes -o wide)
  4. Logs — Que disent kubelet et les composants ? (journalctl, kubectl logs)
  5. Certificats — Sont-ils valides ? (kubeadm certs check-expiration)
  6. Réseau — Les composants communiquent-ils ? (ss, curl, crictl)

Avant de plonger dans les scénarios, voici les commandes clés à maîtriser pour le diagnostic d’infrastructure :

Fenêtre de terminal
# === Depuis votre poste (si kubectl fonctionne) ===
kubectl cluster-info # API server accessible ?
kubectl get nodes -o wide # État de tous les nœuds
kubectl get pods -n kube-system -o wide # Composants du cluster
kubectl get events -n kube-system --sort-by='.lastTimestamp' | tail -20
# === Depuis un nœud (en SSH) ===
systemctl status kubelet # État du service kubelet
journalctl -u kubelet --no-pager --since "10 min ago" | tail -50
crictl ps -a # Conteneurs (via CRI)
crictl pods # Pods vus par le runtime
ss -tlnp | grep -E '6443|2379|10250|10256|10259|10257' # Ports critiques

crictl est l’outil le plus pratique pour inspecter les conteneurs du runtime CRI, mais il n’est pas installé systématiquement sur toutes les distributions. À défaut, utilisez les logs du kubelet (journalctl -u kubelet) et les outils natifs du runtime (ex: ctr pour containerd).

Les ports critiques d’un cluster Kubernetes :

PortComposantRôle
6443kube-apiserverEntrée principale de l’API
2379etcd (client)Requêtes lecture/écriture
2380etcd (peer)Réplication entre membres
10250kubeletAPI kubelet (métriques, exec)
10256kube-proxyHealth check
10257kube-controller-managerHealth check
10259kube-schedulerHealth check

Sur un cluster kubeadm, les composants du control plane tournent en static Pods : leurs manifests YAML sont dans /etc/kubernetes/manifests/. Le kubelet les surveille et les redémarre automatiquement en cas de crash. Une erreur dans un manifest = le composant ne démarre pas.

C’est la panne la plus critique — sans API Server, kubectl est inutilisable.

Symptômes :

  • kubectl retourne The connection to the server was refused ou timeout
  • Les autres composants écrivent des erreurs de connexion dans leurs logs

Diagnostic :

Fenêtre de terminal
# 1. Vérifier si le processus tourne
ssh <control-plane> "crictl ps | grep kube-apiserver"
# 2. Si pas de processus, vérifier le manifest
ssh <control-plane> "cat /etc/kubernetes/manifests/kube-apiserver.yaml | head -30"
# 3. Logs kubelet (c'est lui qui lance les static Pods)
ssh <control-plane> "journalctl -u kubelet --since '5 min ago' | grep -i apiserver"
# 4. Si le conteneur existe mais crash
ssh <control-plane> "crictl logs \$(crictl ps -a --name kube-apiserver -q | head -1)"

Causes fréquentes (CKA) :

CauseSymptôme dans les logsCorrection
Erreur dans le manifest YAMLfailed to create pod dans kubeletCorriger la syntaxe YAML dans /etc/kubernetes/manifests/kube-apiserver.yaml
Mauvais chemin de certificatopen /etc/kubernetes/pki/xxx: no such fileVérifier les chemins --tls-cert-file, --tls-private-key-file
Port déjà utilisébind: address already in useIdentifier le processus sur le port 6443 (ss -tlnp | grep 6443)
etcd inaccessibleconnection refused vers :2379Réparer etcd d’abord (voir section suivante)
Certificats expiréscertificate has expiredRenouveler avec kubeadm certs renew apiserver

Sans scheduler, les nouveaux Pods restent en Pending indéfiniment — ils ne sont assignés à aucun nœud.

Symptômes :

  • Nouveaux Pods en état Pending, sans événement Scheduled dans les events
  • Peu ou pas d’événements récents liés au placement des Pods
  • Le Pod kube-scheduler est absent ou en CrashLoopBackOff dans kube-system

Diagnostic :

Fenêtre de terminal
# Vérifier si le scheduler tourne
kubectl get pods -n kube-system -l component=kube-scheduler
# Logs du scheduler
kubectl logs -n kube-system kube-scheduler-<node>
# Si kubectl ne fonctionne pas, aller sur le nœud
ssh <control-plane> "crictl ps -a | grep scheduler"
ssh <control-plane> "crictl logs \$(crictl ps -a --name kube-scheduler -q | head -1)"

Correction :

Fenêtre de terminal
# Vérifier le manifest
cat /etc/kubernetes/manifests/kube-scheduler.yaml
# Comparer avec la config attendue
# Vérifier notamment :
# - --kubeconfig=/etc/kubernetes/scheduler.conf
# - image: registry.k8s.io/kube-scheduler:v1.XX.X
# - ports: containerPort 10259
# Après correction du manifest, kubelet redémarre le Pod automatiquement
# Vérifier :
crictl ps | grep scheduler

Sans kube-controller-manager, de nombreuses boucles de contrôle cessent de converger : réplication, gestion des Jobs, node lifecycle, service accounts, garbage collection, etc.

Symptômes :

  • Les ReplicaSets ne créent pas de nouveaux Pods
  • Les Deployments ne progressent pas
  • Le node lifecycle controller ne met plus à jour l’état des nœuds
  • Les certificats ne sont plus automatiquement renouvelés

Diagnostic :

Fenêtre de terminal
# Vérifier l'état
kubectl get pods -n kube-system -l component=kube-controller-manager
# Logs
kubectl logs -n kube-system kube-controller-manager-<node>
# Ou directement sur le nœud :
crictl logs $(crictl ps -a --name kube-controller -q | head -1)

Erreurs classiques dans les manifests :

Fenêtre de terminal
# Vérifier le manifest
cat /etc/kubernetes/manifests/kube-controller-manager.yaml
# Points à contrôler :
# --kubeconfig=/etc/kubernetes/controller-manager.conf
# --root-ca-file=/etc/kubernetes/pki/ca.crt
# --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt
# --cluster-signing-key-file=/etc/kubernetes/pki/ca.key
# --service-account-private-key-file=/etc/kubernetes/pki/sa.key

Pour tout composant du control plane qui ne démarre pas, appliquez cette séquence :

  1. Identifier — Le conteneur tourne-t-il ? (crictl ps -a | grep <composant>)
  2. Logs conteneurcrictl logs <container-id> — chercher l’erreur exacte
  3. Logs kubeletjournalctl -u kubelet | grep <composant> — le kubelet signale-t-il une erreur de manifest ?
  4. Manifestcat /etc/kubernetes/manifests/<composant>.yaml — comparer avec un manifest fonctionnel
  5. Corriger — Éditer le manifest, kubelet détecte le changement et redémarre le Pod (quelques secondes)
  6. Validercrictl ps | grep <composant> puis kubectl get pods -n kube-system

etcd est la base de données clé/valeur qui stocke tout l’état du cluster. Si etcd est en panne, l’API Server ne peut ni lire ni écrire — le cluster est paralysé.

Fenêtre de terminal
# État du Pod etcd
kubectl get pods -n kube-system -l component=etcd
# Logs etcd
kubectl logs -n kube-system etcd-<node>
# Ou en SSH sur le nœud
crictl logs $(crictl ps -a --name etcd -q | head -1)
Fenêtre de terminal
# Depuis le nœud control plane
ETCDCTL_API=3 etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
endpoint health
# Réponse attendue :
# https://127.0.0.1:2379 is healthy: successfully committed proposal: took = 2.5ms
# Vérifier les membres du cluster etcd
ETCDCTL_API=3 etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
member list -w table
CauseSymptômeCorrection
Espace disque pleinmvcc: database space exceededCompacter et défragmenter (voir ci-dessous)
Certificats expiréscertificate has expired or is not yet validkubeadm certs renew etcd-server
Données corrompueswal: crc mismatch ou crash en boucleRestaurer depuis un snapshot
Perte de quorum (HA)etcdserver: no leaderRestaurer un membre ou le cluster complet
Mauvais data-diropen /var/lib/etcd/: permission deniedCorriger les permissions ou le chemin dans le manifest

Quand etcd signale database space exceeded :

Fenêtre de terminal
# Récupérer la révision actuelle
rev=$(ETCDCTL_API=3 etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
endpoint status --write-out="json" | jq '.[0].Status.header.revision')
# Compacter
ETCDCTL_API=3 etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
compact "$rev"
# Défragmenter
ETCDCTL_API=3 etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
defrag

Si etcd est irrécupérable, restaurez depuis un snapshot (voir le guide Sauvegarder et restaurer Kubernetes pour la procédure complète).

La procédure ci-dessous correspond au cas le plus fréquent en lab ou en CKA : cluster kubeadm avec un seul control plane. Sur un cluster HA, la restauration etcd dépend de la topologie, des membres et du quorum, et doit être traitée séparément.

Fenêtre de terminal
# Arrêter etcd (renommer le manifest pour que kubelet l'arrête)
mv /etc/kubernetes/manifests/etcd.yaml /etc/kubernetes/manifests/etcd.yaml.bak
# Supprimer l'ancien data-dir
rm -rf /var/lib/etcd
# Restaurer depuis le snapshot
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db \
--data-dir=/var/lib/etcd
# Remettre le manifest en place
mv /etc/kubernetes/manifests/etcd.yaml.bak /etc/kubernetes/manifests/etcd.yaml
# Attendre que kubelet redémarre etcd, puis vérifier
crictl ps | grep etcd
kubectl get pods -n kube-system -l component=etcd

Un nœud qui passe en NotReady ne reçoit plus de nouveaux Pods et les Pods existants sont progressivement évincés (après le pod-eviction-timeout, par défaut 5 minutes).

Fenêtre de terminal
# Identifier le nœud en échec
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# worker-1 NotReady <none> 10d v1.30.2
# Examiner les conditions
kubectl describe node worker-1 | grep -A15 Conditions
# Conditions normales (tout à False sauf Ready) :
# MemoryPressure False
# DiskPressure False
# PIDPressure False
# Ready True ← Doit être True

Le kubelet est le composant fondamental de chaque nœud — s’il ne tourne pas, le nœud ne communique plus avec le control plane.

Fenêtre de terminal
# Se connecter au nœud
ssh worker-1
# Vérifier l'état du service
systemctl status kubelet
# Si "inactive (dead)" ou "activating (auto-restart)"
# Lire les logs pour l'erreur exacte
journalctl -u kubelet --no-pager --since "5 min ago" | tail -50

Causes fréquentes et corrections :

CauseMessage dans journalctlCorrection
kubelet arrêtéActive: inactive (dead)systemctl start kubelet
Crash en bouclecode=exited, status=1/FAILURELire le message d’erreur exact dans les logs
Mauvaise configfailed to load kubelet configVérifier /var/lib/kubelet/config.yaml
Container runtime downfailed to get sandbox image ou CRI connection errorsystemctl status containerd puis systemctl restart containerd
Certificat expirécertificate has expiredRenouveler le certificat kubelet (voir section certificats)
Mauvais serveur APIdial tcp <ip>:6443: connect: connection refusedVérifier /etc/kubernetes/kubelet.conf — l’URL du serveur API est-elle correcte ?

Le kubelet a besoin d’un container runtime fonctionnel. Si containerd (ou CRI-O) est arrêté, aucun Pod ne peut démarrer.

Fenêtre de terminal
# Vérifier containerd
systemctl status containerd
# Si arrêté :
systemctl start containerd
systemctl enable containerd
# Vérifier que le kubelet se reconnecte
systemctl restart kubelet
journalctl -u kubelet --since "1 min ago" | grep -i "connected"

Pression sur les ressources (MemoryPressure, DiskPressure, PIDPressure)

Section intitulée « Pression sur les ressources (MemoryPressure, DiskPressure, PIDPressure) »

Quand un nœud manque de ressources, le kubelet place des conditions qui déclenchent l’éviction des Pods.

Fenêtre de terminal
# Vérifier les conditions du nœud
kubectl describe node <node> | grep -A5 Conditions
# Sur le nœud — diagnostic des ressources
df -h /var/lib/kubelet # Espace disque
free -m # Mémoire disponible
cat /proc/sys/kernel/pid_max # Limite PID
ls /proc | grep -c '^[0-9]' # Nombre de processus actifs

Les conditions MemoryPressure, DiskPressure et PIDPressure sont dérivées de signaux calculés par le kubelet. Les valeurs exactes dépendent de sa configuration. Par défaut sur Linux, Kubernetes applique notamment memory.available<100Mi, nodefs.available<10% et imagefs.available<15%.

ConditionIndicationRemarque
MemoryPressureMémoire réellement disponible insuffisanteLe kubelet utilise ses propres signaux, pas uniquement free -m
DiskPressurePression sur nodefs, imagefs ou containerfsPas seulement /var/lib/kubelet
PIDPressurePlus assez de PID disponiblesDépend des seuils configurés du nœud

Correction :

Fenêtre de terminal
# DiskPressure — Libérer de l'espace
crictl rmi --prune # Supprimer les images inutilisées
journalctl --vacuum-size=500M # Nettoyer les logs
# MemoryPressure — Identifier les processus gourmands
ps aux --sort=-%mem | head -10
# Si un processus hors-Kubernetes consomme trop, l'arrêter
# Après nettoyage, le kubelet réévalue périodiquement les signaux d'éviction
# selon son housekeeping-interval (10 secondes par défaut)

Un cluster kubeadm utilise des dizaines de certificats TLS pour sécuriser les communications entre composants. Sur un cluster géré par kubeadm, les certificats clients générés par kubeadm expirent en général après 1 an. Leur expiration rend le cluster inutilisable.

Fenêtre de terminal
# Commande kubeadm (la plus simple)
kubeadm certs check-expiration
# Résultat type :
# CERTIFICATE EXPIRES RESIDUAL TIME
# admin.conf Mar 25, 2027 08:30 UTC 364d
# apiserver Mar 25, 2027 08:30 UTC 364d
# apiserver-etcd-client Mar 25, 2027 08:30 UTC 364d
# apiserver-kubelet-client Mar 25, 2027 08:30 UTC 364d
# ...
# etcd-server Mar 25, 2027 08:30 UTC 364d
# Vérification manuelle d'un certificat spécifique
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates -subject
# notBefore=Mar 25 08:30:00 2026 GMT
# notAfter=Mar 25 08:30:00 2027 GMT
Fenêtre de terminal
# Renouveler TOUS les certificats
kubeadm certs renew all
# Ou renouveler un certificat spécifique
kubeadm certs renew apiserver
kubeadm certs renew etcd-server
kubeadm certs renew apiserver-etcd-client
# Après renouvellement, redémarrer les composants du control plane
# Méthode : déplacer puis remettre les manifests
cd /etc/kubernetes/manifests
mv kube-apiserver.yaml /tmp/ && sleep 5 && mv /tmp/kube-apiserver.yaml .
mv kube-controller-manager.yaml /tmp/ && sleep 5 && mv /tmp/kube-controller-manager.yaml .
mv kube-scheduler.yaml /tmp/ && sleep 5 && mv /tmp/kube-scheduler.yaml .
mv etcd.yaml /tmp/ && sleep 5 && mv /tmp/etcd.yaml .
# Vérifier que tout redémarre
kubectl get pods -n kube-system

Si un worker node perd la connexion à cause d’un certificat kubelet expiré :

Fenêtre de terminal
# Sur le worker — vérifier le certificat
openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -noout -dates
# Si expiré et la rotation automatique est activée :
# La rotation se fait automatiquement si le kubelet a le flag :
# --rotate-certificates=true (dans /var/lib/kubelet/config.yaml)
# Vérifier la config
grep rotateCertificates /var/lib/kubelet/config.yaml
# rotateCertificates: true ← doit être présent
# Si la rotation automatique ne permet plus la récupération :
# 1. Vérifier d'abord le bootstrap kubeconfig et la configuration de rotation
cat /etc/kubernetes/bootstrap-kubelet.conf
# 2. Sur le control plane, créer un nouveau token
kubeadm token create --print-join-command
# 3. Sur le worker, arrêter le kubelet et supprimer l'ancien certificat
systemctl stop kubelet
rm /var/lib/kubelet/pki/kubelet-client-current.pem
# 4. Mettre à jour le bootstrap-kubeconfig avec le nouveau token, puis redémarrer
systemctl start kubelet

Les problèmes réseau au niveau cluster empêchent la communication entre les composants — et sont souvent les plus difficiles à diagnostiquer.

Le plugin CNI (Calico, Flannel, Cilium…) est responsable du réseau entre Pods. S’il ne fonctionne pas, les Pods ne peuvent pas communiquer et les nœuds nouvellement ajoutés restent en NotReady.

Fenêtre de terminal
# Vérifier les Pods CNI
kubectl get pods -n kube-system | grep -iE 'calico|flannel|cilium|weave'
# Si des Pods CNI sont en CrashLoopBackOff
kubectl logs -n kube-system <cni-pod> --previous
# Vérifier la config CNI sur un nœud
ls /etc/cni/net.d/
cat /etc/cni/net.d/*.conflist

Symptômes d’un CNI défaillant :

SymptômeDiagnosticCorrection
Nœuds NotReady + NetworkUnavailable: Truekubectl describe nodeRéinstaller le CNI ou vérifier ses Pods
Pods ne communiquent pas entre nœudskubectl exec pod-A -- ping <pod-B-IP>Vérifier les logs CNI et les routes réseau
Pods bloqués en ContainerCreatingkubectl describe pod → erreur networkPluginVérifier /etc/cni/net.d/ et le binaire CNI dans /opt/cni/bin/

kube-proxy gère les règles réseau pour le routage des Services. Selon la configuration du cluster, il fonctionne en mode iptables, ipvs (déprécié depuis v1.35), ou nftables. Sans lui, les Services ClusterIP et NodePort ne fonctionnent pas.

Fenêtre de terminal
# Vérifier le DaemonSet kube-proxy
kubectl get ds -n kube-system kube-proxy
kubectl get pods -n kube-system -l k8s-app=kube-proxy
# Logs
kubectl logs -n kube-system -l k8s-app=kube-proxy --tail=30
# Identifier le mode de fonctionnement
kubectl logs -n kube-system -l k8s-app=kube-proxy | grep "Using .* Proxier"
# Vérifier les règles selon le mode (iptables par défaut sur kubeadm)
ssh <node> "iptables -t nat -L KUBE-SERVICES | head -20"

CoreDNS assure la résolution DNS interne du cluster. S’il est en panne, les Pods ne peuvent plus résoudre les noms de Services.

Fenêtre de terminal
# Vérifier les Pods CoreDNS
kubectl get pods -n kube-system -l k8s-app=kube-dns
# Tester la résolution depuis un Pod
kubectl run dnstest --rm -it --image=busybox:1.36 --restart=Never -- nslookup kubernetes.default
# Si la résolution échoue, vérifier les logs CoreDNS
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=30
# Vérifier le Service kube-dns
kubectl get svc -n kube-system kube-dns
kubectl get endpoints -n kube-system kube-dns

Pour le DNS, le bon ordre de vérification est : Pod CoreDNSlogsService kube-dnsendpointstest nslookup depuis un Pod. Cette approche méthodique permet d’isoler rapidement l’origine du problème.


Le kube-apiserver ne démarre pas. Diagnostiquez et corrigez.

Simulation :

Fenêtre de terminal
# Sur le control plane (en SSH)
# Introduire une erreur dans le manifest
sudo sed -i 's/--etcd-servers=https:\/\/127.0.0.1:2379/--etcd-servers=https:\/\/127.0.0.1:2399/' \
/etc/kubernetes/manifests/kube-apiserver.yaml
Solution
Fenêtre de terminal
# kubectl ne fonctionne plus
kubectl get nodes
# The connection to the server was refused
# Aller sur le nœud control plane en SSH
ssh control-plane
# Vérifier si le conteneur tourne
crictl ps -a | grep apiserver
# Le conteneur est en état "Exited"
# Lire les logs du conteneur
crictl logs $(crictl ps -a --name kube-apiserver -q | head -1)
# "dial tcp 127.0.0.1:2399: connect: connection refused"
# → Le port etcd est mauvais (2399 au lieu de 2379)
# Corriger le manifest
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
# Changer --etcd-servers=https://127.0.0.1:2399
# en --etcd-servers=https://127.0.0.1:2379
# Kubelet détecte le changement et redémarre le Pod
# Patienter ~30 secondes
crictl ps | grep apiserver
# Le conteneur est en state "Running"
# Vérifier
kubectl get nodes
# Les nœuds réapparaissent

Un nœud worker est NotReady. Identifiez la cause et corrigez.

Simulation :

Fenêtre de terminal
# Sur le worker (en SSH)
sudo sed -i 's|/var/lib/kubelet/config.yaml|/var/lib/kubelet/config-bad.yaml|' \
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
sudo systemctl daemon-reload
sudo systemctl restart kubelet
Solution
Fenêtre de terminal
# Sur le control plane
kubectl get nodes
# worker-1 NotReady
# Se connecter au worker
ssh worker-1
# Vérifier kubelet
systemctl status kubelet
# Active: activating (auto-restart)
# Lire les logs
journalctl -u kubelet --since "2 min ago" | tail -20
# "failed to load kubelet config file, error: failed to read kubelet
# config file /var/lib/kubelet/config-bad.yaml, error: open ... no such file"
# Le fichier de config est mauvais — vérifier le service
cat /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
# --config=/var/lib/kubelet/config-bad.yaml ← erreur
# Corriger
sudo sed -i 's|config-bad.yaml|config.yaml|' \
/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
sudo systemctl daemon-reload
sudo systemctl restart kubelet
# Vérifier
systemctl status kubelet
# Active: running
# Sur le control plane (après ~40 secondes)
kubectl get nodes
# worker-1 Ready

Le cluster ne répond plus, les certificats sont expirés.

Solution (procédure)
Fenêtre de terminal
# Vérifier l'expiration
kubeadm certs check-expiration
# CERTIFICATE EXPIRES RESIDUAL TIME
# apiserver Mar 25, 2025 08:30 UTC EXPIRED
# Renouveler tous les certificats
kubeadm certs renew all
# certificate embedded in admin.conf renewed
# certificate apiserver renewed
# ...
# Redémarrer les composants du control plane
crictl pods --name kube-apiserver -q | xargs crictl rmp
crictl pods --name kube-controller -q | xargs crictl rmp
crictl pods --name kube-scheduler -q | xargs crictl rmp
crictl pods --name etcd -q | xargs crictl rmp
# Kubelet les redémarre automatiquement
# Mettre à jour le kubeconfig admin
cp /etc/kubernetes/admin.conf ~/.kube/config
# Vérifier
kubectl get nodes

Le cluster est dans un état incohérent — vous devez restaurer depuis un snapshot etcd.

Solution (procédure)
Fenêtre de terminal
# 1. Arrêter etcd
mv /etc/kubernetes/manifests/etcd.yaml /tmp/etcd.yaml
# 2. Attendre que le conteneur s'arrête
crictl ps | grep etcd # Doit être vide après ~10 secondes
# 3. Sauvegarder l'ancien data-dir
mv /var/lib/etcd /var/lib/etcd.bak
# 4. Restaurer depuis le snapshot
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db \
--data-dir=/var/lib/etcd
# 5. Remettre le manifest
mv /tmp/etcd.yaml /etc/kubernetes/manifests/etcd.yaml
# 6. Attendre le redémarrage
sleep 15
crictl ps | grep etcd
# 7. Vérifier l'état du cluster
kubectl get nodes
kubectl get pods -A

Fenêtre de terminal
kubectl cluster-info # API accessible ?
kubectl get nodes -o wide # Nœuds Ready ?
kubectl get pods -n kube-system # Composants OK ?
kubectl get events -n kube-system --sort-by='.lastTimestamp' | tail -10
Fenêtre de terminal
ssh <control-plane>
crictl ps -a | grep -E 'apiserver|scheduler|controller|etcd'
journalctl -u kubelet --since "5 min ago" | grep -i error
cat /etc/kubernetes/manifests/<composant>.yaml # Vérifier syntaxe
Fenêtre de terminal
ssh <worker>
systemctl status kubelet # Service actif ?
journalctl -u kubelet --since "5 min ago" | tail -20 # Erreur ?
systemctl status containerd # Runtime OK ?
df -h && free -m # Ressources ?
Fenêtre de terminal
kubeadm certs check-expiration # Expiration ?
kubeadm certs renew all # Renouveler
# Puis redémarrer les static Pods du control plane

  1. Si kubectl ne répond pas : connectez-vous en SSH au control plane et utilisez crictl + journalctl
  2. Static Pods du control plane : manifest dans /etc/kubernetes/manifests/, kubelet les redémarre automatiquement à toute modification
  3. kubelet arrêté = nœud NotReady — diagnostic avec systemctl status kubelet puis journalctl -u kubelet
  4. etcd défaillant = cluster paralysé — vérifier avec etcdctl endpoint health, restaurer depuis un snapshot si nécessaire
  5. Certificats kubeadm expirent après 1 an — vérifier avec kubeadm certs check-expiration, renouveler avec kubeadm certs renew all
  6. CNI en panne = nœuds NotReady avec NetworkUnavailable: True — vérifier les Pods CNI dans kube-system
  7. Méthode systématique : état global → composants → logs → manifest/config → corriger → valider

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