Vous vous connectez, lancez free et votre estomac se contracte : la mémoire est « utilisée » comme si c’était une mode. Rien n’est manifestement en feu. La latence semble correcte. Le CPU s’ennuie. Pourtant le tableau de bord hurle : RAM 92%. Quelqu’un demande : « Fuite mémoire ? »
Parfois c’est un incident réel. D’autres fois, c’est simplement Linux qui fait son travail : utiliser la RAM libre comme cache, puisque la mémoire inutilisée est une opportunité gâchée. L’astuce est de savoir rapidement ce qui est quoi—sans sacrifices rituels aux dieux du noyau.
Le modèle mental : la RAM n’est pas un seau, c’est un marché
Si vous ne retenez qu’une idée de cet article, retenez celle-ci : « utilisation élevée de la RAM » n’est pas un diagnostic. C’est une observation, et souvent une observation saine.
Trois types de mémoire confondus dans les alertes
- Mémoire anonyme : tas des processus, piles, arènes malloc, heap Java, heap Node/V8, etc. Si cela croît sans limites, vous pourriez avoir une fuite ou une charge non bornée.
- Mémoire adossée à des fichiers : fichiers mappés, bibliothèques partagées, bases de données mappées en mémoire, et en particulier le page cache. C’est là que Linux garde les données de fichiers en mémoire parce que lire depuis la RAM est plus rapide que depuis le disque.
- Mémoire noyau : caches slab, tampons réseau, dentries/inodes et autres structures du noyau. Cela peut croître pour de bonnes raisons (trafic) ou de mauvaises raisons (bugs, mauvaise config).
Pourquoi la métrique « mémoire libre » est trompeuse
Linux veut que la mémoire libre tende vers zéro. Pas parce qu’il est négligent, mais parce que la mémoire inoccupée ne fait rien. Le noyau utilise opportunément la RAM pour le caching et la récupère quand les applications en ont besoin.
Donc quand quelqu’un dit « la RAM est pleine », la question suivante est : pleine de quoi ? Le cache est récupérable. Un tas fuité ne l’est pas (tant que le processus n’est pas terminé).
Deux règles pour vous éviter des ennuis
- Si la latence est stable et qu’il n’y a pas de thrash de reclaim, arrêtez de paniquer. Un système riche en cache peut sembler « plein » et être parfaitement sain.
- Si le swap augmente et que les défauts majeurs grimpent, vous payez des intérêts sur la dette mémoire. C’est là que naissent les pannes en production.
Une vérité sèche : le « % de RAM » du tableau de bord est généralement une mauvaise abstraction. Vous avez besoin de signaux de pression, pas seulement d’occupation.
Faits et historique intéressants (court, concret et utile)
- Le comportement « buff/cache » de Linux embrouille les admins depuis des décennies ; la sortie moderne de
freea ajoutéavailablepour réduire les fausses alertes. - Windows a popularisé le terme « standby memory » pour le cache récupérable ; Linux fait la même chose, avec d’autres étiquettes et outils.
- Le OOM killer existe parce que la surallocation parfaite de mémoire est impossible : quand le noyau ne peut pas satisfaire des allocations, il choisit un processus à tuer plutôt que de bloquer le système.
- Les conteneurs n’ont pas inventé les limites mémoire ; ce sont les cgroups qui l’ont fait. Les conteneurs ont juste rendu facile l’application de cgroups à tout (y compris votre base de données, qui se met alors à râler).
- Les premiers Unix épargnaient le page cache parce que la RAM coûtait cher ; les noyaux modernes sont agressifs parce que les cycles CPU et l’attente I/O coûtent plus que la RAM.
- Le ZFS ARC est essentiellement « page cache, mais pour ZFS » et peut dominer la RAM si vous le laissez faire ; ce n’est pas une fuite, c’est une stratégie.
- Transparent Huge Pages (THP) peut améliorer les performances — ou créer des pics de latence et un gonflement mémoire, selon la charge et la fragmentation.
- Le reporting mémoire de Java est notoirement déroutant : le heap n’est qu’une partie ; le RSS inclut les allocations natives, le JIT, les stacks de threads et les mappings de fichiers.
- Linux peut récupérer rapidement le page cache propre mais les pages dirty exigent un writeback ; si le writeback est lent, « récupérable » devient « pas tout de suite ».
À quoi ressemble une RAM élevée « normale » vs « cassée »
Normal : RAM utilisée comme cache (rapide, silencieuse et réversible)
Le normal ressemble à ceci :
freeaffiche un « used » élevé mais aussi unavailableimportant.- Faible utilisation de swap (ou swap stable qui n’augmente pas).
vmstatmontre dessi/sofaibles et unwafaible.- La latence disque est basse car les hits du cache sont nombreux.
- Le RSS des processus est stable ; rien n’explose.
C’est le noyau qui rend service. Vous pouvez généralement le laisser tranquille. Si vous le « corrigez » en vidant le cache régulièrement, vous ne faites pas d’optimisation ; vous vous sabotez.
Cassé : pression mémoire et thrash de reclaim
Le cassé ressemble à ceci :
availableest faible et en baisse.- L’activité de swap augmente (
si/sonon nuls pendant des périodes soutenues). - Les défauts de page majeurs montent en flèche ; la latence devient bizarre.
- Des messages du OOM killer apparaissent dans les logs.
kswapddu noyau apparaît dans les profils CPU, parce que la machine est occupée à essayer de trouver de la mémoire pour respirer.
À ce stade la question change de « pourquoi la RAM est élevée ? » à « qu’est-ce qui la consomme et peut-on la récupérer en toute sécurité ? »
Les trois causes les plus courantes d’un « c’est cassé »
- Vraie fuite d’application ou croissance mémoire non bornée : mise en file de données en RAM, cache sans éviction, croissance des buffers par connexion, etc.
- Caches mal dimensionnés : buffers de base de données, heap JVM, Redis maxmemory, ZFS ARC, cache CDN, LRU d’application qui n’est pas réellement LRU.
- Croissance de la mémoire noyau : caches slab, tampons réseau, tables conntrack, métadonnées de système de fichiers en forte activité.
Blague #1 : Les fuites mémoire sont comme les paillettes : on ne les voit pas tout de suite, puis soudain elles sont partout dans votre vie.
Feuille de route de diagnostic rapide (premier/deuxième/ troisième)
Premier : Déterminez si c’est de la pression ou juste de l’occupation
- Vérifiez
freepouravailable. - Vérifiez la tendance du swap et
vmstatpour une activité de swap soutenue. - Cherchez des événements OOM dans les logs.
Décision : Si available est sain et que le swap ne grimpe pas, considérez cela comme un cache normal sauf si vous avez des symptômes visibles par les utilisateurs.
Second : Identifiez la classe de mémoire
- S’agit-il du RSS des processus (quelques PID qui grandissent) ?
- S’agit-il du page cache (cache élevé, anon stable) ?
- S’agit-il du slab noyau (slab élevé, objets en croissance) ?
- Dans les conteneurs : est-ce un problème de limite cgroup (RSS OK, mais le cgroup rapporte proche de la limite) ?
Décision : Choisissez le bon outil : inspection par processus, stats cgroup ou répartition des slabs — pas « redémarrer tout » comme méthode de diagnostic.
Troisième : Prouvez le consommateur principal et choisissez l’atténuation la moins risquée
- Obtenez les principaux consommateurs mémoire et confirmez la croissance dans le temps (pas seulement un instantané).
- Vérifiez si le consommateur est réglable (limite de cache) ou bogué (fuite).
- Atténuez : limiter le cache, corriger la requête/charge, ajouter de la mémoire, ou redémarrer comme palliatif contrôlé avec action de suivi.
Décision : Si le système subit une pression active, priorisez la stabilité : prévenir les OOM, arrêter le thrash, puis faire la cause racine calmement.
Tâches pratiques : commandes, sorties et décisions
Voici des tâches réelles que vous pouvez exécuter sur des hôtes Linux en production. Chacune indique ce que la sortie signifie et la décision qu’elle entraîne. Utilisez-les dans l’ordre, pas au hasard.
Task 1: Read memory like an adult (free -h)
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 31Gi 26Gi 600Mi 1.2Gi 4.5Gi 3.8Gi
Swap: 4.0Gi 512Mi 3.5Gi
Ce que cela signifie : « used » inclut le cache et d’autres récupérables. Le nombre qui vous importe en premier est available (approximativement : ce qui peut être alloué sans swapper).
Décision : Si available fait plusieurs GiB et reste stable, il s’agit probablement d’un cache normal. S’il est bas (<5–10% du total) et décroît, passez aux vérifications de pression.
Task 2: Confirm pressure and swap churn (vmstat 1)
cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 524288 612000 82000 3920000 0 0 5 22 430 900 12 4 83 1 0
1 0 524288 598000 82000 3950000 0 0 1 10 420 880 11 4 84 1 0
3 1 525312 120000 81000 2800000 150 320 800 900 1200 2500 25 12 35 28 0
2 1 540000 90000 80000 2700000 220 400 1100 1400 1500 3000 22 15 30 33 0
2 1 560000 70000 79000 2600000 180 380 900 1200 1400 2900 20 14 32 34 0
Ce que cela signifie : Des si/so non nuls soutenus indiquent du swapping. Une wa en hausse suggère que la machine attend l’I/O, souvent aggravé par le swap ou le writeback.
Décision : Si le churn de swap est soutenu, traitez cela comme un incident : réduisez l’utilisation mémoire ou augmentez la mémoire/les limites avant d’obtenir un effondrement de latence ou un OOM.
Task 3: Check for OOM killer evidence (journalctl)
cr0x@server:~$ journalctl -k -S -2h | egrep -i 'oom|out of memory|killed process' | tail -n 20
Feb 05 09:41:12 server kernel: Out of memory: Killed process 21784 (java) total-vm:9876544kB, anon-rss:2456789kB, file-rss:12345kB, shmem-rss:0kB
Ce que cela signifie : Le noyau est tombé à court de mémoire allouable dans ses contraintes et a tué quelque chose. Ce « quelque chose » n’est souvent pas la cause racine — juste la victime malchanceuse avec le mauvais score.
Décision : Si vous voyez des kills OOM, cessez de débattre des définitions et commencez à réduire immédiatement la pression mémoire. Puis faites l’analyse de fond.
Task 4: See system-wide memory breakdown (cat /proc/meminfo)
cr0x@server:~$ egrep 'MemTotal|MemAvailable|Buffers|Cached|SwapTotal|SwapFree|Active|Inactive|AnonPages|Slab|SReclaimable|Dirty|Writeback' /proc/meminfo
MemTotal: 32803520 kB
MemAvailable: 4012340 kB
Buffers: 112340 kB
Cached: 3890120 kB
SwapTotal: 4194300 kB
SwapFree: 3670016 kB
Active: 20123456 kB
Inactive: 8765432 kB
AnonPages: 22123456 kB
Slab: 1456780 kB
SReclaimable: 612340 kB
Dirty: 245600 kB
Writeback: 4200 kB
Ce que cela signifie : AnonPages est un proxy approximatif de la mémoire privée des processus. Cached est le page cache. Slab/SReclaimable vous parle des caches noyau. Dirty/Writeback indique si la récupération est bloquée par l’écriture.
Décision : Un AnonPages élevé vous oriente vers les processus/cgroups. Un Slab élevé pointe vers une croissance d’objets noyau. Un Dirty élevé suggère des problèmes de writeback et des goulots I/O.
Task 5: Identify top processes by RSS (ps)
cr0x@server:~$ ps -eo pid,user,comm,rss,vsz --sort=-rss | head -n 15
PID USER COMMAND RSS VSZ
21784 app java 3854120 9876544
10422 app node 1123400 2456780
2314 postgres postgres 823000 1024000
1981 root dockerd 412000 1650000
1450 root systemd-journ 180000 450000
Ce que cela signifie : RSS est le resident set size : mémoire réellement en RAM (incluant certains mappings adossés à des fichiers). VSZ est virtuel, souvent énorme, souvent sans rapport.
Décision : Si un processus domine et croît dans le temps, suspectez une fuite ou un cache mal dimensionné. Si le RSS est réparti sur beaucoup de processus, suspectez une montée en charge ou une densité de conteneurs.
Task 6: Inspect a suspicious process’s mappings (pmap -x)
cr0x@server:~$ sudo pmap -x 21784 | tail -n 5
00007f2c78000000 262144 260000 260000 rw--- [ anon ]
00007f2c88000000 262144 262144 262144 rw--- [ anon ]
00007f2c98000000 262144 262144 262144 rw--- [ anon ]
00007ffd2c1b1000 132 44 44 rw--- [ stack ]
total kB 9876544 3854120 3720000
Ce que cela signifie : De larges régions anonymes pointent vers des allocations de heap/native. De grands mappings adossés à des fichiers peuvent être des fichiers mmap ou des libs partagées.
Décision : Si l’anonymous RSS gonfle, vous devez investiguer au niveau application (heap dump, profiling, éviction de cache). S’il est file-backed, considérez le comportement de page cache/mmap et le schéma I/O.
Task 7: Detect whether the kernel is spending time reclaiming (sar -B)
cr0x@server:~$ sar -B 1 3
Linux 6.5.0 (server) 02/05/2026 _x86_64_ (16 CPU)
12:01:01 AM pgpgin/s pgpgout/s fault/s majflt/s pgfree/s pgscank/s pgscand/s pgsteal/s %vmeff
12:01:02 AM 5.00 22.00 1200.00 0.00 8000.00 0.00 0.00 0.00 0.00
12:01:03 AM 900.00 1400.00 9000.00 85.00 12000.00 4500.00 0.00 3200.00 71.11
12:01:04 AM 850.00 1350.00 8700.00 90.00 11800.00 4700.00 0.00 3100.00 65.96
Ce que cela signifie : Les défauts majeurs (majflt/s) et le scanning/stealing indiquent une activité de reclaim. %vmeff donne une idée de l’efficacité du reclaim ; une faible efficacité se corrèle souvent avec du thrash.
Décision : Défauts majeurs élevés + scanning intensif = vous êtes sous pression. Corrigez l’usage mémoire ou les limites ; ne vous contentez pas d’« ajouter du swap et espérer ».
Task 8: Examine kernel slab consumers (slabtop)
cr0x@server:~$ sudo slabtop -o -s c | head -n 15
Active / Total Objects (% used) : 812345 / 845000 (96.1%)
Active / Total Slabs (% used) : 22000 / 22000 (100.0%)
Active / Total Caches (% used) : 95 / 120 (79.2%)
Active / Total Size (% used) : 1456780.00K / 1520000.00K (95.8%)
Minimum / Average / Maximum Object : 0.01K / 0.18K / 8.00K
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
220000 219500 99% 0.19K 11000 20 440000K dentry
180000 179000 99% 0.94K 9000 20 360000K inode_cache
95000 94900 99% 0.05K 1250 76 47500K kmalloc-64
Ce que cela signifie : De gros dentry/inode_cache signifient souvent un churn de métadonnées de système de fichiers (beaucoup de fichiers). Cela peut être normal sur des serveurs de build, expéditeurs de logs ou systèmes scannant des répertoires.
Décision : Si le slab est énorme et croissant, investiguez la charge (file storms), des bugs noyau, ou des limites comme vm.vfs_cache_pressure (avec prudence). Ne « droppez » pas les caches en production comme habitude.
Task 9: Check cgroup memory limits (containers/systemd)
cr0x@server:~$ cat /sys/fs/cgroup/memory.max
8589934592
cr0x@server:~$ cat /sys/fs/cgroup/memory.current
8422686720
Ce que cela signifie : Vous pouvez avoir beaucoup de RAM sur l’hôte mais subir un OOM dans un cgroup parce que la limite est serrée. memory.current proche de memory.max est de la pression, indépendamment de la mémoire libre hôte.
Décision : Si le cgroup est proche de sa limite, augmentez la limite ou réduisez la charge/caches dans le conteneur. La « mémoire libre » au niveau hôte ne vous sauvera pas.
Task 10: Identify cgroup OOM events (dmesg / kernel log)
cr0x@server:~$ dmesg | egrep -i 'memory cgroup out of memory|oom-kill|Killed process' | tail -n 10
[123456.789012] Memory cgroup out of memory: Killed process 10422 (node) total-vm:2456780kB, anon-rss:980000kB, file-rss:12000kB, shmem-rss:0kB
Ce que cela signifie : C’est un OOM de conteneur/cgroup, pas forcément un OOM hôte. La remédiation concerne les limites, pas « vider le cache ».
Décision : Ajustez les limites cgroup et définissez des requests/limits réalistes. Sinon vous jouez à la loterie où le prix est une indisponibilité.
Task 11: Understand “missing memory” via smaps rollup
cr0x@server:~$ sudo cat /proc/21784/smaps_rollup | egrep 'Rss|Pss|Private|Shared|Swap'
Rss: 3854120 kB
Pss: 3801200 kB
Shared_Clean: 12000 kB
Shared_Dirty: 4000 kB
Private_Clean: 35000 kB
Private_Dirty: 3803120 kB
Swap: 120000 kB
Ce que cela signifie : Private_Dirty est un signal fort de mémoire anonyme privée — souvent le heap. Le Swap indique que le processus paie la taxe du swap.
Décision : Si le private dirty croît avec la charge et ne redescend jamais, planifiez une correction applicative. Si le swap augmente, pensez à ajuster les limites mémoire et à investiguer les hotspots.
Task 12: Check open file descriptors and mmap pressure (lsof)
cr0x@server:~$ sudo lsof -p 21784 | wc -l
18234
Ce que cela signifie : Beaucoup de FD peuvent être corrélés à des buffers par connexion, de larges ensembles de mmap, et parfois des fuites (une fuite de FD n’est pas une fuite mémoire, mais elles voyagent souvent ensemble).
Décision : Si le nombre de FD augmente sans limite, traitez-le comme une classe de fuite. Corrigez l’application ; augmenter les ulimits n’est qu’un palliatif.
Task 13: Track memory trend over time (ps loop)
cr0x@server:~$ for i in {1..5}; do date; ps -p 21784 -o pid,rss,etime,cmd; sleep 60; done
Mon Feb 5 10:00:00 UTC 2026
PID RSS ELAPSED CMD
21784 3720000 01:22:10 java -jar service.jar
Mon Feb 5 10:01:00 UTC 2026
PID RSS ELAPSED CMD
21784 3755000 01:23:10 java -jar service.jar
Mon Feb 5 10:02:00 UTC 2026
PID RSS ELAPSED CMD
21784 3812000 01:24:10 java -jar service.jar
Mon Feb 5 10:03:00 UTC 2026
PID RSS ELAPSED CMD
21784 3899000 01:25:10 java -jar service.jar
Mon Feb 5 10:04:00 UTC 2026
PID RSS ELAPSED CMD
21784 3980000 01:26:10 java -jar service.jar
Ce que cela signifie : La tendance de croissance l’emporte sur un instantané. Si le RSS augmente régulièrement, ce n’est probablement pas du « cache » ; c’est de l’accumulation.
Décision : Montez en niveau vers du profiling et des correctifs au niveau du code ; implémentez des garde-fous (limites, backpressure) pendant la réparation.
Task 14: Check writeback congestion (grep vmstat counters)
cr0x@server:~$ egrep 'nr_dirty|nr_writeback|pgscan|pgsteal|oom_kill' /proc/vmstat | head
nr_dirty 61234
nr_writeback 2100
pgscan_kswapd 987654
pgsteal_kswapd 765432
oom_kill 3
Ce que cela signifie : Des niveaux élevés de scanning/stealing indiquent du travail de reclaim. Les niveaux dirty/writeback donnent une idée si le reclaim est bloqué par des flushs lents.
Décision : Si le writeback est élevé et l’I/O lente, corrigez les performances de stockage ou les limites dirty ; sinon la pression mémoire semblera pire qu’elle ne « devrait » l’être.
Trois micro-récits d’entreprise depuis les tranchées mémoire
Micro-récit 1 : L’incident causé par une mauvaise hypothèse
Une entreprise de taille moyenne exploitait une flotte de VMs Linux derrière un load balancer. Leur outil de monitoring n’avait qu’une métrique en titre : « RAM used % ». Ça alertait à 85%. Ça alertait souvent. Les gens ont appris à l’ignorer, ce qui est une astuce pratique jusqu’à ce que ça ne le soit plus.
Un après-midi, l’alerte RAM s’est déclenchée sur un nœud API critique. L’ingénieur on-call a regardé vite fait : used 90%, CPU OK. Il a haussé les épaules — « c’est juste du cache » — et est retourné à ses occupations.
Trente minutes plus tard, la latence a grimpé puis s’est effondrée. Le nœud a commencé à ne plus répondre aux checks de santé et a été retiré du load balancer. Un second nœud a suivi. Puis un troisième. Résultat : outage.
La cause racine n’était pas le page cache. Une nouvelle release avait introduit une file en mémoire non bornée quand une dépendance aval ralentissait. Le graphique « used % » ressemblait à d’habitude, mais MemAvailable s’effondrait et le churn de swap augmentait. Ils avaient un problème de pression et l’ont traité comme un problème cosmétique.
La correction a été double : implémenter du backpressure et intégrer MemAvailable, l’activité swap et les événements OOM dans les alertes principales. L’erreur n’était pas « Linux utilise le cache ». L’erreur était « haute utilisation signifie toujours la même chose ».
Micro-récit 2 : L’optimisation qui s’est retournée contre eux
Une équipe voulait réduire l’I/O disque d’un service de traitement de logs. Elle a augmenté significativement une taille de cache interne. En staging ça a fonctionné et les graphes semblaient super : moins de lectures, débit plus lisse.
En production, le même changement a provoqué une défaillance lente. Le trafic de pointe a réchauffé le cache rapidement, faisant monter le RSS. Cela aurait été acceptable — les machines avaient assez de RAM. Mais le service tournait dans des conteneurs avec des limites mémoire conservatrices définies des mois plus tôt, quand le trafic était plus faible et « l’efficacité » était un KPI.
Le cgroup a commencé à récupérer agressivement. La latence a augmenté. Le service a fait plus de retries, ce qui a augmenté la mémoire, ce qui a accentué la récupération. Puis le OOM killer du cgroup a commencé à terminer des conteneurs. Le redémarrage automatique a empiré la situation en créant des troupeaux de warm-ups de cache.
Le post-mortem n’a pas dit « les caches sont mauvais ». Il a dit « les caches sont des charges de travail ». Si vous changez le profil mémoire, vous devez changer les limites et les alarms. Sinon vous déplacez le goulot dans une boîte plus petite et feignez la surprise quand ça fait mal.
Micro-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise
Une société proche de la finance faisait tourner un cluster de base de données et quelques services sur les mêmes hôtes. Pas idéal, mais les budgets existent. Un SRE a insisté pour un drill hebdomadaire : enregistrer des découpages mémoire de base et conserver un runbook avec les « normales connues » : page cache, slab, buffers DB, et RSS typique pour chaque service.
C’était fastidieux. Ça ne produisait pas d’endorphine. Mais quand la mémoire a commencé à augmenter sur un ensemble de nœuds, ils n’ont pas débattu de la normalité — ils ont comparé au baseline.
Les slabs étaient dans la plage normale, le page cache typique, mais AnonPages était supérieur au baseline de quelques GiB et en tendance haussière. Le top RSS pointait vers un sidecar qui « ne devrait pas faire grand-chose ». Cette phrase est un bon indicateur de travail futur.
Ils ont rollbacké le changement du sidecar avant tout OOM. L’analyse ultérieure a montré une mise à jour de librairie qui changeait le comportement de buffering selon certains patterns de réponse. Le sauvetage n’a pas été héroïque. C’était avoir un baseline, et s’y fier.
Erreurs courantes : symptôme → cause racine → correction
1) Symptôme : « RAM à 95% utilisée, ça doit être une fuite »
Cause racine : Interpréter « used » comme « indisponible ». Le page cache gonfle le « used » et est récupérable.
Correction : Alarmez sur MemAvailable, l’activité swap, les défauts majeurs et les événements OOM. Apprenez à votre équipe à lire correctement free.
2) Symptôme : « Vider les caches a corrigé » (temporairement)
Cause racine : Vous avez vidé le page cache et le slab, ce qui a réduit la mémoire utilisée, mais vous avez aussi détruit les performances et masqué la croissance réelle.
Correction : N’utilisez pas drop_caches en routine. Si vous devez le faire pendant un diagnostic, documentez-le et mesurez l’impact sur les performances immédiatement après.
3) Symptôme : OOM kills alors que l’hôte a de la « mémoire libre »
Cause racine : Limite cgroup/conteneur atteinte. La mémoire hôte est hors sujet par rapport à cette limite.
Correction : Inspectez memory.max/memory.current, augmentez les limites et définissez des requests/limits sensés. Distinguez les alertes OOM cgroup des OOM hôte.
4) Symptôme : Pics de latence avec beaucoup de RAM
Cause racine : Thrash de reclaim ou stalls liés à THP/compaction. La mémoire « available » peut être correcte en moyenne mais pas dans la bonne forme.
Correction : Vérifiez les défauts majeurs, les stats de reclaim et les réglages THP. Envisagez de désactiver THP pour les charges sensibles à la latence quand il fait plus de mal que de bien.
5) Symptôme : Le swap est utilisé, panique générale
Cause racine : L’utilisation du swap n’est pas intrinsèquement mauvaise ; le swap-in/out constant l’est. Linux peut déplacer des pages froides dans le swap par politique.
Correction : Regardez vmstat si/so et les défauts majeurs. Si c’est stable, c’est acceptable. Si c’est du churn, traitez comme de la pression.
6) Symptôme : La mémoire augmente après chaque déploiement, puis se « stabilise »
Cause racine : Comportement de warmup (JIT, caches, pools de connexions) qui ressemble à une fuite si vous ne regardez que la première heure.
Correction : Comparez l’état après warmup. Définissez des alertes sur le taux de croissance, pas seulement sur le niveau, et annotez les déploiements.
7) Symptôme : « Used memory » monte avec des charges intensives sur le système de fichiers
Cause racine : Croissance du slab (dentry/inode) sous churn de métadonnées.
Correction : Confirmez avec slabtop. Réduisez le churn (moins de fichiers, plus de lots), ajustez prudemment et assurez-vous que les noyaux sont à jour.
8) Symptôme : Nœud de base de données « bouffe toute la RAM »
Cause racine : Cache de buffers DB + cache OS double-caching, ou utilisation volontaire de la RAM pour la performance.
Correction : Dimensionnez les caches DB intentionnellement et laissez une marge pour l’OS et les autres services. Ne colocalisez pas des services gourmands en mémoire sans budgets explicites.
Checklists / plan étape par étape (prêt pour la production)
Checklist A: Quand vous êtes appelé pour « haute mémoire »
- Exécutez
free -h. Concentrez-vous suravailable, pas sur « used ». - Exécutez
vmstat 1 10. Cherchez dessi/sosoutenus et unwaélevé. - Cherchez les événements OOM :
journalctl -k -S -2h | egrep -i 'oom|killed process'. - Si vous êtes en conteneurs, vérifiez le cgroup :
memory.currentvsmemory.max. - Si la pression est réelle, identifiez les principaux consommateurs (
ps) et vérifiez la croissance sur 5–15 minutes. - Choisissez une atténuation : limiter les caches, réduire la concurrence, décharger la charge, augmenter les limites ou ajouter de la RAM.
- Ce n’est qu’après cela que vous envisagez un redémarrage — et traitez-le comme un palliatif avec ticket de suivi.
Checklist B: Stabiliser un hôte sous pression mémoire (sans faire quelque chose de regrettable)
- Arrêtez l’hémorragie : réduisez le trafic/la concurrence ou rollbackez le changement qui a augmenté la mémoire.
- Protégez le noyau : assurez-vous d’avoir du swap configuré de façon sensée et pas sur un média extrêmement lent ; évitez de désactiver le swap par réflexe.
- Priorisez les services critiques : ajustez les priorités/limites cgroup pour que la base de données ne meure pas pour sauver un job batch.
- Mesurez le reclaim : défauts majeurs,
pgscan,pgstealet churn swap vous disent si vous thrashez. - Faites un seul changement à la fois : augmenter un cache et réduire la concurrence dans la même minute vous empêche de raisonner.
Checklist C: Construire de meilleures alertes pour que ça n’arrive plus
- Alertez sur une faible MemAvailable soutenue (hôte) et sur memory.current proche de memory.max (cgroup).
- Alertez sur swap-in/out soutenu, pas sur « swap utilisé ».
- Alertez sur les OOM kills comme événements dignes d’une page avec contexte clair victime/cause.
- Surveillez les top RSS processes et leur pente après les déploiements.
- Annotez les déploiements et changements de config sur les graphes mémoire.
Blague #2 : « On va juste augmenter le cache » est l’équivalent technique de « je desserre la ceinture » — ça marche jusqu’au moment où il faut courir.
Une citation à garder sur votre mur (ou au moins dans votre runbook)
Idée paraphrasée de Gene Kranz (mission operations) : « Tough and competent » — restez calmes, tenez-vous aux fondamentaux et exécutez la checklist.
FAQ
1) Pourquoi Linux utilise-t-il presque toute la RAM même quand rien ne tourne ?
Parce que « rien ne tourne » est rarement vrai (démons, caches, structures noyau), et parce que Linux utilise la RAM disponible pour le page cache. Ce cache accélère les lectures futures et est récupéré sous pression.
2) Est-ce mauvais si le swap est non nul ?
Pas automatiquement. Une utilisation stable du swap peut signifier que des pages froides ont été déplacées. Ce qui est mauvais, c’est le swap-in/out soutenu (vmstat si/so), la montée des défauts majeurs et la latence côté utilisateur.
3) Quelle est la façon la plus rapide de distinguer cache et fuite ?
Commencez par free : si available est sain, c’est probablement du cache. Confirmez ensuite avec /proc/meminfo : un Cached élevé avec des AnonPages stables indique du cache ; des AnonPages en hausse signalent une croissance mémoire des processus.
4) Pourquoi le même service utilise-t-il plus de RAM avec le temps même sans fuite ?
Warmup des caches, JIT (Java), comportement de l’allocateur (arènes glibc), pools de connexions et changements de charge peuvent tous augmenter l’état stable de la mémoire. La question est de savoir si cela se stabilise et si les signaux de pression restent calmes.
5) Dans Kubernetes, pourquoi suis-je OOMKilled alors que le nœud a de la mémoire libre ?
Parce que le pod a atteint sa limite mémoire. Le noyau applique les limites cgroup ; il se fiche que le nœud ait de la marge. Corrigez en dimensionnant correctement requests/limits et/ou en réduisant le caching dans le conteneur.
6) Dois-je exécuter echo 3 > /proc/sys/vm/drop_caches en production ?
Presque jamais. C’est un outil de diagnostic au mieux, et cela peut provoquer une chute de performance en forçant des lectures disque qui étaient des hits de cache. Si vous le faites, faites-le intentionnellement, lors d’une enquête contrôlée, et attendez-vous à un impact.
7) Qu’en est-il du ZFS ARC — fuite ou cache ?
Généralement du cache. L’ARC s’étendra pour utiliser la RAM disponible à moins d’être limité. Si l’ARC concurrence les applications, vous verrez de la pression : faible MemAvailable, swapping, reclaim. Corrigez en dimensionnant l’ARC et en laissant de la marge.
8) Pourquoi « available » diffère-t-il de « free » ?
free est littéralement les pages inutilisées à cet instant. available estime la mémoire qui peut être allouée sans swap en récupérant le cache et autres récupérables. C’est le nombre le plus utile opérationnellement.
9) Comment décider entre « ajouter de la RAM » et « corriger l’application » ?
Si vous êtes sous pression maintenant, ajouter de la RAM (ou augmenter les limites) peut être l’atténuation la moins risquée immédiatement. Mais si le RSS croît sans borne, plus de RAM ne fait que retarder la panne. Utilisez la tendance de croissance et les signaux de pression pour décider.
10) La croissance des slabs du noyau peut-elle provoquer des pannes ?
Oui. Le slab peut consommer beaucoup de RAM, notamment avec un churn de métadonnées de système de fichiers ou des tables réseau. Confirmez avec slabtop et enquêtez sur le pattern de charge et la version du noyau avant de toucher aux réglages.
Conclusion : étapes pratiques suivantes (faites celles-ci, pas des impressions)
- Corrigez votre modèle mental : cessez de traiter « RAM utilisée » comme « RAM indisponible ». Utilisez
MemAvailableet les indicateurs de pression. - Améliorez vos alertes : alarmes sur OOM kills, churn swap soutenu et faible mémoire disponible — pas sur le « used % ».
- Classifiez la mémoire : anonyme vs cache fichier vs slab vs cgroup. Choisissez des outils adaptés à chaque classe.
- Mesurez les tendances : les instantanés mentent. Suivez les top RSS et leurs pentes après les déploiements.
- Rendez les budgets mémoire explicites : les caches (DB, JVM, Redis, ZFS ARC) ont besoin de marge. Si vous ne pouvez pas expliquer le budget, vous jouez.
- Utilisez les redémarrages avec parcimonie : ils sont acceptables comme palliatif quand la pression est aiguë, mais uniquement si vous ouvrez aussi une investigation « pourquoi ça a crû ? ».
Si vous administrez des systèmes en production assez longtemps, vous verrez les deux : des machines « RAM pleine » parfaitement saines et de petites fuites silencieuses qui ruinent votre week-end. La différence tient à savoir si vous cherchez la pression et l’attribution — ou si vous vous contentez de regarder un pourcentage et d’inventer une histoire.