Dépannage de la performance Proxmox : CPU steal, IO wait, ARC ZFS et voisins bruyants

Cet article vous a aidé ?

Les problèmes de performance sur Proxmox ne se présentent presque jamais sous la forme d’une erreur nette et unique. Ils se manifestent par « la base de données rame », « le RDP est saccadé », « les nœuds Kubernetes se déconnectent », ou « pourquoi la charge de l’hôte est à 60 alors que le CPU est à 10 % ? » Vous obtiendrez des graphiques contradictoires et des théories très assurées de chacun dans la pièce.

Voici un guide de terrain pour rompre l’impasse. Nous allons séparer le CPU steal de l’IO wait, relier le comportement de l’ARC ZFS à la latence réelle, et traquer la VM voisine bruyante qui transforme votre nœud en micro-ondes d’open space.

Playbook de diagnostic rapide

Vous n’avez pas besoin d’un tableau de bord à 40 volets pour trouver le goulot. Vous avez besoin des trois bonnes vérifications, dans le bon ordre, avec la discipline d’arrêter de deviner.

Première étape : confirmer quel type de « lenteur » c’est (contention CPU vs stockage vs pression mémoire)

  • L’hôte semble lent mais le CPU paraît faible : suspectez IO wait, steal time ou reclamation mémoire (swap/kswapd).
  • Le CPU invité est saturé mais le CPU hôte ne l’est pas : suspectez limites CPU, steal time ou incompatibilité de topologie vCPU.
  • Tout va bien jusqu’à ce qu’une sauvegarde/réplication démarre : suspectez saturation IO et comportement des transaction groups ZFS.

Deuxième étape : identifier le limiteur sur l’hôte (one-liners qui ne mentent pas)

Exécutez ces commandes sur le nœud Proxmox :

  • Snapshot CPU + steal + iowait : mpstat -P ALL 1 5
  • Pression mémoire / swap / reclaim : vmstat 1 10
  • Latence disque et mise en file : iostat -x 1 10
  • Comportement du pool ZFS : zpool iostat -v 1 10

Troisième étape : relier au workload ou à la VM coupable

  • VM(s) au top CPU : qm list + ps -eo pid,cmd,%cpu --sort=-%cpu | head + corréler les PIDs QEMU
  • VM(s) au top IO : iotop -oPa et pvesh get /nodes/$(hostname)/qemu --output-format json
  • Principal auteur de pression mémoire : métriques de ballooning et swap hôte, plus « qui alloue le page cache »

Si vous ne faites qu’une chose : choisissez un hôte, une fenêtre de 10 minutes, et capturez les snapshots ci‑dessus. C’est votre vérité terrain. Tout le reste n’est que spéculation.

Un modèle mental qui vous garde honnête

Les problèmes de performance Proxmox sont généralement l’une des quatre choses :

  1. Contention CPU : les vCPU veulent tourner ; le planificateur ne peut pas leur donner du temps. Sur une VM vous verrez souvent cela comme du steal time.
  2. Latence stockage : les CPU sont inactifs parce que les threads attendent le disque. C’est de l’IO wait, et ce n’est pas un problème CPU — c’est un problème de canalisation de stockage.
  3. Pression mémoire : ARC, page cache, mémoire anonyme et ballooning se disputent la RAM. Si l’hôte swappe, tout devient « mystérieusement lent ».
  4. Effets de voisin bruyant : une VM sature l’IO, inonde le CPU d’interruptions, ou déclenche une amplification d’écriture ZFS pathologique qui pénalise tout le monde.

L’astuce est d’éviter de mélanger les symptômes. La load average inclut les tâches exécutables et les tâches bloquées en sommeil ininterrompu. C’est pourquoi vous pouvez avoir une charge de 40 et un CPU majoritairement au repos. Ce n’est pas « Linux qui ment ». C’est vous qui posez une question vague et obtenez une réponse honnête.

Une citation à coller sur votre écran : Paraphrase d’une idée de Deming : sans données, vous n’êtes qu’une autre personne avec une opinion. C’est douloureusement pertinent quand trois équipes se disputent pour savoir si « c’est le réseau ».

Faits et historique intéressants à utiliser

  1. Le steal time est né à l’aube de la virtualisation pour quantifier la fréquence à laquelle un invité était exécutable mais l’hyperviseur en planifiait un autre. C’est un compteur de dette de planification, pas un bug invité.
  2. La load average Linux précède les piles IO modernes ; elle compte les tâches en état D (sommeil ininterrompu), donc une forte latence stockage gonfle la load même si les CPU dorment.
  3. L’ARC ZFS n’est pas « juste un cache ». C’est un consommateur de mémoire auto-ajustable avec plusieurs listes (MRU/MFU et compagnons), et il prendra volontiers la RAM jusqu’à ce que quelque chose le force à se restreindre.
  4. ZFS a été conçu d’abord pour l’intégrité des données (copy-on-write, sommes de contrôle, sémantique transactionnelle). Le tuning de performance est réel, mais il paie toujours un tribut pour l’intégrité.
  5. Les IOPS sont devenus une métrique business à cause de la virtualisation : quand de nombreux flux IO aléatoires partagent des disques, le débit cesse d’être le goulot et la latence domine.
  6. L’amplification d’écriture n’est pas qu’un problème SSD. Les systèmes de fichiers copy-on-write peuvent aussi amplifier les écritures, surtout avec de petits writes synchrones et la fragmentation.
  7. Virtio n’était pas le défaut au début. Les pilotes paravirtualisés ont été introduits pour éviter le surcoût d’émulation ; utiliser un mauvais modèle de disque/contrôleur nuit encore aujourd’hui.
  8. La mise à l’échelle de fréquence CPU peut imiter une « performance aléatoire ». Si les gouverneurs baissent trop la fréquence, votre « même charge » devient différente chaque minute.
  9. Le ballooning a résolu l’économie de l’overcommit mais introduit un nouveau mode de panne : l’hôte semble « correct » pendant que les invités thrashent, parce que la douleur est déléguée.

CPU steal : quand les invités sont prêts mais ne peuvent pas tourner

CPU steal est le temps pendant lequel le vCPU d’une VM voulait s’exécuter mais n’a pas pu parce que le planificateur hôte (ou une autre couche) ne l’a pas planifié. Sur du bare metal, le steal est à peu près nul. En virtualisation, le steal est une confession : « je suis en contention ».

Comment le steal se manifeste (et comment il vous trompe)

  • À l’intérieur d’une VM, top montre un %st élevé, mais %us n’est pas fou.
  • Les applications expirent alors que les graphiques d’utilisation CPU semblent modérés.
  • La latence interactive est mauvaise : les frappes SSH répondent lentement, les cron s’exécutent en retard.

Le steal n’est pas « la VM qui utilise trop de CPU ». C’est « la VM qui n’obtient pas le CPU quand elle en a besoin ». Cette distinction compte quand vous décidez d’ajouter des cœurs, de déplacer des VMs ou d’arrêter l’overcommit.

Causes courantes de steal sur Proxmox

  • Overcommit trop agressif : somme(vCPU) bien supérieure aux cœurs physiques, et les pics de charge coïncident.
  • Limites CPU et shares : quotas cgroup ou unités CPU Proxmox qui affament une VM en cas de contention.
  • Mauvais appairage NUMA/topologie : grosses VMs réparties sur sockets, accès mémoire distant et pertes de cache créant un comportement « CPU lent » même sans gros steal.
  • Fréquence CPU de l’hôte bridée : ressemble à de la contention, agit comme de la contention, mais c’est juste de l’underclocking.

Conseil pratique : si vous voyez un steal soutenu au‑dessus de quelques pourcents pendant un incident visible par les utilisateurs, considérez‑le comme un vrai problème. Un steal ponctuel n’est pas fatal ; un steal soutenu l’est.

Blague n°1 : Si votre VM a 30% de steal, elle ne « vole » pas — elle attend poliment pendant que quelqu’un d’autre lui pique son déjeuner.

IO wait : le CPU est inactif parce que le stockage est lent

IO wait signifie que le CPU n’avait rien à exécuter parce que des threads étaient bloqués sur des opérations IO. Ce n’est pas le CPU qui est « occupé ». C’est le CPU qui est au chômage pendant que le stockage pourrit le week-end de tout le monde.

Ce qui fait monter l’IO wait sur Proxmox

  • Sauvegardes/snapshots/réplication générant de lourdes lectures séquentielles mêlées à des écritures aléatoires.
  • Écritures synchrones provenant de bases de données ou de configurations NFS qui forcent des flushs.
  • Surcharge de profondeur de file sur SSD SATA ou ensembles HDD : la latence explose avant que le débit paraisse saturé.
  • Comportement des TXG ZFS : des rafales d’écritures aux frontières de commit peuvent ressembler à des blocages périodiques.
  • Stockage thin-provisioned ou pools presque pleins entraînant fragmentation et allocations plus lentes.

Interpréter l’iowait sans se mentir

Un pourcentage élevé d’iowait vous dit : « le stockage limite la progression ». Il ne vous dit pas si le coupable est le pool, le contrôleur, le firmware du SSD, le système de fichiers invité ou une VM unique qui martèle des écritures synchrones.

Concentrez‑vous sur les métriques de latence : await, svctm (moins utile sur les noyaux modernes), la taille de file, et le comportement par vdev ZFS. Les graphiques de débit rassurent mais mentent si votre charge est sensible à la latence.

ARC ZFS : cache, pression mémoire et le piège du swap

L’ARC ZFS est une fonctionnalité puissante et un bouc émissaire fréquent. Il met en cache les lectures, les métadonnées, et peut réduire drastiquement les IO disque. Mais sur un hôte de virtualisation, l’ARC est aussi un acteur politique : il entre en compétition avec les invités pour la RAM.

Les modes de défaillance ARC que vous voyez en production

  • Swap de l’hôte : le noyau swappe parce que ARC + page cache + processus qemu + tout le reste dépassent la RAM. Une fois que l’hôte swappe, la latence devient étrange et « aléatoire ».
  • ARC trop petit : des misses de cache constants obligent les disques réels à travailler ; l’IO wait monte ; les VMs saccadent.
  • ARC trop grand : les VMs perdent de la mémoire, le ballooning démarre, les invités swapent, et l’hôte « paraît correct » tandis que l’application brûle.
  • Pression metadata : beaucoup de petits fichiers ou de nombreux datasets peuvent gonfler les métadonnées ; l’ARC devient riche en metadata et moins efficace pour les blocs VM réels.

Conseil d’allocation ARC orienté Proxmox

Si vous exécutez de nombreuses VMs et voulez un comportement prévisible, définissez une taille maximale pour l’ARC. Laisser l’ARC grandir automatiquement peut convenir sur un appliance de stockage ; sur un nœud de virtualisation avec mémoire invitée changeante, c’est la façon dont vous finissez par déboguer une « lenteur fantôme ».

Il n’existe pas un pourcentage magique, mais un point de départ courant est : limiter l’ARC pour que l’hôte garde toujours une marge pour les invités + le noyau + l’overhead qemu. Ensuite surveillez le hit ratio réel et la latence. Ajustez en vous basant sur les preuves, pas sur les impressions.

Note sur SLOG/L2ARC (parce qu’on vous le demandera)

Un SLOG séparé peut aider la latence des écritures synchrones si vous avez des charges sync‑heavy et comprenez les risques et l’endurance. L2ARC peut aider les charges orientées lecture mais consomme de la RAM pour les métadonnées et peut se retourner contre vous si vous manquez déjà de mémoire.

Voisins bruyants : trouver la VM qui gâche votre journée

« Voisin bruyant » est le terme corporate pour « une charge est égoïste et tout le monde paie pour ça ». Sur Proxmox, les voisins bruyants se manifestent typiquement par :

  • Une VM générant des écritures aléatoires extrêmes (souvent des écritures synchrones).
  • Une VM effectuant un scan disque complet, un travail d’indexation, une analyse antivirus ou une sauvegarde interne.
  • Une VM saturant le CPU avec des taux d’interruptions élevés (inondations de paquets, polling mal configuré, boucles actives).
  • Une VM avec trop de vCPUs provoquant des frictions de planification pour les VMs plus petites.

Le mouvement diagnostic : arrêtez de regarder les moyennes de l’hôte et commencez à attribuer la consommation aux processus QEMU individuels, puis corrélez aux VMIDs. La plupart des « contentions mystères » deviennent un nom et un propriétaire en moins de 15 minutes.

Tâches pratiques : commandes, sorties, décisions (12+)

Task 1: Snapshot CPU usage, iowait, and steal per core

cr0x@server:~$ mpstat -P ALL 1 5
Linux 6.8.12-pve (pve01)  12/28/2025  _x86_64_  (32 CPU)

12:01:11 PM  CPU   %usr  %nice   %sys %iowait  %irq %soft  %steal  %idle
12:01:12 PM  all   12.10   0.00   4.20   9.80   0.00  1.10    6.50  66.30
12:01:12 PM    0   22.00   0.00   6.00  18.00   0.00  2.00   10.00  42.00
12:01:12 PM    1    8.00   0.00   3.00   1.00   0.00  0.50    0.00  87.50

Ce que ça signifie : %steal à 6,5 % sur l’ensemble des CPU suggère une contention de planification pour les invités. %iowait à 9,8 % suggère aussi que la latence stockage limite la progression.

Décision : Si le steal est soutenu > 5 % pendant l’incident, traitez la contention CPU comme réelle : réduisez l’overcommit vCPU, déplacez les VMs chaudes, ou ajustez les limites. Si l’iowait est aussi élevé, lancez les vérifications stockage pour déterminer la cause principale.

Task 2: Confirm memory pressure and swapping at the host level

cr0x@server:~$ vmstat 1 10
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 5  3  262144  18432  10240 8123456  80  120   900  1400  9200 18000 12  4 66 10  8
 3  2  262144  16000  10240 8012345  60  100  1100  1600  9400 17500 10  4 67 12  7

Ce que ça signifie : Des si/so non nuls indiquent un swap actif. b (processus bloqués) s’aligne avec l’IO wait. Avoir peu de free seul n’est pas mauvais ; c’est le swap qui importe.

Décision : Si l’hôte swappe, corrigez la pression mémoire d’abord : caper l’ARC, arrêter les jeux d’overcommit par ballooning, ajouter de la RAM, ou réduire les allocations invitées. Le tuning du stockage ne vous sauvera pas si l’hôte pagine.

Task 3: Identify disk latency and saturation symptoms

cr0x@server:~$ iostat -x 1 5
Linux 6.8.12-pve (pve01)  12/28/2025  _x86_64_  (32 CPU)

Device            r/s   w/s  rkB/s  wkB/s  rrqm/s wrqm/s  %util  await  r_await  w_await
nvme0n1          1200  1800 48000  92000     0.0    0.0   98.5   18.2     6.1     26.4
nvme1n1           110  1600  3200  88000     0.0    0.0   91.0   22.8     4.5     24.1

Ce que ça signifie : Un %util élevé plus un await élevé indiquent que vos périphériques sont saturés et que la latence augmente. La latence d’écriture est particulièrement élevée.

Décision : Passez à une ventilation ZFS (zpool iostat -v). Si les pics d’await coïncident avec des sauvegardes ou des réplications, limitez ou façonnez ces tâches.

Task 4: Break down ZFS IO by vdev to find the real limiter

cr0x@server:~$ zpool iostat -v rpool 1 5
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
rpool       3.12T  1.48T  1.20K  1.85K  46.2M  92.8M
  mirror    3.12T  1.48T  1.20K  1.85K  46.2M  92.8M
    nvme0n1     -      -    620    980  23.1M  46.4M
    nvme1n1     -      -    580    870  23.0M  46.4M

Ce que ça signifie : Les lectures/écritures sont équilibrées entre les membres du miroir, donc le pool n’est pas « un disque qui meurt » (encore). Si un vdev décroche, vous verriez un déséquilibre.

Décision : Si débit et ops sont élevés mais que la latence reste mauvaise, cherchez des écritures synchrones, de la fragmentation, ou une pression mémoire provoquant des misses de cache constants.

Task 5: Check pool health, errors, and slow devices

cr0x@server:~$ zpool status -xv
all pools are healthy

Ce que ça signifie : Pas d’erreurs ZFS évidentes. C’est bon. Ça ne veut pas dire que la performance est bonne.

Décision : Si la performance est mauvaise mais l’état est sain, concentrez‑vous sur la forme du workload, la latence et la contention plutôt que sur « un disque qui meurt ».

Task 6: Observe ARC size and hit ratio signals

cr0x@server:~$ arcstat 1 3
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsz     c
12:03:01  4.2K  1.1K    26   210   19   540   49   350   32   52.1G  60.0G
12:03:02  4.0K  1.4K    35   260   19   700   50   440   31   52.4G  60.0G

Ce que ça signifie : L’ARC est volumineux (52G) et plafonné à 60G. Un taux de miss de 26–35 % suggère que les disques effectuent encore du travail. Ce n’est pas forcément mauvais, mais c’est un indice.

Décision : Si miss% est élevé et que l’IO wait est élevé, envisagez si l’ARC est trop petit pour le working set. Si l’hôte swappe, l’ARC est trop grand pour votre réalité.

Task 7: Confirm host swap and memory accounting (don’t trust “free” alone)

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:           128Gi       109Gi       18Gi       2.1Gi        1.6Gi       15Gi
Swap:           16Gi       256Mi        15Gi

Ce que ça signifie : Un peu de swap est utilisé. Ce n’est pas immédiatement fatal, mais s’il croît ou si vmstat montre un swap actif, vous avez un problème.

Décision : Si l’usage swap est stable et que si/so sont zéro, vous pouvez l’accepter. Si le swap est actif, réduisez la pression mémoire avant de tuner autre chose.

Task 8: Identify top IO processes on the host (often QEMU)

cr0x@server:~$ iotop -oPa
Total DISK READ: 65.20 M/s | Total DISK WRITE: 110.30 M/s
  PID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN  IO>  COMMAND
18342 be/4  root      2.10 M/s  38.70 M/s   0.00 % 92.10%  kvm -id 107 -name vm107 ...
19110 be/4  root      0.40 M/s  26.80 M/s   0.00 % 88.30%  kvm -id 112 -name vm112 ...

Ce que ça signifie : Deux VMs sont responsables de la plupart des écritures. IO> indique le temps d’attente IO.

Décision : Investiguer les VM 107 et 112 : que font‑elles, sauvegardent‑elles, sont‑elles des bases avec écritures sync, sont‑elles mal configurées ?

Task 9: Map QEMU PID to VMID and confirm Proxmox sees the same “hot” VM

cr0x@server:~$ qm list
      VMID NAME                 STATUS     MEM(MB)    BOOTDISK(GB) PID
       107 db-prod-01           running    32768      256.00        18342
       112 files-prod-02        running    16384      1024.00       19110

Ce que ça signifie : Les PIDs correspondent à la sortie de iotop. Vous avez maintenant une attribution réelle : db-prod-01 et files-prod-02 sont de gros écrivains.

Décision : Si le gros écrivain est une base de données, évaluez le comportement sync, les réglages de cache et la pertinence d’un SLOG. Si c’est un serveur de fichiers, vérifiez scans, tempêtes rsync ou snapshots.

Task 10: Check per-VM CPU limits, CPU units, and ballooning that can create contention

cr0x@server:~$ qm config 107
balloon: 16384
boot: order=scsi0;net0
cores: 16
cpu: x86-64-v2-AES
memory: 32768
name: db-prod-01
net0: virtio=DE:AD:BE:EF:10:07,bridge=vmbr0,firewall=1
scsi0: rpool:vm-107-disk-0,discard=on,iothread=1,ssd=1
sockets: 1

Ce que ça signifie : Le ballooning est activé et peut récupérer de la mémoire sous pression. cores=16 peut être trop si l’hôte est en contention ; des nombres de vCPU élevés augmentent la friction de planification.

Décision : Si le steal est élevé, envisagez de réduire les allocations vCPU surdimensionnées pour les VMs qui ne scale pas. Si la pression mémoire existe, désactivez le ballooning pour les workloads critiques à faible latence et ajustez la mémoire correctement.

Task 11: Check CPU frequency and throttling (the “why is it slow today” classic)

cr0x@server:~$ lscpu | egrep 'Model name|Socket|Thread|CPU\(s\)'
CPU(s):                               32
Model name:                           Intel(R) Xeon(R) Silver 4216 CPU @ 2.10GHz
Socket(s):                            2
Thread(s) per core:                   2
cr0x@server:~$ cpupower frequency-info | egrep 'current CPU frequency|governor'
current CPU frequency: 1200 MHz (asserted by call to kernel)
  governor "powersave" may decide which speed to use

Ce que ça signifie : Les CPU tournent à 1.2GHz sous un gouverneur powersave. Cela peut absolument ressembler à une « contention mystérieuse ».

Décision : Sur les nœuds de virtualisation, préférez performance ou une politique de gouverneur tunée à moins d’avoir une raison mesurée de ne pas le faire. Si vous avez une contrainte d’énergie, acceptez explicitement le compromis de performance.

Task 12: Verify interrupt/softirq pressure (network or storage storms)

cr0x@server:~$ sar -I SUM 1 3
Linux 6.8.12-pve (pve01)  12/28/2025  _x86_64_  (32 CPU)

12:05:12 PM  INTR    intr/s
12:05:13 PM  SUM     82000.00
12:05:14 PM  SUM     91000.00

Ce que ça signifie : Un taux d’interruptions très élevé peut consumer le CPU en softirq et créer de la latence. C’est courant avec un haut PPS réseau ou certains drivers de stockage.

Décision : Si %soft dans mpstat est élevé, inspectez les bridges réseau, les réglages virtio-net, et vérifiez si une VM cause une inondation de paquets.

Task 13: Check kernel logs for storage timeouts or resets (the “it’s fine” lie detector)

cr0x@server:~$ journalctl -k --since "30 min ago" | egrep -i 'nvme|blk|zfs|reset|timeout|error' | tail -n 20
Dec 28 11:41:03 pve01 kernel: nvme nvme0: I/O 123 QID 7 timeout, aborting
Dec 28 11:41:03 pve01 kernel: nvme nvme0: Abort status: 0x371
Dec 28 11:41:04 pve01 kernel: blk_update_request: I/O error, dev nvme0n1, sector 123456789 op 0x1:(WRITE) flags 0x0 phys_seg 1 prio class 0

Ce que ça signifie : Vous avez des problèmes au niveau du périphérique. Le tuning de performance est hors sujet tant que la stabilité hardware/firmware n’est pas réglée.

Décision : Traitez‑le comme un incident : vérifiez le firmware, le câblage, les erreurs PCIe, la santé des disques et le comportement du contrôleur. Planifiez le remplacement si nécessaire.

Task 14: Measure ZFS dataset properties that impact VM IO behavior

cr0x@server:~$ zfs get -o name,property,value -r compression,atime,recordsize,sync,logbias rpool | head
NAME               PROPERTY     VALUE
rpool              compression  zstd
rpool              atime        off
rpool              recordsize   128K
rpool              sync         standard
rpool              logbias      latency

Ce que ça signifie : atime=off est sensé. recordsize compte : les volumes VM se comportent souvent mieux avec des recordsize plus petits quand l’IO aléatoire domine, mais il faut mesurer. sync=standard respecte la sémantique sync invitée ; le changer peut être dangereux.

Décision : Ne changez pas sync en disabled pour « performer » à moins d’accepter explicitement le risque de perte de données et d’avoir une approbation business. Tondez le recordsize et les devices spéciaux avec précaution, et testez sur des IO représentatifs.

Task 15: Confirm what the VM disk actually is (virtio-scsi + iothread vs legacy)

cr0x@server:~$ qm config 112 | egrep 'scsi|sata|ide|virtio|iothread'
scsi0: rpool:vm-112-disk-0,discard=on,iothread=1,ssd=1

Ce que ça signifie : Vous êtes sur virtio-scsi avec un IO thread. C’est typiquement une bonne base pour la performance et l’isolation.

Décision : Si vous voyez sata0 ou des disques IDE sur des VMs sensibles à la performance, corrigez ça. Les contrôleurs émulés ne sont plus acceptables en 2025.

Trois mini-récits d’entreprise issus du terrain

Incident causé par une mauvaise hypothèse : « Faible utilisation CPU signifie que l’hôte est OK »

Une entreprise de taille moyenne exploitait un cluster Proxmox hébergeant des applications web et quelques bases de données. Un matin, l’on‑call a reçu la plainte habituelle : « les pages mettent 10 secondes à charger ». Les graphes CPU de l’hôte semblaient calmes. Quelqu’un a conclu à une régression applicative et a commencé à rollback des déploiements.

Pendant ce temps, la load average était élevée. Le rollback n’a rien amélioré. Les gens ont haussé le ton. L’équipe réseau a été entraînée dans l’affaire parce que c’est ce qui arrive quand personne n’a une théorie fiable.

Finalement, quelqu’un a lancé iostat -x. L’array SATA sous‑jacente montrait un await élevé avec %util saturé. Puis iotop a pointé une seule VM effectuant d’énormes rafales d’écritures. C’était un job de reporting « temporaire » qui faisait des exports complets de table et compressait à l’intérieur de la VM, écrivant un torrent de petits blocs fortement synchrones sur le disque VM.

L’hypothèse erronée était subtile : ils ont égalé « CPU pas occupé » avec « système sain ». En réalité, le CPU attendait le stockage, et le stockage était martelé par une charge que personne ne considérait comme « production ». Le correctif fut ennuyeux et efficace : planifier le job hors‑pic, le rate‑limiter, et déplacer la VM vers un pool avec une meilleure latence d’écriture. Le rollback n’était que du spectacle.

Optimisation qui a mal tourné : « Désactiver sync sur ZFS et regarder voler les performances »

Une autre organisation avait une VM PostgreSQL se plaignant de latence d’écriture. Un ingénieur bien intentionné a proposé de mettre sync=disabled sur le dataset ZFS du stockage VM pour « régler » le problème. Les benchs semblaient excellents. Tout le monde s’est félicité. Ils l’ont déployé en production.

Deux semaines plus tard, un nœud a subi une coupure d’alimentation brutale. Pas d’arrêt propre, juste une extinction. Au redémarrage, la VM DB a booté, mais la base présentait des symptômes de corruption. Ils ont restauré depuis des backups, mais la fenêtre de récupération fut pénible et l’équipe a dû expliquer pourquoi un « changement de performance » avait augmenté le risque de perte de données.

Le retour de bâton n’était pas que ZFS soit mauvais. Il a fait ce qu’il promettait. L’équipe avait changé le contrat de durabilité : les écritures sync invitées n’étaient plus durables. C’est acceptable pour certains workloads, catastrophique pour d’autres, et ça ne doit pas se faire à la légère.

Ils ont finalement résolu le problème initial de latence de la façon la plus solide : déplacer la VM DB vers des NVMe miroir plus rapides, valider les politiques de cache d’écriture, et ajouter un SLOG avec protection contre la perte de puissance après avoir calculé l’endurance. La leçon a été assimilée : les hacks de performance qui réécrivent la correction ne sont pas des optimisations ; ce sont des paris avec paperasse.

Pratique ennuyeuse mais correcte qui a sauvé la mise : marge de capacité et limites prévisibles

Une troisième équipe exploitait Proxmox pour des services internes. Pas glamour. Ils avaient quelques règles qui semblaient excessives : garder les pools ZFS en dessous d’un certain niveau de remplissage, caper l’ARC sur tous les nœuds, et interdire les demandes « donne‑lui juste 32 vCPU » sauf si quelqu’un prouvait que la charge scaleait.

Puis ils ont eu un incident réel : une VM vendor a mal fonctionné après une mise à jour. Elle a commencé à écrire des logs à un rythme ridicule et les a fait tourner constamment. Cela aurait normalement été un incendie de cluster.

Au lieu de cela, le rayon d’impact a été limité. Parce qu’ils avaient de la marge et des limites ARC sensées, l’hôte n’a pas commencé à swapper. Parce qu’ils avaient un dimensionnement CPU raisonnable et des limites, la VM n’a pas pu voler tout le nœud. Parce qu’ils surveillaient la latence disque par VM, le coupable a été évident en quelques minutes.

Ils ont bridés l’IO de la VM et l’ont déplacée sur un nœud moins critique pendant que le vendor corrigeait. Personne n’a acclamé. Personne n’a écrit d’article sur une « mitigation héroïque ». Mais la production est restée en ligne, et c’est l’essentiel des pratiques ennuyeuses.

Blague n°2 : Le meilleur correctif de performance est celui qui n’exige pas de salle de crise — en grande partie parce que les salles de crise fonctionnent au café et au déni.

Erreurs courantes : symptôme → cause racine → correctif

1) La load average est énorme, le CPU est majoritairement inactif

Symptôme : load 30–80, CPU idle 60%+, utilisateurs se plaignent de latence.

Cause racine : tâches bloquées en état D en attente du stockage ; l’IO wait est la vraie limite.

Correctif : vérifiez avec vmstat (b élevé, wa élevé) et iostat -x (await élevé, %util élevé) ; ensuite identifiez la VM IO principale via iotop et façonnez/déplacez la charge.

2) La VM signale un CPU élevé, mais le CPU hôte semble normal

Symptôme : l’invité dit CPU saturé, le tableau de bord hôte n’est pas alarmant.

Cause racine : steal CPU ou quota/limite cgroup ; l’invité veut CPU mais n’est pas planifié.

Correctif : vérifiez le %st invité et le steal sur l’hôte via mpstat ; examinez les limites/units CPU de la VM ; réduisez l’overcommit ou déplacez la VM.

3) « ZFS bouffe toute la mémoire » panique

Symptôme : faible mémoire « free », ARC énorme, envie de « désactiver l’ARC ».

Cause racine : mauvaise compréhension du comptage mémoire Linux ; le vrai problème est le swap ou la pression de reclaim, pas la faible mémoire libre.

Correctif : vérifiez vmstat pour si/so, vérifiez la mémoire available ; capez l’ARC si l’hôte swappe ; sinon ignorez « free » et concentrez‑vous sur la latence et le hit rate.

4) Stalls périodiques aléatoires toutes les quelques secondes/minutes

Symptôme : les applis se figent brièvement puis reprennent, en boucle.

Cause racine : pics de commit TXG ZFS, rafales de snapshot/réplication, ou comportement de flush du contrôleur.

Correctif : corrélez avec zpool iostat 1 et les horaires de sauvegarde ; limitez les jobs ; envisagez des vdevs plus rapides ou séparez le trafic backup ; vérifiez la stabilité firmware/des disques.

5) La performance s’est dégradée après « avoir tuné recordsize »

Symptôme : plus d’IOPS, latence pire ; ou mieux en séquentiel, pire en aléatoire.

Cause racine : recordsize inadapté au pattern IO ; pour les volumes VM, le changer aveuglément peut augmenter l’amplification et la fragmentation.

Correctif : revenez à une base sensée ; mesurez avec la charge réelle ; tunez par dataset (et comprenez que zvol vs dataset diffèrent).

6) Les sauvegardes détruisent la production chaque nuit

Symptôme : incidents récurrents la nuit ; la journée est OK.

Cause racine : lectures de sauvegarde saturant le pool et entrant en concurrence avec la latence d’écriture ; les chaînes de snapshot et la compression amplifient le travail.

Correctif : planifier et limiter ; stockage séparé pour les backups ; limiter les jobs concurrents ; envisager d’externaliser les lectures lourdes vers des nœuds de réplication.

7) « On a ajouté L2ARC et maintenant c’est plus lent »

Symptôme : latence augmentée, pression mémoire accrue après ajout d’un cache.

Cause racine : overhead metadata L2ARC consommant de la RAM ; cache qui se réchauffe lentement ; le device ajoute de la contention.

Correctif : retirez L2ARC sauf si vous avez un working set lecture‑lourd prouvé qui ne tient pas dans l’ARC et que vous avez de la RAM libre.

Listes de vérification / plan étape par étape

Checklist A : Quand les utilisateurs disent « tout est lent »

  1. Sur l’hôte : capturez mpstat, vmstat, iostat -x, et zpool iostat pendant 2–5 minutes.
  2. Si le steal est élevé : réduisez la contention CPU (déplacez des VMs, baissez vCPU, revoyez les limites, corrigez le gouverneur).
  3. Si le iowait est élevé : identifiez les VMs IO principales (iotop), puis corrélez au workload (backup, DB, scan, réplication).
  4. Si le swap est actif : arrêtez l’hémorragie (caper l’ARC, réduire le ballooning, libérer de la mémoire, migrer une VM), puis corrigez la capacité.
  5. Vérifiez les logs noyau pour erreurs/timeouts stockage. Si présents, arrêtez le tuning et traitez la stabilité hardware/driver en priorité numéro un.

Checklist B : Quand une VM est lente mais les autres vont bien

  1. Dans la VM : vérifiez top pour %st et %wa.
  2. Sur l’hôte : mappez VMID→PID (qm list) et observez le CPU/IO de ce PID (ps, iotop).
  3. Vérifiez le type disque/contrôleur : virtio-scsi avec iothread pour les VMs IO‑intensives.
  4. Vérifiez les limites CPU/ballooning qui peuvent contraindre la VM silencieusement.
  5. Si c’est une DB : confirmez si la charge est écriture sync‑heavy ; envisagez un stockage conçu pour les écritures basse‑latence, pas seulement « rapide séquentiel ».

Checklist C : Avant de changer les réglages ZFS en production

  1. Notez les propriétés dataset/zvol courantes que vous prévoyez de modifier.
  2. Définissez les métriques de succès : latence p99, temps de requête, temps fsync, fenêtre de backup, iowait hôte, hit% ARC.
  3. Changez une chose à la fois, idéalement sur une VM ou un dataset.
  4. Ayez un plan de rollback qui prend des minutes, pas des heures.
  5. Ne sacrifiez jamais la durabilité pour la vitesse sans approbation business explicite (sync=disabled n’est pas une « option de tuning », c’est la réécriture d’un contrat).

FAQ

1) Quel est un « mauvais » pourcentage de CPU steal ?

Il n’y a pas de seuil universel, mais un steal soutenu au‑dessus d’environ 5 % pendant une latence visible par les utilisateurs est un fort indice de contention. Le steal ponctuel est courant ; le steal soutenu indique un problème de capacité ou de planification.

2) Pourquoi la load average est élevée quand l’utilisation CPU est faible ?

Parce que la load compte les tâches exécutables et les tâches bloquées en sommeil ininterrompu (généralement en attente d’IO). Une forte latence IO produit une load élevée sans CPU élevé.

3) Dois‑je désactiver atime sur ZFS ?

Pour le stockage VM et la plupart des workloads serveur, atime=off est généralement le bon choix pour éviter des écritures supplémentaires. Si un workload dépend des sémantiques atime, conservez‑le activé uniquement pour ce dataset.

4) L’ARC ZFS « vole »‑t‑il la mémoire aux VMs ?

L’ARC utilise agressivement la mémoire disponible par conception, mais elle est récupérable. Le vrai problème survient lorsque l’hôte swappe ou lorsque le ballooning pousse les invités en swap. Cappez l’ARC si l’hôte est sous pression mémoire.

5) Ajouter un SSD L2ARC est‑ce une bonne idée pour Proxmox ?

Parfois, mais pas par défaut. L2ARC consomme de la RAM pour les métadonnées et aide surtout les working sets lecture‑lourds qui ne tiennent pas dans l’ARC. Si vous manquez de RAM, L2ARC provoque souvent une régression.

6) Mon IO wait est élevé. Est‑ce que j’ai besoin de disques plus rapides ?

Peut‑être, mais commencez par identifier le type d’IO. Une VM unique effectuant des écritures synchrones aléatoires peut saturer un excellent matériel. Identifiez le coupable, le pattern d’accès, et si votre layout de stockage lui correspond.

7) Dois‑je donner beaucoup de vCPUs à chaque VM « au cas où » ?

Non. Surdimensionner les vCPUs augmente la friction de planification et peut aggraver la latence de queue pour tout le monde. Commencez plus petit, mesurez, et augmentez les vCPU seulement si le workload prouve un bénéfice.

8) Les sauvegardes Proxmox doivent‑elles nécessairement impacter la performance ?

Les sauvegardes consomment de l’IO. La question est de savoir si le système est conçu pour l’absorber : stockage backup séparé, throttling et limites de concurrence. Si les backups provoquent régulièrement des incidents de production, le design de sauvegarde est incomplet.

9) Comment trouver rapidement la VM voisine bruyante sur un nœud ?

Utilisez iotop -oPa pour trouver les processus QEMU lourds en IO et mappez leurs PIDs aux VMIDs via qm list. Pour la contention CPU, utilisez mpstat et ps trié par CPU, puis corrélez.

10) Dois‑je désactiver le ballooning ?

Pour les VMs critiques sensibles à la latence, souvent oui — le ballooning peut créer une pression mémoire imprévisible. Pour les workloads moins critiques, le ballooning permet d’augmenter la densité. L’important est d’éviter à tout prix le swap hôte.

Conclusion : prochaines étapes qui font réellement avancer les choses

Si votre nœud Proxmox est lent, cessez de débattre et commencez à attribuer : capturez mpstat, vmstat, iostat -x, et zpool iostat. Décidez si le limiteur est la planification CPU (steal), la latence stockage (iowait + await), ou la pression mémoire (swap/reclaim). Puis nommez la VM principale coupable avec iotop et qm list.

Ensuite, appliquez les correctifs peu glamour en premier : capez l’ARC pour protéger l’hôte, empêchez le swap hôte, redimensionnez les vCPUs, et throttlez les backups. Ce n’est qu’après le diagnostic que vous devriez envisager des changements structurels comme des vdevs plus rapides, des pools séparés pour les workloads sensibles, ou l’ajout d’un SLOG correctement conçu. Le tuning sans diagnostic n’est que de la dépense improvisée.

← Précédent
Debian 13 — Changement du port SSH : corriger le pare-feu et l’ordre sshd sans se bloquer (cas n°87)
Suivant →
Résoudre l’échec de pvestatd.service sur Proxmox : Restaurer rapidement graphiques et statistiques

Laisser un commentaire