Les « gels aléatoires » de VM sur Proxmox ont un talent particulier : ils surviennent pendant la seule réunion où vous aviez promis que la plateforme était « stable maintenant ». L’invité cesse de répondre, la supervision se tait, puis — minutes plus tard — il revient comme si de rien n’était. Pas de crash. Pas de redémarrage. Juste un trou temporel et une confiance décroissante dans votre hyperviseur.
La plupart du temps, ce n’est pas une VM hantée. C’est un blocage de writeback au niveau de l’hôte : le noyau Linux laisse la mémoire sale s’accumuler, puis applique une forte limitation quand il doit enfin vidanger. Vos VM le ressentent comme un gel parce que les threads QEMU sont bloqués derrière des E/S hôtes et la pression de writeback mémoire. La correction est ennuyeuse et précise : ajustez les paramètres vm.dirty_* de l’hôte pour que le noyau commence à écrire plus tôt et limite moins violemment.
À quoi ressemble un « gel » (et ce que ce n’est pas)
Les gens parlent de « gel aléatoire de VM » parce qu’ils l’expérimentent côté invité : SSH ne répond plus, RDP se fige, les applications expirent, les agents de supervision cessent de rapporter, puis tout revient sans intervention. Mais, vu depuis l’hôte, ce n’est souvent pas aléatoire. C’est un arrêt prévisible déclenché par une vidange de pages sales accumulées, une rafale d’écritures synchrones ou un périphérique de stockage qui décide soudainement ce qu’il pense de la latence.
Le schéma classique
- Une ou plusieurs VM deviennent non réactives pendant des dizaines de secondes à quelques minutes.
- L’hôte Proxmox est « up » (le ping fonctionne, peut‑être même l’interface s’affiche) mais semble lent.
iowaitgrimpe ou l’utilisation CPU paraît étrangement basse pendant que tout est bloqué.- Les graphiques de stockage montrent un mur de latence : les IOPS chutent, la latence augmente.
- Après le blocage, tout « rattrape » son retard et les logs présentent un trou temporel.
Ce que ce n’est généralement pas
Avant d’accuser le writeback, éliminons les faux-fuyants habituels :
- Ce n’est pas forcément un panic du kernel invité. Ceux‑ci laissent des traces évidentes.
- Ce n’est pas toujours une exhaustion de RAM. La pression mémoire peut contribuer, mais le symptôme ici est la throttling des écritures par l’hôte.
- Ce n’est pas toujours que « ZFS est lent ». ZFS peut amplifier le problème si les écritures sync ou le slog sont en jeu, mais le mécanisme de blocage peut se produire sur ext4, XFS, Ceph, etc.
- Ce n’est pas (seulement) du steal CPU. Le steal nuit, mais un gel de plusieurs minutes avec une utilisation CPU minimale crie généralement « throttling I/O et congestion de writeback ».
Voici la vérité cynique : votre VM est un processus, et Linux mettra volontiers ce processus en attente pour protéger l’intégrité du stockage et empêcher le système de se noyer sous les données sales. Le noyau n’est pas méchant. Il est cohérent.
Blague n°1 : les « gels aléatoires » ressemblent aux problèmes DNS intermittents : ils sont toujours réels, et ils arrivent toujours quand vous essayez de prouver qu’ils n’existent pas.
La famille de paramètres noyau qui résout généralement le problème : vm.dirty_*
Si vous voulez un levier qui stoppe beaucoup de « gels » de VM Proxmox, c’est celui‑ci : réduire la quantité de mémoire sale que l’hôte peut accumuler avant de démarrer le writeback et avant d’appliquer du throttling.
Linux utilise la RAM comme tampon d’écriture. Quand un processus écrit dans un fichier, il écrit souvent d’abord dans le cache de pages (pages sales). Plus tard, le noyau vide ces pages sales sur le disque (« writeback »). C’est en général un gain de performance. Mais si le système laisse les pages sales s’accumuler trop, la vidange éventuelle peut devenir un événement violent : tempêtes de writeback, saturation des files d’attente du périphérique et throttling qui bloque les processus — y compris vos invités QEMU/KVM.
Les réglages qui comptent
vm.dirty_background_ratio/vm.dirty_background_bytes: moment où le writeback en arrière-plan démarre.vm.dirty_ratio/vm.dirty_bytes: moment où les processus en premier plan sont throttlés pour forcer le writeback.vm.dirty_expire_centisecs: combien de temps les données sales peuvent rester avant d’être considérées comme anciennes et devoir être vidangées.vm.dirty_writeback_centisecs: fréquence de réveil des threads flusher pour écrire les données sales.
Le piège courant sur Proxmox est que les valeurs par ratio par défaut augmentent avec la RAM. Hôte avec beaucoup de RAM ? Gros tampon dirty. Gros tampon + stockage lent ou en rafales ? Éventuellement, un blocage de writeback suffisamment grand pour geler les VM.
Pourquoi ça semble être un problème de VM
Parce que le disque virtuel de la VM vit sur le stockage de l’hôte, et que les threads I/O de QEMU sont juste des threads hôtes. Quand le noyau hôte décide « nous écrivons maintenant, et les autres attendront », vos invités attendent aussi. Votre application voit une pause. Votre SRE reçoit un pager. Votre CFO se demande « pourquoi on paie pour ça ? »
Une citation à garder sur son mur, parce qu’elle est douloureusement opérationnelle :
« L’espoir n’est pas une stratégie. » — James Cameron
Quand vous administrez des hyperviseurs, « espérer que le noyau vide en douceur » est exactement cela : de l’espoir.
Pourquoi Proxmox rend ce mode d’échec visible
Proxmox n’est pas particulièrement cassé ici. Il est juste honnête sur ce que vous avez construit : un système de stockage et de mémoire partagé qui multiplexe de nombreuses charges dans un même noyau. Ce noyau doit choisir des gagnants quand la contention arrive.
Multiplication de la rafale
Sur un serveur applicatif bare‑metal unique, une tempête de writeback signifie « l’application est lente ». Sur un hyperviseur, c’est « la moitié de l’entreprise est lente ». Vous agrégez des patterns d’I/O : bases de données faisant des fsync, expéditeurs de logs, mises à jour Windows, jobs de sauvegarde, couches de conteneur et le développeur du dimanche qui lance des benchmarks parce qu’il «avait besoin de chiffres».
La pile de stockage peut amplifier les blocages
Certaines configurations courantes sont performantes, mais elles rendent aussi les pauses catastrophiques :
- ZFS avec charges sync intenses : si les invités effectuent beaucoup d’écritures synchrones (bases de données, journaling, Windows), les pics de latence peuvent ressembler à des gels.
- Ceph pendant recovery/backfill : la variabilité de latence est la norme, et le writeback peut buter au pire moment possible.
- SSD grand public avec comportement de cache SLC : ils sprintent, puis marchent, puis rampent. Le cache de pages croit au sprint.
- Contrôleurs RAID avec politiques de cache : une cache d’écriture sans protection par batterie est une farce de latence prête à arriver.
Quand vous combinez « gros tampon RAM » + « réalité en rafales », l’hôte finit par appliquer la discipline. L’application de cette discipline est ce que vous ressentez comme un gel.
Playbook de diagnostic rapide (premier/deuxième/troisième)
Si vous n’avez que 10 minutes entre « quelque chose a gelé » et « c’est revenu », faites ceci dans l’ordre. Vous ne collectez pas des trivia. Vous décidez s’il s’agit de writeback/I/O, de pression mémoire ou de quelque chose d’autre.
Premier : confirmer que c’est I/O + writeback, pas un crash invité
- Consultez les logs hôte pour des tâches bloquées et des messages de writeback.
- Vérifiez si la mémoire dirty était élevée puis a chuté.
- Contrôlez la latence du stockage sur l’hôte pendant la fenêtre.
Deuxième : identifier ce qui est saturé (disque, contrôleur, stockage réseau)
- Exécutez
iostatet regardez%utilet la latence. - Vérifiez les files d’attente par périphérique ; un périphérique fautif peut geler tout si son journal/pool est bloqué.
- Confirmez si vous êtes sur ZFS, Ceph, LVM-thin ou fichiers simples. La « bonne » prochaine étape diffère.
Troisième : vérifier la pression mémoire et le comportement de swap de l’hôte
- Regardez
MemAvailable, swap in/out et si l’hôte fait un reclaim agressif. - Confirmez si le ballooning ou KSM n’ajoute pas de turbulence.
Si les preuves pointent vers des blocages de writeback, arrêtez de débattre et ajustez vm.dirty_*. Vous pouvez toujours chasser la charge qui a déclenché l’événement, mais d’abord il faut éviter que la plateforme se fige.
Tâches pratiques : commandes, sorties et décisions (12+)
Ceux‑ci sont des contrôles réels et exécutables sur un hôte Proxmox (basé Debian). Chaque tâche inclut : la commande, ce que signifie la sortie et la décision suivante. Exécutez-les en root ou avec sudo.
Task 1: Identify Proxmox and kernel version (context matters)
cr0x@server:~$ pveversion -v
proxmox-ve: 8.1.0 (running kernel: 6.5.13-5-pve)
pve-manager: 8.1.3
pve-kernel-6.5: 6.5.13-5
What it means: Kernel behavior and defaults vary. Knowing whether you’re on a PVE kernel and which series helps explain writeback and blk-mq behavior.
Decision: If you’re on an older kernel series and seeing blocked task bugs already fixed upstream, plan a kernel update after stabilizing settings.
Task 2: Check current dirty settings (the suspects)
cr0x@server:~$ sysctl vm.dirty_ratio vm.dirty_background_ratio vm.dirty_expire_centisecs vm.dirty_writeback_centisecs
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10
vm.dirty_expire_centisecs = 3000
vm.dirty_writeback_centisecs = 500
What it means: With 256 GB RAM, dirty_ratio=20 can allow ~51 GB of dirty cache before forced throttling. That’s not a buffer; that’s a lifestyle.
Decision: On big-memory hosts with shared storage, prefer *_bytes over ratios, or use much smaller ratios.
Task 3: See how much dirty memory is currently present
cr0x@server:~$ egrep -i 'dirty|writeback' /proc/meminfo
Dirty: 124812 kB
Writeback: 0 kB
WritebackTmp: 0 kB
What it means: “Dirty” is what’s waiting to be written. During a freeze event, you may see Dirty balloon and then collapse after writeback catches up.
Decision: If Dirty spikes into gigabytes during incidents, you’re a good candidate for stricter dirty thresholds.
Task 4: Look for blocked tasks and writeback stalls in the kernel log
cr0x@server:~$ journalctl -k -b --no-pager | egrep -i 'blocked|hung|writeback|congestion|task'
[ 2893.441122] INFO: task kvm:23144 blocked for more than 120 seconds.
[ 2893.441126] Tainted: P O 6.5.13-5-pve #1
[ 2893.441130] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 2893.441133] task:kvm state:D stack:0 pid:23144 ppid:1 flags:0x00004002
[ 2893.441140] Call Trace:
[ 2893.441150] __io_schedule+0x2d/0x60
[ 2893.441161] io_schedule+0x12/0x40
[ 2893.441170] bit_wait_io+0x11/0x60
[ 2893.441185] __wait_on_bit+0x4c/0x110
What it means: state:D is uninterruptible sleep, commonly I/O wait. If QEMU/KVM threads show up here, the VM is “frozen” because the host thread is stuck waiting on I/O.
Decision: If you see repeated blocked tasks tied to writeback or filesystem waits, prioritize writeback tuning and storage latency investigation.
Task 5: Check I/O latency and utilization quickly
cr0x@server:~$ iostat -x 1 5
Linux 6.5.13-5-pve (server) 02/04/2026 _x86_64_ (32 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
3.21 0.00 2.11 38.44 0.00 56.24
Device r/s w/s rkB/s wkB/s aqu-sz await svctm %util
nvme0n1 12.0 980.0 512.0 65536.0 45.12 46.8 0.9 92.5
What it means: High %iowait, high await, and high %util suggest the device is saturated and requests are queueing.
Decision: If await is tens/hundreds of ms during freezes, treat storage latency as a first-class incident. Dirty tuning helps, but you also need to reduce burstiness or upgrade the storage path.
Task 6: Confirm the storage backend for the VM disks
cr0x@server:~$ pvesm status
Name Type Status Total Used Available %
local dir active 19633960 2341232 16210228 11.92%
local-zfs zfspool active 191260672 84528128 106732544 44.19%
ceph-vm rbd active 0 0 0 0.00%
What it means: Knowing whether a VM lives on ZFS, Ceph RBD, or a directory-backed image changes where you look next.
Decision: If VMs are on ZFS and freezes correlate with sync-heavy workloads or scrubs, you’ll also evaluate ZFS settings and slog. If on Ceph, check cluster health and backfill.
Task 7: If ZFS: check pool health and latency suspects
cr0x@server:~$ zpool status -v
pool: rpool
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
rpool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
nvme0n1 ONLINE 0 0 0
nvme1n1 ONLINE 0 0 0
errors: No known data errors
What it means: A healthy pool doesn’t guarantee good latency, but an unhealthy pool guarantees bad days.
Decision: If you see degraded vdevs or resilvering, expect stalls and postpone performance tuning debates until redundancy is restored.
Task 8: If ZFS: check whether sync writes are being forced
cr0x@server:~$ zfs get -o name,property,value -s local,default sync rpool
NAME PROPERTY VALUE
rpool sync standard
What it means: sync=standard means ZFS honors O_SYNC/fsync semantics. If someone set sync=disabled, they “fixed” latency by deleting safety.
Decision: If sync=disabled is set on VM storage, revert it unless you’re comfortable explaining data loss to auditors.
Task 9: Check memory pressure and swap activity
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 251Gi 182Gi 6.2Gi 2.1Gi 63Gi 54Gi
Swap: 16Gi 3.1Gi 13Gi
What it means: If available is low and swap usage is growing fast during incidents, you might have a memory pressure problem that worsens writeback behavior.
Decision: If swapping is active on a Proxmox host, investigate ballooning and overcommit. But don’t confuse swap thrash with writeback stalls; they can co-exist.
Task 10: Catch real-time dirty/writeback changes during a stall
cr0x@server:~$ watch -n 1 'grep -E "Dirty|Writeback" /proc/meminfo; echo; vmstat 1 2 | tail -1'
Every 1.0s: grep -E Dirty|Writeback /proc/meminfo; echo; vmstat 1 2 | tail -1
Dirty: 8421120 kB
Writeback: 412512 kB
2 0 0 123456 789012 345678 0 0 20480 10240 38 4 56 2 0
What it means: Dirty in the multi-GB range plus sustained block I/O (bi/bo) and high wa indicates the system is flushing heavily.
Decision: If Dirty climbs until a “flush cliff” occurs, your dirty thresholds are too permissive for your storage reality.
Task 11: Inspect per-VM QEMU processes for D-state hints
cr0x@server:~$ ps -eo pid,stat,comm,args | egrep 'qemu-system|kvm' | head
23144 D qemu-system-x86 /usr/bin/kvm -id 103 -name vm103 ...
23188 S qemu-system-x86 /usr/bin/kvm -id 104 -name vm104 ...
What it means: D state for QEMU is consistent with uninterruptible I/O wait. One stuck VM can indicate a specific disk; many stuck VMs indicates shared storage saturation.
Decision: If many QEMU processes go D-state at once, stop blaming the guests. Focus on the host kernel + storage path.
Task 12: Check disk scheduler and queue settings (context, not a silver bullet)
cr0x@server:~$ for d in nvme0n1 nvme1n1; do echo "== $d =="; cat /sys/block/$d/queue/scheduler; cat /sys/block/$d/queue/nr_requests; done
== nvme0n1 ==
[mq-deadline] kyber none
1024
== nvme1n1 ==
[mq-deadline] kyber none
1024
What it means: Modern kernels use blk-mq. Schedulers matter less than they used to, but queue depth can still influence latency under burst.
Decision: Don’t “tune” schedulers randomly. If you change these, do it with measurement and a rollback plan. Your first lever remains dirty writeback thresholds.
Task 13: Check whether you’re using ratios or bytes (avoid scaling surprises)
cr0x@server:~$ sysctl vm.dirty_bytes vm.dirty_background_bytes
vm.dirty_bytes = 0
vm.dirty_background_bytes = 0
What it means: 0 means the ratio settings are active. On large RAM, ratios can be too generous.
Decision: Consider switching to bytes-based thresholds to keep behavior consistent across hosts.
Task 14: Validate that writeback threads are doing work (and not stuck)
cr0x@server:~$ ps -eo pid,stat,comm | egrep 'flush|writeback|kworker' | head -n 10
157 S flush-8:0
158 S flush-8:16
612 S kworker/u64:3
948 S kworker/u64:7
What it means: Flush threads exist per backing device. If they’re present but the system still stalls, the bottleneck is usually the device latency or queueing, not “missing threads.”
Decision: If the host stalls and you see blocked tasks waiting on I/O, focus on lowering dirty thresholds and reducing burstiness.
Task 15: Confirm what changed recently (because it always did)
cr0x@server:~$ journalctl --since "24 hours ago" --no-pager | egrep -i 'apt|kernel|zfs|ceph|firmware' | head -n 30
Feb 04 01:12:03 server apt[11902]: upgrade zfsutils-linux:amd64 2.2.2-pve1 to 2.2.3-pve1
Feb 04 01:12:10 server apt[11902]: upgrade pve-kernel-6.5.13-4-pve to 6.5.13-5-pve
What it means: Kernel and storage stack updates can change writeback behavior, defaults, and performance regressions.
Decision: If freezes began after an update, don’t roll back blindly. Capture evidence, tune writeback, and then evaluate regressions with controlled tests.
Valeurs recommandées (valeurs sûres et quand dévier)
Vous voulez un writeback plus précoce et plus régulier. Cela signifie des seuils plus bas et un flush en arrière-plan plus fréquent. L’objectif n’est pas « débit maximal ». L’objectif est la stabilité de la latence pour que les VM ne se figent pas comme si elles avaient heurté un nid-de-poule à grande vitesse.
Ma recommandation par défaut pour les hôtes Proxmox
Préférez des seuils basés sur les octets. Ils se comportent de la même façon sur un nœud 64 GB et sur un nœud 512 GB, ce que vous voulez dans un cluster.
vm.dirty_background_bytes: 268435456 (256 MB)vm.dirty_bytes: 1073741824 (1 GB)vm.dirty_expire_centisecs: 3000 (30 secondes)vm.dirty_writeback_centisecs: 100 (1 seconde)
Ce sont des valeurs conservatrices. Elles empêchent le cache dirty de devenir une bombe temporelle de plusieurs Go. Si vous avez un stockage exceptionnellement rapide avec une latence stable (bon NVMe entreprise, Ceph bien cadré avec marge), vous pouvez les augmenter. Si vous avez des SSD grand public, un stockage réseau à latence variable ou des charges mixtes (bases de données + sauvegardes), gardez‑les basses.
Quand les ratios sont acceptables
Si vous insistez pour utiliser des ratios, utilisez des valeurs beaucoup plus petites que les défauts sur des hôtes à grande RAM :
vm.dirty_background_ratio: 3–5vm.dirty_ratio: 8–12
Mais comprenez l’échelle : 10 % de 512 GB, c’est beaucoup de données sales à vidanger quand votre stockage décide de faire du ménage.
Remarque sur « corriger » en désactivant la sécurité
Si vous voyez des conseils pour définir ZFS sync=disabled pour éliminer les pauses, ce n’est pas du tuning. C’est renoncer à la durabilité des données. Vous aurez peut‑être une latence plus faible. Vous aurez aussi des corruptions de base de données « surprenantes » après un événement d’alimentation. Choisissez ce que vous pouvez accepter. La plupart des entreprises ne peuvent pas accepter cela.
Blague n°2 : désactiver les écritures synchrones pour « résoudre les performances » revient à enlever les ceintures de sécurité pour alléger la voiture. Techniquement vrai, spirituellement maudit.
Appliquer la correction et la rendre persistante
Faites-le en direct d’abord (pour observer l’impact), puis rendez‑le persistant. Les hôtes Proxmox sont en production ; traitez‑les comme tels : contrôle des changements, fenêtre de maintenance si nécessaire, et plan de retour arrière.
Appliquer temporairement (effet immédiat)
cr0x@server:~$ sysctl -w vm.dirty_background_bytes=268435456
vm.dirty_background_bytes = 268435456
cr0x@server:~$ sysctl -w vm.dirty_bytes=1073741824
vm.dirty_bytes = 1073741824
cr0x@server:~$ sysctl -w vm.dirty_writeback_centisecs=100
vm.dirty_writeback_centisecs = 100
cr0x@server:~$ sysctl -w vm.dirty_expire_centisecs=3000
vm.dirty_expire_centisecs = 3000
What it means: The host will start background flushing at ~256 MB dirty and throttle harder around 1 GB dirty, rather than tens of GB.
Decision: Watch for improved latency stability under bursty writes. If throughput drops slightly but freezes stop, that’s a win on hypervisors.
Persist across reboots
Create a dedicated sysctl drop-in. Don’t jam it into random files you’ll forget in six months.
cr0x@server:~$ cat > /etc/sysctl.d/99-proxmox-writeback.conf <<'EOF'
# Proxmox host writeback tuning to reduce VM stalls under bursty IO
vm.dirty_background_bytes = 268435456
vm.dirty_bytes = 1073741824
vm.dirty_writeback_centisecs = 100
vm.dirty_expire_centisecs = 3000
EOF
cr0x@server:~$ sysctl --system
* Applying /etc/sysctl.d/99-proxmox-writeback.conf ...
vm.dirty_background_bytes = 268435456
vm.dirty_bytes = 1073741824
vm.dirty_writeback_centisecs = 100
vm.dirty_expire_centisecs = 3000
What it means: Settings are now part of boot configuration.
Decision: Record this change in your infra repo or ticketing system. Future you deserves receipts.
Confirm ratios are no longer active
cr0x@server:~$ sysctl vm.dirty_ratio vm.dirty_background_ratio vm.dirty_bytes vm.dirty_background_bytes
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10
vm.dirty_bytes = 1073741824
vm.dirty_background_bytes = 268435456
What it means: Ratios may still show values, but bytes take precedence when non-zero.
Decision: Leave ratio values alone unless you want to standardize configs; the effective behavior is bytes-based now.
Erreurs courantes : symptômes → cause racine → correctif
1) Symptom: VM freezes for 30–180 seconds, then recovers; host shows high iowait
Root cause: Dirty page accumulation leads to writeback storm; QEMU threads blocked in D-state.
Fix: Reduce dirty thresholds (prefer vm.dirty_background_bytes and vm.dirty_bytes), increase writeback frequency (vm.dirty_writeback_centisecs=100), verify storage latency.
2) Symptom: Freezes correlate with backups or vzdump windows
Root cause: Backup jobs create write bursts (temporary files, compression, snapshot activity) that overflow page cache and saturate storage.
Fix: Writeback tuning + stagger backups + cap backup I/O via storage-level QoS if available. Also verify backup target latency.
3) Symptom: “Fix” attempted by setting ZFS sync=disabled, freezes reduce, later data integrity scares appear
Root cause: Latency was masked by removing synchronous durability; application assumptions break after power loss or crash.
Fix: Restore sync=standard. If sync latency is real, add proper SLOG on power-loss-protected media or move sync-heavy workloads to appropriate storage.
4) Symptom: Only one VM freezes, others are fine; host not obviously in trouble
Root cause: That VM is hammering a specific volume, sparse file, or storage path; could be a single RBD image, a single ZVOL, or a single disk in a pool causing retries.
Fix: Check per-device latency (iostat -x), per-VM disk stats, and storage health. Dirty tuning still helps overall, but isolate the hot spot.
5) Symptom: Host stays responsive, but guest clocks jump and apps time out
Root cause: Guest vCPU threads are stalled; timekeeping catches up when the VM runs again.
Fix: Same core fix: reduce host writeback stalls. Also verify guest agent/clocksource configuration if time drift becomes chronic.
6) Symptom: Freezes appear after “performance optimization” that increased cache or RAM usage
Root cause: More RAM means ratios allow more dirty data; flush events become larger and less predictable.
Fix: Switch to bytes-based dirty thresholds. Stability beats theoretical throughput on a hypervisor.
7) Symptom: Ceph-backed VMs freeze during recovery/backfill
Root cause: Backend latency spikes cause host writeback to backlog and then throttle.
Fix: Writeback tuning on hypervisors plus Ceph recovery tuning and capacity headroom. Don’t pretend the hypervisor can paper over a saturated cluster.
Trois mini-récits d’entreprise
Mini-récit n°1 : L’incident causé par une mauvaise hypothèse
L’équipe venait de rafraîchir ses nœuds Proxmox : plus de cœurs, plus de RAM, même baie de stockage. Ils ont supposé que la mise à jour n’apporterait que des améliorations. Et pendant une semaine, c’était vrai. Puis les « gels aléatoires » ont commencé. Pas quotidiennement. Pas toutes les heures. Juste assez pour être imputés à « cette vieille appli ».
L’hypothèse erronée était subtile : ils croyaient que si la baie de stockage supportait des pointes dans des benchmarks synthétiques, elle supporterait aussi les rafales en production. Les benchmarks étaient propres. La production avait des sauvegardes, des rotations de logs et une base qui checkpoints aux pires moments.
Pendant une fenêtre de gel, l’hôte n’était pas down. Il attendait. Les logs du noyau montraient des threads QEMU bloqués. /proc/meminfo montrait Dirty en dizaines de gigaoctets juste avant la fin du blocage. La grosse montée en RAM avait augmenté la taille du tampon dirty parce que le système utilisait des valeurs basées sur des ratios.
Ils sont passés à des seuils basés sur les octets et ont activé un flush background agressif. Les gels ont cessé. Le débit dans les benchmarks a légèrement baissé. Personne ne s’en est soucié, parce que la plateforme avait arrêté de faire des voyages temporels pendant les heures de travail.
Mini-récit n°2 : L’optimisation qui s’est retournée contre eux
Un autre groupe a voulu jouer les malins avec le tuning. Ils ont constaté que les pics de latence de stockage coïncidaient avec des écritures sync invitées, alors ils ont appliqué la « solution » classique : mettre ZFS sync=disabled sur le dataset qui héberge les disques VM. Immédiatement, les graphiques étaient magnifiques. Les « gels » semblaient disparus. Le ticket de tuning a été fermé avec un commentaire fier sur « avoir débloqué les performances de ZFS ».
Deux mois plus tard, un incident d’alimentation a touché une partie de la baie. Les UPS ont fonctionné, en général. Un nœud n’a pas fermé proprement. Plusieurs VM sont revenues avec des bases de données malheureuses. Pas toutes ; juste assez pour une revue d’incident avec des questions désagréables.
Le retour de bâton n’était pas que ZFS soit peu fiable. ZFS a fait exactement ce qu’on lui avait demandé : il a ack les écritures sync avant qu’elles ne soient durables. L’équipe avait troqué la stabilité de latence contre la durabilité, puis a été surprise quand la physique a porté plainte.
La récupération a combiné le rétablissement de sync=standard, l’ajout de dispositifs de log protégés contre la perte de puissance pour les charges qui avaient vraiment besoin de sync, et — oui — le tuning vm.dirty_* pour éviter que l’hôte ne construise d’énormes falaises de writeback.
Mini-récit n°3 : La pratique ennuyeuse mais correcte qui a sauvé la mise
Une troisième organisation gérait un cluster Proxmox pour des services internes. Rien de glamour : ticketing, runners CI, quelques VM Windows pour des outils de licence. Ils faisaient une chose ennuyeuse de manière cohérente : un profil sysctl hôte de base appliqué via la gestion de configuration, incluant le tuning de writeback. Chaque nœud ressemblait au même état au jour 1.
Un trimestre, ils ont ajouté une nouvelle charge : un pipeline de données qui écrivait de gros fichiers séquentiels puis faisait des rafales de mises à jour de métadonnées. La charge était bruyante et augmentait l’utilisation du stockage. Mais elle n’a pas provoqué de « gels aléatoires ». Les seuils dirty empêchaient les événements de vidange massifs ; le writeback s’exécutait en continu en arrière‑plan.
Quand un nouveau nœud a été construit à la hâte durant une extension, quelqu’un a oublié d’appliquer le profil de base. Ce nœud a commencé à geler des VM sous la nouvelle charge pipeline. L’équipe n’a pas passé des jours à débattre des fournisseurs de stockage. Ils ont comparé les sysctls entre nœuds, vu le profil manquant, l’ont appliqué et ont continué leur vie.
Ce n’était pas héroïque. C’était correct. Le meilleur incident est celui auquel vous n’êtes pas invité.
Checklists / plan étape par étape
Étape par étape : stabiliser un nœud Proxmox qui gèle en production
- Capturer des preuves immédiatement : extrait de log noyau avec tâches bloquées ; valeurs Dirty/Writeback ; sortie
iostat -xpendant le blocage. - Confirmer le backend de stockage : ZFS vs Ceph vs LVM-thin vs images dir. Ne pas dépanner à l’aveugle.
- Appliquer un tuning temporaire de writeback : définir des seuils en octets et un intervalle writeback plus court.
- Observer pendant un cycle de charge : sauvegardes, jobs batch ou la fenêtre qui déclenchait avant les gels.
- Rendre les réglages persistants : drop-in sysctl, gestion de configuration et enregistrement du changement.
- Réduire la rafale : échelonner les sauvegardes, limiter la concurrence, éviter que toutes les VM flushent en même temps.
- Valider la marge de latence du stockage : si
awaitreste élevé, vous avez toujours un problème de stockage. Le tuning évite des falaises ; il ne rend pas les disques lents rapides. - Revue post-incident : identifier la charge qui vous a fait basculer et décider de l’isoler, de la brider ou de la déplacer.
Checklist : ce qu’il faut standardiser sur un cluster Proxmox
- Seuils dirty basés sur les octets (éviter les surprises liées à la taille de la RAM).
- Série de noyau cohérente entre nœuds (ne pas mélanger les comportements).
- Politique d’ordonnancement des sauvegardes (échelonner, limiter la concurrence).
- Surveillance du stockage axée sur la latence, pas seulement le débit.
- Position documentée sur le comportement ZFS sync (pas de désactivation ad hoc).
- Politique swap et ballooning des hôtes documentée.
Plan de retour arrière (parce que vous êtes adulte)
- Garder une copie des valeurs sysctl précédentes (ou exporter un snapshot
sysctl -apour le sous‑ensemble vm.*). - Si la performance est inacceptable, augmentez
vm.dirty_bytesprogressivement (par ex. 1 GB → 2 GB) plutôt que de revenir aux ratios d’un coup. - Si l’hôte gèle encore, le chemin de stockage est probablement saturé ou défaillant ; poursuivez le diagnostic de latence tout en gardant des seuils conservateurs.
Faits intéressants & historique (parce que les noyaux ont la mémoire longue)
- Le writeback Linux est une zone de bataille récurrente depuis les jours de 2.4/2.6 ; l’équilibre débit vs latence évolue avec le matériel.
- Le cache de pages « dirty » existe parce que le disque est lent, mais il devient dangereux quand le disque est imprévisible—comme les SSD en GC.
- Les valeurs par ratio augmentent avec la RAM, ce qui avait du sens quand les serveurs avaient beaucoup moins de mémoire ; aujourd’hui cela peut créer des flushs de plusieurs Go.
- Les avertissements « blocked task » sont la façon dont Linux vous dit : des threads sont coincés en sommeil ininterruptible, généralement en attente d’I/O.
- Les noyaux modernes utilisent blk-mq (multi-queue), ce qui change le comportement des files et des ordonnanceurs par rapport aux anciennes conceptions à file unique.
- NVMe a rendu le débit bon marché, mais n’a pas supprimé la latence de queue ; c’est la latence extrême qui fige les VM.
- ZFS met l’accent sur l’intégrité des données ; le tuner pour la vitesse en désactivant les semantics sync n’est pas anodin—ça change la correction.
- Les piles de virtualisation amplifient la contention parce que de nombreuses charges partagent les politiques I/O et mémoire d’un seul noyau ; le tuning hôte compte plus que sur un serveur mono‑usage.
- Le tuning writeback est un classique SRE : vous ne tunez pas une application ; vous modelez le comportement système sous charge pour éviter des défaillances en cascade.
FAQ
1) Is vm.dirty_* really “one setting”?
C’est un seul sous‑système avec plusieurs réglages. En pratique, utiliser des seuils basés sur les octets plus un intervalle de writeback plus court est le changement hôte le plus impactant pour ces motifs de gel.
2) Will this fix every Proxmox freeze?
Non. Cela corrige une classe courante : les blocages de writeback hôte et la congestion I/O qui bloquent les threads QEMU. Si vous avez de la contention CPU, des erreurs PCIe, des firmwares défaillants ou un disque mourant, cela ne les réparera pas magiquement.
3) Should I use dirty_ratio or dirty_bytes?
Sur les hyperviseurs, utilisez dirty_bytes et dirty_background_bytes. Les ratios varient avec la RAM et provoquent des comportements incohérents entre nœuds de tailles différentes.
4) Won’t smaller dirty thresholds reduce performance?
Parfois, oui—le débit de pointe peut chuter parce que vous vidangez plus continuellement. Sur un hyperviseur, c’est généralement un bon compromis : la stabilité de latence vaut mieux que des falaises occasionnelles qui figent plusieurs VM.
5) What values should I start with?
Commencez par dirty_background_bytes=256MB, dirty_bytes=1GB, dirty_writeback_centisecs=100, dirty_expire_centisecs=3000. Ajustez ensuite en fonction de la latence observée et de la rafale des charges.
6) Does this interact with ZFS ARC?
Oui, indirectement. L’ARC et le page cache utilisent tous deux la RAM. L’ARC de ZFS n’est pas le cache de pages Linux, mais la dynamique de pression mémoire peut quand même affecter le writeback. Le tuning ici cible le writeback des pages sales Linux, pas l’ARC.
7) What about Ceph-backed VMs?
Toujours pertinent. L’hôte met toujours en cache et écrit. La variabilité de latence Ceph peut déclencher des arriérés plus importants et un throttling plus sévère. Tuning writeback et garantir que le cluster Ceph dispose de marge et n’est pas en récupération constante.
8) Should I disable swap on the Proxmox host?
Ne le désactivez pas aveuglément. Une petite quantité de swap peut être un filet de sécurité, mais un swap actif en conditions normales indique généralement un overcommit ou des problèmes de ballooning. Traitez la cause, ne masquez pas le symptôme.
9) Can I set vm.dirty_writeback_centisecs too low?
Oui. Des valeurs extrêmement basses peuvent augmenter l’activité de flush background et l’overhead. 100 (1 seconde) est un point de départ pragmatique pour les hyperviseurs ; mesurez et ajustez si nécessaire.
10) How do I prove the tuning worked?
Mesurez avant/après : fréquence et durée des blocages, iostat await tail latency pendant les rafales, comportement Dirty/Writeback pendant les fenêtres de sauvegarde, et si les threads QEMU atteignent encore l’état D lors d’incidents.
Prochaines étapes à faire cette semaine
- Implémentez des seuils dirty basés sur les octets sur un nœud Proxmox, observez pendant un cycle complet de sauvegarde, puis déployez sur l’ensemble du cluster.
- Ajoutez un script de capture d’incident rapide (même un snippet shell) qui enregistre :
iostat -x, compteurs Dirty de/proc/meminfoet lignes de log noyau pertinentes quand des gels sont signalés. - Auditez votre position sur la durabilité du stockage : si quelqu’un a « corrigé les performances » avec
sync=disabled, rétablissez et concevez une vraie solution (SLOG, placement de charges ou montée en gamme du stockage). - Planifiez les jobs rafales (sauvegardes, scrubs, réplications) pour qu’ils ne se synchronisent pas comme une chorégraphie de natation synchronisée.
- Fixez les attentes en interne : les hyperviseurs sont des systèmes sensibles à la latence. Optimisez pour la latence tail et la prévisibilité, pas seulement le débit affiché.
Si vous ne faites qu’une chose : définissez vm.dirty_background_bytes et vm.dirty_bytes sur des valeurs sensées. Cette famille de « paramètres noyau » est souvent la différence entre des « gels aléatoires » et une plateforme en laquelle on peut avoir confiance.