Debian 13 : la swap augmente et les performances s’effondrent — corrections de pression mémoire qui aident vraiment

Cet article vous a aidé ?

Vous vous connectez et tout paraît… lent. SSH met une seconde de trop. Un apt “rapide” traîne. Vos tableaux de bord montrent que le CPU va bien,
le disque ne semble pas saturé, et pourtant la latence grimpe comme si elle participait à une course d’escalier.
Puis vous le remarquez : l’utilisation du swap augmente. Lentement au début, puis sans relâche. La machine n’est pas tombée, mais elle n’est pas non plus vivante.

Sur Debian 13, ce n’est généralement pas que « le swap est mauvais », mais plutôt que « votre système négocie avec la physique ». La bonne nouvelle : vous pouvez diagnostiquer la pression mémoire
rapidement, choisir la bonne intervention, et arrêter de traiter le swap comme une superstition. La mauvaise nouvelle : certaines « optimisations » courantes aggravent le problème.
Faisons les corrections qui tiennent en production.

Playbook de diagnostic rapide (vérifiez ceci en premier)

Quand le swap monte et que les performances chutent, vous voulez répondre à trois questions rapidement :
(1) Sommes‑nous réellement en pression mémoire, ou gardons‑nous juste du cache ?
(2) Si la pression est réelle, qu’est‑ce qui la cause — un processus, une limite cgroup, ou le comportement de reclaim du noyau ?
(3) Le ralentissement vient‑il des E/S de swap, des blocages de reclaim direct, ou des deux ?

Premier : confirmer la pression et le type de douleur

  • Regardez mémoire + swap + indicateurs de reclaim : free, vmstat, et PSI dans /proc/pressure.
  • Regardez les plus gros consommateurs : tri RSS avec ps, puis les cgroups.
  • Regardez les blocages : fort si/so (swap in/out), fort wa, et PSI “some/full”.

Second : identifier la frontière

  • Si vous êtes sur bare metal/VM sans limites cgroup, la frontière est « RAM + swap ».
  • Si vous êtes sur un hôte avec conteneurs, la frontière peut être un memory.max de cgroup ; le swap peut croître sur l’hôte pendant qu’un conteneur suffoque.
  • Si systemd-oomd est activé, il peut tuer (ou ne pas tuer) selon les signaux PSI et la configuration des unités.

Troisième : choisir la classe d’intervention

  • Fuite ou runaway : corriger l’application, redémarrer en toute sécurité, ajouter des garde‑fous (limites/oomd).
  • Charge lourde en cache : régler le reclaim et éviter les boutons panique « drop caches ».
  • Thrash de swap : réduire le swap (swappiness, tuning memcg) ou rendre le swap plus rapide (zram/NVMe) pendant que vous traitez la vraie cause.
  • Système mal dimensionné : ajoutez de la RAM ou réduisez la concurrence. Oui, parfois la solution est de dépenser de l’argent.

Une idée paraphrasée de John Allspaw (opérations et fiabilité) : « Vous ne résolvez pas les incidents en chassant une seule ‘cause racine’ ; vous corrigez les conditions qui ont permis la défaillance. »
C’est la croissance du swap en résumé : c’est généralement un ensemble de conditions, pas un seul méchant.

Ce qui se passe vraiment quand le swap augmente

Linux utilise la RAM pour plus que le tas de votre application. Il conserve les données de fichiers dans le page cache, suit les métadonnées du système de fichiers,
et garde des pages anonymes (la mémoire des processus). Quand la RAM se remplit, le noyau récupère de la mémoire : il libère des pages de cache propres,
écrit les pages sales, et, si nécessaire, échange des pages anonymes vers l’espace de swap.

La croissance du swap ne signifie pas automatiquement que le système est « en manque de mémoire ». Cela peut aussi signifier que le noyau a jugé certaines pages comme froides
et les a mises en swap pour faire de la place au cache qui améliore le débit. Ça paraît raisonnable — jusqu’à ce que ça ne le soit plus.

Les trois modes d’échec que vous verrez réellement

  1. Swap bénin : le swap est utilisé un peu, mais le taux de swap‑in reste faible. La machine est réactive. Vous pouvez l’ignorer.
  2. Thrash de swap : les taux swap‑in/out flambent, la latence explose, le CPU montre du temps en I/O wait, et les tâches interactives rampent.
    C’est votre scénario « les performances s’effondrent ».
  3. Blocages de reclaim direct sans E/S de swap massive : le noyau passe du temps à récupérer des pages ; PSI mémoire “some/full” augmente.
    La machine paraît lente même si les E/S de swap ne sont pas énormes, surtout avec certaines charges et une fragmentation mémoire.

Sur Debian 13, vous aurez typiquement un noyau moderne et systemd. C’est bien — PSI est disponible, cgroup v2 est courant, et
systemd-oomd existe. Mais cela signifie aussi que beaucoup de « valeurs par défaut intelligentes » peuvent interagir de façon intelligente individuellement
et stupide collectivement.

Petite blague #1 : Le swap, c’est comme un tiroir à bazar — correct jusqu’au moment où vous avez besoin d’une chose rapidement et qu’elle est enfouie sous d’anciennes notes de resto.

Faits et contexte : swap, reclaim et pourquoi Debian se comporte ainsi

  • Fait 1 : Le swap Linux précède l’époque du « RAM bon marché » ; il a été conçu quand la mémoire était rare et les charges plus petites,
    donc les politiques de reclaim ont évolué sur des décennies, pas des mois.
  • Fait 2 : Le noyau distingue la mémoire anonyme (pages de processus) de la mémoire adossée à des fichiers (page cache).
    Les pages adossées aux fichiers peuvent être abandonnées ; les pages anonymes nécessitent le swap (ou la libération via un kill).
  • Fait 3 : PSI (Pressure Stall Information) est arrivé pour mesurer le temps pendant lequel les tâches sont bloquées à cause de la pression des ressources (mémoire/CPU/E/S),
    ce qui est plus exploitable que la « mémoire libre » pour diagnostiquer la latence.
  • Fait 4 : cgroup v2 a changé la sémantique du contrôle mémoire et a fait de memory.high un bouton de throttling plutôt qu’une simple limite dure ;
    cela importe parce que le throttling peut ressembler à une « lenteur mystérieuse ».
  • Fait 5 : Le OOM killer est au niveau noyau et brutal ; systemd-oomd est en espace utilisateur et piloté par des politiques,
    souvent déclenché par des signaux PSI plutôt que d’attendre un OOM total.
  • Fait 6 : La valeur par défaut de vm.swappiness a changé selon les époques et les distributions ; ce n’est pas un jugement moral,
    c’est un curseur d’arbitrage, et les valeurs par défaut sont réglées pour un usage « général », pas pour votre charge spécifique.
  • Fait 7 : Swapper sur NVMe peut « fonctionner » mais ruiner les latences de queue car le swap‑in est souvent sur le chemin critique du traitement des requêtes.
  • Fait 8 : Les Transparent Huge Pages (THP) peuvent gonfler l’empreinte mémoire et compliquer le reclaim ; pour certaines bases de données c’est bénéfique,
    pour d’autres c’est une source constante de douleur.
  • Fait 9 : La fragmentation mémoire peut provoquer des échecs d’allocation ou des blocages de reclaim même quand la « mémoire libre » semble non nulle,
    en particulier pour les allocations contiguës larges (y compris les huge pages).

Tâches pratiques : commandes, sorties et décisions (le vrai travail)

Ce ne sont pas des commandes « exécutez et vous irez mieux ». Chacune suit le schéma : commande → ce que signifie la sortie → décision à prendre.
Exécutez‑les dans l’ordre jusqu’à ce que l’histoire devienne évidente.

Tâche 1 : Établir l’état de base mémoire et swap

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:            62Gi        51Gi       1.2Gi       1.5Gi        10Gi       3.4Gi
Swap:           16Gi       9.8Gi       6.2Gi

Ce que cela signifie : « available » est la ligne clé, pas « free ». Ici, seulement 3.4Gi est rapidement récupérable sans douleur majeure.
Le swap est déjà ~60% utilisé.
Décision : Poursuivre : il faut voir si le swap est activement utilisé (thrash) ou seulement alloué et froid.

Tâche 2 : Vérifier l’activité swap en direct (thrash vs pages garées)

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 10032128 120064  89216 8675328  12  18    22    40  820 2150 12  6 80  2  0
 1  0 10032256 118720  89216 8675456   0   0     0     8  790 2080 10  5 84  1  0
 3  1 10110464  93248  89216 8629312 420  980   120   640 1100 3200 14  7 62 17  0
 2  1 10135680  90112  89216 8622336 510 1200   180   920 1180 3400 15  8 55 22  0
 1  0 10136576  95040  89216 8622912  10   40    16    88  840 2250 12  6 79  3  0

Ce que cela signifie : Regardez si/so (swap in/out) et wa (I/O wait). Les échantillons du milieu montrent de fortes E/S de swap et un wait élevé.
C’est du thrash, pas du swap bénin.
Décision : Identifiez qui force cela, et si la pression est globale ou à l’intérieur d’un cgroup.

Tâche 3 : Identifier les plus gros consommateurs résidents (RSS)

cr0x@server:~$ ps -eo pid,comm,rss,vsz,%mem --sort=-rss | head -n 12
  PID COMMAND           RSS    VSZ %MEM
 4121 java          18842340 25011240 29.6
 2337 postgres       9241120 10012560 14.5
 2875 python3        4021152  5120032  6.3
 1998 node           2568896  3101024  4.0
 1552 dockerd         812224  1887744  1.3
  911 systemd-journald 392448   566288 0.6

Ce que cela signifie : RSS est le « resident set », ce qui est réellement en RAM. VSZ inclut les mappings qui ne sont pas forcément résidents.
Si un processus domine le RSS, c’est votre principal suspect.
Décision : Pour les gros processus, vérifiez si la croissance mémoire est attendue (tas, cache) ou une fuite ; vérifiez aussi les limites cgroup.

Tâche 4 : Confirmer si vous utilisez cgroup v2 (commun sur Debian moderne)

cr0x@server:~$ stat -fc %T /sys/fs/cgroup/
cgroup2fs

Ce que cela signifie : cgroup v2 est actif. La pression mémoire peut se produire à l’intérieur d’une unité/conteneur même si l’hôte semble « ok », ou l’inverse.
Décision : Inspectez l’utilisation mémoire et les limites par unité ou conteneur.

Tâche 5 : Trouver les unités avec la pire pression mémoire via systemd

cr0x@server:~$ systemctl status --no-pager --full user.slice
● user.slice - User and Session Slice
     Loaded: loaded (/usr/lib/systemd/system/user.slice; static)
     Active: active since Mon 2025-12-29 08:12:10 UTC; 2h 21min ago
       Docs: man:systemd.special(7)
      Tasks: 246 (limit: 76800)
     Memory: 14.8G
        CPU: 1h 10min 32.920s
     CGroup: /user.slice
             ├─user-1000.slice
             │ ├─session-4.scope
             │ │ ├─4121 java
             │ │ └─...

Ce que cela signifie : systemd peut afficher la mémoire par slice. Si une slice ou un service gonfle, vous pouvez le contenir.
Décision : Approfondissez l’unité de service spécifique (ou le scope du conteneur) et vérifiez ses contrôles mémoire.

Tâche 6 : Inspecter les limites mémoire et l’utilisation actuelle pour une unité spécifique

cr0x@server:~$ systemctl show myapp.service -p MemoryCurrent -p MemoryPeak -p MemoryMax -p MemoryHigh -p ManagedOOMMemoryPressure
MemoryCurrent=20521447424
MemoryPeak=22231822336
MemoryMax=infinity
MemoryHigh=infinity
ManagedOOMMemoryPressure=auto

Ce que cela signifie : Pas de plafond mémoire. Si l’app grossit, elle poussera le système vers reclaim et swap.
Décision : Si c’est un hôte multi‑locataire, ajoutez des garde‑fous MemoryHigh/MemoryMax et définissez une politique OOM.

Tâche 7 : Lire la pression mémoire PSI (cela corrèle avec « tout est lent »)

cr0x@server:~$ cat /proc/pressure/memory
some avg10=18.42 avg60=12.01 avg300=6.55 total=922337
full avg10=3.21 avg60=1.70 avg300=0.62 total=120044

Ce que cela signifie : « some » est le temps pendant lequel au moins une tâche est bloquée sur la mémoire. « full » est le temps où le système est totalement bloqué (aucun progrès).
Ces valeurs sont assez élevées pour expliquer des pics de latence et des plaintes utilisateurs.
Décision : Traitez cela comme un problème de fiabilité, pas comme un simple réglage. Réduisez la pression ou appliquez des limites.

Tâche 8 : Vérifier les périphériques swap et leur priorité (un swap lent peut être fatal)

cr0x@server:~$ swapon --show --bytes
NAME       TYPE      SIZE        USED       PRIO
/dev/nvme0n1p3 partition 17179865088 10522624000 -2

Ce que cela signifie : Le swap est sur une partition NVMe, mais la priorité est basse (-2). Si vous avez aussi zram ou d’autres backends swap, la priorité compte.
Décision : Si le swap est inévitable, préférez un swap plus rapide (souvent zram pour les pics) et définissez les priorités de manière intentionnelle.

Tâche 9 : Observer les défauts de page majeurs et les fautes de swap par processus

cr0x@server:~$ pidstat -r -p 4121 1 3
Linux 6.12.0 (server)  12/29/2025  _x86_64_  (32 CPU)

09:41:10      UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
09:41:11     1000      4121   1200.00     35.00 25011240 18842340  29.6  java
09:41:12     1000      4121   1305.00     42.00 25011240 18850012  29.7  java
09:41:13     1000      4121   1104.00     38.00 25011240 18861020  29.7  java

Ce que cela signifie : Les défauts majeurs (majflt/s) signifient souvent des E/S disque pour ramener des pages — le swap‑in est une cause courante.
Des défauts majeurs soutenus avec activité de swap sont un indice fort de thrash.
Décision : Réduire le working set ou augmenter la RAM ; envisager aussi le réglage du heap et des limites mémoire.

Tâche 10 : Vérifier les stats de reclaim du noyau (est‑on en train de broyer le page cache ?)

cr0x@server:~$ egrep 'pgscan|pgsteal|pswpin|pswpout' /proc/vmstat | head
pgscan_kswapd 18223344
pgscan_direct 992311
pgsteal_kswapd 17199812
pgsteal_direct 801223
pswpin 621044
pswpout 1200033

Ce que cela signifie : Un pgscan_direct élevé suggère du reclaim direct (tâches bloquées). Un pswpin/out élevé indique du churn de swap.
Décision : Si le reclaim direct est significatif, la pression nuit à la latence. Priorisez la réduction du working set et l’ajout de limites ; le tuning de swappiness seul ne sauvera pas.

Tâche 11 : Vérifier swappiness et autres knobs VM (ne pas tuner aveuglément)

cr0x@server:~$ sysctl vm.swappiness vm.vfs_cache_pressure vm.dirty_ratio vm.dirty_background_ratio
vm.swappiness = 60
vm.vfs_cache_pressure = 100
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10

Ce que cela signifie : swappiness=60 est une valeur par défaut polyvalente. Sur des serveurs sensibles à la latence, elle peut être trop encline à swapper sous pression.
Les ratios dirty affectent les rafales de writeback ; un mauvais réglage peut créer une congestion E/S qui amplifie la douleur du swap.
Décision : Si vous observez du thrash réel (fort si/so), baissez la swappiness (avec précaution) et assurez‑vous que les settings dirty n’entraînent pas des vagues d’écriture.

Tâche 12 : Vérifier les réglages THP (peut gonfler l’empreinte et bloquer reclaim)

cr0x@server:~$ cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never

Ce que cela signifie : THP est activé « always ». Cela peut convenir, mais pour certaines charges (notamment certaines bases de données/cache) cela provoque des pics de latence ou une inflation mémoire.
Décision : Si vous observez des blocages de reclaim et une latence imprévisible, testez le passage à madvise (ou never) dans un environnement contrôlé.

Tâche 13 : Confirmer la corrélation entre iowait disque et E/S swap

cr0x@server:~$ iostat -xz 1 3
Linux 6.12.0 (server)  12/29/2025  _x86_64_  (32 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          12.10    0.00    6.50   18.40    0.00   63.00

Device            r/s     w/s   rKB/s   wKB/s  avgrq-sz avgqu-sz   await  svctm  %util
nvme0n1         85.00  140.00  9200.0 18000.0    210.0     4.20   18.50   0.45  92.00

Ce que cela signifie : %iowait est élevé et le NVMe est proche de la saturation. Les E/S de swap entrent en concurrence avec tout le reste et abiment les latences en queue.
Décision : Si le swap est sur le même périphérique que votre base de données ou vos logs, vous invitez des interférences. Séparez les périphériques ou réduisez le swap.

Tâche 14 : Vérifier le journal et les logs noyau pour OOM et événements de pression mémoire

cr0x@server:~$ journalctl -k --since "1 hour ago" | egrep -i 'oom|out of memory|memory pressure|kswapd' | tail -n 20
Dec 29 09:02:14 server kernel: oom_reaper: reaped process 4121 (java), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
Dec 29 09:02:14 server kernel: Out of memory: Killed process 4121 (java) total-vm:25011240kB, anon-rss:18842340kB, file-rss:10240kB, shmem-rss:0kB, UID:1000 pgtables:52000kB oom_score_adj:0

Ce que cela signifie : Si vous voyez des kills OOM, vous ne « avez pas réparé le swap », vous l’avez survécu. Notez aussi : l’OOM noyau est un dernier recours, souvent après un long thrash.
Décision : Mettez en place une politique (limites, oomd) pour échouer plus vite et de façon plus prévisible, et corrigez le dimensionnement/la fuite mémoire.

Tâche 15 : Si vous exécutez des conteneurs, inspectez les événements mémoire (l’assassin silencieux)

cr0x@server:~$ cat /sys/fs/cgroup/system.slice/docker.service/memory.events
low 0
high 1242
max 0
oom 0
oom_kill 0

Ce que cela signifie : Beaucoup d’événements « high » signifie que le groupe déclenche fréquemment le throttling de memory.high. Cela ressemble à une lenteur aléatoire.
Décision : Augmentez le seuil memory.high, réduisez la concurrence de la charge, ou corrigez l’empreinte du service. Le throttling est utile, mais reste douloureux.

Corrections qui aident réellement (et pourquoi)

Il existe deux catégories de « corrections » : structurelles et tactiques. Les corrections structurelles traitent la raison pour laquelle le working set ne tient pas en RAM. Les corrections tactiques réduisent le rayon d’impact
quand ça arrive de toute façon. Vous voulez les deux. Et vous voulez éviter le tuning cargo‑cult.

1) Mettre des garde‑fous mémoire là où le problème vit (unités systemd / cgroups)

Si un service peut bouffer l’hôte, il finira par le faire — par accident, par pic de trafic, ou par une fonctionnalité déployée à 16h55 un vendredi.
Sur Debian avec systemd, utilisez les contrôles mémoire au niveau des unités.

cr0x@server:~$ sudo systemctl edit myapp.service
[Service]
MemoryHigh=18G
MemoryMax=22G
ManagedOOMMemoryPressure=kill
ManagedOOMMemoryPressureLimit=20%

Comment y penser :
MemoryHigh signifie « commencer à appliquer de la pression » (reclaim/throttling). MemoryMax est l’arrêt dur. Si votre service ne survit pas au reclaim,
mieux vaut le tuer et le redémarrer que le laisser empoisonner tout le nœud.

2) Configurer systemd-oomd intentionnellement (ou le désactiver explicitement)

systemd-oomd n’est pas le OOM killer du noyau. C’est un moteur de politique basé sur des métriques de pression. Cela peut être fantastique — si vous le configurez pour votre topologie.
Cela peut aussi tuer la mauvaise chose si vous traitez les valeurs par défaut comme des évangiles.

cr0x@server:~$ systemctl status systemd-oomd --no-pager
● systemd-oomd.service - Userspace Out-Of-Memory (OOM) Killer
     Loaded: loaded (/usr/lib/systemd/system/systemd-oomd.service; enabled)
     Active: active (running) since Mon 2025-12-29 08:12:11 UTC; 2h 35min ago

Décision : Si vous gérez un hôte multi‑service, activer oomd avec des politiques par service correctes est généralement mieux que d’attendre l’OOM noyau.
Si vous exécutez un appareil mono‑usage avec un contrôle fort côté app, vous pouvez choisir de désactiver oomd pour éviter des kills surprises — mais alors vous devez avoir d’autres garde‑fous.

3) Baisser la swappiness pour les services sensibles à la latence (mais ne pas prétendre que c’est une solution)

vm.swappiness contrôle l’agressivité du noyau pour swapper la mémoire anonyme par rapport au reclaim du cache fichier.
Sur des serveurs où la latence compte plus que gratter chaque hit de cache, une swappiness plus basse peut aider à réduire le churn de swap.
Ce n’est pas une baguette magique qui rend un hôte sous‑dimensionné apte.

cr0x@server:~$ sudo sysctl -w vm.swappiness=10
vm.swappiness = 10
cr0x@server:~$ sudo tee /etc/sysctl.d/99-swappiness.conf >/dev/null <<'EOF'
vm.swappiness=10
EOF

Décision : Si vous observez du thrash réel (fort si/so), baisser la swappiness vaut la peine d’être testée.
Si vous observez un PSI « full » élevé et du reclaim direct, vous devez toujours réduire la demande mémoire ou appliquer des limites.

4) Corriger d’abord le plus gros working set : plafonner les heaps, tuner les caches, éviter le double‑caching

Le coupable le plus courant d’un « swap qui grossit sans fin » est une application avec un heap ou un cache élastique sans plafond.
Java, Node, Python avec cache agressif, et les bases de données peuvent tous se comporter ainsi.

  • Java : définissez -Xmx de façon réfléchie ; ne le laissez pas flotter jusqu’à « ce que l’OS permet ».
  • PostgreSQL : gardez shared_buffers raisonnable et souvenez‑vous que le page cache OS est déjà un cache.
  • Elasticsearch / caches : plafonnez la mémoire ; ne laissez pas le cache être « infini » simplement parce que l’hôte a du swap.

Le piège classique est le double‑caching : votre application met en cache des données dans le heap pendant que le noyau met en cache les mêmes données dans le page cache. Vous payez deux fois, puis vous swappez.
La hiérarchie mémoire n’est pas un buffet.

5) Envisager zram pour des pics intermittents (surtout sur petites VMs)

Si votre hôte est occasionnellement juste en mémoire, zram (swap compressé en RAM) peut absorber les pics sans marteler votre disque.
Ce n’est pas gratuit — la compression coûte du CPU — mais cela peut être un gain net quand la latence disque est l’ennemi principal.

cr0x@server:~$ sudo apt-get update
Hit:1 deb.debian.org stable InRelease
Reading package lists... Done
cr0x@server:~$ sudo apt-get install -y zram-tools
Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
  zram-tools
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.

Décision : Si le thrash de swap a lieu sur un disque lent ou un stockage partagé, zram peut être une bonne mitigation tactique.
Si vos charges sont déjà liées CPU, zram peut se retourner contre vous. Mesurez.

6) Placer le swap sur le bon stockage, avec les bonnes attentes

Le swap sur disques rotatifs est un voyage temporel vers 2009. Le swap sur blocs réseau est une aventure non souhaitée.
Le swap sur NVMe peut être acceptable, mais s’il partage le périphérique avec des bases critiques, il peut toujours détruire la latence en queue.

Bonnes pratiques :

  • Privilégiez un périphérique swap dédié ou au moins séparé des volumes DB WAL/logs intensifs.
  • Assurez‑vous que le swap est activé tôt et a la bonne priorité si plusieurs backends existent.
  • Dimensionnez correctement le swap. Si vous « avez besoin » d’un swap énorme pour rester en ligne, vous masquez un problème de capacité.

7) Ajuster le writeback dirty pour éviter les tempêtes d’I/O qui amplifient le mal du swap

Pression mémoire + rafales de writeback = mauvais moment. Si des pages dirty s’accumulent, le noyau finit par forcer le writeback, ce qui peut saturer les E/S juste quand le swap‑in en a besoin.
C’est ainsi que l’on obtient un serveur qui swappe et est « lent au hasard » même après l’arrêt de la croissance du swap.

cr0x@server:~$ sudo sysctl -w vm.dirty_background_ratio=5 vm.dirty_ratio=10
vm.dirty_background_ratio = 5
vm.dirty_ratio = 10

Décision : Des ratios plus bas peuvent lisser le writeback sur des systèmes avec des écritures en rafales et une sensibilité à la latence.
Mais ne touchez pas à cela isolément ; vérifiez le débit de stockage et les schémas d’écriture des applications.

8) Éviter « drop caches » comme habitude

Oui, echo 3 > /proc/sys/vm/drop_caches fera paraître la « mémoire libre » meilleure. Cela détruit aussi du cache utile et peut provoquer un effet de masse de rereads.
C’est un outil de dépannage ultime, pas une solution. Si vous en avez besoin chaque semaine, vous gérez un système de production sur des on‑dit.

9) Ne désactivez pas le swap sauf si vous êtes prêt à une mort abrupte

Désactiver le swap peut réduire le thrash, mais cela change le mode d’échec de « lent » à « tué ». Parfois c’est souhaitable. Souvent non.
Si vous désactivez le swap, vous devez avoir :

  • des limites mémoire strictes par service
  • une politique de redémarrage claire
  • des alertes sur l’approche des limites et sur PSI
  • un plan pour les pics de trafic

Petite blague #2 : Désactiver le swap pour résoudre la pression mémoire, c’est comme enlever le détecteur de fumée parce que le bip est ennuyeux.

10) Admettre quand la machine est trop petite

Si votre working set en état stable dépasse la RAM, vous allez soit swappez, soit bloquer, soit tuer des processus. Le tuning peut choisir quelle misère vous préférez ;
il ne réécrit pas l’arithmétique. Ajoutez de la RAM, réduisez la concurrence, shartez la charge, ou déplacez les services lourds hors du nœud.

Trois mini-histoires d’entreprise (comment ça échoue en pratique)

Mini‑histoire 1 : L’incident causé par une mauvaise hypothèse

Une équipe exécutait une API client sur des hôtes Debian avec « beaucoup de mémoire ». Ils avaient le swap configuré parce que « c’est plus sûr ».
Leurs tableaux suivaient le CPU, le taux de requêtes et l’utilisation disque. La mémoire n’était qu’une seule ligne : « free ».
Tout semblait correct la plupart du temps. Puis la latence doublait pendant dix minutes, plusieurs fois par jour, sans motif évident.

L’hypothèse erronée était subtile : ils croyaient que si l’hôte n’était pas out of memory, la mémoire n’était pas le problème.
L’utilisation du swap augmentait progressivement pendant les pics de trafic, mais comme rien ne plantait, cela n’alarmait pas.
Pendant ce temps, le noyau swappait des pages froides d’un service Java. Sous des rafales ultérieures, ces pages n’étaient plus froides.
Les swap‑in atterrissaient sur le même volume NVMe utilisé par le WAL de la base de données.

L’incident s’est manifesté comme « la base de données devient lente », parce que c’est ce que tout le monde voyait en premier : des requêtes en attente d’E/S et des verrous.
Mais la condition racine était la pression mémoire provoquant des E/S de swap, qui entraient en compétition avec le WAL et amplifiaient les latences en queue.
L’équipe a cherché des index et des pools de connexions pendant une semaine.

La correction n’était pas exotique. Ils ont ajouté des alertes basées sur PSI, baissé la swappiness, séparé le swap du volume base de données,
et — surtout — plafonné le heap Java et les caches en processus. Après cela, le swap est resté majoritairement stable,
et quand la pression est revenue, elle fut visible tôt au lieu d’être un mystère quotidien.

Mini‑histoire 2 : L’optimisation qui s’est retournée contre eux

Une autre organisation voulait « utiliser la mémoire efficacement » et a poussé pour maximiser le page cache pour des charges lecture‑lourdes.
Quelqu’un a suggéré d’augmenter la swappiness « pour que Linux garde le cache fichier chaud ». Ils ont aussi activé les Transparent Huge Pages partout
parce que « les pages plus grandes sont plus rapides ».

Sur le papier, c’était propre : plus de hits de cache, moins de lectures disque. En pratique, deux services partageaient l’hôte :
une API lourde en cache et un job batch qui montait en mémoire lors du traitement quotidien.
Avec une swappiness élevée, les pages anonymes étaient swappées agressivement sous pression ; avec THP, l’empreinte mémoire devint moins prévisible.
Le job batch déclenchait du reclaim ; le reclaim déclenchait du swap ; le swap volait de la bande passante I/O ; et l’API interactive en payait le prix.

La partie réellement douloureuse : l’optimisation améliorait le débit dans des benchmarks isolés.
Elle ne faillait qu’en conditions de charge mixte, ce qui est l’état par défaut des serveurs d’entreprise.
L’équipe voyait un « bon ratio de cache hit » et supposait le succès tandis que la latence client se dégradait.

Le rollback fut simple : remettre la swappiness à la baisse, passer THP en madvise, et déplacer le job batch dans un scope systemd avec un cap mémoire dur.
Ils cessèrent aussi de co‑localiser le traitement batch avec des API sensibles à la latence sur la même classe de nœud.
L’« optimisation » n’était pas mauvaise en soi ; elle était mal appliquée et sans limites.

Mini‑histoire 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Une équipe plateforme gérait une flotte de serveurs Debian hébergeant plusieurs services internes. Rien de glamour : logs, métriques, quelques API,
et quelques workers de fond. Ils avaient une règle ennuyeuse : chaque service obtient une unité systemd avec des frontières mémoire, et chaque nœud
exporte des métriques PSI avec des alertes. Pas d’exceptions. Les développeurs se plaignaient. Silencieusement, tout le monde se conformait.

Un après‑midi, un déploiement introduisit une fuite mémoire dans un worker Python. Le RSS monta lentement sur quelques heures.
Sur des hôtes sans garde‑fous, ce genre de fuite devient une panne au ralenti : le swap grossit, la latence augmente, on blame le réseau,
puis finalement quelque chose plante.

Ici, le worker a atteint MemoryHigh en premier et a commencé à être throttlé. PSI a grimpé pour l’unité, pas pour l’ensemble du nœud.
Des alertes ont déclenché avec un contexte clair : « unité worker en pression mémoire » plutôt que « l’hôte est lent ».
systemd-oomd a tué le worker quand la pression a dépassé la limite configurée. systemd l’a redémarré, restaurant le service.

Personne n’a célébré. C’est le but. Le système a dégradé de façon prévisible et s’est rétabli sans transformer tout le nœud en fournaise à swap.
Le travail de suivi fut ciblé : corriger la fuite, ajouter un test de régression, et garder les garde‑fous. L’ennuyeux a gagné. Encore.

Erreurs courantes : symptôme → cause racine → correctif

1) « Le swap utilisé est élevé, donc on est à court de mémoire »

Symptôme : Le swap est non nul ou croissant, mais le système semble ok.
Cause racine : Swap bénin : pages anonymes froides swappées ; pas de taux significatif de swap‑in.
Correctif : Vérifiez vmstat pour si/so et PSI. Si le swap‑in est proche de zéro et que PSI est bas, ne le touchez pas.

2) « On va régler ça en mettant swappiness=1 »

Symptôme : Le swap diminue, mais le système commence à OOMer ou à staller pendant le reclaim.
Cause racine : Le working set ne tient toujours pas ; vous avez simplement changé quelles pages sont sacrifiées. Une faible swappiness n’empêche pas la pression mémoire.
Correctif : Plafonnez la mémoire des applications, définissez memory.high/memory.max, réduisez la concurrence, ou ajoutez de la RAM. Utilisez swappiness comme réglage fin, pas comme parachute.

3) « Désactiver le swap et tout ira bien »

Symptôme : Plus de thrash lent, mais des kills et redémarrages soudains ; parfois l’OOM noyau tue le mauvais service.
Cause racine : Le mode d’échec a changé de « dégradé » à « abrupte ». Sans politique, c’est le chaos.
Correctif : Si vous désactivez le swap, imposez des limites par service et adoptez une politique de kill/restart prévisible (systemd-oomd ou supervision).

4) « C’est la performance disque ; réglons le système de fichiers »

Symptôme : Fort iowait, forte utilisation stockage, mais l’événement racine est la pression mémoire.
Cause racine : Les E/S de swap entrent en compétition avec les vraies E/S ; le disque semble coupable parce qu’il est utilisé comme RAM d’urgence.
Correctif : Réduisez d’abord le swap. Séparez le périphérique swap si besoin. Puis réévaluez le tuning du disque.

5) « On va juste drop caches »

Symptôme : Amélioration à court terme, puis pire performance et plus d’E/S.
Cause racine : Vous avez détruit un cache utile ; le système doit relire les données, augmentant les E/S et la pression.
Correctif : Ne le faites pas sauf en expérience contrôlée. Corrigez le dimensionnement et l’empreinte applicative.

6) « Le conteneur a une limite mémoire, donc l’hôte est protégé »

Symptôme : Le swap de l’hôte augmente ; un conteneur ralentit ; pas d’événements OOM clairs.
Cause racine : Throttling memory.high et reclaim à l’intérieur du cgroup ; le page cache de l’hôte et d’autres services continuent de concurrencer ; les limites n’empêchent pas la pression d’affecter les voisins.
Correctif : Configurez sensiblement memory.high et memory.max ; isolez les services bruyants ; surveillez cgroup PSI et memory.events.

7) « Le swap est lent car il est sur NVMe ; ça ne peut pas être ça »

Symptôme : Le NVMe est rapide mais la latence reste atroce sous swap.
Cause racine : Le swap‑in est sur le chemin critique ; l’ordonnancement et la contention nuisent aux latences en queue même sur des périphériques rapides.
Correctif : Arrêtez de swapper en réduisant le working set. Utilisez zram pour les pics si le CPU le permet. Séparez le swap des chemins I/O chauds.

Listes de contrôle / plan pas à pas

Checklist A : Quand vous êtes on‑call et que la machine est « lente »

  1. Exécutez free -h et enregistrez « available » et le swap utilisé.
  2. Exécutez vmstat 1 10. Si si/so flambe ou wa est élevé, suspectez du thrash swap.
  3. Lisez /proc/pressure/memory. Si « full avg10 » est non trivial, traitez comme incident.
  4. Vérifiez iostat -xz 1 3 pour voir si le swap sature votre disque principal.
  5. Trouvez les plus gros consommateurs RSS avec ps ; confirmez avec les métriques service/cgroup.
  6. Si un seul service est runaway : redémarrez‑le en sécurité et ajoutez une limite temporaire (MemoryHigh/Max) pour éviter la récidive.
  7. Ouvrez une tâche de suivi : plan de capacité, plafonds mémoire par service, et alertes PSI.

Checklist B : Correctifs permanents sur un hôte multi‑service Debian 13

  1. Inventoriez les services et définissez des frontières mémoire : MemoryHigh pour la pression douce, MemoryMax pour l’arrêt dur.
  2. Décidez d’une politique : utilisez systemd-oomd pour tuer les unités sous pression soutenue, ou gardez l’OOM noyau en dernier recours (non recommandé en multi‑tenant).
  3. Réglez la swappiness sur une valeur testée (souvent 10–30 pour les hôtes sensibles à la latence).
  4. Évaluez zram pour absorber les pics ; validez la marge CPU disponible.
  5. Placez le swap sur un stockage approprié ; évitez le partage avec DB/WAL intensifs.
  6. Validez le comportement THP ; passez en madvise si cela réduit les pics pour votre charge.
  7. Alertez sur PSI mémoire « some/full » et sur les taux swap‑in/out, pas seulement sur le swap utilisé.

Checklist C : Si vous suspectez une fuite

  1. Capturez la croissance RSS dans le temps : snapshots ps ou pidstat -r.
  2. Confirmez le comportement de swap‑in via les défauts majeurs : pidstat -r majflt.
  3. Ajoutez un cap mémoire dur pour éviter l’impact sur l’hôte pendant le debug.
  4. Redémarrez le service pour restaurer la stabilité ; rédigez un rapport d’incident avec preuves : tendance RSS, PSI, vmstat, et logs.

FAQ

1) L’utilisation du swap est‑elle toujours mauvaise ?

Non. C’est l’activité du swap qui vous tue. Si le swap utilisé est élevé mais que vmstat montre des si/so proches de zéro et que PSI est bas, c’est probablement acceptable.

2) Quel est le meilleur indicateur unique pour « la mémoire nuit à la latence » ?

La pression mémoire PSI (/proc/pressure/memory). Elle indique le temps pendant lequel les tâches sont bloquées. Elle corrèle mieux avec « les utilisateurs sont fâchés » que la « RAM libre ».

3) Dois‑je baisser la swappiness sur les serveurs Debian 13 ?

Souvent oui pour les services sensibles à la latence, mais seulement après avoir confirmé un thrash de swap. Commencez par 10–30, mesurez les swap‑in/out et PSI.
N’utilisez pas la swappiness pour masquer un working set surdimensionné.

4) Dois‑je désactiver complètement le swap ?

Seulement si vous acceptez des kills OOM abrupte et que vous avez des garde‑fous (limites par service, politiques de redémarrage et monitoring). Désactiver le swap peut améliorer la prévisibilité
pour certains clusters, mais ce n’est pas une mise à jour universelle.

5) Qu’est‑ce qui est mieux : l’OOM killer du noyau ou systemd-oomd ?

Pour les hôtes multi‑service, systemd-oomd avec des politiques d’unité explicites est souvent meilleur car il peut agir plus tôt en fonction de la pression et cibler l’unité appropriée.
L’OOM noyau est un dernier recours et peut abattre quelque chose de critique après des minutes de thrash.

6) Pourquoi les performances chutent‑elles même quand les E/S de swap ne sont pas massives ?

Reclaim direct et blocages. Le noyau peut passer du temps à scanner et récupérer des pages pendant que les tâches attendent. PSI « some/full » le montrera généralement.
La fragmentation et les interactions avec THP peuvent aussi contribuer.

7) Zram est‑il sûr pour des serveurs ?

Oui, lorsqu’il est utilisé délibérément. C’est excellent pour des pics de pression et pour des systèmes où le swap disque est lent ou disputé.
Cela coûte du CPU ; si vous êtes lié CPU, vous pouvez simplement déplacer le goulot d’étranglement.

8) Mon conteneur a une limite mémoire ; pourquoi l’hôte swappe ?

Parce que l’hôte gère encore la mémoire globale et peut swapper en raison de la pression totale. De plus, le throttling cgroup (memory.high) peut causer des lenteurs sans événements OOM.
Inspectez memory.events et PSI au niveau des unités.

9) Quelle quantité de swap pour un serveur Debian 13 ?

Assez pour gérer des pics courts et permettre un comportement ordonné, pas tellement que cela masque un sous‑dimensionnement chronique. Il n’y a pas de nombre universel.
Si vous vous appuyez régulièrement sur du swap profond, vous avez besoin de plus de RAM ou de working sets plus petits.

10) Pourquoi le swap continue d’augmenter et ne diminue jamais ?

Linux ne remet pas agressivement les pages en mémoire sauf si elles sont accédées. Si les pages swappées sont vraiment froides, elles restent swappées.
Ce n’est pas un bug. Ça devient un problème quand ces pages cessent d’être froides et que vous commencez à swaper‑in sous charge.

Conclusion : prochaines étapes pratiques

Si le swap monte et que les performances de Debian 13 chutent, traitez‑le comme ce que c’est : une pression mémoire qui se transforme en latence et en contention I/O.
Ne vous disputez pas avec le graphe de swap. Utilisez‑le comme un indice, puis prouvez le mode de défaillance avec l’activité de swap et PSI.

  1. Tout de suite : exécutez vmstat, free, PSI, et iostat. Décidez si vous avez du thrash ou du swap bénin.
  2. Dans l’heure : identifiez le plus gros consommateur RSS et s’il est borné par des cgroups/unités systemd.
  3. Dans la journée : ajoutez des garde‑fous mémoire (MemoryHigh/MemoryMax) et une politique OOM délibérée.
  4. Dans la semaine : corrigez le working set (taille heap/cache), évaluez zram pour les pics, et assurez‑vous que le placement du swap ne rivalise pas avec les I/O critiques.
  5. Toujours : alertez sur PSI et swap‑in/out, pas sur le swap utilisé. Vos utilisateurs subissent des blocages, pas des écritures comptables.

L’état final souhaité n’est pas « le swap est zéro ». C’est « la pression est visible, bornée et récupérable » — et la machine reste réactive quand ça compte.

← Précédent
VRAM Mythes : Quand 8/12/16 Go comptent et quand ce n’est qu’un chiffre
Suivant →
Versions des modules ZFS : éviter les conflits entre le noyau et ZFS

Laisser un commentaire