Métriques d'une VM: CPU, charge, RAM, swap...
L'idée en une phrase
Les graphiques d'une machine (CPU, RAM, charge, swap, disque) racontent ce que vit ton application. Une métrique seule dit peu de choses ; c'est en les lisant ensemble qu'on comprend si l'application calcule trop, attend quelque chose ou manque de mémoire.
Une image pour comprendre : le bilan médical
Un médecin ne pose pas un diagnostic sur la seule température. Fièvre + toux, ce n'est pas la même chose que fièvre + mal de ventre. Il croise les mesures, et il les compare à ce qui est normal pour ce patient.
Avec une machine, c'est pareil :
- un CPU à 90 % n'est pas forcément un problème ;
- un CPU à 90 % et des temps de réponse qui explosent depuis le déploiement de ce matin, ça raconte une histoire.
Garde ce réflexe pour toute la fiche : combiner les métriques et comparer avec la normale.
D'où viennent les graphiques ?
Dans un projet classique, deux sources alimentent les tableaux de bord (souvent dans Grafana, avec Prometheus qui collecte les mesures) :
| Source | Ce qu'elle mesure | Exemples |
|---|---|---|
| La machine (via un agent comme node_exporter) | ce que voit le système | CPU, RAM, charge, swap, disque, réseau |
| L'application Spring Boot (via Actuator et Micrometer) | ce que vit Java à l'intérieur | heap, GC, temps de réponse HTTP, connexions à la base |
Les deux sont indispensables. La machine dit que quelque chose se passe ; l'application aide à dire quoi.
Les métriques une par une
Le CPU
Le pourcentage de temps où le processeur travaille. Le total se découpe en plusieurs parts, et c'est ce découpage qui est intéressant :
| Part | Signification | Si elle est élevée… |
|---|---|---|
user |
le processeur exécute des programmes (ton application) | l'application calcule beaucoup |
system |
le processeur exécute le système (réseau, fichiers…) | beaucoup d'échanges avec le système |
iowait |
le processeur attend le disque | le disque est trop lent ou trop sollicité |
steal |
la VM attend que l'hébergeur lui donne du CPU | la machine physique est surchargée par d'autres VM |
idle |
le processeur ne fait rien | tout va bien de ce côté |
Note :
stealn'existe que sur une machine virtuelle. S'il monte, le problème n'est pas dans ton code : la machine physique qui héberge ta VM est partagée et saturée. C'est un sujet pour l'hébergeur.
La charge (load average)
C'est le nombre de tâches qui veulent travailler : celles qui utilisent un cœur, celles qui attendent leur tour, et (sous Linux) celles qui attendent le disque.
On la lit en trois valeurs : moyenne sur 1, 5 et 15 minutes. Par exemple 2.10 1.80 0.90 : la charge monte (elle est plus forte sur la dernière minute que sur le dernier quart d'heure).
Pour l'interpréter, compare-la au nombre de cœurs :
| Machine à 4 cœurs | Lecture |
|---|---|
| charge à 2 | les cœurs ne sont pas tous occupés : confortable |
| charge à 4 | les cœurs sont pleinement utilisés |
| charge à 12 | trois fois plus de tâches que de cœurs : des tâches font la queue |
Astuce : une charge élevée avec un CPU bas, c'est le signe que les tâches attendent le disque, pas le processeur. Regarde alors
iowait.
La RAM
C'est le piège le plus courant pour un débutant : une RAM « pleine » n'est pas forcément un problème.
Linux utilise la mémoire libre pour garder en cache les fichiers lus récemment. Ça accélère tout, et il la rend dès qu'un programme en a besoin. Une machine saine affiche donc souvent une mémoire « utilisée » élevée.
La bonne métrique est la mémoire disponible (available) : ce qui peut réellement être donné à un programme, cache compris.
| Métrique | À regarder ? |
|---|---|
| mémoire utilisée (used) | trompeuse : elle compte le cache |
| mémoire disponible (available) | ✅ c'est elle qui compte |
Une particularité de Java : au démarrage, la JVM réserve de la mémoire pour sa heap et la rend rarement au système, même quand la heap se vide. Vue de la machine, la RAM de l'application reste donc haute et plate. C'est normal. Pour savoir ce qui se passe vraiment, il faut regarder la heap côté application (voir plus bas).
Le swap
Le swap est un espace sur le disque que le système utilise quand il n'a plus assez de RAM. Le disque étant des milliers de fois plus lent que la RAM, tout ralentit.
Deux mesures à ne pas confondre :
| Mesure | Lecture |
|---|---|
| swap occupé | un peu de swap occupé peut être ancien et sans conséquence |
| activité de swap (pages écrites et relues en continu) | 🚨 la machine manque de RAM maintenant |
Java supporte très mal le swap : le garbage collector parcourt toute la heap, et si une partie est sur le disque, chaque nettoyage devient interminable. L'application se fige par moments, sans erreur.
Le disque
Deux choses à surveiller :
- l'espace libre : un disque plein fait planter l'application ou la base de données. La cause la plus fréquente : des logs qui grossissent sans être archivés ni supprimés.
- l'occupation (le disque est-il occupé en permanence ?) : elle se voit aussi dans
iowait.
Les métriques de l'application
Une application Spring Boot avec Actuator expose ses propres mesures. Les plus parlantes :
| Métrique | Ce qu'elle montre |
|---|---|
| heap utilisée | la mémoire occupée par les objets Java |
| pauses du GC | le temps passé par Java à faire le ménage |
| temps de réponse HTTP | ce que ressentent les utilisateurs |
| connexions à la base actives / en attente | si le pool de connexions est saturé |
Lire les métriques ensemble : les cas typiques
C'est le cœur de la fiche. Chaque cas part d'un symptôme, croise plusieurs graphiques, et en tire une explication.
1. Le CPU est à 100 % en user
Ce que tu vois : CPU très haut, charge élevée, application lente.
Ce que ça révèle : l'application calcule énormément. Deux pistes :
- un traitement lourd (une boucle sur une grosse liste, un export, un calcul) ;
- le garbage collector qui tourne sans arrêt parce que la heap est presque pleine.
Pour trancher : regarde la heap et les pauses du GC. Si la heap est au plafond et que le GC est très actif, le CPU n'est que la conséquence : le vrai problème est la mémoire (voir la fiche sur la mémoire en Java).
2. Le CPU est bas, mais l'application est lente
Ce que tu vois : CPU calme, charge normale, mais des temps de réponse élevés.
Ce que ça révèle : l'application attend quelque chose : la base de données, une API externe, ou une connexion libre dans le pool.
Pour trancher : regarde les connexions à la base. Si des requêtes sont en attente d'une connexion, le pool est saturé (souvent à cause de requêtes SQL lentes qui gardent leur connexion trop longtemps). Sinon, regarde les temps de réponse des services appelés. La machine n'y est pour rien : elle se tourne les pouces.
3. La charge est haute, le CPU est bas, iowait monte
Ce que tu vois : une charge à 10 sur une machine à 4 cœurs, mais un CPU à 20 %.
Ce que ça révèle : les tâches font la queue pour le disque. Causes fréquentes : beaucoup de logs écrits (un niveau DEBUG oublié en production), une base de données sur la même machine qui lit beaucoup, ou… du swap (cas suivant).
4. La RAM disponible baisse et le swap s'active
Ce que tu vois : mémoire disponible proche de zéro, activité de swap, iowait qui grimpe, application qui se fige par moments.
Ce que ça révèle : la machine n'a plus assez de RAM pour tout ce qui tourne dessus. Souvent : trop de programmes sur la même VM, ou une heap Java réglée plus grande que ce que la machine peut offrir.
Ce qui arrive ensuite : si rien ne change, Linux finit par tuer un programme pour récupérer de la mémoire (l'OOM killer). Souvent, c'est le plus gros… donc ton application Java.
Note : ne confonds pas les deux « out of memory ». Un
OutOfMemoryErrorde Java laisse une erreur dans les logs de l'application. Quand c'est Linux qui tue le processus, l'application disparaît sans aucune erreur Java : la trace se trouve dans les logs du système.
5. La heap remonte un peu plus haut après chaque nettoyage
Ce que tu vois : sur le graphique de la heap, une courbe en dents de scie (elle monte, le GC passe, elle redescend)… mais le bas des dents remonte jour après jour.
Ce que ça révèle : une fuite mémoire. Des objets restent désignés et le GC ne peut plus les supprimer. Le plantage n'est qu'une question de temps.
Normal : Fuite :
/\ /\ /\ /\ /\/\
/ \/ \/ \/ \ /\/\/
/\/\/
/\/\/
Des dents de scie au même niveau, c'est sain : c'est le GC qui fait son travail.
6. steal monte, sans raison côté application
Ce que tu vois : application lente, CPU apparemment occupé, mais une part importante en steal.
Ce que ça révèle : la machine physique de l'hébergeur est saturée par d'autres VM. Ton code n'y est pour rien et aucune modification n'y changera quoi que ce soit : c'est à remonter à l'équipe qui gère l'hébergement.
7. L'espace disque baisse régulièrement
Ce que tu vois : une courbe d'espace libre qui descend en ligne droite, jour après jour.
Ce que ça révèle : quelque chose écrit sans jamais nettoyer, le plus souvent des fichiers de logs. Prolonge la ligne : tu sais quand le disque sera plein.
Le tableau récapitulatif
| CPU | Charge | RAM disponible | Swap | Piste principale |
|---|---|---|---|---|
haut (user) |
haute | normale | non | calcul lourd, ou GC qui s'emballe |
| bas | normale | normale | non | l'application attend (base, API, pool) |
bas (iowait haut) |
haute | normale | non | disque saturé (logs, base de données) |
variable (iowait haut) |
haute | basse | oui | manque de RAM sur la machine |
haut (steal) |
variable | normale | non | hébergeur saturé |
Si tu as accès à la machine
Quelques commandes Linux pour vérifier par toi-même. Elles ne modifient rien :
uptime # la charge sur 1, 5 et 15 minutes
nproc # le nombre de cœurs, pour comparer avec la charge
free -h # la RAM : regarde la colonne "available"
top # les programmes qui consomment le plus ; la ligne %Cpu montre us, sy, wa (iowait), st (steal)
vmstat 1 # une ligne par seconde ; colonnes si/so différentes de 0 = activité de swap
df -h # l'espace libre sur chaque disque
Les bonnes habitudes
- Connais la normale. Regarde les tableaux de bord quand tout va bien : c'est ce qui te permettra de repérer ce qui est anormal.
- Ne conclus jamais sur une seule métrique. Croise au moins le CPU, la charge, la mémoire et les temps de réponse.
- Regarde la RAM disponible, pas la RAM utilisée.
- Regarde l'activité du swap, pas seulement le swap occupé.
- Pour la mémoire d'une application Java, regarde la heap, pas la RAM de la machine.
- Situe le problème dans le temps. Un déploiement, un traitement planifié, une heure de pointe ? La plupart des incidents s'expliquent par « qu'est-ce qui a changé à ce moment-là ».
- Décris ce que tu vois avant de proposer une solution. « La charge est à 10 sur 4 cœurs avec 40 % d'
iowaitdepuis 14 h » aide toute l'équipe ; « le serveur rame » n'aide personne.
À retenir
- Une métrique seule ne dit presque rien : c'est la combinaison qui révèle ce qui se passe.
- CPU haut : l'application calcule (ou le GC s'emballe). CPU bas mais lenteur : l'application attend quelque chose.
- La charge se compare au nombre de cœurs ; haute avec un CPU bas, elle pointe vers le disque.
- Une RAM « pleine » est normale sous Linux et avec Java ; le vrai signal d'alarme, c'est le swap actif.
- Une heap dont le niveau bas remonte jour après jour signale une fuite mémoire.
stealélevé : le problème est chez l'hébergeur, pas dans ton code.