VM Windows sur Proxmox lente : 8 réglages (disque/cache/iothread/drivers) qui comptent

Cet article vous a aidé ?

Rien n’humilie autant un administrateur sûr de lui qu’une VM Windows « correcte » sur le papier mais misérable en réalité. Vous cliquez sur Démarrer, elle réfléchit. Vous ouvrez une appli, elle négocie. La longueur de la file d’attente disque ressemble à une file de navette pour un café.

Proxmox peut faire tourner Windows rapidement — d’une façon ennuyeusement rapide. Mais il faut tourner les bons quelques boutons. Pas tous les boutons. Huit d’entre eux. Et il faut valider avec des mesures, pas des impressions, parce que Windows peut cacher la douleur du stockage derrière « System » CPU et Proxmox peut la masquer derrière « io=… ».

Méthode de diagnostic rapide (trouver le goulot en 10 minutes)

Quand une VM Windows est lente, votre cerveau veut blâmer Windows. Votre travail est d’identifier quelle couche attend réellement : ordonnancement CPU invité, mise en file d’attente du stockage invité, émulation de périphérique QEMU, IO hôte, ou backend de stockage. Le chemin le plus rapide est de trianguler avec la latence, pas le débit.

Première étape : décider si c’est l’ordonnancement CPU ou la latence stockage

  • Vérifier le steal/ready CPU sur l’hôte : si les vCPU ne sont pas programmés, tout paraît trop lent.
  • Vérifier la latence IO de l’hôte : si l’IO est lent, Windows « gèle » de façons qui ressemblent à des problèmes CPU.

Deuxième étape : confirmer que la VM utilise les bons périphériques et drivers

  • Windows sur SATA/IDE ou utilisant le driver générique de Microsoft est essentiellement une taxe que vous payez pour toujours.
  • Mauvais contrôleur + pas de VirtIO = CPU élevé par IO et files d’attente peu profondes.

Troisième étape : isoler où la file se construit

  • File dans l’invité (longue file d’attente disque élevée) mais disque hôte au repos : souvent configuration driver/contrôleur ou mismatch du mode cache.
  • File dans l’hôte (await élevé dans iostat) et invité lent aussi : latence du backend de stockage.
  • File dans le thread QEMU (utilisation CPU monoproc élevée sur l’hôte) : iothread manquant ou mauvais contrôleur.

Ordre minimal des opérations (faire dans cet ordre)

  1. Sur l’hôte : vérifier la latence IO et la contention CPU (iostat, pvesh/qm status, top).
  2. Sur la config VM : vérifier le contrôleur (VirtIO SCSI), le mode cache, iothread, discard et le type CPU.
  3. Dans Windows : vérifier que les drivers VirtIO sont installés et réellement utilisés; vérifier la longueur de file disque et l’utilisation de storport.
  4. Sur le backend de stockage : alignement ZFS recordsize/volblocksize, comportement sync, réglages Ceph RBD, ou scheduler et cache LVM.

Si vous faites ces quatre étapes, vous trouverez généralement le coupable avant que quelqu’un ne suggère « augmentez juste les vCPU », ce qui transforme des problèmes de performance en incidents de production.

Faits et contexte qui expliquent pourquoi cela arrive

  • VirtIO existe parce que l’émulation de « vrai » matériel est lente. KVM est rapide en virtualisation CPU ; l’émulation de périphérique est là où ça coûte.
  • IDE est historiquement simple, pas historiquement rapide. L’émulation IDE est une béquille de compatibilité ; elle brûle du CPU par IO et a des files d’attente peu profondes.
  • La pile de stockage Windows a évolué selon les versions. Les drivers basés sur Storport et les améliorations de mise en file d’attente font que Windows moderne profite davantage de contrôleurs virtuels appropriés.
  • Les modes de cache d’écriture sont un contrat de durabilité. « writeback » peut être une fusée ou un piège selon que l’hôte garantit les sémantiques de flush ou pas.
  • ZFS est transactionnel et honnête sur les écritures synchrones. Si votre charge émet des écritures sync (beaucoup de patterns Windows le font), ZFS vous fera payer sauf si vous concevez en conséquence.
  • Ceph échange latence contre résilience distribuée. Il peut être rapide, mais les petites écritures aléatoires sont très sensibles au jitter réseau et au tuning des backends.
  • NVMe n’a pas été conçu pour une seule file. Les SSD modernes veulent de nombreuses files et un fort parallélisme ; un chemin IO mono-thread devient le nouveau goulot.
  • Le ballooning a été conçu pour la densité, pas pour le confort. Il peut rendre une VM « adaptée », mais Windows réagit mal à une pression mémoire soudaine.
  • Les ordonnanceurs IO et les couches de cache peuvent se contredire. Deux couches « optimisant » le même flux IO signifient souvent qu’aucune n’est réellement efficace.

Une idée paraphrasée attribuée à Werner Vogels (CTO d’Amazon) : Tout échoue, donc concevez des systèmes pour continuer à fonctionner quand des parties cassent inévitablement. Le tuning de performance est similaire : supposez que quelque chose va se bloquer, puis réduisez le rayon d’impact.

Les 8 réglages qui font vraiment la différence

1) Bus et contrôleur disque : VirtIO SCSI (et quand ne pas l’utiliser)

Si le disque de votre VM Windows est en IDE ou SATA dans Proxmox, vous avez déjà trouvé un problème. Ce sont des choix de compatibilité, pas de performance. Le « SCSI » par défaut peut être bon, mais le type de contrôleur compte.

Par défaut recommandé pour Windows sur Proxmox : contrôleur VirtIO SCSI (généralement virtio-scsi-single pour la simplicité) plus le driver de stockage VirtIO dans Windows.

Pourquoi c’est important : VirtIO est un périphérique para-virtualisé. Il réduit les sorties de VM, réduit le CPU par IO, et supporte des files d’attente plus profondes. Les charges Windows — surtout « beaucoup de petites lectures » au démarrage et pendant les mises à jour — en profitent énormément.

Quand choisir autre chose :

  • Disque virtuel NVMe peut être excellent pour des charges à haut IOPS car il correspond bien au modèle de mise en file moderne. Il est aussi parfois plus simple que SCSI.
  • SATA peut convenir si vous êtes coincé avec un ancien installateur Windows et que vous ne voulez pas injecter de drivers — uniquement comme pont temporaire.

Avis tranché : ne mettez pas un « pont SATA temporaire » en production. C’est ainsi que le temporaire devient permanent, comme le panneau en carton sur une porte cassée qui est toujours là deux ans plus tard.

2) Mode cache : choisir et connaître l’impact

Le mode cache décide qui peut mentir sur la durabilité. Windows s’en soucie. Les bases de données s’en soucient encore plus. Et votre futur vous s’en soucie le plus.

Modes de cache Proxmox courants :

  • cache=none : généralement le choix par défaut le plus sûr. Utilise le direct IO, évite le double caching, respecte correctement les sémantiques de flush. Souvent le meilleur pour ZFS et Ceph.
  • cache=writeback : écritures perçues plus rapides parce que le cache de pages hôte les absorbe. Risque plus élevé en cas de perte de courant ou de crash de l’hôte si vous n’avez pas de protection d’alimentation et de gestion des flushs.
  • cache=writethrough : plus sûr que writeback, souvent plus lent.

À quoi ressemble la lenteur quand le cache est mal choisi : pauses aléatoires, grande variance de latence IO, ou excellents benchmarks qui s’effondrent en charge réelle parce que les flushs forcent la vérité.

Recommandation : commencez avec cache=none, mesurez, puis envisagez writeback seulement si vous pouvez défendre la durabilité des données (UPS, SSD entreprise avec PLP, et compréhension du stack de stockage).

3) IO thread : séparer le chemin lent du reste

QEMU a des threads. Votre émulation de périphérique de stockage et le traitement des virtqueues peuvent devenir une voie unique surchargée si vous ne lui donnez pas sa propre voie. C’est ce que font les IO threads : isoler le traitement des IO disque du thread vCPU principal.

Symptômes quand il faut iothread :

  • La VM paraît « saccadée » sous charge disque même quand l’utilisation CPU semble modeste.
  • Un cœur CPU hôte est saturé lors d’un fort IO, tandis que les autres dorment.
  • Les pics de latence corrèlent avec des tâches en arrière-plan (Windows Defender, mises à jour, indexation).

Activez un iothread pour le disque (ou utilisez un contrôleur qui le supporte proprement). C’est un changement sans glamour mais souvent évident sur un graphe avant/après.

4) Discard/TRIM et émulation SSD : arrêter de mentir à la VM

Windows suppose qu’il peut indiquer au stockage les blocs libérés (TRIM). Si l’invité ne peut pas faire de discard, le backend peut se dégrader lentement, surtout sur des volumes thin-provisioned ou des pools SSD qui dépendent de savoir ce qui est libre.

Activer discard sur le disque virtuel si votre backend le supporte (les zvol ZFS le peuvent, Ceph RBD le peut, LVM-thin le peut). Ensuite activer l’optimisation Windows (qui le fait généralement automatiquement sur un disque « SSD »).

Envisager aussi l’émulation SSD : informer la VM qu’elle est sur SSD peut modifier le comportement de Windows (défragmentation vs optimisation/trim). Ce n’est pas magique, mais ça évite des travaux inutiles.

Attention : discard n’est pas gratuit. Sur certains backends il peut générer de la charge. L’objectif est d’abord la correction, ensuite la mesure.

5) Drivers VirtIO et outils invités : le système nerveux de la VM

Les problèmes de performance adorent les drivers manquants. Windows fonctionnera avec des drivers génériques, mais il fonctionnera comme une voiture de location avec le frein à main légèrement serré.

Dans Windows vous voulez :

  • Driver de stockage VirtIO (viostor ou vioscsi selon le contrôleur)
  • Driver réseau VirtIO (NetKVM)
  • Driver balloon seulement si vous utilisez volontairement le ballooning (beaucoup d’environnements ne devraient pas)
  • QEMU guest agent pour de meilleures opérations lifecycle et parfois un meilleur comportement temporel

Ne montez pas l’ISO de drivers et n’oubliez pas ensuite. Confirmez que le driver est actif dans le Gestionnaire de périphériques et que le disque utilise le contrôleur attendu.

Blague #1 : Windows sans drivers VirtIO, c’est comme une voiture de sport livrée avec des roues carrées — techniquement ça roule, mais personne n’est content.

6) Type de CPU et NUMA : arrêter de priver Windows

Si votre VM Windows est lente sous charge, vous payez peut-être des flags CPU conservateurs ou une topologie médiocre. Proxmox propose plusieurs types de CPU. Le piège sûr-mais-lent est d’utiliser un modèle CPU générique alors que « host » serait approprié.

Recommandation : utiliser type CPU : host pour les VMs sensibles à la performance sur un cluster stable (ou quand les contraintes de migration en direct sont acceptables). Cela expose plus de fonctionnalités CPU à l’invité, améliorant les performances pour crypto, compression et certains comportements d’ordonnancement.

NUMA : Si vous allouez beaucoup de vCPU et de RAM à une VM, mais qu’elle s’étale sur des nœuds NUMA sans en tenir compte, la latence augmente. Windows va planifier des threads à travers les nœuds ; si la topologie VM est inappropriée, vous obtenez des blocages aléatoires qui ressemblent à du stockage mais ne le sont pas.

Règle générale : ne pas allouer une VM plus grande qu’un nœud NUMA sauf si vous avez une bonne raison et que vous comprenez la disposition de l’hôte.

7) Ballooning mémoire et swap : la mort par « utilité »

Le ballooning est séduisant : « On peut surcommitter et tout ira bien. » Windows n’est pas d’accord. Quand la mémoire est récupérée, Windows utilise son propre paging, les caches s’effondrent, et la VM commence à faire de l’IO disque juste pour compenser le manque de RAM. C’est ainsi qu’un problème mémoire devient un problème disque.

Recommandation : pour les VM Windows sensibles à la performance, définir une taille mémoire fixe et désactiver le ballooning à moins d’avoir un processus de gestion de capacité éprouvé.

Sur l’hôte, assurez-vous que vous ne swappez pas en charge. L’activité de swap hôte rend la latence invité chaotique, et la latence chaotique est ce que les utilisateurs perçoivent comme « lent ».

8) Tuning du backend de stockage (ZFS/Ceph/LVM) : faire correspondre tailles de bloc et files

C’est là où la plupart des posts « ma VM est lente » meurent : le backend fait exactement ce que vous avez demandé, pas ce que vous vouliez. Proxmox abstrait le stockage, mais vos disques obéissent toujours à la physique, à l’amplification d’écriture et aux sémantiques de flush.

ZFS (zvols et datasets)

  • volblocksize compte pour les zvols. S’il est mal assorti à la charge, vous payez en amplification d’écriture et en latence.
  • les écritures sync sont coûteuses sans un SLOG approprié. Windows peut générer des patterns quasi-synchrones (métadonnées, journaling, flushs applicatifs).
  • la compression peut aider ou nuire selon le CPU et la charge ; les CPU modernes la rendent souvent gagnante.

Ceph RBD

  • Ceph peut fournir un excellent débit mais avoir une latence de base plus élevée que du NVMe local.
  • Les petites écritures aléatoires sont sensibles aux performances réseau et des OSD ; « c’est juste 4k » n’est pas rassurant.
  • Le cache RBD et les paramètres client peuvent changer le comportement, mais commencez par mesurer la distribution de latence.

LVM-thin / SSD local

  • Le thin provisioning a besoin de discard pour éviter une pression d’espace silencieuse.
  • Vérifiez le scheduler du périphérique sous-jacent et la profondeur de file ; les valeurs par défaut ne sont pas toujours optimales.
  • Surveillez le comportement de cliff d’écriture sur les SSD grand public (épuisement du cache SLC). Vous le verrez comme des pics de latence soudains.

Blague #2 : Si votre backend de stockage est un seul SSD grand public sans protection contre la perte d’alimentation, « writeback cache » n’est que la manière rapide de préparer votre CV.

Tâches pratiques : commandes, sorties et décision à prendre

Voici les tâches que je lance réellement quand une VM Windows semble lente sur Proxmox. Chacune inclut une commande, une sortie d’exemple, et la décision que cela implique. Exécutez-les sur l’hôte Proxmox sauf indication contraire.

Task 1: Identify VM configuration (disk bus, cache, iothread, discard)

cr0x@server:~$ qm config 104
boot: order=scsi0;ide2;net0
cores: 8
cpu: x86-64-v2-AES
memory: 16384
name: win-app-01
net0: virtio=DE:AD:BE:EF:10:04,bridge=vmbr0,firewall=1
ostype: win11
scsi0: local-zfs:vm-104-disk-0,cache=none,discard=on,iothread=1,ssd=1,size=200G
scsihw: virtio-scsi-single

Ce que cela signifie : Le disque est sur VirtIO SCSI single, cache=none, discard=on, iothread activé, émulation SSD activée. C’est la forme des « bons réglages par défaut ».

Décision : Si vous voyez ide0, sata0, cache=writeback sans histoire de durabilité, ou l’absence de iothread=1, corrigez la configuration avant de courir après des fantômes.

Task 2: Confirm the VM is actually running and not memory balloon-thrashing

cr0x@server:~$ qm status 104 --verbose
status: running
cpus: 8
memory: 16384
balloon: 0
uptime: 91234

Ce que cela signifie : balloon: 0 implique que le ballooning est désactivé (mémoire fixe). Bon pour une performance prévisible.

Décision : Si le ballooning est activé et que l’hôte manque de RAM, désactivez-le pour les Windows sensibles à la latence, ou corrigez la capacité de l’hôte.

Task 3: Find which process/thread is burning CPU on the host during “disk slowness”

cr0x@server:~$ top -H -p $(pgrep -f "kvm.*104" | head -n1)
top - 10:03:11 up 12 days,  5:44,  2 users,  load average: 6.10, 5.92, 5.80
Threads:  52 total,   1 running,  51 sleeping
%Cpu(s): 22.0 us,  3.0 sy,  0.0 ni, 75.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
31241 root      20   0 6143200 902144  21760 S  98.0   1.4  10:22.11 iothread
31200 root      20   0 6143200 902144  21760 S  12.0   1.4   2:13.45 CPU 0/KVM
31201 root      20   0 6143200 902144  21760 S  11.5   1.4   2:11.88 CPU 1/KVM

Ce que cela signifie : Un iothread est présent et occupé. C’est normal s’il correspond à une charge disque réelle. Si le thread KVM principal est saturé sur IO, il vous faut probablement un iothread ou un meilleur contrôleur.

Décision : Si un seul thread QEMU est à 100% pendant l’IO, activez iothread et assurez-vous d’utiliser VirtIO SCSI/NVMe.

Task 4: Measure host disk latency and queueing

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

avg-cpu:  %user %nice %system %iowait  %steal  %idle
          10.12  0.00    2.31    8.44    0.00  79.13

Device            r/s     w/s   rkB/s   wkB/s  rrqm/s  wrqm/s  %util  await  r_await  w_await
nvme0n1         220.0   180.0  8800.0  7200.0     0.0     5.0   92.0  18.2    9.1     29.0

Ce que cela signifie : await en double chiffre sous charge suggère une latence réelle. Si c’est le périphérique qui sert votre VM et que Windows est « lent », le backend est probablement la limite.

Décision : Si %util est élevé et await aussi, corrigez le stockage (support plus rapide, meilleur layout de pool, SLOG pour sync, réduire l’amplification d’écriture). Si les disques hôte vont bien mais que la VM est lente, regardez la config VM/drivers.

Task 5: Identify which storage device backs the VM disk

cr0x@server:~$ pvesm path local-zfs:vm-104-disk-0
/dev/zvol/rpool/data/vm-104-disk-0

Ce que cela signifie : Le disque VM est un zvol ZFS. Les règles de tuning ZFS s’appliquent.

Décision : Si c’est sur ZFS, vérifiez volblocksize, le comportement sync, et si le pool a un log device rapide pour les charges sync-intensives.

Task 6: Check ZFS pool health and latency signals

cr0x@server:~$ zpool status -v rpool
  pool: rpool
 state: ONLINE
  scan: scrub repaired 0B in 00:18:44 with 0 errors on Sun Dec 22 03:12:18 2025
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

Ce que cela signifie : Pool sain. La santé ne signifie pas rapide, mais cela élimine « resilvering dégradé » comme coupable de performance.

Décision : Si le pool est dégradé ou en resilvering, attendez-vous à de la latence. Réparez l’état matériel/pool d’abord ; le tuning ne rattrapera pas une reconstruction.

Task 7: Inspect ZFS dataset properties that affect VM disks

cr0x@server:~$ zfs get -o name,property,value -s local recordsize,compression,atime,sync rpool/data
NAME        PROPERTY     VALUE
rpool/data  recordsize   128K
rpool/data  compression  lz4
rpool/data  atime        off
rpool/data  sync         standard

Ce que cela signifie : Recordsize s’applique aux datasets, pas aux zvols, mais cela indique une intention générale. Compression activée et atime off sont généralement de bons choix.

Décision : N’« optimisez » pas en mettant sync=disabled sur le stockage VM sauf si vous acceptez volontairement la perte de données en crash. Utilisez le bon matériel à la place.

Task 8: Check zvol volblocksize (critical for Windows VM IO patterns)

cr0x@server:~$ zfs get -o name,property,value volblocksize rpool/data/vm-104-disk-0
NAME                      PROPERTY      VALUE
rpool/data/vm-104-disk-0   volblocksize  8K

Ce que cela signifie : Volblocksize 8K est souvent un compromis raisonnable pour des charges VM générales. Trop grand amplifie les petites écritures ; trop petit augmente l’overhead métadonnées.

Décision : Si vous voyez 128K volblocksize sur un disque système Windows avec beaucoup de petites écritures aléatoires, envisagez de recréer le disque avec un volblocksize plus petit et de migrer.

Task 9: Observe ZFS IO and latency pressure in real time

cr0x@server:~$ zpool iostat -v rpool 1 5
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
rpool       1.20T  600G    800    650   60.0M  48.0M
  mirror-0  1.20T  600G    800    650   60.0M  48.0M
    nvme0n1     -      -   420    330   31.0M  24.0M
    nvme1n1     -      -   380    320   29.0M  24.0M

Ce que cela signifie : Vous voyez les taux de lecture/écriture et ops réels. Si Windows « gèle » quand ces chiffres montent, vous êtes corrélé à l’activité stockage.

Décision : Si le pool est saturé pendant les arrêts visibles par l’utilisateur, déplacez les voisins bruyants, ajoutez des vdevs plus rapides, ou séparez les charges.

Task 10: Check host memory pressure and swap (latency’s silent killer)

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:           256Gi       210Gi        12Gi       2.0Gi        34Gi        38Gi
Swap:           16Gi       3.2Gi        13Gi

Ce que cela signifie : Le swap est utilisé. Cela peut être historique, ou une douleur active.

Décision : Si le swap augmente pendant la fenêtre de lenteur, arrêtez le surcommit mémoire ou déplacez des VMs. Le swap hôte rend la latence invité chaotique.

Task 11: See if the kernel is actively swapping under load

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 3355443 1200000  8000 32000000    0    0   120   220  800 1200 12  3 77  8  0
 3  1 3355443 1150000  8000 31500000    0  256  1024  4096 1200 1800 10  4 65 21  0
 2  0 3355700 1100000  8000 31000000  128  512   900  3800 1100 1600 11  4 62 23  0

Ce que cela signifie : Des si/so non nuls indiquent un swapping actif. C’est un incident de performance au ralenti.

Décision : Corrigez la pression mémoire. Ne touchez pas aux modes cache pour compenser le swap ; c’est comme changer la pression des pneus pour réparer un cognement moteur.

Task 12: Check block device scheduler and queue settings (local disks)

cr0x@server:~$ cat /sys/block/nvme0n1/queue/scheduler
[mq-deadline] none

Ce que cela signifie : Le scheduler est mq-deadline. Pour NVMe, c’est couramment approprié. Pour certains arrays, « none » peut être meilleur ; pour des charges mixtes, un comportement de type deadline aide la latence de queue.

Décision : Si vous dépannez la latence tail, testez les changements de scheduler avec précaution et mesurez. Ne faites pas du « none partout » sans réflexion.

Task 13: Check VM disk options at the QEMU commandline level (sanity)

cr0x@server:~$ ps -ef | grep -E "kvm.*104" | head -n1
root     31200     1 18 09:40 ?        00:42:10 /usr/bin/kvm -id 104 -name win-app-01 -m 16384 -smp 8 -cpu x86-64-v2-AES ... -device virtio-scsi-pci,id=scsihw0 ... -drive file=/dev/zvol/rpool/data/vm-104-disk-0,if=none,id=drive-scsi0,cache=none,aio=io_uring,discard=unmap ...

Ce que cela signifie : Confirme les réglages effectifs (cache, discard, aio). Cela détecte les divergences entre ce que vous pensez que Proxmox a configuré et ce que QEMU exécute réellement.

Décision : Si vous attendez discard=unmap et qu’il est absent, revérifiez les options matérielles VM et le support stockage.

Task 14: Verify Ceph latency quickly (if using RBD)

cr0x@server:~$ ceph -s
  cluster:
    id:     9c1f3a1a-aaaa-bbbb-cccc-1234567890ab
    health: HEALTH_OK

  services:
    mon: 3 daemons, quorum mon1,mon2,mon3
    mgr: mgr1(active), standbys: mgr2
    osd: 12 osds: 12 up, 12 in

  data:
    pools:   4 pools, 256 pgs
    objects: 1.20M objects, 4.6 TiB
    usage:   13 TiB used, 22 TiB / 35 TiB avail
    pgs:     256 active+clean

Ce que cela signifie : HEALTH_OK n’assure pas une faible latence, mais cela élimine « cluster en feu » de votre liste.

Décision : Si l’état n’est pas OK (backfill, dégradé, opérations lentes), arrêtez de tuner la VM et réparez Ceph d’abord. Windows ne gagnera pas face à des opérations lentes obstinées.

Task 15: Confirm Windows is using VirtIO storage driver (host-side check via agent)

cr0x@server:~$ qm agent 104 get-osinfo
{
  "id": "mswindows",
  "kernel-release": "10.0.22631",
  "name": "Microsoft Windows 11 Pro",
  "pretty-name": "Microsoft Windows 11 Pro",
  "version": "11"
}

Ce que cela signifie : L’agent invité fonctionne. Ce n’est pas un gain de performance en soi, mais cela permet des opérations plus fiables et une meilleure visibilité.

Décision : Si l’agent n’est pas installé, installez-le. Quand vous diagnostiquez la performance, il vaut mieux avoir moins d’angles morts.

Erreurs courantes : symptôme → cause racine → correction

1) « Windows est lent seulement pendant les mises à jour et les redémarrages »

Symptôme : Les redémarrages prennent une éternité, les mises à jour avancent au pas, « Travail sur les mises à jour » ressemble à un choix de vie.

Cause racine : Windows Update est riche en métadonnées et en flushs ; mauvais contrôleur disque, driver VirtIO manquant, ou latence sync ZFS exposée.

Correction : Déplacer le disque système vers VirtIO SCSI (ou NVMe virtuel), installer le driver de stockage VirtIO, utiliser cache=none, et s’assurer que le backend peut gérer les écritures sync (SLOG ou matériel adapté).

2) « Les benchmarks sont excellents, les applis réelles sont horribles »

Symptôme : Les tests séquentiels semblent bien ; l’interaction utilisateur et le lancement d’applis saccadent.

Cause racine : Vous avez optimisé le débit, mais la charge est sensible à la latence tail. Souvent : cache writeback masquant les flushs, ou chemin IO mono-thread sans iothread.

Correction : Activer iothread, préférer cache=none, et mesurer la distribution de latence (await, pas seulement MB/s).

3) « Gel aléatoire de 2–10 secondes, puis récupération »

Symptôme : La VM « se bloque » brièvement, surtout sous charge ; latence souris/clavier dans la console.

Cause racine : Swap hôte, contention des transaction groups ZFS, ou pics de latence du backend stockage (cliff d’un SSD grand public, ops Ceph lentes).

Correction : Arrêter le swap hôte (plus de RAM, moins d’overcommit), s’assurer que le stockage n’est pas saturé, vérifier pour ops lentes/rebuild, et éviter le ballooning.

4) « L’utilisation CPU est élevée mais ça semble lié à l’IO »

Symptôme : Windows montre un CPU élevé ; l’hôte affiche un cœur occupé ; les métriques disque semblent modérées.

Cause racine : Surcharge due à l’émulation de périphérique (IDE/SATA) ou absence de drivers para-virtualisés provoquant un CPU élevé par IO.

Correction : Passer à VirtIO SCSI/NVMe et installer les bons drivers ; activer iothread.

5) « Le réseau est lent, mais seulement pour cette VM Windows »

Symptôme : Les copies SMB sont lentes ; les autres VMs vont bien.

Cause racine : Utilisation de l’émulation e1000 ou driver VirtIO net manquant ; paramètres d’offload mal configurés.

Correction : Utiliser VirtIO net ; installer le driver NetKVM ; confirmer MTU et configuration du bridge ; mesurer avec iperf-like et ne pas confondre disque et réseau.

6) « Tout allait bien jusqu’à ce qu’on active discard »

Symptôme : Pics IO périodiques après activation de discard/trim.

Cause racine : Le backend traite discard comme du vrai travail (mises à jour metadata thin provisioning, discards Ceph, ou maps d’espace libre ZFS) et vous l’avez exposé.

Correction : Garder discard (la correction compte), mais planifier les tâches d’optimisation Windows, envisager un throttling, et dimensionner correctement le backend. Si les discards sont pathologiques, revoir la configuration backend plutôt que de désactiver discard aveuglément.

Trois mini-récits d’entreprise depuis les tranchées de la performance

Mini-récit 1 : L’incident causé par une fausse hypothèse

Le ticket commençait par « Citrix est lent. » Comme toujours. Les utilisateurs signalaient qu’ouvrir Outlook dans une VM Windows prenait des minutes. Quelques admins insistaient que c’était la nouvelle politique antivirus, parce que « le disque est SSD et le réseau va bien. » Cette hypothèse — « SSD implique faible latence » — était la graine de l’incident.

Sur l’hôte Proxmox, iostat montrait un débit modéré mais des pics d’await moches. Les VMs Windows étaient sur ZFS, et le pool était sain. Le détail décisif : la charge était sync-heavy dû au comportement de flush de l’application et à la façon dont Windows met à jour les métadonnées. Il n’y avait pas de log device dédié, et le pool reposait sur des vdevs miroir de NVMe grand public sans protection perte d’alimentation.

L’équipe avait aussi activé cache=writeback « pour la vitesse », pensant que c’était inoffensif parce que « c’est sur SSD ». Sous pression, le système oscillait entre des rafales rapides et des blocs quand les flushs revenaient. Les utilisateurs percevaient cela comme des gels aléatoires. L’hôte, lui, vivait un périphérique stockage qui devait parfois « dire la vérité ».

La correction fut douloureusement simple et politiquement irritante : revenir à cache=none, déployer des NVMe entreprise avec PLP, et ajouter un fast log device pour le pool ZFS où vivaient les VMs sync-heavy. Soudain, les mêmes VMs se comportaient comme si elles appartenaient à un datacenter plutôt qu’à une foire scientifique.

La leçon du postmortem n’était pas « ZFS est lent » ni « Windows est bizarre ». C’était que la pile a des contrats. Si vous supposez que SSD = durabilité et faible latence, vous dépannerez des attentes humaines, pas des machines.

Mini-récit 2 : L’optimisation qui s’est retournée contre eux

Une autre organisation exécutait un cluster Proxmox mixte : certains nœuds avec NVMe local, d’autres backed par Ceph. Ils voulaient « une performance VM cohérente », alors ils standardisèrent un template VM : VirtIO SCSI, iothread activé, discard on, et un disque virtuel unique pour la simplicité.

Puis ils firent un changement malin : activer le ballooning mémoire agressif sur la flotte pour améliorer la consolidation. Les graphiques ressemblaient à du succès. Le CFO était ravi. Les VMs Windows, pas du tout.

Pendant les heures de pointe, l’hôte récupérait de la mémoire. Windows répondit en paginant et en vidant ses caches. Cela créa davantage d’IO disque. Sur les nœuds Ceph, cela signifiait plus de petites écritures aléatoires et davantage de churn metadata. La latence augmenta. La latence accrue ralentit les applications, ce qui augmenta les retries utilisateurs, augmentant la charge. Une boucle de rétroaction de performance, présentée comme « efficacité de capacité ».

Ils essayèrent d’y répondre en augmentant les vCPU. Cela empirait la contention : plus de threads aptes à tourner se disputant la même bande passante IO et mémoire. Les VMs paraissaient plus occupées tout en accomplissant moins — un grand classique du « nous avons mis à l’échelle le problème ».

La correction finale fut ennuyeuse et efficace : désactiver le ballooning pour les serveurs d’applications Windows, réserver de la mémoire sur l’hôte, et séparer les charges sensibles à la latence des bruyantes. La densité diminua un peu. Les incidents chutèrent beaucoup. Cet arbitrage s’appelle « devenir adulte ».

Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Une équipe avec laquelle j’aimais bosser avait un rituel : chaque fois qu’ils déployaient un nouveau nœud Proxmox ou modifiaient le stockage, ils exécutaient la même suite de validations. Pas un cirque de benchmarks — juste quelques vérifications reproductibles : comportement swap hôte, await iostat sous charge synthétique, et une vérification sanity d’une VM Windows confirmant drivers VirtIO et types de contrôleur.

Ils gardaient aussi des templates VM stricts. Personne n’était autorisé à lancer Windows en SATA « juste pour l’installer ». Le template contenait VirtIO SCSI et l’ISO de drivers attachée ; les étapes de build incluaient la vérification du binding driver. C’était ennuyeux. Ça fonctionnait.

Un trimestre, une mise à jour de firmware stockage introduisit une régression de latence subtile. Rien ne cassait. Mais les checks routiniers montrèrent une latence tail plus élevée sur les écritures aléatoires. Ils stoppèrent le déploiement, revinrent sur le firmware des nœuds mis à jour, et évitèrent un mois de tickets « les utilisateurs disent que c’est lent » qui ne se reproduisent jamais quand on regarde.

Ce n’était pas de la magie. C’était de la discipline : une petite checklist, une baseline connue, et l’humilité de croire que les régressions de performance sont réelles même quand personne ne pointe un cratère fumant.

Listes de contrôle / plan pas à pas

Checklist A: Make an existing slow Windows VM sane (minimal downtime approach)

  1. Collecter des métriques de base : hôte iostat -x, hôte vmstat, config VM via qm config.
  2. Vérifier contrôleur et options disque : assurer VirtIO SCSI (ou NVMe), cache=none, iothread=1, discard=on quand supporté.
  3. Installer les drivers VirtIO dans Windows si absent (stockage + réseau). Confirmer qu’ils sont actifs.
  4. Désactiver le ballooning pour les charges sensibles à la latence ; définir une mémoire fixe.
  5. Basculer le type CPU sur host là où les contraintes de migration le permettent ; s’assurer qu’il y a un nombre de vCPU raisonnable.
  6. Retester en charge réelle et vérifier que la latence hôte s’est améliorée ou au moins stabilisée.

Checklist B: New Windows VM template that won’t embarrass you later

  1. Machine type : moderne (q35) sauf besoin de compatibilité legacy.
  2. Disque : VirtIO SCSI single (ou NVMe), cache=none, iothread=1, discard=on, ssd=1.
  3. Réseau : VirtIO net.
  4. CPU : host (ou un modèle cohérent sur le cluster si migration seamless nécessaire).
  5. Mémoire : fixe ; ballooning off par défaut pour les serveurs d’applications Windows.
  6. Installation : ISO driver VirtIO attachée ; confirmer les bons drivers avant de finir le build.
  7. Post-install : QEMU guest agent installé ; plan d’alimentation Windows réglé pour serveurs (éviter économies d’énergie agressives).

Checklist C: Storage backend sanity for Windows VMs

  1. Confirmer la santé du stockage (pas de rebuild/backfill).
  2. Mesurer la latence (iostat -x) sous charge IO représentative.
  3. ZFS : valider le choix de volblocksize avant provisionnement ; envisager SLOG pour les charges sync-heavy.
  4. Ceph : surveiller les slow ops et le jitter réseau ; éviter de mélanger workloads critiques en latence et workloads bulk sans plan.
  5. Thin provisioning : s’assurer que discard fonctionne et surveiller la pression d’espace libre.

FAQ

1) Dois-je utiliser VirtIO SCSI ou NVMe virtuel pour Windows sur Proxmox ?

Si vous voulez un défaut sûr : VirtIO SCSI (souvent virtio-scsi-single) avec iothread activé. Si vous visez un IOPS élevé avec Windows moderne et préférez la sémantique NVMe, NVMe virtuel peut être excellent. Mesurez dans les deux cas ; ne présumez pas.

2) Est-ce que cache=writeback est toujours plus rapide ?

Il paraît souvent plus rapide jusqu’à ce que les flushs arrivent, puis la réalité réapparaît. Ne l’utilisez que si vous pouvez défendre la durabilité (protection d’alimentation, sémantiques de flush correctes, et backend de stockage fiable en cas de crash).

3) Pourquoi Windows « gèle » quand le disque est occupé ?

Parce qu’une grande partie de l’interface Windows et du comportement des services est entièrement dépendante de la latence de stockage, pas du débit. Une haute latence tail rend tout le système bloqué même si la moyenne MB/s semble correcte.

4) Activer discard/TRIM aide-t-il la performance ?

Ça aide la correction et la stabilité à long terme sur des systèmes thin et SSD en informant le backend des espaces libres. À court terme, cela peut ajouter du travail. Si activer discard provoque des pics, vous avez appris quelque chose sur votre backend.

5) Combien de vCPU donner à une VM Windows ?

Autant que nécessaire pour la concurrence de la charge, pas assez pour créer de la contention d’ordonnancement. Commencez petit et augmentez si besoin. Surdimensionner les vCPU peut aggraver la latence, surtout sur des hôtes chargés.

6) Dois-je activer le ballooning pour les VMs Windows ?

Pour des environnements test/dev ou des desktops à faible enjeu, peut-être. Pour des serveurs d’applications Windows en production où les humains perçoivent la latence, généralement non. La mémoire fixe apporte de la prévisibilité.

7) Mon IO hôte a l’air correct, mais Windows a toujours une longue file disque. Pourquoi ?

Souvent un problème de driver/contrôleur (mauvais bus, VirtIO manquant), ou le chemin IO de la VM est mono-thread et sature un thread QEMU. Vérifiez le type de contrôleur, iothread, et le binding du driver Windows.

8) ZFS peut-il être rapide pour des VMs Windows ?

Oui. Mais il faut respecter les écritures sync et la taille des blocs. ZFS ne prétendra pas que les écritures sync sont bon marché. Si votre charge exige une faible latence sync, concevez le pool en conséquence.

9) Quel est le changement ayant le plus d’impact pour une VM Windows lente ?

Passer d’un IDE/SATA émulé à VirtIO SCSI (ou NVMe) avec le driver de stockage VirtIO approprié. Ce n’est pas subtil.

10) Si je ne peux pas réinstaller Windows, puis-je quand même changer de contrôleur ?

En général oui, mais faites-le avec précaution : installez d’abord les drivers VirtIO pendant que l’ancien contrôleur permet encore le démarrage, puis ajoutez le nouveau contrôleur/mapping disque, et basculez le boot. Testez avec snapshots/sauvegardes.

Conclusion : prochaines étapes qui ne gâcheront pas votre week-end

Accélérez votre VM Windows en corrigeant les parties ennuyeuses : le contrôleur disque, le contrat de cache, le threading IO, et les drivers. Validez ensuite que l’hôte ne swappe pas et que la latence du backend de stockage est compatible avec les attentes humaines.

Prochaines étapes concrètes :

  1. Exécuter qm config <vmid> et confirmer VirtIO SCSI/NVMe, cache=none, iothread=1, discard=on quand supporté.
  2. Mesurer la latence hôte avec iostat -x 1 pendant la lenteur. Si await est mauvais, arrêtez de tuner l’invité et réparez le stockage.
  3. Désactiver le ballooning pour la VM (et corriger la pression RAM hôte) si vous observez du swapping ou de la récupération mémoire.
  4. Standardiser un template Windows qui intègre les bons choix contrôleur/driver pour ne pas retomber là-dessus le trimestre suivant.

Le travail de performance n’est rarement une question d’astuces géniales. Il s’agit d’éliminer des goulots accidentels et de refuser d’expédier des valeurs par défaut conçues pour la compatibilité, pas pour la vitesse.

← Précédent
ZFS Scrub vs SMART Long Test : lequel détecte quoi
Suivant →
Proxmox « QEMU exited with code 1 » : lire l’erreur, trouver la cause réelle

Laisser un commentaire