Aller au contenu
English
Conteneurs & Orchestration medium

Observer la santé d'un cluster Kubernetes en 5 commandes

40 min de lecture

logo kubernetes

Cinq commandes kubectl suffisent pour savoir si un cluster Kubernetes est sain. Ce guide vous montre comment vérifier l'état des nœuds, détecter les pressions sur les ressources, lire la consommation CPU/mémoire et interpréter les événements système. Vous pourrez ainsi repérer un problème avant qu'il n'affecte vos applications.

  • Vérifier que tous les nœuds sont Ready et interpréter les conditions
  • Lire les ressources allouées vs capacité d'un nœud
  • Installer metrics-server pour activer kubectl top
  • Surveiller la consommation CPU/mémoire en temps réel
  • Analyser les événements pour repérer les anomalies
  • Un cluster Kubernetes fonctionnel (v1.28+)
  • kubectl configuré et connecté au cluster
  • Des droits de lecture sur les nœuds, pods, événements et métriques du cluster
  • Connaissances de base sur les Pods et les nœuds Kubernetes

Le kubelet (l'agent qui tourne sur chaque nœud) met à jour l'état du nœud et renouvelle régulièrement un objet Lease dans le namespace kube-node-lease. Si le plan de contrôle ne reçoit plus ces signaux, il peut marquer le nœud comme injoignable (Ready: Unknown) au bout d'environ 40 secondes par défaut, puis attendre 5 minutes avant de lancer la première éviction des pods du nœud.

Concrètement, le kubelet met à jour deux choses :

  • Le statut du nœud (.status.conditions) : plusieurs conditions qui signalent les pressions sur les ressources, notamment Ready, MemoryPressure, DiskPressure, PIDPressure et, selon le contexte, NetworkUnavailable
  • Un objet Lease dans kube-node-lease : un "je suis vivant" léger qui sert de heartbeat rapide

Quand une condition passe à True, le nœud signale un problème. La seule exception est Ready, qui doit rester True. Et quand Ready passe à Unknown, c'est que le control plane a perdu le contact.

ConditionÉtat sainCe que cela indique si anormal
ReadyTrueFalse = kubelet ou nœud défaillant ; Unknown = nœud injoignable
MemoryPressureFalseMémoire disponible sous les seuils d'éviction
DiskPressureFalsePression sur nodefs, imagefs ou les inodes selon la config du kubelet
PIDPressureFalseManque de PID disponibles
NetworkUnavailableFalseRéseau du nœud non prêt selon le provider/CNI

La première commande à lancer est kubectl get nodes. Elle donne une vue d'ensemble rapide de tous les nœuds du cluster :

Fenêtre de terminal
kubectl get nodes

Résultat attendu, Tous les nœuds doivent afficher Ready dans la colonne STATUS :

NAME STATUS ROLES AGE VERSION
ks-cp1 Ready control-plane 41h v1.37.0
ks-worker1 Ready <none> 41h v1.37.0
ks-worker2 Ready <none> 41h v1.37.0

Pour obtenir plus de détails (IP, runtime, OS), ajoutez -o wide :

Fenêtre de terminal
kubectl get nodes -o wide
Status dans la sortieSignificationAction
ReadyLe nœud fonctionne normalementAucune
NotReadyLe kubelet ne répond pasVérifier le kubelet et le réseau du nœud
SchedulingDisabledLe nœud est en mode cordonNormal si maintenance planifiée

Pour comprendre pourquoi un nœud est dans un état donné, utilisez kubectl describe node :

Fenêtre de terminal
kubectl describe node ks-worker1

La section Conditions est la plus importante. Voici à quoi elle ressemble sur un nœud sain :

Conditions:
Type Status Reason Message
---- ------ ------ -------
NetworkUnavailable False CalicoIsUp Calico is running on this node
MemoryPressure False KubeletHasSufficientMemory kubelet has sufficient memory available
DiskPressure False KubeletHasNoDiskPressure kubelet has no disk pressure
PIDPressure False KubeletHasSufficientPID kubelet has sufficient PID available
Ready True KubeletReady kubelet is posting ready status

Comment lire ce tableau :

  • Ready: True = le kubelet fonctionne et accepte des pods
  • MemoryPressure: False = la mémoire est suffisante
  • DiskPressure: False = assez d'espace disque
  • PIDPressure: False = nombre de processus dans les limites

Plus bas dans la sortie de describe node, la section Allocated resources montre la consommation cumulée des pods sur ce nœud :

Allocated resources:
Resource Requests Limits
-------- -------- ------
cpu 455m (32%) 7 (500%)
memory 432730Ki (38%) 4501513472 (390%)

Les Requests représentent ce que les pods ont réservé. Les Limits sont le maximum qu'ils peuvent utiliser. Quand les Requests dépassent 80 % de la capacité, le nœud risque de ne plus pouvoir planifier de nouveaux pods.

Des Limits dont la somme dépasse 100 % de la capacité sont normales, et ce n'est pas un défaut de configuration : cela signifie seulement que les pods pourraient dépasser la capacité du nœud s'ils consommaient tous leur plafond en même temps, ce qui n'arrive pas. Ce sont les Requests qu'il faut surveiller, puisque ce sont elles que le scheduler réserve.

Étape 3 : vérifier la santé du plan de contrôle

Section intitulée « Étape 3 : vérifier la santé du plan de contrôle »

Le plan de contrôle (API server, scheduler, controller-manager, etcd) est le cerveau du cluster. L'API server expose deux endpoints de santé dédiés.

Depuis Kubernetes v1.16, deux endpoints remplacent l'ancien /healthz :

  • /livez : le processus API server est-il vivant ?
  • /readyz : l'API server est-il prêt à servir des requêtes ?
Fenêtre de terminal
kubectl get --raw='/readyz?verbose' | head -20

Chaque ligne [+] confirme un sous-système fonctionnel :

[+]ping ok
[+]log ok
[+]etcd ok
[+]poststarthook/start-apiserver-admission-initializer ok
[+]poststarthook/generic-apiserver-start-informers ok
...

Si une ligne affiche [-], le sous-système correspondant est en échec.

Pour vérifier également la liveness :

Fenêtre de terminal
kubectl get --raw='/livez?verbose' | head -20

Pour voir concrètement si les composants du plan de contrôle tournent :

Fenêtre de terminal
kubectl get pods -n kube-system -o wide

Vérifiez que les pods etcd, kube-apiserver, kube-controller-manager et kube-scheduler sont en état Running avec RESTARTS à 0.

Deux commandes traînent dans les procédures anciennes et méritent d'être abandonnées : /healthz, déprécié depuis la v1.16 au profit de /readyz et /livez, et kubectl get componentstatuses, déprécié depuis la v1.19. Elles répondent encore sur beaucoup de clusters, et c'est précisément le problème : elles donnent une réponse sans garantir qu'elle reflète l'état réel.

Étape 4 : surveiller la consommation avec metrics-server

Section intitulée « Étape 4 : surveiller la consommation avec metrics-server »

La commande kubectl top affiche la consommation CPU et mémoire en temps réel. Elle nécessite metrics-server, un composant qui collecte les métriques depuis chaque kubelet et alimente la Metrics API utilisée notamment par les autoscalers (HPA/VPA).

Si kubectl top nodes répond error: Metrics API not available, la cause est presque toujours la même : metrics-server n'est pas installé. Ce n'est pas un composant livré avec Kubernetes, et il manque sur la plupart des clusters de test, kind compris. La section suivante montre comment l'ajouter.

Déplier les étapes d'installation
  1. Téléchargez le manifeste officiel :

    Fenêtre de terminal
    kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
  2. Sur un cluster sans certificat TLS (comme un lab), ajoutez le flag --kubelet-insecure-tls :

    Fenêtre de terminal
    kubectl -n kube-system patch deployment metrics-server --type=json \
    -p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'
  3. Attendez que metrics-server soit prêt :

    Fenêtre de terminal
    kubectl -n kube-system rollout status deployment/metrics-server --timeout=90s
  4. Vérifiez que l'API Metrics est disponible :

    Fenêtre de terminal
    kubectl get apiservices | grep metrics

    Résultat attendu :

    v1beta1.metrics.k8s.io kube-system/metrics-server True 59s

Une fois metrics-server installé, la commande kubectl top nodes affiche la consommation réelle :

Fenêtre de terminal
kubectl top nodes
NAME CPU(cores) CPU(%) MEMORY(bytes) MEMORY(%)
ks-cp1 131m 9% 1129Mi 102%
ks-worker1 72m 5% 833Mi 75%
ks-worker2 74m 5% 935Mi 85%

Comment interpréter :

  • CPU(cores) : consommation instantanée en millicores (1000m = 1 CPU)
  • CPU% : pourcentage par rapport à la capacité allocatable
  • MEMORY(bytes) : mémoire réellement utilisée (working set)
  • MEMORY% : pourcentage de la mémoire allocatable
Fenêtre de terminal
kubectl top pods -A --sort-by=cpu | head -15

Cette commande trie tous les pods par consommation CPU décroissante. Très utile pour identifier rapidement un pod qui consomme trop.

Pour un namespace spécifique :

Fenêtre de terminal
kubectl top pods -n kube-system

Comptez quelques minutes avant qu'un Pod fraîchement créé apparaisse dans kubectl top. Ce délai est normal : la chaîne de collecte doit accumuler plusieurs points de mesure avant d'en déduire une consommation. Un Pod absent de la sortie n'est donc pas un Pod en panne.

Gardez en tête ce que cette commande ne fait pas. kubectl top donne un instantané, sans historique ni alerte : elle sert à trier vite, pas à comprendre une dérive. Dès qu'il faut répondre à « depuis quand ? » ou « est-ce que ça empire ? », il faut une chaîne d'observabilité complète, Prometheus et Grafana par exemple.

Les événements Kubernetes enregistrent ce qui se passe dans le cluster : créations, erreurs de scheduling, redémarrages, évictions. C'est la boîte noire du cluster.

Depuis Kubernetes v1.26, la sous-commande kubectl events offre un affichage plus lisible avec des options de filtrage natives. Pour voir les warnings récents :

Fenêtre de terminal
kubectl events -A --types=Warning

La commande classique kubectl get events reste disponible pour des filtrages plus fins via --field-selector :

Fenêtre de terminal
kubectl get events -A --sort-by=.metadata.creationTimestamp | tail -20
Type eventExemplesSignification
NormalPulling, Created, StartedOpérations normales du kubelet
WarningFailedScheduling, BackOff, UnhealthyQuelque chose ne fonctionne pas
ÉvénementCause probableAction
FailedSchedulingPas assez de ressources sur les nœudsVérifier kubectl describe node, libérer des ressources
BackOff / CrashLoopBackOffLe conteneur plante en boucleVérifier les logs : kubectl logs <pod>
FailedMountVolume non disponibleVérifier le PVC et le StorageClass
UnhealthyLa probe a échouéVérifier la configuration des probes
EvictedNœud sous pression (mémoire/disque)Vérifier les conditions du nœud

Le filtrage par ressource est souvent plus direct que la lecture de toute la liste :

Fenêtre de terminal
kubectl events -A --for=node/ks-worker1
kubectl events -n default --for=pod/mon-pod

Étape 6 : interroger les métriques internes (kube-apiserver, kubelet)

Section intitulée « Étape 6 : interroger les métriques internes (kube-apiserver, kubelet) »

Au-delà de kubectl top, le kube-apiserver et le kubelet exposent des endpoints /metrics au format Prometheus. C'est la source canonique pour Grafana, Prometheus ou pour un diagnostic ponctuel à la ligne de commande.

Ces métriques sont celles que Prometheus consomme, mais rien n'oblige à déployer Prometheus pour les lire : kubectl get --raw interroge directement le point d'exposition et affiche du texte brut. C'est le moyen le plus rapide de vérifier qu'une métrique existe bien sous le nom que vous croyez, avant d'écrire une requête PromQL qui rendrait une série vide sans rien expliquer.

Fenêtre de terminal
# Métriques globales du plan de contrôle
kubectl get --raw /metrics | grep -E "^# HELP (apiserver|etcd_)" | head

Quelques métriques utiles :

MétriqueCe qu'elle indique
apiserver_request_duration_secondsLatence des requêtes API (par verbe et ressource)
apiserver_request_totalNombre total de requêtes API (utile pour repérer un pic d'activité)
etcd_request_duration_secondsLatence des appels à etcd
etcd_bookmark_totalNombre de bookmarks etcd émis (renommée en 1.36, voir ci-dessous)

Le kubelet expose ses propres métriques, distinctes de celles de l'API server, et c'est une distinction qui fait perdre du temps quand on l'ignore : une métrique cherchée sur le mauvais composant rend un résultat vide qui ressemble à une métrique disparue. Tout ce qui concerne les conteneurs et les volumes vient du nœud, et se lit à travers le proxy de l'API.

Fenêtre de terminal
NODE=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')
# Métriques propres au kubelet
kubectl get --raw "/api/v1/nodes/${NODE}/proxy/metrics" | grep -E "^# HELP" | head
# Métriques cAdvisor (par conteneur)
kubectl get --raw "/api/v1/nodes/${NODE}/proxy/metrics/cadvisor" | grep -E "^# HELP" | head

Depuis Kubernetes 1.36, les métriques PSI (Pressure Stall Information) sont GA. Elles exposent, via cgroup v2, le temps pendant lequel les tâches d'un conteneur ont attendu ou ont été bloquées par manque de CPU, mémoire ou IO. C'est un indicateur plus fin que la simple utilisation moyenne.

Fenêtre de terminal
kubectl get --raw "/api/v1/nodes/${NODE}/proxy/metrics/cadvisor" \
| grep -E "^container_pressure_(cpu|memory|io)_(stalled|waiting)"

Les six métriques exposées :

MétriqueSens
container_pressure_cpu_waiting_seconds_totalTâches en attente de CPU
container_pressure_cpu_stalled_seconds_totalAucune progression possible (CPU saturé)
container_pressure_memory_waiting_seconds_totalPression mémoire (allocation/swap)
container_pressure_memory_stalled_seconds_totalTâches bloquées par la pression mémoire
container_pressure_io_waiting_seconds_totalAttente IO
container_pressure_io_stalled_seconds_totalBlocage IO total

Une dérivée croissante de la métrique *_stalled_seconds_total est un signal fort que le conteneur sature la ressource correspondante, typiquement, une pré-condition à un OOMKill ou à un throttling agressif.

Si vous gardez des dashboards Grafana ou des règles d'alerte Prometheus de longue date, deux métriques ont été renommées dans Kubernetes 1.36 :

Avant (≤ 1.35)Après (1.36+)
volume_operation_total_errorsvolume_operation_errors_total
etcd_bookmark_countsetcd_bookmark_total

Ajustez vos requêtes PromQL et vos tableaux de bord après une montée de version : sans cela, ils afficheront des séries vides, sans rien signaler.

Attention à l'endroit où vous cherchez : ces deux métriques ne sont pas exposées par le même composant. etcd_bookmark_total vient de l'API server, et se lit donc bien ainsi :

Fenêtre de terminal
kubectl get --raw /metrics | grep etcd_bookmark_total

Les métriques volume_operation_* viennent en revanche du kubelet, et sont introuvables sur l'API server. Il faut interroger le nœud :

Fenêtre de terminal
kubectl get --raw "/api/v1/nodes/${NODE}/proxy/metrics" | grep '^volume_operation'

Chercher une métrique sur le mauvais composant donne un résultat vide qui ressemble à s'y méprendre à une métrique disparue.

Ces cinq commandes se lancent dans cet ordre, et l'ordre a un sens : on part du plus large, l'état des nœuds, pour descendre vers le plus précis. Chacune élimine une famille de causes avant que la suivante ne creuse. Si les cinq passent, le problème n'est pas dans l'infrastructure du cluster.

#CommandeCe qu'elle vérifie
1kubectl get nodesTous les nœuds sont Ready
2kubectl describe node <nom>Conditions détaillées et ressources allouées
3kubectl get --raw='/readyz?verbose'Santé du plan de contrôle
4kubectl top nodes / kubectl top podsConsommation CPU/mémoire en temps réel
5kubectl events -A --types=WarningAnomalies récentes dans le cluster

Les symptômes ci-dessous ont un point commun : ils ressemblent à une panne du cluster alors qu'ils désignent le plus souvent un outil manquant ou une lecture au mauvais endroit. Vérifier ces causes-là en premier évite d'ouvrir une investigation sur un cluster qui va parfaitement bien.

SymptômeCause probableSolution
Nœud NotReadyKubelet arrêté ou réseau coupéSe connecter au nœud, vérifier systemctl status kubelet
MemoryPressure: TrueMémoire insuffisanteIdentifier les pods gourmands avec kubectl top pods, augmenter la mémoire ou réduire les loads
DiskPressure: TrueDisque plein (images, logs)Nettoyer les images inutilisées : crictl rmi --prune
kubectl top renvoie "Metrics API not available"metrics-server absentInstaller metrics-server (voir étape 4)
/readyz affiche [-]etcdetcd indisponibleVérifier l'état du pod etcd : kubectl logs -n kube-system etcd-<nom>
Beaucoup d'événements EvictedNœud sous pression prolongéeAjouter des nœuds ou réduire la charge de travail
  • kubectl get nodes est votre premier réflexe : tous les nœuds doivent être Ready
  • Les 5 conditions d'un nœud (Ready, MemoryPressure, DiskPressure, PIDPressure, NetworkUnavailable) résument sa santé
  • kubectl describe node révèle les ressources allouées vs la capacité, surveillez le ratio Requests/Allocatable
  • metrics-server est indispensable pour kubectl top, il n'est pas installé par défaut sur tous les clusters
  • Les événements Warning sont votre système d'alerte natif : consultez-les régulièrement
  • Ces commandes donnent un instantané, pour du monitoring continu, déployez Prometheus + Grafana

Sept questions sur ce qui se lit de travers : des conditions de nœud dont une seule doit valoir True, un surengagement de ressources qui n'est pas un défaut, et une métrique introuvable parce qu'on interroge le mauvais composant.

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