infra / monitoring-observabilite
Monitoring de conteneurs : cAdvisor et Kubernetes
Explication
Ce que vous allez apprendre
- Comprendre la différence entre la consommation réelle (cAdvisor) et l'état déclaratif (kube-state-metrics)
- Déployer cAdvisor pour surveiller la consommation de conteneurs Docker
- Détecter un conteneur proche de l'OOM-kill avant qu'il ne soit tué
- Utiliser un ServiceMonitor pour automatiser la découverte de cibles dans Kubernetes
- Repérer un déploiement Kubernetes dégradé via ses métriques de replicas
Dans quel contexte ?
L'infrastructure a évolué : mon-api ne tourne plus sur un serveur unique surveillé par node_exporter (leçon précédente), mais dans des conteneurs Docker, bientôt orchestrés par Kubernetes. Un conteneur peut consommer toute la mémoire disponible sans que ça n'apparaisse jamais dans les métriques classiques du serveur hôte, car cette consommation reste isolée à l'intérieur du conteneur — un nouvel angle mort qu'il faut couvrir spécifiquement.
D'abord, il faut un exporter capable de voir À L'INTÉRIEUR des conteneurs
node_exporter donne une vue globale de la machine, mais ne distingue pas la consommation de chaque conteneur individuellement. cAdvisor (Container Advisor), développé par Google, comble ce manque : il expose la consommation CPU, mémoire et réseau conteneur par conteneur, pas seulement machine par machine.
Cette distinction devient cruciale dès qu'un seul serveur héberge plusieurs applications indépendantes : sans cAdvisor, impossible de savoir LEQUEL des dix conteneurs consomme la mémoire qui manque.
| Outil | Ce qu'il mesure | Question à laquelle il répond |
|---|---|---|
| node_exporter | Consommation de la machine entière | "Le serveur va-t-il manquer de ressources ?" |
| cAdvisor | Consommation par conteneur individuel | "Quel conteneur consomme le plus ?" |
| kube-state-metrics | État déclaratif des objets Kubernetes | "Le déploiement a-t-il le bon nombre de replicas ?" |
Prérequis
Une connaissance de base de Docker (voir le cours dédié) est nécessaire pour comprendre les volumes montés par cAdvisor (/sys, /var/lib/docker) ; des notions Kubernetes aident pour la seconde moitié de la leçon.
Une fois cAdvisor en place, un cas d'usage concret devient immédiatement possible
En comparant container_memory_usage_bytes à container_spec_memory_limit_bytes, on peut détecter qu'un conteneur approche dangereusement de sa limite mémoire — et donc d'un OOM-kill imminent, le mécanisme par lequel le noyau Linux tue brutalement un processus qui dépasse sa limite.
Piège fréquent
Attendre l'alerte "conteneur redémarré" pour réagir revient toujours à réagir APRÈS l'incident. Poser une alerte sur container_memory_usage_bytes / container_spec_memory_limit_bytes > 0.9 permet d'intervenir (augmenter la limite, corriger une fuite mémoire) avant que le conteneur ne soit tué par le noyau.
Maintenant que la consommation est couverte, il reste une autre dimension propre à Kubernetes : l'état déclaratif
Kubernetes fonctionne de façon déclarative : on décrit l'état voulu ("3 replicas de mon-api"), et le contrôleur s'efforce de le maintenir. kube-state-metrics expose justement cet écart entre l'état voulu et l'état réel, une information que cAdvisor, focalisé sur la consommation, ne fournit pas du tout.
kube_deployment_status_replicas_available < kube_deployment_spec_replicas détecte ainsi un déploiement dégradé — par exemple si un pod crash en boucle — souvent avant même que l'application ne remonte la moindre erreur applicative.
Il reste un dernier problème pratique : comment scraper automatiquement des pods qui changent constamment ?
Astuce
Dans un cluster Kubernetes dynamique, éditer prometheus.yml à la main à chaque nouveau service devient vite intenable. Le CRD ServiceMonitor du Prometheus Operator automatise cette découverte : il suffit qu'un Service Kubernetes porte le bon label pour que Prometheus commence à le scraper automatiquement, sans redéploiement de configuration.
Après cette plongée dans les conteneurs et Kubernetes, la prochaine leçon revient au code : comment écrire ses propres exporters personnalisés pour des systèmes qui n'en ont pas encore.
Commandes & code
Monitoring de conteneurs : cAdvisor et Kubernetes
# docker-compose.yml — cAdvisor expose les métriques de TOUS les conteneurs d'un hôte Docker
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.49.1
ports: ["8080:8080"]
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
privileged: true# Métriques cAdvisor par conteneur — filtrer par le label "name" ou "container_label_com_docker_compose_service"
sum(rate(container_cpu_usage_seconds_total{name=~"app.*"}[5m])) by (name) # CPU par conteneur
container_memory_usage_bytes{name=~"app.*"} / 1024 / 1024 # mémoire en Mo
rate(container_network_receive_bytes_total{name=~"app.*"}[5m]) # réseau entrant
# Détecter les conteneurs en train de se faire OOM-kill
container_memory_usage_bytes / container_spec_memory_limit_bytes > 0.9 # >90% de la limite mémoire# Kubernetes : kube-state-metrics + node_exporter (DaemonSet) + cAdvisor (déjà intégré au kubelet)
# kube-state-metrics expose l'état DÉCLARATIF des objets K8s (pas la conso, mais l'état : replicas désirés vs actuels)
apiVersion: apps/v1
kind: Deployment
metadata:
name: kube-state-metrics
namespace: monitoring
spec:
replicas: 1
template:
spec:
containers:
- name: kube-state-metrics
image: registry.k8s.io/kube-state-metrics/kube-state-metrics:v2.13.0
ports:
- containerPort: 8080# ServiceMonitor (CRD du Prometheus Operator) : découverte automatique des cibles à scraper dans K8s
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: mon-api-monitor
namespace: monitoring
spec:
selector:
matchLabels:
app: mon-api # cible tous les Services portant ce label
endpoints:
- port: metrics # nom du port défini dans le Service K8s
interval: 15s
path: /metrics# Métriques Kubernetes essentielles
kube_deployment_status_replicas_available{deployment="mon-api"}
< kube_deployment_spec_replicas{deployment="mon-api"}
# -> vrai si moins de replicas disponibles que voulus (déploiement dégradé)
rate(container_cpu_usage_seconds_total{namespace="production"}[5m])
/ on(pod) kube_pod_container_resource_limits{resource="cpu"}
# -> % d'utilisation CPU par rapport à la limite définie dans le manifest (détecte le throttling)
kube_pod_container_status_restarts_total > 5 # pods qui crash-loop (redémarrages fréquents)# Sidecar de scraping dans un Pod K8s (pattern courant sans Operator) : annotation lue par Prometheus
apiVersion: v1
kind: Pod
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8000"
prometheus.io/path: "/metrics"Résumé
- cAdvisor donne la CONSOMMATION réelle par conteneur (CPU, mémoire, réseau) ; kube-state-metrics donne l'ÉTAT DÉCLARATIF des objets K8s (replicas, restarts).
- Le Prometheus Operator (CRD
ServiceMonitor) automatise la découverte des cibles à scraper dans un cluster, sans éditerprometheus.ymlà la main. container_memory_usage_bytes / container_spec_memory_limit_bytesproche de 1 annonce un OOM-kill imminent : alerte à poser systématiquement.- Comparer
kube_deployment_status_replicas_availableàkube_deployment_spec_replicasdétecte un déploiement dégradé avant même l'alerte applicative.
Exercices pratiques
Mission : le conteneur qui va se faire tuer
Objectif : Détecter un conteneur proche de l'OOM-kill avant qu'il ne soit tué, et diagnostiquer un déploiement Kubernetes dégradé via ses métriques déclaratives.
Contexte
mon-api tourne maintenant dans un Deployment Kubernetes avec 3 replicas voulus. cAdvisor est en place. Un des conteneurs consomme une mémoire anormalement croissante et le déploiement semble instable, mais aucune alerte applicative n'a encore été déclenchée.