Vous pouvez exécuter ZFS à l’intérieur d’une VM sur Proxmox. Des gens le font tous les jours. Certains d’entre eux dorment même la nuit.
Mais le « comment » importe : le passthrough HBA est généralement le choix mature, tandis que les disques virtuels sont le raccourci tentant qui se transforme en incident à 3 h du matin une fois que vous mélangez couches de cache, ordonnancement des écritures et contrôleurs RAID « serviables ».
Prenez la décision d’abord : ce que vous optimisez
Il n’y a que quelques raisons légitimes pour mettre ZFS dans une VM :
- Vous voulez les fonctionnalités ZFS à l’intérieur de l’invité : flux natifs send/receive, politiques au niveau des datasets, chiffrement, instantanés que l’invité contrôle.
- Vous fournissez « stockage en tant que service » à quelque chose comme Kubernetes et vous voulez que la pile de stockage soit isolée du cycle de vie de l’hyperviseur.
- Vous migrez depuis ZFS bare-metal et voulez conserver la mémoire opérationnelle et les procédures en place.
- Vous avez des contraintes matérielles (hôtes partagés, baies limitées) et vous tentez de consolider sans renoncer à la sémantique ZFS.
Il existe aussi des raisons qui paraissent légitimes jusqu’à ce qu’elles ne le soient pas :
- « Je vais juste créer quelques disques virtuels et laisser ZFS les gérer. » Ce n’est pas « faux », mais cela empile caches, barrières d’écriture et rapport d’erreurs d’une manière qui rend les pannes plus difficiles à comprendre. C’est une taxe sur la fiabilité que vous paierez plus tard.
- « Le passthrough fait peur. » Ce n’est pas effrayant. C’est pointilleux. Ce sont des choses différentes.
Si vous voulez une recommandation par défaut claire :
- Pour les données sérieuses : passez en passthrough un HBA (ou des périphériques NVMe entiers) et laissez l’invité voir de vrais disques.
- Pour des charges jetables ou de test : les disques virtuels conviennent, mais choisissez des modes de cache sûrs et acceptez les limites.
Voici votre seul raccourci autorisé : si les données comptent et que vous demandez « est-ce correct ? », la réponse est non. Faites du passthrough.
Faits intéressants et bref historique (vous les utiliserez plus tard)
- ZFS a été conçu pour mettre fin à la corruption silencieuse des données, et il suppose qu’il peut voir les erreurs de périphérique et l’ordonnancement. La virtualisation du stockage brouille souvent les deux.
- Le « ZIL » n’est pas un journal séparé par défaut. C’est un journal d’intention sur le pool ; le SLOG n’est qu’un périphérique externe pour les écritures synchrones.
- Les disques à secteurs 4K ont forcé le monde à se soucier de l’alignement. C’est pourquoi ashift existe, et pourquoi « ça passe au benchmark » peut quand même être faux.
- Le passthrough VT-d/IOMMU était autrefois une fonctionnalité de luxe. Maintenant c’est courant, mais la topologie PCIe de la carte mère décide toujours si votre journée sera facile.
- Virtio a été conçu pour être paravirtualisé et rapide, mais c’est toujours une abstraction. Les abstractions cachent des choses, y compris des ennuis.
- Les caches d’écriture sur les contrôleurs RAID ont causé une décennie de pertes de données surprises. Certains de ces contrôleurs sont encore dans des serveurs, souriant poliment.
- Les sommes de contrôle ZFS couvrent les données et les métadonnées, mais il ne peut pas valider ce qu’il ne reçoit jamais. Si l’hyperviseur ment, ZFS ne peut pas le contester.
- Le NVMe grand public est devenu rapide avant d’être prévisible. Les pics de latence importent plus pour les VM que le débit annoncé.
Deux modèles : passthrough HBA vs disques virtuels
Modèle A : passthrough HBA (ou passthrough de périphérique)
C’est le modèle « ZFS voit de vrais disques ». Vous passez en passthrough un HBA (LSI/Broadcom en mode IT est le classique), ou des périphériques NVMe entiers, et l’invité possède la pile de stockage du contrôleur au pool.
Ce que vous gagnez :
- Vrai reporting d’erreurs (SMART quand pris en charge, codes sense réels, timeouts réels).
- Ordonnancement des écritures prévisible : moins de cas où « l’invité pensait que c’était durable ».
- Réglage de performance plus propre : vous réglez ZFS, pas ZFS plus QEMU plus système de fichiers hôte plus backend de stockage.
- Les scrubs et les resilvers se comportent comme un vrai ZFS, pas comme « ZFS au-dessus du fichier de quelqu’un ».
Ce que vous payez :
- Les groupes IOMMU peuvent vous forcer à passer plus de périphériques que vous ne le souhaitez (ou vous bloquer complètement).
- La migration à chaud devient difficile ou impossible sauf si vous déplacez aussi le périphérique physique (ce que vous ne pouvez pas faire).
- La visibilité depuis l’hôte est réduite. L’hôte ne peut pas facilement sauvegarder « à l’intérieur » du pool sans coopération de l’invité.
- Opérations : vous gérez maintenant ZFS dans l’invité. C’est correct — admettez-le simplement.
Modèle B : disques virtuels (qcow2/raw sur ZFS, LVM-thin, Ceph, etc.)
C’est le modèle « ZFS dans l’invité, mais les disques de l’invité sont virtuels ». L’invité voit /dev/vda ou /dev/sdX comme périphériques virtuels. Ces périphériques sont rétroportés par quelque chose sur l’hôte : un zvol ZFS, un fichier sur ZFS, un volume logique LVM, ou un backend distribué comme Ceph.
Ce que vous gagnez :
- Cycle de vie facile : snapshots, sauvegardes, clonage au niveau de l’hyperviseur.
- La migration à chaud est faisable (selon le backend).
- Indépendance matérielle : pas de drame IOMMU.
- Surveillance centralisée depuis l’hôte.
Ce que vous payez :
- Vous superposez des systèmes de fichiers/piles de stockage. Quand ça casse, vous devez déboguer toute la lasagne.
- Les choix de mode de cache comptent. Un bit incorrect et « écriture durable » devient une « fiction optimiste ».
- Le comportement TRIM/discard peut être surprenant, surtout avec des snapshots.
- SMART et la télémétrie détaillée du disque disparaissent généralement (ou deviennent « meilleur effort »).
Règle opiniâtre : Si vous prévoyez d’exécuter ZFS dans l’invité, ne le soutenez pas avec qcow2 sauf si vous échangez volontairement intégrité et performance contre commodité. Utilisez raw ou des périphériques bloc si vous insistez sur les disques virtuels.
Blague #1 : Une pile de stockage avec trois couches de cache est comme un organigramme d’entreprise : tout le monde revendique la propriété, personne n’assume la responsabilité.
Vérification IOMMU : groupes, ACS, et pourquoi votre NIC a déménagé
Le passthrough n’est pas « activer un interrupteur ». C’est « convaincre la plateforme d’isoler correctement un périphérique PCIe afin que l’hyperviseur puisse le donner à un invité sans transformer le DMA en cauchemar ». C’est ce que fait l’IOMMU : elle fournit remappage et isolation pour le DMA des périphériques.
Ce qui se passe habituellement mal
- Votre HBA partage un groupe IOMMU avec quelque chose dont vous avez besoin (une carte réseau, un contrôleur USB, parfois le port racine PCIe entier). Si vous le passez en passthrough, vous perdez l’autre périphérique sur l’hôte.
- ACS est manquant ou limité. Certaines cartes mères grand public sont conçues pour les GPU de jeu, pas pour une isolation stricte des périphériques.
- Problèmes de reset : certains HBA ne se réinitialisent pas proprement entre les démarrages de VM, conduisant au syndrome « ça marche après un reboot de l’hôte ».
- Gestion des interruptions et affinité CPU : pas strictement IOMMU, mais c’est là que la latence apparaît une fois que vous avez « réussi » le passthrough.
Ce que signifie vraiment « ACS override »
Linux peut parfois séparer les groupes IOMMU avec un paramètre noyau ACS override. C’est un hack. Parfois c’est un hack raisonnable, parfois c’est le genre de hack qui finit en réunion conformité. Si la plateforme ne peut pas fournir l’isolation, vous demandez au logiciel de faire semblant.
Pour les laboratoires domestiques, l’ACS override est souvent « acceptable ». Pour la production avec un risque significatif, achetez du matériel avec une isolation PCIe adéquate. Votre futur vous enverra peut-être un panier de fruits. Ou au moins il ne vous réveillera pas.
Performance et intégrité : où gisent les cadavres
Ordonnancement des écritures : le tueur silencieux
ZFS se soucie de l’ordonnancement des écritures parce que c’est transactionnel. Il s’attend à ce que si l’OS dit « ceci est sur un stockage stable », le périphérique (ou la pile en dessous) soit d’accord. La virtualisation peut casser cela de manière subtile :
- Le mode de cache de l’hôte « writeback » peut accuser réception des écritures avant qu’elles ne soient durables.
- Le backend de stockage peut réordonner les écritures à moins que les barrières/flush soient honorées de bout en bout.
- Des hôtes sans UPS avec des caches agressifs transforment une coupure de courant en atelier d’intégrité des données.
Conclusion pratique : si vous utilisez des disques virtuels, choisissez des modes de cache et des backends qui préservent la sémantique de durabilité. Si vous utilisez le passthrough, validez que le contrôleur ne fait pas de RAID ni ne ment sur les flushs.
ZFS double : oui, certains le font ; non, vous ne devriez pas par défaut
Exécuter ZFS sur l’hôte et ZFS dans l’invité (l’invité étant soutenu par un zvol ou un fichier) est courant. C’est aussi un excellent moyen de créer des domaines de panne confus :
- Le ZFS invité pense gérer des disques ; il gère en fait « une tranche d’un pool ».
- La synchronisation des scrubs et les modèles d’IO peuvent se combattre : scrub hôte plus scrub invité égale « pourquoi tout est lent ? »
- Les choix de compression et de recordsize peuvent s’empiler négativement.
- L’amplification d’écriture augmente, surtout pour les petites écritures aléatoires.
Si vous voulez des fonctionnalités ZFS, choisissez la couche qui les possède. ZFS hôte avec zvols pour les disques VM est correct. ZFS invité avec passthrough est correct. ZFS-sur-ZFS est un cas spécial, pas une pratique par défaut.
SLOG et écritures synchrones dans une VM
Si votre charge est riche en synchrones (NFS, bases de données avec fsync, images de VM stockées dans l’invité), ZFS utilisera le chemin ZIL. Dans une VM, cela se complique :
- Un SLOG rapide aide seulement si la sémantique sync est vraiment durable de bout en bout.
- Si l’hôte ment sur les flushes, votre « sync rapide » n’est qu’une corruption accélérée.
- Si vous passez en passthrough un NVMe comme SLOG, assurez-vous qu’il a une protection contre la perte de puissance si vous tenez aux écritures synchrones reconnues.
TRIM/discard et provisionnement fin : l’espace ment dans les deux sens
Avec des disques virtuels, le thin provisioning est pratique jusqu’à ce que vous découvriez que l’invité ne peut pas rendre efficacement l’espace, ou que les snapshots de l’hôte empêchent la récupération. Avec le passthrough, TRIM est plus proche de la réalité (bien que toujours dépendant du support du disque/contrôleur). La différence opérationnelle est énorme : un modèle échoue par « pools mystérieusement pleins », l’autre échoue par « endurance SSD mystérieusement morte ». Choisissez votre aventure, puis surveillez en conséquence.
Idée paraphrasée (attribuée) : Werner Vogels a un mantra opérationnel bien connu : « Tout échoue, tout le temps. » Concevez comme si vous y croyiez.
Tâches pratiques : commandes, sorties, et ce que la sortie signifie (et ce que vous faites ensuite)
Vous ne déboguez pas le stockage à l’instinct. Vous le déboguez avec des preuves. Ci‑dessous des vérifications concrètes qui fonctionnent sur de vrais hôtes Proxmox et de vrais invités ZFS.
Tâche 1 : Confirmer que l’IOMMU est réellement activé sur l’hôte Proxmox
cr0x@server:~$ dmesg | egrep -i 'DMAR|IOMMU|AMD-Vi' | head -n 20
[ 0.823456] DMAR: IOMMU enabled
[ 0.823789] DMAR: Host address width 39
[ 0.824001] DMAR: DRHD base: 0x000000fed90000 flags: 0x0
Ce que cela signifie : Vous avez Intel VT-d/DMAR activé et le noyau l’utilise.
Décision : Si vous ne voyez pas « IOMMU enabled », corrigez les paramètres du BIOS et les paramètres de démarrage du noyau avant de toucher aux configurations de passthrough.
Tâche 2 : Vérifier les paramètres de démarrage du noyau pour IOMMU et compatibilité passthrough
cr0x@server:~$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-6.8.12-4-pve root=/dev/mapper/pve-root ro quiet intel_iommu=on iommu=pt
Ce que cela signifie : intel_iommu=on active l’IOMMU ; iommu=pt réduit la surcharge pour les périphériques non-passthrough en utilisant des mappings passthrough.
Décision : Si vous manquez les flags IOMMU, ajoutez-les et redémarrez. Si vous êtes sur AMD, recherchez amd_iommu=on.
Tâche 3 : Identifier votre HBA et son adresse PCI
cr0x@server:~$ lspci -nn | egrep -i 'sas|sata|lsi|megaraid'
03:00.0 Serial Attached SCSI controller [0107]: Broadcom / LSI SAS2008 PCI-Express Fusion-MPT SAS-2 [1000:0072] (rev 03)
Ce que cela signifie : Le contrôleur est à 03:00.0 et est un périphérique de classe LSI SAS2008.
Décision : Utilisez l’adresse PCI dans la configuration de passthrough. Confirmez aussi qu’il est en mode IT si vous voulez que ZFS voie les disques individuellement.
Tâche 4 : Inspecter le groupe IOMMU pour ce périphérique
cr0x@server:~$ readlink -f /sys/bus/pci/devices/0000:03:00.0/iommu_group
/sys/kernel/iommu_groups/18
cr0x@server:~$ ls -l /sys/kernel/iommu_groups/18/devices
total 0
lrwxrwxrwx 1 root root 0 Feb 4 10:12 0000:03:00.0 -> ../../../../bus/pci/devices/0000:03:00.0
Ce que cela signifie : Le HBA est seul dans son groupe. C’est la bonne situation.
Décision : Si d’autres périphériques critiques partagent le groupe, déplacez les slots PCIe, changez les réglages de la carte mère, ou abandonnez le passthrough sur ce matériel.
Tâche 5 : Vérifier quel pilote possède actuellement le HBA (côté hôte)
cr0x@server:~$ lspci -k -s 03:00.0
03:00.0 Serial Attached SCSI controller: Broadcom / LSI SAS2008 PCI-Express Fusion-MPT SAS-2 (rev 03)
Subsystem: Broadcom / LSI SAS2008 PCI-Express Fusion-MPT SAS-2
Kernel driver in use: mpt3sas
Kernel modules: mpt3sas
Ce que cela signifie : L’hôte utilise mpt3sas. Pour le passthrough, vous voulez que vfio-pci le possède à la place.
Décision : Liegez-le à vfio-pci ; si l’hôte l’utilise pour son propre stockage, arrêtez-vous et repensez votre architecture.
Tâche 6 : Lier le HBA à vfio-pci (et vérifier)
cr0x@server:~$ echo "options vfio-pci ids=1000:0072" | sudo tee /etc/modprobe.d/vfio.conf
options vfio-pci ids=1000:0072
cr0x@server:~$ sudo update-initramfs -u
update-initramfs: Generating /boot/initrd.img-6.8.12-4-pve
cr0x@server:~$ sudo reboot
Connection to server closed by remote host.
cr0x@server:~$ lspci -k -s 03:00.0
03:00.0 Serial Attached SCSI controller: Broadcom / LSI SAS2008 PCI-Express Fusion-MPT SAS-2 (rev 03)
Kernel driver in use: vfio-pci
Kernel modules: mpt3sas
Ce que cela signifie : vfio-pci possède le périphérique ; l’hôte ne touchera plus à ses disques.
Décision : Il est maintenant sûr de l’attacher à une VM. S’il est toujours lié à mpt3sas, vous avez manqué initramfs ou une configuration conflictuelle.
Tâche 7 : Attacher le HBA à une VM Proxmox et confirmer que QEMU le voit
cr0x@server:~$ sudo qm set 120 -hostpci0 03:00.0,pcie=1
update VM 120: -hostpci0 03:00.0,pcie=1
cr0x@server:~$ sudo qm config 120 | egrep -i 'hostpci|machine|bios'
bios: ovmf
hostpci0: 03:00.0,pcie=1
machine: q35
Ce que cela signifie : Vous utilisez q35 et OVMF, tous deux adaptés au passthrough PCIe moderne.
Décision : Si vous êtes sur l’ancien i440fx, passez à q35 sauf raison impérative de rester.
Tâche 8 : Dans l’invité, confirmer que les disques sont visibles et les identifier en toute sécurité
cr0x@zfs-vm:~$ lsblk -o NAME,SIZE,MODEL,SERIAL,TYPE
NAME SIZE MODEL SERIAL TYPE
sda 14.6T ST16000NM001G ZR123ABC disk
sdb 14.6T ST16000NM001G ZR124DEF disk
sdc 14.6T ST16000NM001G ZR125GHI disk
sdd 14.6T ST16000NM001G ZR126JKL disk
Ce que cela signifie : L’invité voit de vrais disques avec modèle/numéro de série. C’est ce que vous voulez pour l’identité des périphériques ZFS.
Décision : Utilisez des identifiants persistants (by-id) lors de la création des pools. Si les disques apparaissent comme « QEMU HARDDISK » générique, vous n’êtes pas en passthrough réel de périphérique.
Tâche 9 : Construire le pool avec des chemins de périphériques persistants et ashift correct
cr0x@zfs-vm:~$ ls -l /dev/disk/by-id | egrep 'ZR123ABC|ZR124DEF|ZR125GHI|ZR126JKL'
lrwxrwxrwx 1 root root 9 Feb 4 10:20 ata-ST16000NM001G_ZR123ABC -> ../../sda
lrwxrwxrwx 1 root root 9 Feb 4 10:20 ata-ST16000NM001G_ZR124DEF -> ../../sdb
lrwxrwxrwx 1 root root 9 Feb 4 10:20 ata-ST16000NM001G_ZR125GHI -> ../../sdc
lrwxrwxrwx 1 root root 9 Feb 4 10:20 ata-ST16000NM001G_ZR126JKL -> ../../sdd
cr0x@zfs-vm:~$ sudo zpool create -o ashift=12 tank raidz1 \
/dev/disk/by-id/ata-ST16000NM001G_ZR123ABC \
/dev/disk/by-id/ata-ST16000NM001G_ZR124DEF \
/dev/disk/by-id/ata-ST16000NM001G_ZR125GHI \
/dev/disk/by-id/ata-ST16000NM001G_ZR126JKL
cr0x@zfs-vm:~$ zpool status tank
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz1-0 ONLINE 0 0 0
ata-ST16000NM001G_ZR123ABC ONLINE 0 0 0
ata-ST16000NM001G_ZR124DEF ONLINE 0 0 0
ata-ST16000NM001G_ZR125GHI ONLINE 0 0 0
ata-ST16000NM001G_ZR126JKL ONLINE 0 0 0
Ce que cela signifie : Le pool est en ligne et utilise des identifiants stables. ashift=12 est généralement correct pour les disques à secteurs 4K (et sûr pour la plupart des disques modernes).
Décision : Si vous vous trompez sur ashift, vous ne « réparez » pas ça plus tard. Vous reconstruisez. Décidez maintenant, pas après avoir stocké 40 To.
Tâche 10 : Valider le comportement synchrone et les signaux de latence depuis ZFS
cr0x@zfs-vm:~$ sudo zfs set sync=standard tank
cr0x@zfs-vm:~$ zpool iostat -v tank 1 3
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 1.20T 42.5T 0 210 0 52.0M
raidz1-0 1.20T 42.5T 0 210 0 52.0M
sda - - 0 52 0 13.1M
sdb - - 0 52 0 13.0M
sdc - - 0 53 0 13.0M
sdd - - 0 53 0 12.9M
Ce que cela signifie : La distribution des IO semble saine. Si un disque est systématiquement plus lent, c’est un problème de disque/contrôleur/câble, pas « ZFS qui fait ZFS ».
Décision : Si vous voyez des écritures très inégales, enquêtez sur ce chemin de périphérique spécifique, le câblage ou le port HBA.
Tâche 11 : Sur l’hôte Proxmox, vérifier le backend de disque VM et le mode cache (scénario disque virtuel)
cr0x@server:~$ qm config 130 | egrep -i 'scsi|virtio|cache|discard'
scsi0: local-zfs:vm-130-disk-0,cache=none,discard=on,iothread=1,size=200G
scsihw: virtio-scsi-single
Ce que cela signifie : Cette VM utilise un zvol ZFS sur l’hôte (local-zfs), avec cache=none (plus sûr pour la durabilité), discard activé, et un IO thread.
Décision : Si vous voyez cache=writeback sur un hôte sans BBU ni UPS, changez-le. Vous comptez actuellement sur la chance et l’électricité qui se comporte bien.
Tâche 12 : Mesurer la latence réelle depuis la perspective de l’invité
cr0x@zfs-vm:~$ iostat -x 1 3
Linux 6.5.0 (zfs-vm) 02/04/2026 _x86_64_ (8 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
2.13 0.00 3.45 8.20 0.10 86.12
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %util await svctm
sda 0.00 55.00 0.00 14080.0 0.00 1.00 62.00 11.20 0.35
sdb 0.00 54.00 0.00 13824.0 0.00 0.00 61.50 11.10 0.34
sdc 0.00 56.00 0.00 14336.0 0.00 0.00 62.30 11.30 0.35
sdd 0.00 55.00 0.00 14080.0 0.00 0.00 62.10 11.25 0.35
Ce que cela signifie : await est d’environ 11 ms pour les écritures, ce qui est plausible pour des HDD sous charge modérée. Si await grimpe à des centaines de ms, vous avez de l’encombrement ou des blocages du backend.
Décision : Si %steal est élevé, vous êtes en contention CPU ; le réglage du stockage ne vous sauvera pas. Si await est élevé avec une faible util, suspectez la surcharge de virtualisation ou des blocages IO côté hôte.
Tâche 13 : Confirmer que ZFS n’est pas à court de mémoire (le thrashing ARC ressemble à des « disques lents »)
cr0x@zfs-vm:~$ cat /proc/meminfo | egrep 'MemTotal|MemFree|Cached'
MemTotal: 33554432 kB
MemFree: 1823400 kB
Cached: 16200480 kB
cr0x@zfs-vm:~$ sudo arcstat 1 3
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
10:33:01 812 142 17 60 42 82 58 0 0 12.0G 12.0G
10:33:02 790 150 19 65 43 85 57 0 0 12.0G 12.0G
10:33:03 805 155 19 70 45 85 55 0 0 12.0G 12.0G
Ce que cela signifie : L’ARC est stable à 12G et le taux de miss est modéré. Si l’ARC est minuscule ou constamment en diminution, les performances donneront l’impression que « l’IO aléatoire est maudit ».
Décision : Si la VM n’a pas assez de RAM pour l’ARC, donnez-lui de la RAM, déplacez ZFS sur l’hôte, ou acceptez le profil de performance.
Tâche 14 : Vérifier que vous n’exécutez pas ZFS accidentellement au-dessus d’un volume RAID
cr0x@zfs-vm:~$ sudo smartctl -a /dev/sda | egrep 'Vendor|Product|Rotation|SMART support'
Vendor: SEAGATE
Product: ST16000NM001G
Rotation Rate: 7200 rpm
SMART support is: Available - device has SMART capability.
Ce que cela signifie : L’invité peut interroger SMART, ce qui suggère un chemin relativement direct vers le disque. Si vous voyez un volume virtuel RAID à la place, vous obtiendrez souvent des chaînes fournisseurs génériques et un SMART manquant.
Décision : Si vous êtes sur un volume RAID matériel, arrêtez-vous et reflash le contrôleur en mode IT/HBA, ou remplacez-le. ZFS veut des disques, pas du théâtre.
Tâche 15 : Sur l’hôte Proxmox, vérifier l’attente IO et la saturation des périphériques sous-jacents
cr0x@server:~$ pveperf
CPU BOGOMIPS: 76800.00
REGEX/SECOND: 1975679
HD SIZE: 98.23 GB (rbd)
FSYNCS/SECOND: 2321.41
DNS EXT: 37.82 ms
DNS INT: 0.86 ms
Ce que cela signifie : FSYNCS/SECOND donne une idée de la performance synchrone pour la racine Proxmox / le backend de stockage. Ce n’est pas une suite de benchmark, mais cela détecte les nœuds manifestement « malades ».
Décision : Si FSYNCS/SECOND est catastrophique sur un nœud qui devrait être sain, enquêtez d’abord le stockage hôte. Le réglage invité ne battra pas un backend cassé.
Méthode de diagnostic rapide (quoi vérifier en premier/deuxième/troisième)
C’est la méthode « c’est lent » et « ZFS est furieux ». Ne faites pas de freestyle. Suivez la chaîne.
Premier : décidez où vit la vérité sur le stockage
- Passthrough HBA/périphérique : traitez l’invité comme du bare metal. Commencez dans l’invité pour la santé des disques et les signaux ZFS.
- Disques virtuels : commencez sur l’hôte. L’invité ne peut rapporter que ce qu’il voit, et ce qu’il voit peut être un mensonge poli.
Second : déterminez si c’est la latence, le débit ou l’ordonnancement CPU
- Dans l’invité :
iostat -x 1et regardezawaitet%steal. - Sur l’hôte :
iostat -x 1ettop(ouhtop) pour IO wait.
Si %steal est élevé, votre « problème stockage » peut être l’ordonnancement des vCPU. Si await est énorme avec une faible util, suspectez des blocages plus hauts (queueing hyperviseur, flushs backend, ou un contrôleur malade).
Troisième : vérifiez ZFS lui-même pour ce qu’il fait
zpool status -xv: erreurs, vdevs dégradés, problèmes de checksum.zpool iostat -v 1: déséquilibre par vdev.zfs get compressratio,recordsize,atime,syncpour le dataset concerné.
Quatrième : confirmez que vous n’avez pas construit une bombe à retardement de cache d’écriture
- Disques virtuels : confirmez que le mode cache Proxmox est
noneou une alternative consciemment choisie et sûre. - Passthrough : confirmez que le contrôleur est en mode IT et n’effectue pas de writeback sans protection.
Cinquième : cherchez les « pièges » spécifiques à la virtualisation
- IO threads activés pour virtio-scsi quand approprié.
- Paramètres multi-queue, affinité vCPU et alignement NUMA pour les charges IO lourdes.
- Ballooning désactivé pour les invités ZFS (pression mémoire + ARC = tristesse).
Trois mini-récits d’entreprise des tranchées du stockage
Incident : la mauvaise hypothèse (« l’hyperviseur va garder ça sain »)
Une entreprise de taille moyenne utilisait Proxmox pour des services internes. Une équipe voulait les fonctionnalités ZFS dans une VM car ils avaient un flux de réplication astucieux basé sur ZFS send/receive. Raisonnable. Ils ont créé une VM, attaché un ensemble de disques qcow2 sur le stockage hôte, et construit un pool raidz dans l’invité. Les benchmarks semblaient bons. Tout le monde s’est tapé dans la main.
Des mois plus tard, il y a eu un incident électrique. Pas dramatique. Une courte coupure, l’UPS a fait ce qu’il pouvait, mais quelques nœuds sont tombés durement. Quand le cluster est remonté, le pool d’une VM s’est importé mais a commencé à générer des erreurs de checksum. Une autre n’arrivait pas à s’importer sans forcer. Ça sentait les écritures partielles.
La cause profonde n’était pas un bug unique. C’était une pile d’hypothèses : le mode cache hôte accusait réception des écritures avant qu’elles ne soient engagées de façon durable, et le backend de stockage avait son propre comportement de cache. ZFS dans l’invité croyait recevoir des flushs corrects. Ce n’était pas le cas. Le pool a survécu suffisamment pour être terrifiant : pas une panne nette, pas une perte évidente. Une semaine longue et coûteuse a suivi.
La correction fut ennuyeuse et structurelle : ils ont reconstruit le design. Pour les charges ZFS-in-VM importantes, ils sont passés au passthrough HBA et ont validé la durabilité. Pour celles qui avaient besoin de migration à chaud et de snapshots hôteliers, ils ont arrêté d’exécuter ZFS dans l’invité et ont utilisé ZFS hôte à la place. Même matériel. Contrat différent.
Optimisation qui s’est retournée : « Utilisons un mode cache plus rapide »
Une autre organisation exécutait une application lourde en stockage avec beaucoup d’appels fsync. Quelqu’un a remarqué une latence élevée et un faible débit sur leurs disques virtuels. Ils ont changé le cache disque Proxmox en writeback parce que cela rendait les graphiques plus jolis. Et ça a fonctionné — la latence a chuté, le débit a augmenté, tout le monde est retourné à ignorer le stockage.
Puis est venu un redémarrage de maintenance pendant une période bruyante. L’appli a redémarré, mais la base de données a signalé de la corruption. Pas immédiatement catastrophique — plutôt le type « j’ai trouvé des choses que je ne peux pas concilier ». Les sauvegardes étaient disponibles, mais la récupération signifiait une perte de données entre les snapshots, plus une fenêtre de restauration pénible.
Le post-mortem a trouvé l’évidence : le cache writeback améliorait les performances en accusant réception des écritures tôt. La partie moins évidente était culturelle : personne n’avait défini ce que « écriture durable » signifiait dans leur environnement. Ils avaient optimisé une métrique sans préciser l’exigence de fiabilité derrière.
Ils ont fait marche arrière vers des réglages de cache plus sûrs, ajouté la protection contre la perte de puissance là où c’était important, et re-testé avec des scénarios de crash. La performance était plus basse, mais honnête. C’est ce qu’on peut opérer.
Pratique ennuyeuse mais correcte qui a sauvé la mise : « Nous testons resilver et scrub comme une fonctionnalité »
Un troisième acteur exécutait ZFS dans une VM avec passthrough HBA. Ce n’était pas glamour ; c’était choisi parce qu’ils voulaient un comportement de panne prévisible et une télémétrie propre. L’équipe avait une habitude qui paraissait excessive : ils planifiaient des scrubs réguliers, et une fois par trimestre ils mettaient volontairement un disque hors ligne pendant une fenêtre de maintenance pour exercer les procédures de remplacement et de resilver.
Un jour, un disque a commencé à générer des erreurs intermittentes. Rien de dramatique : une poignée d’erreurs de lecture qui se corrigeaient au début. Le scrub l’a signalé, et comme l’équipe avait déjà vu ce film, ils n’ont pas débattu. Ils ont remplacé le disque, resilveré, et ont continué.
Deux semaines plus tard, un autre disque de la même série a commencé la même chose. Encore une fois : remplacer, resilver, continuer. Pas de panique, pas de Slack « pourquoi le pool est dégradé ».
Le vrai gain est venu plus tard : le fournisseur a reconnu un souci sur une série de production. Beaucoup d’entreprises l’ont découvert en perdant un vdev pendant un resilver. Celle-ci l’a découvert quand le graphique de scrub a tangué. La pratique était ennuyeuse. Le résultat ne l’était pas.
Blague #2 : La seule chose plus persistante que la décroissance des bits est un tableau qui affirme que votre stockage est « vert ».
Erreurs fréquentes : symptômes → cause profonde → fix
1) Pool ZFS de la VM corrompu après un crash de l’hôte
Symptômes : Le pool s’importe avec des erreurs, des erreurs de checksum apparaissent, les datasets se comportent bizarrement après un arrêt non propre.
Cause profonde : Le mode de cache du disque virtuel et le backend n’ont pas respecté les flushs de bout en bout ; ZFS invité a fait confiance à une durabilité qui n’était pas réelle.
Correctif : Utiliser des modes de cache plus sûrs (cache=none pour beaucoup de configurations), éviter qcow2 pour ZFS-in-guest si vous tenez à l’intégrité, ou passer en passthrough HBA/périphérique.
2) « Le passthrough ne fonctionne pas » même si l’IOMMU est activé
Symptômes : La VM ne démarre pas, Proxmox rapporte des erreurs VFIO, le périphérique disparaît ou cause une instabilité hôte.
Cause profonde : Le périphérique partage un groupe IOMMU avec du matériel critique pour l’hôte, ou le périphérique a des problèmes de reset.
Correctif : Vérifier l’appartenance aux groupes ; déplacer les slots PCIe ; choisir une carte mère/plateforme CPU différente ; parfois mettre à jour le BIOS/firmware. Évitez de compter sur ACS override en production si vous avez des exigences de risque.
3) L’invité ZFS est lent, mais les disques semblent en bonne santé
Symptômes : Haute latence, faible débit, pas de problèmes SMART évidents, ZFS ne montre pas d’erreurs.
Cause profonde : Contention vCPU et %steal élevé, ou ballooning mémoire provoquant un thrash de l’ARC.
Correctif : Pinner les vCPUs pour les charges IO lourdes, désactiver le ballooning pour les invités ZFS, allouer suffisamment de RAM, et éviter la surréservation CPU sur les VMs de stockage.
4) Le pool continue de « se remplir mystérieusement » avec des disques virtuels thin-provisionnés
Symptômes : Le stockage hôte se remplit tandis que l’invité montre de l’espace libre ; les discards ne récupèrent pas l’espace comme prévu.
Cause profonde : Discard/TRIM non activé de bout en bout, des snapshots empêchent la récupération d’espace, ou le backend ne libère pas efficacement les trous.
Correctif : Activer discard sur les disques Proxmox, s’assurer que l’invité envoie des TRIM, gérer les snapshots volontairement, et surveiller la taille allouée réelle sur l’hôte.
5) Les scrubs sont douloureusement lents dans une VM
Symptômes : Le scrub prend une éternité ; la charge de production souffre pendant les fenêtres de scrub.
Cause profonde : L’IO de scrub concurrence l’IO de la VM ; sur des disques virtuels vous pouvez obtenir une contention composée (hôte plus invité). En passthrough, c’est souvent « les disques sont occupés » mais cela peut être un problème de profondeur de file d’attente.
Correctif : Planifier les scrubs, définir des priorités de scrub/resilver, éviter d’exécuter le scrub sur ZFS hôte et invité simultanément, et valider les réglages de file d’attente HBA si applicable.
6) « ZFS ne voit pas SMART » après le passthrough
Symptômes : smartctl retourne des informations limitées ou des erreurs ; les disques affichent des identifiants génériques.
Cause profonde : Vous avez passé un contrôleur RAID qui fait encore du RAID, ou vous êtes derrière un expander/contrôleur qui nécessite des options smartctl spécifiques.
Correctif : Mettre le contrôleur en mode IT/HBA ; utiliser les flags smartctl appropriés pour SAS ; confirmer que l’invité voit des périphériques réels, pas des volumes logiques.
Listes de contrôle / plan pas à pas
Plan A : Vous voulez ZFS dans la VM pour des données réelles (chemin recommandé)
- Achetez/choisissez du matériel qui supporte une isolation IOMMU propre. Les cartes serveur ont tendance à mieux se comporter ; la topologie PCIe compte.
- Activez VT-d/AMD-Vi dans le BIOS, démarrez avec les flags IOMMU, vérifiez dans
dmesg. - Identifiez le HBA, confirmez qu’il est en mode IT, et vérifiez qu’il est seul dans son groupe IOMMU.
- Liez le HBA à vfio-pci, redémarrez, confirmez le propriétaire du pilote.
- Créez une VM de stockage dédiée : q35 + OVMF, pas de ballooning, assez de RAM, un nombre de vCPU sensible, envisagez le pinning CPU si sensible à la latence.
- Passez le HBA en passthrough, puis à l’intérieur de l’invité créez le pool en utilisant les chemins
/dev/disk/by-id. - Définissez les propriétés ZFS intentionnellement par dataset (recordsize, compression, atime).
- Surveillez et testez le comportement en cas de panne : scrubs, procédure de remplacement de disque, tests de reboot, et une simulation planifiée de perte de puissance si vous êtes brave et préparé.
Plan B : Vous insistez pour des disques virtuels mais voulez réduire le rayon d’explosion
- Privilégiez les disques raw ou soutenus par zvol plutôt que qcow2 pour ZFS-in-guest.
- Utilisez virtio-scsi avec
iothread=1pour les patterns IO lourds. - Définissez le mode de cache consciemment : par défaut
cache=nonesauf si vous pouvez prouver la durabilité autrement. - Activez discard de bout en bout si le thin provisioning est important.
- Ne lancez pas le scrub ZFS hôte en même temps que le scrub ZFS invité si vous pouvez l’éviter. Échelonnez la maintenance.
- Testez la récupération : simulez un arrêt non propre de la VM et vérifiez le comportement d’import du pool et l’intégrité des applications.
Plan C : Vous n’avez pas vraiment besoin de ZFS dans l’invité
- Exécutez ZFS sur l’hôte Proxmox et utilisez des zvols pour les disques VM.
- Utilisez les snapshots et sauvegardes Proxmox au niveau de l’hyperviseur.
- Exposez le stockage aux invités via virtio et gardez le cerveau du stockage à un seul endroit.
FAQ
1) Le passthrough HBA est-il toujours plus rapide ?
Non. Il est souvent plus prévisible. Les disques virtuels peuvent être rapides sur de bons backends, mais le passthrough réduit les couches qui ajoutent des pics de latence et des discordances sémantiques.
2) Puis-je migrer à chaud une VM qui utilise le passthrough HBA ?
Pas d’une manière significative. Les disques sont physiquement attachés à un seul hôte. Vous pouvez migrer le calcul, pas les câbles.
3) Est-il acceptable d’exécuter ZFS sur qcow2 ?
Pour les tests et les données non critiques, oui. Pour des données importantes, c’est une manière séduisante d’ajouter fragmentation et complexité tout en rendant l’analyse des pannes plus difficile.
4) Si j’utilise ZFS hôte Proxmox, dois-je aussi utiliser ZFS invité ?
Réponse par défaut : non. Choisissez une couche pour posséder les responsabilités ZFS. ZFS-sur-ZFS est une conception de niche, pas une bonne pratique générale.
5) Quel mode de cache devrais-je utiliser pour les disques virtuels ?
Commencez avec cache=none. Ce n’est pas le plus rapide, mais c’est honnête. Si vous le changez, faites-le avec une histoire de durabilité claire (protection contre la perte de puissance, garanties du backend, tests de crash).
6) Un SLOG aide-t-il ZFS dans une VM ?
Parfois. Il améliore la latence des écritures synchrones quand la charge force des écritures sync. Mais il n’aide que si les semantics de flush/durabilité sont réelles de bout en bout.
7) Pourquoi mon HBA partage-t-il un groupe IOMMU avec ma NIC ?
Parce que la topologie PCIe et le support ACS sont déterminés par la conception de la carte mère et du CPU. Linux ne peut pas fabriquer une isolation que le matériel n’a pas fournie.
8) Dois-je activer le ballooning sur une VM ZFS ?
Non, pas si vous tenez à la cohérence des performances. ZFS utilise la mémoire pour le cache ARC ; le ballooning transforme le cache en une fête d’évictions surprises.
9) Ai-je besoin spécifiquement du mode IT ?
Si vous voulez que ZFS gère correctement les disques individuels, oui. Le mode RAID cache les disques derrière des volumes logiques et gêne souvent la visibilité des erreurs et le comportement de récupération.
10) Quelle est l’architecture la plus simple « sûre » pour Proxmox + stockage ?
ZFS hôte + zvols pour disques VM + sauvegardes Proxmox est la configuration la plus sûre et la plus simple pour de nombreux environnements. Ajoutez le passthrough seulement quand vous avez besoin d’un ZFS appartenant à l’invité.
Étapes pratiques suivantes
Choisissez votre architecture en fonction de ce que vous voulez garantir :
- Si l’intégrité des données et des modes de panne clairs sont prioritaires : construisez une VM de stockage avec passthrough HBA/périphérique et traitez-la comme un serveur de stockage.
- Si la commodité opérationnelle et la mobilité sont prioritaires : n’exécutez pas ZFS dans l’invité ; exécutez-le sur l’hôte Proxmox et gardez les disques VM simples.
- Si vous devez absolument faire ZFS-in-guest sur disques virtuels : utilisez des périphériques raw/soutenus par zvol,
cache=none, activez discard délibérément, et testez le comportement en cas de crash avant la production.
Puis faites la partie peu glamour : exécutez les commandes ci‑dessus, enregistrez les sorties, et décidez sur la base des preuves. Le stockage est un des rares domaines où la réalité gagne toujours. Ce n’est juste pas toujours rapide.