ZFS ZVOL vs Dataset : la décision qui façonne vos douleurs futures

Cet article vous a aidé ?

Vous pouvez exploiter ZFS pendant des années sans jamais vous poser la question de la différence entre un dataset et un zvol.
Puis vous virtualisez quelque chose d’important, vous ajoutez des snapshots « au cas où », la réplication devient une exigence du comité,
et soudainement votre plateforme de stockage développe des opinions. Assumées.

Le choix zvol vs dataset n’est pas théorique. Il modifie la façon dont les IO sont façonnés, ce que le cache peut faire, le comportement des snapshots,
comment la réplication casse, et quels réglages existent réellement. Se tromper ne donne pas seulement des performances plus lentes — vous accumulez
une dette opérationnelle qui s’empile chaque trimestre.

Datasets et zvols : ce qu’ils sont vraiment (pas ce qu’on lit dans Slack)

Dataset : un système de fichiers avec les super-pouvoirs de ZFS

Un dataset ZFS est un système de fichiers ZFS. Il a une sémantique de fichiers : répertoires, permissions, appartenances, attributs étendus.
Il peut être exporté via NFS/SMB, monté localement et manipulé avec des outils classiques. ZFS ajoute sa propre couche de fonctionnalités :
snapshots, clones, compression, checksums, quotas/réservations, réglage du recordsize, et toute la sécurité transactionnelle qui
vous aide à dormir un peu mieux.

Lorsque vous placez des données dans un dataset, ZFS contrôle la manière dont il dispose des « records » de taille variable (blocs, mais pas des blocs de taille fixe comme
les systèmes de fichiers traditionnels). Cela importe parce que ça change l’amplification, l’efficacité du cache et les schémas d’IO. Le réglage clé est
recordsize.

Zvol : un périphérique bloc taillé dans ZFS

Un zvol est un volume ZFS : un périphérique bloc virtuel exposé comme /dev/zvol/pool/volume. Il ne comprend pas les fichiers.
Votre filesystem invité (ext4, XFS, NTFS) ou votre moteur de base de données voit un disque et écrit des blocs. ZFS stocke ces blocs en tant qu’objets
avec une taille de bloc fixe contrôlée par volblocksize.

Les zvols existent pour les cas où le consommateur veut un périphérique bloc : LUNs iSCSI, disques VM, certains runtimes de conteneurs, certains hyperviseurs,
et parfois des piles applicatives qui exigent des périphériques bruts.

La traduction en pratique

  • Dataset = « ZFS est le système de fichiers ; les clients parlent des protocoles de fichiers ; ZFS voit les fichiers et peut s’optimiser autour d’eux. »
  • Zvol = « ZFS fournit un faux disque ; autre chose construit un filesystem ; ZFS voit des blocs et devine. »

ZFS est extrêmement bon dans les deux cas, mais ils se comportent différemment. La douleur vient de supposer qu’ils se comportent de la même façon.

Petite blague courte, parce que le stockage exige de l’humilité : si vous voulez lancer un débat animé dans un datacenter, évoquez les niveaux RAID.
Si vous voulez le clore, mentionnez « zvol volblocksize » et regardez tout le monde vérifier discrètement ses notes.

Règles de décision : quand utiliser un dataset, quand utiliser un zvol

Position par défaut : les datasets sont le choix ennuyeux — et l’ennui gagne

Si votre charge peut consommer le stockage comme un système de fichiers (montage local, NFS, SMB), utilisez un dataset. Vous obtenez des opérations plus simples :
inspection facilitée, copie/restauration plus aisée, permissions directes, et moins de cas limites liés aux tailles de blocs et au TRIM/UNMAP.
Vous bénéficiez aussi du comportement ZFS adapté aux fichiers par défaut.

Les datasets sont aussi plus faciles à déboguer parce que vos outils parlent toujours « fichier ». Vous pouvez mesurer la fragmentation au niveau fichier, regarder les
répertoires, raisonner sur les métadonnées et garder un modèle mental propre.

Quand un zvol est l’outil approprié

Utilisez un zvol lorsque le consommateur exige un périphérique bloc :

  • Disques VM (surtout pour des hyperviseurs qui veulent des volumes bruts, ou quand vous voulez des snapshots ZFS gérés du disque virtuel)
  • Cibles iSCSI (les LUNs sont par définition bloc)
  • Certains déploiements clusterisés qui répliquent des périphériques blocs ou nécessitent la sémantique SCSI
  • Applications legacy qui ne supportent que « placer la base de données sur un périphérique brut » (rare, mais ça arrive)

Le modèle zvol est puissant : les snapshots ZFS d’un disque VM sont rapides, les clones sont instantanés, la réplication fonctionne, et vous pouvez tout compresser et
checksummer.

Mais : les périphériques bloc multiplient les responsabilités

Quand vous utilisez un zvol, vous prenez en charge la couche entre le filesystem invité et ZFS. L’alignement compte. La taille de bloc compte.
Les barrières d’écriture comptent. Le comportement Trim/UNMAP compte. Les réglages sync deviennent une question de politique, pas un détail de tuning.

Une matrice de décision simple que vous pouvez défendre

  • Besoins NFS/SMB ou fichiers locaux ? Dataset.
  • Besoins LUN iSCSI ou bloc brut pour hyperviseur ? Zvol.
  • Besoin de visibilité par fichier, restauration facile d’un fichier isolé ? Dataset.
  • Besoin de clones VM instantanés depuis une image maîtresse ? Zvol (ou un dataset avec fichiers creux, mais connaissez vos outils).
  • Besoin d’un snapshot cohérent d’une application qui gère son propre filesystem ? Zvol (et coordonnez flush/quiesce).
  • Vous essayez « d’optimiser les performances » sans connaître les patterns IO ? Dataset, mesurez ensuite. Le tuning héroïque vient plus tard.

Recordsize vs volblocksize : où la performance se décide

Datasets : recordsize est la taille maximale d’un bloc de données que ZFS utilisera pour les fichiers. Les gros fichiers séquentiels (sauvegardes,
médias, logs) aiment un large recordsize comme 1M. Les bases de données et les IO aléatoires préfèrent des valeurs plus petites (16K, 8K) parce que réécrire une petite
région n’entraîne pas une forte rotation de gros blocs.

Zvols : volblocksize est fixé à la création. Choisir mal et vous ne pouvez pas le changer ultérieurement sans reconstruire le zvol.
Ce n’est pas « ennuyeux ». C’est « nous planifions une migration au T4 parce que les graphiques de latence ressemblent à une scie. »

Snapshots : apparemment similaires, opérationnellement différents

Snapshoter un dataset capture l’état du système de fichiers. Snapshoter un zvol capture des blocs bruts. Dans les deux cas, ZFS utilise le copy-on-write,
donc le snapshot est peu coûteux à la création et coûteux ensuite si vous continuez à réécrire des blocs référencés par des snapshots.

Avec les zvols, cette dépense est plus facile à déclencher, parce que les disques VM réécrivent des blocs constamment : mises à jour de métadonnées, churn des journaux,
entretien du filesystem, même « rien ne se passe » peut signifier que quelque chose réécrit. Les snapshots gardés trop longtemps deviennent une taxe.

Quotas, réservations et le piège du thin-provisioning

Les datasets vous donnent quota et refquota. Les zvols vous donnent une taille fixe, mais vous pouvez créer des volumes creux
et faire croire que vous avez plus d’espace que vous n’en avez. C’est une décision business qui se déguise en fonctionnalité technique.

Le thin-provisioning va quand la surveillance, l’alerte et la supervision adulte existent. C’est un désastre quand utilisé pour éviter de dire
« non » dans une file de tickets.

Deuxième blague courte (et la dernière) : le thin provisioning, c’est comme commander un pantalon une taille en dessous comme « motivation ».
Parfois ça marche, mais la plupart du temps vous ne pouvez juste pas respirer.

Modes de défaillance que vous rencontrez seulement en production

Amplification d’écriture due à des blocs mal dimensionnés

Un dataset avec recordsize=1M servant de backend à une base de données qui fait des écritures aléatoires de 8K peut causer une amplification douloureuse : chaque petite
mise à jour touche un grand record. ZFS a des logiques pour gérer des écritures plus petites (et stockera des blocs plus petits dans certains cas), mais ne comptez pas dessus pour
vous sauver d’une mauvaise adéquation. Pendant ce temps, un zvol avec volblocksize=128K servant un filesystem VM qui écrit des blocs de 4K est tout aussi inadapté.

Symptom : débit correct dans les benchs, latence tail misérable en charge réelle.

Semantiques sync : où la latence se cache

ZFS respecte les écritures synchrones. Si une application (ou un hyperviseur) émet des écritures sync, ZFS doit les confirmer de façon sûre — c’est-à-dire sur un stockage stable, pas seulement en RAM.
Sans un SLOG dédié (rapide, protégé contre les pertes d’alimentation), les charges à forte proportion de sync peuvent s’enliser sur la latence du pool principal.

Les consommateurs de zvol utilisent souvent les écritures sync plus agressivement que les protocoles fichiers. Les VMs et les bases de données tiennent à la durabilité.
Les clients NFS peuvent émettre des écritures sync selon les options de montage et le comportement applicatif. Quoi qu’il en soit, si vos pics de latence corrèlent avec la charge d’écriture
sync, le débat « zvol vs dataset » devient « comprenons-nous notre chemin d’écriture sync ? ».

TRIM/UNMAP et le mythe du « l’espace revient automatiquement »

Les datasets peuvent libérer des blocs quand des fichiers sont supprimés. Les zvols dépendent du guest qui émet le TRIM/UNMAP (et de votre pile qui le fait passer).
Sans cela, votre zvol paraît plein pour toujours, les snapshots gonflent, et vous commencez à blâmer la « fragmentation ZFS » pour ce qui est en réalité une absence de signal de garbage collection.

Explosions de rétention de snapshots

Conserver des snapshots horaires pendant 90 jours d’un zvol VM semble responsable jusqu’à ce que vous réalisiez que vous retenez chaque bloc churné à travers chaque mise à jour Windows, exécution du gestionnaire de paquets et rotation de logs.
Les mathématiques deviennent rapidement moches. Les datasets souffrent aussi de ça, mais le churn VM est un genre d’enthousiasme spécial.

Surprise de réplication : les datasets sont plus amicaux pour la logique incrémentale

La réplication ZFS fonctionne pour datasets et zvols, mais la réplication de zvol peut être plus volumineuse et plus sensible au churn des blocs.
Un petit changement dans un filesystem invité peut réécrire des blocs partout. Votre send incrémental peut ressembler à un envoi complet, et votre lien WAN vous envoie une lettre de démission.

Frottement des outils : les humains font partie du système

La plupart des équipes ont plus d’expérience opérationnelle autour des systèmes de fichiers que des périphériques bloc. Elles savent vérifier les permissions, comment copier des fichiers, comment monter et inspecter.
Les workflows zvol vous poussent vers d’autres outils : tables de partition, filesystems invités, contrôles au niveau bloc. La friction se manifeste à 3h du matin, pas en réunion de conception.

Faits et historique intéressants à manier en revue de conception

  1. ZFS a introduit le checksumming de bout en bout comme fonctionnalité centrale, pas comme un add-on ; cela a changé la manière dont on débat de la « corruption silencieuse ».
  2. Le copy-on-write n’était pas nouveau quand ZFS est arrivé, mais ZFS l’a rendu opérationnellement courant pour les piles de stockage générales.
  3. Les zvols ont été conçus pour s’intégrer aux écosystèmes bloc comme iSCSI et les plateformes VM, bien avant que « hyperconvergé » ne devienne un mot commercial.
  4. Les valeurs par défaut de recordsize ont été choisies pour des charges de fichiers polyvalentes, pas pour les bases de données ; les défauts sont de la politique intégrée au code.
  5. Volblocksize est immuable après création du zvol dans la plupart des implémentations courantes ; ce seul détail motive de nombreuses migrations.
  6. L’ARC (Adaptive Replacement Cache) a rendu le comportement de cache de ZFS distinct de beaucoup de systèmes de fichiers traditionnels ; ce n’est pas « juste un page cache ».
  7. L2ARC est arrivé comme cache de second niveau, mais il n’a jamais remplacé la nécessité de dimensionner correctement la RAM ; il change surtout les taux de hit, pas qu’il fasse des miracles.
  8. Les dispositifs SLOG sont devenus un modèle standard parce que la latence des écritures synchrones domine certaines charges ; « SSD rapide » sans protection contre la perte d’alimentation n’est pas un SLOG.
  9. Le send/receive de réplication a donné à ZFS un primitif de sauvegarde intégré ; ce n’est pas « rsync », c’est un flux de transactions de blocs.

Tâches pratiques : commandes, sorties et ce qu’il faut décider

Ce ne sont pas des commandes « mignonnes de démonstration ». Ce sont celles que vous exécutez quand vous essayez de choisir entre un dataset et un zvol, ou quand
vous devez vous prouver que vous avez fait le bon choix.

Tâche 1 : Faire l’inventaire de ce que vous avez réellement

cr0x@server:~$ zfs list -o name,type,used,avail,refer,mountpoint -r tank
NAME                         TYPE   USED  AVAIL  REFER  MOUNTPOINT
tank                         filesystem  1.12T  8.44T   192K  /tank
tank/vm                      filesystem   420G  8.44T   128K  /tank/vm
tank/vm/web01                volume      80.0G  8.44T  10.2G  -
tank/vm/db01                 volume     250G   8.44T   96.4G  -
tank/nfs                     filesystem  320G  8.44T   320G  /tank/nfs

Signification : Vous avez à la fois des datasets (filesystem) et des zvols (volume). Les zvols n’ont pas de mountpoint.

Décision : Identifiez quelles charges résident sur des volumes et demandez-vous : nécessitent-elles vraiment du bloc, ou est-ce de l’inertie ?

Tâche 2 : Vérifier le recordsize du dataset (et s’il correspond à la charge)

cr0x@server:~$ zfs get -o name,property,value recordsize tank/nfs
NAME      PROPERTY    VALUE
tank/nfs  recordsize  128K

Signification : Ce dataset utilise des records de 128K, une valeur générale correcte.

Décision : Si ce dataset héberge des bases de données ou des images VM en tant que fichiers, envisagez 16K ou 32K ; s’il héberge des sauvegardes, envisagez 1M.

Tâche 3 : Vérifier le volblocksize du zvol (le réglage « qu’on ne peut pas changer plus tard »)

cr0x@server:~$ zfs get -o name,property,value volblocksize tank/vm/db01
NAME         PROPERTY     VALUE
tank/vm/db01 volblocksize 8K

Signification : Ce zvol utilise des blocs de 8K — couramment raisonnable pour des bases de données à IO aléatoire et de nombreux filesystems VM.

Décision : Si vous voyez 64K/128K ici pour des disques de démarrage VM généraux, attendez-vous à de l’amplification d’écriture et envisagez une reconstruction correcte.

Tâche 4 : Vérifier la politique sync, car elle contrôle durabilité vs latence

cr0x@server:~$ zfs get -o name,property,value sync tank/vm
NAME     PROPERTY  VALUE
tank/vm  sync      standard

Signification : ZFS respectera les écritures sync mais n’obligera pas que toutes les écritures soient sync.

Décision : Si quelqu’un a mis sync=disabled « pour les performances », planifiez une conversation sur les risques et un plan de retour en arrière.

Tâche 5 : Voir l’état de la compression et le ratio (cela décide souvent du coût)

cr0x@server:~$ zfs get -o name,property,value,source compression,compressratio tank/vm/db01
NAME         PROPERTY       VALUE   SOURCE
tank/vm/db01 compression    lz4     local
tank/vm/db01 compressratio  1.62x   -

Signification : LZ4 est activé et aide.

Décision : Gardez-le. Si la compression est désactivée sur des disques VM, activez-la sauf si vous avez une preuve d’un goulot CPU.

Tâche 6 : Vérifier combien de snapshots vous traînez

cr0x@server:~$ zfs list -t snapshot -o name,used,refer -S used | head
NAME                               USED  REFER
tank/vm/db01@hourly-2025-12-24-23  8.4G  96.4G
tank/vm/db01@hourly-2025-12-24-22  7.9G  96.4G
tank/vm/web01@hourly-2025-12-24-23 2.1G  10.2G
tank/nfs@daily-2025-12-24          1.4G  320G

Signification : La colonne USED est l’espace de snapshot unique à ce snapshot.

Décision : Si des snapshots horaires VM consomment chacun plusieurs gigaoctets, raccourcissez la rétention ou réduisez la fréquence ; les snapshots ne sont pas gratuits.

Tâche 7 : Identifier « l’espace détenu par les snapshots » sur un zvol

cr0x@server:~$ zfs get -o name,property,value usedbysnapshots,usedbydataset,logicalused tank/vm/db01
NAME         PROPERTY         VALUE
tank/vm/db01 usedbysnapshots  112G
tank/vm/db01 usedbydataset    96.4G
tank/vm/db01 logicalused      250G

Signification : Les snapshots retiennent plus d’espace que les données vivantes actuelles.

Décision : Votre « politique de sauvegarde » est maintenant une politique de planification de capacité. Corrigez la rétention et envisagez le comportement TRIM/UNMAP du guest.

Tâche 8 : Vérifier l’état du pool et les erreurs d’abord (le tuning sur un pool malade, c’est comique)

cr0x@server:~$ zpool status -v tank
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 02:14:33 with 0 errors on Sun Dec 22 03:10:11 2025
config:

        NAME                        STATE     READ WRITE CKSUM
        tank                        ONLINE       0     0     0
          mirror-0                  ONLINE       0     0     0
            ata-SSD1                ONLINE       0     0     0
            ata-SSD2                ONLINE       0     0     0

errors: No known data errors

Signification : Pool sain, scrub propre.

Décision : Si vous voyez des erreurs de checksum ou des vdevs dégradés, arrêtez. Réparez le matériel/les chemins avant de débattre zvol vs dataset.

Tâche 9 : Surveiller les IO en temps réel par dataset/zvol

cr0x@server:~$ zpool iostat -v tank 2 3
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        1.12T  8.44T    210    980  12.4M  88.1M
  mirror-0                  1.12T  8.44T    210    980  12.4M  88.1M
    ata-SSD1                    -      -    105    490  6.2M   44.0M
    ata-SSD2                    -      -    105    490  6.2M   44.1M
--------------------------  -----  -----  -----  -----  -----  -----

Signification : Vous voyez les IOPS de lecture/écriture et la bande passante ; cela vous indique si vous êtes limité en IOPS ou en débit.

Décision : Des IOPS d’écriture élevées avec faible bande passante suggèrent des écritures aléatoires petites — volblocksize et le chemin sync comptent beaucoup.

Tâche 10 : Vérifier la pression ARC (parce que la RAM est votre premier niveau de stockage)

cr0x@server:~$ arcstat 1 3
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  size     c
12:20:01   532    41      7    12   2     29   5      0   0  48.1G  52.0G
12:20:02   611    58      9    16   2     42   7      0   0  48.1G  52.0G
12:20:03   590    55      9    15   2     40   7      0   0  48.1G  52.0G

Signification : Les taux de miss ARC sont faibles ; le cache est sain.

Décision : Si miss% est constamment élevé sous charge, ajouter de la RAM bat souvent des changements astucieux de layout de stockage.

Tâche 11 : Vérifier si un zvol est sparse (thin) et si c’est sûr

cr0x@server:~$ zfs get -o name,property,value refreservation,volsize,used tank/vm/web01
NAME          PROPERTY        VALUE
tank/vm/web01 refreservation  none
tank/vm/web01 volsize         80G
tank/vm/web01 used            10.2G

Signification : Pas de réservation : c’est effectivement thin du point de vue de l’espace garanti.

Décision : Si vous exécutez des VMs critiques, définissez refreservation pour garantir l’espace ou acceptez le risque d’incidents pool-full.

Tâche 12 : Confirmer ashift (votre base d’alignement des secteurs physiques)

cr0x@server:~$ zdb -C tank | grep -E 'ashift|vdev_tree' -n | head
45:        vdev_tree:
67:            ashift: 12

Signification : ashift=12 signifie des secteurs 4K. Généralement correct pour SSD et HDD modernes.

Décision : Si ashift est incorrect (trop petit), les performances peuvent être altérées de façon permanente ; on reconstruit le pool, on ne le « tune » pas.

Tâche 13 : Évaluer la taille d’envoi snapshot avant de répliquer sur un lien réduit

cr0x@server:~$ zfs send -nvP tank/vm/db01@hourly-2025-12-24-23 | head
send from @hourly-2025-12-24-22 to tank/vm/db01@hourly-2025-12-24-23 estimated size is 18.7G
total estimated size is 18.7G

Signification : L’incrémental est encore de 18.7G — le churn de blocs est élevé.

Décision : Réduisez la fréquence/la rétention des snapshots, améliorez le TRIM invité, ou changez d’architecture (stockage applicatif basé dataset) si possible.

Tâche 14 : Vérifier si TRIM est activé sur le pool

cr0x@server:~$ zpool get -o name,property,value autotrim tank
NAME  PROPERTY  VALUE
tank  autotrim  on

Signification : Le pool effectue le trimming des blocs libérés vers les SSD.

Décision : Si autotrim est off sur des pools SSD, envisagez de l’activer — surtout si vous dépendez des invités zvol pour rendre l’espace.

Tâche 15 : Vérifier les propriétés par dataset qui changent le comportement de façon sournoise

cr0x@server:~$ zfs get -o name,property,value atime,xattr,primarycache,logbias tank/vm
NAME     PROPERTY      VALUE
tank/vm  atime         off
tank/vm  xattr         sa
tank/vm  primarycache  all
tank/vm  logbias       latency

Signification : atime off réduit les écritures de métadonnées ; xattr=sa stocke les xattrs plus efficacement ; logbias=latency privilégie la latence sync.

Décision : Pour des zvols VM, logbias=latency est typiquement raisonnable. Si logbias=throughput apparaît, vérifiez que ce n’était pas une astuce mimétique.

Guide de diagnostic rapide (trouver le goulot en quelques minutes)

Quand les performances sont mauvaises, le débat zvol vs dataset devient souvent une distraction. Utilisez cette séquence pour localiser vite la vraie limite.

Première étape : prouver que le pool n’est pas malade

  1. Exécutez : zpool status -v
    Recherchez : vdevs dégradés, erreurs de checksum, resilver en cours, scrub lent.
    Interprétation : Si le pool est en mauvaise santé, tout le reste est du bruit.
  2. Exécutez : dmesg | tail (et vos logs OS spécifiques)
    Recherchez : réinitialisations de lien, timeouts, erreurs NVMe, problèmes HBA.
    Interprétation : Un chemin de disque qui clignote ressemble à des « pics de latence aléatoires ».

Deuxième étape : classer les IO (petit aléatoire vs grand séquentiel, sync vs async)

  1. Exécutez : zpool iostat -v 2
    Recherchez : IOPS élevées avec peu de MB/s (aléatoire) vs MB/s élevés (séquentiel).
    Interprétation : L’IO aléatoire sollicite la latence, le séquentiel sollicite la bande passante.
  2. Exécutez : zfs get sync tank/... et vérifiez les paramètres applicatifs
    Recherchez : charges sync sans SLOG ou sur des médias lents.
    Interprétation : Les écritures sync exposeront le chemin durable le plus lent.

Troisième étape : vérifier la mémoire et le caching avant d’acheter du matériel

  1. Exécutez : arcstat 1
    Recherchez : miss% élevé, ARC qui ne grossit pas, pression mémoire.
    Interprétation : Si vous manquez constamment le cache, vous forcez des lectures disque évitables.
  2. Exécutez : zfs get primarycache secondarycache tank/...
    Recherchez : quelqu’un a mis le cache sur metadata-only « pour économiser de la RAM ».
    Interprétation : Cela peut être valide dans certains designs, mais souvent c’est s’automutiler par accident.

Quatrième étape : valider la taille des blocs et la taxe des snapshots

  1. Exécutez : zfs get recordsize tank/dataset ou zfs get volblocksize tank/volume
    Interprétation : Mismatch = amplification = latence tail.
  2. Exécutez : zfs get usedbysnapshots tank/...
    Interprétation : Si les snapshots retiennent beaucoup d’espace, ils augmentent aussi le travail des métadonnées et des allocations.

Trois mini-récits d’entreprise (anonymisés, mais douloureusement réels)

Mini-récit 1 : Un incident causé par une mauvaise hypothèse (« un zvol, c’est essentiellement un dataset »)

Une entreprise SaaS de taille moyenne a migré d’un SAN legacy vers ZFS. L’ingénieur stockage — intelligent, rapide, un peu trop confiant — a standardisé sur les zvols
pour tout « parce que les disques VM sont des volumes, et c’est ce que faisait le SAN. » Le stockage applicatif basé NFS a aussi été déplacé dans des ext4 sur zvols.
Ça a marché en test. Ça a même marché en production pendant un moment.

Les premiers signes étaient subtils : les fenêtres de sauvegarde ont commencé à s’étirer. La réplication manquait son RPO, mais seulement sur certains volumes.
Puis un pool stable depuis des mois a soudainement atteint un cliff de capacité. « Nous avons 30% de libre », a dit quelqu’un en montrant le dashboard. « Alors pourquoi ne peut-on pas créer un nouveau disque VM ? »

La réponse était les snapshots. Les zvols étaient snapshotés chaque heure, et les filesystems invités remuaient les blocs constamment. Les fichiers supprimés à l’intérieur des guests ne
se traduisaient pas en bloc libéré à moins que TRIM ne traverse toute la pile. Ce n’était pas le cas, parce que les OS invités n’étaient pas configurés et que le chemin hyperviseur ne le passait pas proprement.

Pendant ce temps, la charge de type NFS exécutée à l’intérieur du guest ext4 n’avait aucune raison d’être dans un zvol. Ils voulaient des sémantiques fichier mais ont construit un gâteau de couches file-on-block-on-ZFS.
La réponse on-call a été de supprimer des « vieux snapshots » jusqu’à ce que le pool arrête de hurler, ce qui a fonctionné brièvement puis est devenu un rituel d’urgence.

La correction n’était pas glamour : migrer les données de type NFS vers des datasets exportés directement, mettre en place une rétention de snapshots sensée pour les zvols VM,
et valider TRIM de bout en bout. Il a fallu un mois de migration minutieuse pour démêler un design basé sur la fausse supposition que « volume vs filesystem n’est qu’un emballage ».

Mini-récit 2 : Une optimisation qui s’est retournée (« set sync=disabled, ça va »)

Une autre organisation, proche de la finance et extrêmement allergique aux indisponibilités, exploitait un cluster de bases de données virtualisé. La latence montait pendant les heures de pointe.
Quelqu’un a fouillé les forums, trouvé les mots magiques sync=disabled, et l’a proposé comme solution rapide. Le changement a été appliqué sur la hiérarchie zvol qui supportait les disques VM.

La latence s’est améliorée immédiatement. Les graphiques étaient magnifiques. L’équipe a déclaré la victoire et est passée à d’autres incendies. Pendant quelques semaines, tout était calme, ce qui est précisément la manière dont le risque vous apprend à l’ignorer.

Puis il y a eu un événement d’alimentation : pas un arrêt propre, pas un basculement gracieux — juste un instant où le plan UPS a rencontré la réalité et la réalité a gagné.
L’hyperviseur est revenu. Plusieurs VMs ont démarré. Certaines non. La base de données a redémarré, mais a rollbacké plus de transactions qu’on ne l’aimait, et au moins un filesystem a nécessité une réparation.

La revue d’incident a été gênante parce que personne n’a pu dire, en toute honnêteté, qu’il n’avait pas troqué la durabilité contre la performance. Ils l’avaient fait. C’est ce que fait ce réglage.
Le retour en arrière a consisté à restaurer sync=standard et ajouter un SLOG approprié avec protection contre la perte d’alimentation. La solution à long terme a été culturelle : aucune « correction de performance » qui change la sémantique de durabilité sans acceptation de risque écrite et un test simulant une perte d’alimentation.

Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise (tester la taille d’envoi et la discipline des snapshots)

Une grande équipe plateforme interne exploitait deux datacenters avec réplication ZFS entre eux. Ils avaient l’habitude, vue comme fastidieuse, de réaliser : avant de mettre en production une nouvelle charge,
ils lançaient une « répétition de réplication » d’une semaine avec snapshots et zfs send -nvP pour estimer les tailles incrémentales. Ils imposaient aussi des politiques de rétention de snapshots comme des adultes : faible rétention pour les volumes churny, plus longue pour les datasets stables.

Une équipe produit a demandé « snapshots horaires pendant six mois » pour une flotte de VMs. L’équipe plateforme n’a pas argumenté philosophiquement. Ils ont lancé la répétition. Les incrémentaux étaient énormes et erratiques, et le lien WAN aurait été saturé régulièrement.
Au lieu de dire « non », ils ont proposé une alternative ennuyeuse : quotidienne pour longue rétention, horaire pour courte rétention, plus des sauvegardes au niveau applicatif pour les données critiques. Ils ont aussi déplacé certaines données hors des disques VM vers des datasets exportés NFS, parce que c’étaient des données fichier faisant semblant d’être bloc.

Des mois plus tard, une panne sur un site a forcé un basculement. La réplication était à jour, la récupération prévisible, et le post-mortem agréablement sans histoire. Le mérite est allé à une pratique que personne ne voulait faire parce que ce n’était pas « de l’ingénierie », mais du « process ».
Elle les a sauvés quand même.

Erreurs communes : symptômes → cause racine → correction

1) Le stockage VM est lent et instable, surtout pendant les mises à jour

  • Symptômes : pics de latence tail, gel d’UI, démarrages lents, blocages IO périodiques.
  • Cause racine : zvol volblocksize mal assorti à la taille IO invité ; snapshots conservés trop longtemps ; écritures sync bloquées sur des médias lents.
  • Correction : reconstruire les zvols avec un volblocksize sensé (souvent 8K ou 16K pour les VMs générales), réduire la rétention des snapshots, valider SLOG pour les charges sync-heavy.

2) Le pool affiche beaucoup d’espace libre, mais vous tombez en « out of space »

  • Symptômes : allocations échouent, écritures bloquées, création de nouveaux zvols impossible, ENOSPC bizarre dans les guests.
  • Cause racine : thin provisioning sans refreservation ; snapshots retenant de l’espace ; pool trop plein (ZFS a besoin de marge).
  • Correction : imposer des réservations pour les zvols critiques, supprimer/expirer les snapshots, garder le pool sous un seuil d’utilisation raisonnable, et implémenter des alertes de capacité incluant la croissance des snapshots.

3) Les incrémentaux de réplication sont énormes pour des VMs basées sur zvol

  • Symptômes : send/receive tourne des heures, saturation réseau, RPO manqués.
  • Cause racine : churn du filesystem invité ; absence de TRIM/UNMAP ; intervalle de snapshot mal choisi.
  • Correction : activer et vérifier TRIM depuis le guest jusqu’au zvol, ajuster la cadence des snapshots, déplacer les données de type fichier vers des datasets, et tester les tailles d’envoi estimées avant de définir la politique.

4) « Nous avons désactivé sync et rien de grave n’est arrivé » (encore)

  • Symptômes : latence incroyable ; dashboards suspectement calmes ; aucune panne immédiate.
  • Cause racine : changement des sémantiques de durabilité ; vous confirmez des écritures avant qu’elles soient sûres.
  • Correction : revenir à sync=standard ou sync=always selon le cas ; ajouter un SLOG approprié ; tester les scénarios de perte d’alimentation et documenter l’acceptation du risque si vous tenez à tricher avec la physique.

5) Une charge NFS performe mal quand elle est stockée à l’intérieur d’une VM sur un zvol

  • Symptômes : charges riches en métadonnées lentes ; sauvegardes et restaurations compliquées ; dépannage douloureux.
  • Cause racine : couche inutile : workload fichier placé dans un filesystem invité sur un zvol, perdant les optimisations et la visibilité fichier-level de ZFS.
  • Correction : stocker et exporter en tant que dataset directement ; régler recordsize et atime ; garder la pile simple.

6) Le rollback de snapshot « fonctionne » mais l’app revient corrompue

  • Symptômes : après rollback, le filesystem monte mais les données applicatives sont incohérentes.
  • Cause racine : inadéquation crash-consistency ; les snapshots zvol capturent des blocs, pas la quiescence de l’application ; les snapshots dataset sont aussi sujets à cela s’ils ne sont pas coordonnés.
  • Correction : quiescer les applications (fsfreeze, flush DB, hooks des agents invités hyperviseur) avant les snapshots ; valider les procédures de restauration périodiquement.

Checklists / plan étape par étape

Étape par étape : choisir dataset vs zvol pour une nouvelle charge

  1. Identifier l’interface nécessaire : protocole fichier (NFS/SMB/montage local) → dataset ; protocole bloc (iSCSI/disque VM) → zvol.
  2. Noter les hypothèses de pattern IO : principalement séquentiel ? principalement aléatoire ? sync-heavy ? Cela détermine recordsize/volblocksize et les besoins SLOG.
  3. Choisir la couche la plus simple opérationnelle : éviter file-on-block-on-ZFS sauf nécessité.
  4. Activer par défaut compression lz4 sauf preuve du contraire.
  5. Décider la politique de snapshots dès le départ : fréquence et rétention ; ne laissez pas cela devenir un substitut de sauvegarde.
  6. Décider des attentes de réplication : faire une répétition avec estimation des tailles d’envoi si vous tenez à RPO/RTO.
  7. Garde-fous de capacité : réservations pour zvols critiques ; quotas pour datasets ; garder une marge dans le pool.
  8. Documenter la récupération : comment restaurer un fichier, une VM ou une base de données ; inclure les étapes de quiescence.

Checklist : configurer un zvol pour disques VM (baseline production)

  • Créer avec un volblocksize sensé (souvent 8K ou 16K ; faites correspondre au guest et à l’hyperviseur).
  • Activer compression=lz4.
  • Garder sync=standard ; ajouter un SLOG si la latence sync importe.
  • Planifier la rétention des snapshots en fonction du churn ; tester zfs send -nvP pour dimensionner la réplication.
  • Vérifier le TRIM/UNMAP de bout en bout si vous attendez une reclamation d’espace.
  • Envisager refreservation pour les guests critiques afin d’éviter les catastrophes pool-full.

Checklist : configurer un dataset pour applications et stockage de fichiers

  • Choisir recordsize selon l’IO : 1M pour sauvegardes/médias ; plus petit pour les patterns type base de données.
  • Activer compression=lz4.
  • Désactiver atime sauf si vraiment nécessaire.
  • Utiliser quota/refquota pour empêcher « un tenant de manger le pool ».
  • Snapshotter avec rétention, pas thésaurisation.
  • Exporter via NFS/SMB avec paramètres clients sensés ; mesurer avec des charges réelles.

FAQ

1) Un zvol est-il toujours plus rapide qu’un dataset pour disques VM ?

Non. Un zvol peut être excellent pour des disques VM, mais « plus rapide » dépend du comportement sync, de la taille de bloc, du churn des snapshots et du chemin IO hyperviseur.
Un dataset hébergeant des fichiers QCOW2/raw peut aussi très bien performer avec le bon recordsize et le comportement de cache adapté. Mesurez, ne vibrez pas.

2) Puis-je changer volblocksize plus tard ?

Pratiquement : non. Traitez volblocksize comme immuable. Si vous avez mal choisi, la solution propre est la migration vers un nouveau zvol avec la bonne taille et une coupure contrôlée.

3) Dois-je définir recordsize=16K pour les bases de données sur datasets ?

Souvent raisonnable, mais pas universel. Beaucoup de bases utilisent des pages 8K ; 16K peut être un compromis acceptable. Mais si votre charge est principalement faite de scans séquentiels ou de gros blobs, un recordsize plus grand peut aider.
Profilez votre IO.

4) Les snapshots ZFS sont-ils des sauvegardes ?

Ce sont un composant puissant, pas une stratégie de sauvegarde. Les snapshots ne protègent pas contre la perte du pool, les erreurs opérateur sur le pool, ou la corruption répliquée si vous répliquez trop tôt. Utilisez snapshots avec réplication et/ou stockage de sauvegarde séparé et une rétention adaptée.

5) Pourquoi supprimer des fichiers dans une VM ne libère pas d’espace sur le pool ZFS ?

Parce que ZFS voit un périphérique bloc. À moins que le guest n’émette TRIM/UNMAP et que la pile le fasse traverser, ZFS ne sait pas quels blocs sont libres à l’intérieur du filesystem invité.

6) Puis-je utiliser dedup sur des zvols pour économiser de l’espace ?

Généralement non. La déduplication consomme beaucoup de RAM et est opérationnellement impitoyable. La compression vous donne typiquement des gains sûrs avec moins de risques.
Si vous voulez dedup, prouvez-le avec des données réalistes et budgétez la RAM en conséquence.

7) Un SLOG aide-t-il toutes les écritures ?

Non. Un SLOG aide les écritures synchrones. Si votre charge est majoritairement asynchrone, un SLOG ne bougera pas beaucoup la courbe. Si votre charge est sync-heavy, un SLOG approprié peut faire la différence entre « ça va » et « tout est en feu ».

8) Quand préférer les datasets pour les conteneurs ?

Si votre plateforme de conteneurs peut utiliser directement des datasets ZFS (commun sur beaucoup de setups Linux), les datasets donnent généralement une meilleure visibilité et des opérations plus simples que d’empiler le stockage des conteneurs dans des disques VM sur zvols. Minimisez les couches.

9) Puis-je utiliser sans risque sync=disabled pour des disques VM si j’ai un UPS ?

Un UPS réduit le risque ; il ne l’élimine pas. Kernel panics, réinitialisations de contrôleurs, bugs de firmware et erreurs humaines existent toujours. Si vous avez besoin de durabilité, gardez les sémantiques sync correctes et concevez le chemin matériel (SLOG avec protection contre la perte d’alimentation) pour le supporter.

10) Quel est le meilleur choix par défaut : zvol ou dataset ?

Par défaut, optez pour dataset sauf si le consommateur nécessite du bloc. Quand vous avez besoin de bloc, utilisez les zvols intentionnellement : choisissez volblocksize, planifiez les snapshots et confirmez TRIM et le comportement sync.

Prochaines étapes réalisables cette semaine

Voici le chemin pratique qui réduit la douleur future sans transformer votre stockage en expérience scientifique.

  1. Inventoriez votre environnement : listez datasets vs volumes, et cartographiez-les aux charges. Tout ce qui est « de type fichier » vivant dans un zvol est un drapeau rouge à enquêter.
  2. Auditez les réglages irréversibles : vérifiez volblocksize sur les zvols et recordsize sur les datasets clés. Notez les divergences avec les patterns de charge.
  3. Mesurez la taxe des snapshots : identifiez quels zvols/datasets ont de gros usedbysnapshots. Alignez la rétention sur le besoin business, pas sur l’anxiété.
  4. Validez le comportement sync : trouvez tout sync=disabled et traitez-le comme une demande de changement nécessitant une acceptation de risque explicite. Si la latence sync est un problème, concevez une solution avec un SLOG, pas de l’optimisme.
  5. Faites une répétition de réplication : utilisez zfs send -nvP pour estimer les incrémentaux sur une semaine. Si les chiffres sont délirants, corrigez les sources de churn avant de promettre des RPO serrés.

Une idée paraphrasée de John Allspaw (opérations/fiabilité) : Les incidents viennent du travail normal dans des systèmes complexes, pas d’une seule mauvaise personne ayant une mauvaise journée. (idée paraphrasée)

Le choix zvol vs dataset est exactement ce genre de décision « travail normal ». Faites-le délibérément. Le vous du futur aura toujours des incidents,
mais ils seront du genre intéressant — ceux que vous pouvez réparer — plutôt que le genre lent et usant causé par un primitif de stockage mal choisi il y a des années et défendu par fierté.

← Précédent
Docker Compose : les variables d’environnement vous trahissent — les erreurs .env qui cassent la prod
Suivant →
Délai d’attente des volumes NFS Docker : options de montage qui améliorent réellement la stabilité

Laisser un commentaire