Vous avez hérité d’un pool. Les VM semblent « correctes » jusqu’à la nuit des patchs, la nuit des sauvegardes ou cette nuit d’un traitement analytique.
Quelqu’un dit : « Changeons simplement volblocksize et on aura de meilleures IOPS. » Vous hochez la tête parce que ça ressemble à un réglage.
Puis vous exécutez la commande, elle l’accepte, et… rien ne s’améliore. Parfois c’est pire. Puis vous apprenez la dure vérité : vous avez changé une propriété, pas la physique des blocs déjà écrits.
Les ZVOL semblent simples : un périphérique bloc soutenu par ZFS. Mais leur comportement de taille de bloc n’est pas comme le recordsize d’un dataset filesystem.
Quand vous « migrez » volblocksize, vous changez surtout la façon dont les écritures futures seront disposées. Les données existantes restent organisées à l’ancienne sauf si vous les réécrivez.
En production, « réécrire » signifie généralement « recréer le ZVOL et déplacer les données de manière intentionnelle ».
volblocksize n’est pas une machine à remonter le temps
Voici l’essentiel : modifier volblocksize sur un ZVOL existant change rarement les performances de manière significative tant que
les données n’ont pas été réécrites. ZFS ne revient pas « empaqueter » un ZVOL parce que vous l’avez demandé gentiment. Vous pouvez définir la propriété aujourd’hui,
mais les blocs déjà présents sur disque conservent leur taille, leur segmentation et leur structure d’indirect blocks d’origine.
Ce n’est pas que ZFS soit têtu. C’est que ZFS est cohérent. ZFS utilise le copy-on-write : il écrit de nouveaux blocs ailleurs, met à jour
les métadonnées, puis bascule les pointeurs. Il n’écrase pas les anciens blocs in situ. Si vous voulez que les données existantes soient réécrites
avec une nouvelle taille de bloc, il vous faut un flux de travail qui provoque une réécriture logique complète du volume : réplication vers un nouveau ZVOL,
restauration depuis une sauvegarde, ou copie bloc-à-bloc vers une cible fraîche.
Le résultat pratique : la plupart des « migrations volblocksize » sont en réalité des projets « recréer-et-déplacer ». Le reste est de l’illusion,
plus un ticket de changement mentionnant « tuning de performance » et un postmortem indiquant « impact non mesurable ».
Ce que volblocksize contrôle réellement (et ce qu’il ne contrôle pas)
volblocksize : l’unité d’allocation du ZVOL
Un ZVOL est un dataset ZFS de type volume. Il exporte un périphérique bloc (par exemple /dev/zvol/pool/vm-101-disk-0)
que les consommateurs traitent comme un disque. Pour les ZVOL, volblocksize est la taille maximale d’un bloc que ZFS allouera pour
les données écrites sur le ZVOL.
Si vous définissez volblocksize=16K, ZFS allouera des blocs jusqu’à 16KiB pour les données du ZVOL. Si vous le mettez à 8K,
jusqu’à 8KiB, etc. Le « jusqu’à » a de l’importance : ZFS peut encore allouer des blocs plus petits quand l’écriture est plus petite ou quand la compression
la réduit. Mais la valeur configurée oriente fortement l’allocation et le profil d’I/O qui en résulte.
recordsize concerne les systèmes de fichiers, pas les ZVOL
Sur un dataset filesystem, recordsize contrôle la taille maximale d’enregistrement pour les données de fichier. Il s’agit des blocs de fichiers.
Il interagit avec la taille d’E/S de l’application, la compression et les accès aléatoires. Sur les ZVOL, vous n’avez pas d’enregistrements de fichiers ;
vous avez un disque virtuel. Le système de fichiers invité choisit ses propres tailles et dispositions de blocs, et ZFS voit des écritures sur des LBAs.
Si vous retenez une idée : le tuning de recordsize est souvent indulgent parce que les systèmes de fichiers réécrivent naturellement
les fichiers chauds au fil du temps. Les ZVOL qui servent des disques VM peuvent rester longtemps avec une ancienne disposition de blocs car
beaucoup de charges ne réécrivent pas tout le disque virtuel—en particulier les images OS et certaines bases de données.
D’où vient la douleur : amplification d’écriture et inadéquation d’I/O
La façon la plus simple de penser à un mauvais volblocksize est une inadéquation. Votre charge effectue des écritures aléatoires 4K, mais vous avez fixé
volblocksize=128K. ZFS tend maintenant à allouer (et plus tard à lire/modifier/écrire) des morceaux beaucoup plus grands. Sur des charges lourdes en sync,
cette inadéquation peut se transformer en pics de latence, métadonnées gonflées et un profil d’I/O qui ressemble à un éléphant confus sur des patins à roulettes.
Une autre inadéquation est entre volblocksize et le ashift du pool (alignement à la taille de secteur physique). On peut « vivre »
avec un désalignement, mais on le paie en I/O supplémentaires, pire fragmentation et amplification d’écriture au niveau du périphérique. La facture
arrive sous forme de latence.
Blague n°1 : Changer volblocksize sur un ZVOL occupé en espérant une amélioration instantanée, c’est repeindre un chariot élévateur et l’appeler
une mise à niveau turbo.
Pourquoi le changer corrige rarement les données existantes
Les propriétés ZFS ne sont pas toujours rétroactives
Les propriétés ZFS se répartissent en catégories. Certaines affectent le comportement à l’exécution immédiatement (comme compression pour les écritures futures),
certaines influencent les décisions de métadonnées, et d’autres sont surtout des politiques par défaut pour les nouvelles allocations. volblocksize appartient
au groupe « nouvelles allocations ». Il ne déclenche pas une réécriture des blocs existants car ce serait une opération de fond massive et risquée.
Le copy-on-write signifie « la réécriture n’a lieu que quand la charge réécrit »
ZFS alloue de nouveaux blocs lors d’une modification. Il ne va pas toucher les anciens blocs pour « normaliser » leur taille. Donc quand vous modifiez
volblocksize, seuls les blocs écrits après ce point refléteront probablement la nouvelle taille. Si votre disque VM contient une grosse image OS
principalement statique et un petit fichier de base de données très actif, vous verrez peut‑être qu’une petite partie des blocs change, tandis que la majorité reste
figée dans l’ancienne disposition.
Même si l’invité réécrit, les snapshots peuvent épingler les anciens blocs
Les snapshots sont un autre piège. Si vous avez des snapshots fréquents (sauvegardes VM, points de réplication, snapshots « au cas où » qui ne sont jamais supprimés),
les anciens blocs restent référencés et ne peuvent pas être libérés. L’invité peut réécrire des données, mais les anciens blocs restent épinglés par les snapshots,
laissant la fragmentation et l’utilisation d’espace inchangées. Votre nouvelle disposition coexiste avec l’ancienne. Félicitations, vous avez maintenant un musée.
Le piège « la propriété a été acceptée »
ZFS accepte volontiers zfs set volblocksize=... sur beaucoup de systèmes quand un ZVOL n’est pas en usage actif, ou parfois il refuse avec « in use »
selon la plateforme et l’implémentation ZFS. L’acceptation ne signifie pas que vous avez obtenu la migration désirée. Cela signifie que le dataset a maintenant une valeur
de propriété qui orientera les allocations futures. C’est tout.
Pourquoi la recréation est généralement la réponse propre
Recréer le ZVOL force tous les blocs à être alloués à neuf sous la nouvelle politique. C’est la seule façon déterministe de garantir que l’ensemble du volume adopte
le nouveau comportement volblocksize. Tout le reste est probabiliste et lent, et se heurte aux snapshots, à la provision fine et aux réécritures partielles.
Faits intéressants et contexte historique
- ZFS est né chez Sun au milieu des années 2000, conçu autour de l’intégrité bout-en-bout, du copy-on-write et du stockage poolé — des idées qui sont ensuite devenues la norme.
- Les ZVOL ont été une passerelle « périphérique bloc » délibérée : ils permettent à ZFS de servir des charges qui exigent une abstraction disque (VM, cibles iSCSI)
sans forcer un filesystem ZFS à l’intérieur de l’invité. - L’accent initial sur ZFS était la justesse plutôt que les micro-optimisations ; des propriétés comme la taille de bloc étaient des réglages politiques, pas des mécanismes de repacking en direct.
- Les disques Advanced Format (secteurs 4K) ont rendu les problèmes d’alignement très visibles ;
ashiftest devenu une décision critique de conception de pool. - Le stockage VM a popularisé les ZVOL parce que les hyperviseurs et outils SAN parlent nativement périphériques bloc, même si des images fichiers seraient parfois plus simples.
- L’adoption précoce de ZFS-on-Linux a accéléré des pratiques opérationnelles comme la réplication
zfs send/receive, faisant de la « recréation et stream » une démarche normale. - La compression est devenue mainstream non seulement pour la capacité, mais aussi pour les performances : moins d’I/O peut battre plus de CPU, surtout sur des pools SSD.
- Les snapshots ont changé la culture opérationnelle : les équipes ont commencé à tout snapshotter parce que c’était bon marché — jusqu’à ce que ça ne le soit plus, surtout avec des blocs épinglés et des chaînes de rétention longues.
- Avec la baisse de latence NVMe, les frais logiciels et l’amplification d’I/O sont devenus plus visibles ; une mauvaise taille de bloc peut gaspiller l’avantage des médias rapides.
Méthode rapide de diagnostic
Quand quelqu’un se plaint « le ZVOL est lent », ne commencez pas par changer volblocksize. Commencez par déterminer quelle couche ment.
Voici une séquence serrée qui trouve le goulot d’étranglement rapidement.
1) D’abord : est-ce la latence ou le débit ?
- Si les utilisateurs se plaignent de « VM lente » et de « timeouts DB », supposez la latence.
- Si les sauvegardes ou copies en masse sont lentes, supposez le débit — sauf si ce sont des écritures sync.
2) Deuxième : la charge est-elle liée aux écritures synchrones ?
- Vérifiez le comportement
syncet si vous avez un SLOG adapté (ou pas, et c’est acceptable aussi). - Les écritures sync intensives amplifient chaque mauvais choix : taille de bloc, fragmentation et mise en file des périphériques.
3) Troisième : confirmez la taille d’I/O réellement vue par le pool
- Observez les tailles d’I/O au niveau ZFS. Si vous voyez des écritures 128K alors que l’application annonce 4K, quelque chose coalesce — ou ment.
4) Quatrième : vérifiez la fragmentation et l’épinglage par snapshots
- Une fragmentation élevée plus des chaînes de snapshots longues peuvent tuer l’I/O aléatoire même sur SSD.
- Si les blocs ne peuvent pas être libérés, le « tuning » devient un placebo.
5) Cinquième : seul alors décidez si volblocksize est le levier
- Si la charge est dominée par des I/O aléatoires 4K/8K (bases de données, tempêtes de boot VM), un
volblocksizeplus petit aide souvent. - Si ce sont des écritures/lectures séquentielles importantes (vidéo, sauvegardes dans l’invité), des blocs plus grands peuvent aider — à condition que l’invité émette de grosses écritures.
Tâches pratiques : commandes, sorties et décisions
Le but des commandes n’est pas de paraître occupé. C’est de transformer « je pense » en « je sais », puis de prendre une décision que vous pouvez défendre.
Ci‑dessous des tâches pratiques que j’utilise réellement pour diagnostiquer ou planifier une migration volblocksize d’un ZVOL.
Task 1: Identify the ZVOL and verify its current volblocksize
cr0x@server:~$ zfs list -t volume -o name,volsize,volblocksize,compression,sync pool/vm-101-disk-0
NAME VOLSIZE VOLBLOCKSIZE COMPRESS SYNC
pool/vm-101-disk-0 200G 128K lz4 standard
Ce que cela signifie : Ce ZVOL est configuré pour allouer jusqu’à 128K de blocs pour les écritures futures. Il est aussi compressé en lz4.
sync est standard (honore les demandes d’application).
Décision : Si la charge invitée est majoritairement des I/O aléatoires 4K/8K, 128K est suspect. Ne changez pas encore. Mesurez d’abord.
Task 2: Check if the property is inherited or explicitly set
cr0x@server:~$ zfs get -H -o property,value,source volblocksize pool/vm-101-disk-0
volblocksize 128K local
Ce que cela signifie : C’est défini localement. Quelqu’un a choisi cette valeur.
Décision : Traitez cela comme une tentative de tuning volontaire. Demandez quel était la charge et pourquoi. Supposez que la raison est perdue dans le temps.
Task 3: Confirm pool ashift and vdev layout (alignment reality check)
cr0x@server:~$ zdb -C pool | sed -n '1,120p'
MOS Configuration:
version: 5000
name: 'pool'
state: 0
txg: 1234567
pool_guid: 1234567890123456789
hostid: 1122334455
hostname: 'server'
vdev_tree:
type: 'root'
id: 0
guid: 9876543210987654321
children[0]:
type: 'mirror'
id: 0
guid: 1111111111111111111
ashift: 12
Ce que cela signifie : ashift: 12 implique des secteurs 4K (2^12). Bonne base pour SSD/HDD modernes.
Décision : Si ashift était 9 (512B) sur du matériel 4K, vous auriez des problèmes plus profonds que volblocksize. Planifiez une migration de pool, pas un ajustement de ZVOL.
Task 4: Check ZVOL “in use” state and whether a live change is even allowed
cr0x@server:~$ zfs set volblocksize=16K pool/vm-101-disk-0
cannot set property for 'pool/vm-101-disk-0': volume is busy
Ce que cela signifie : Le kernel utilise le périphérique bloc (mappé, exporté via iSCSI, attaché à une VM, etc.).
Décision : Ne forcez pas. Planifiez une migration vers un nouveau ZVOL avec la taille voulue, puis basculez.
Task 5: Identify what’s consuming the ZVOL (VM, iSCSI, multipath)
cr0x@server:~$ ls -l /dev/zvol/pool/vm-101-disk-0
lrwxrwxrwx 1 root root 13 Dec 26 02:10 /dev/zvol/pool/vm-101-disk-0 -> ../../zd0
cr0x@server:~$ lsblk -o NAME,TYPE,SIZE,MOUNTPOINT,FSTYPE /dev/zd0
NAME TYPE SIZE MOUNTPOINT FSTYPE
zd0 disk 200G
Ce que cela signifie : Le ZVOL est un disque brut zd0. Si vous le voyez monté, mappé à DM, ou utilisé par iSCSI,
cela explique qu’il soit « busy ».
Décision : Suivez la chaîne de dépendances avant de planifier une fenêtre de migration. Les gens s’énerveront si vous détachez « juste un disque ».
Task 6: Check snapshot count and retention risk (pinned blocks)
cr0x@server:~$ zfs list -t snapshot -o name,used,refer -s creation | grep '^pool/vm-101-disk-0@' | tail -n 5
pool/vm-101-disk-0@auto-2025-12-26_0000 1.2G 180G
pool/vm-101-disk-0@auto-2025-12-26_0100 600M 180G
pool/vm-101-disk-0@auto-2025-12-26_0200 400M 180G
pool/vm-101-disk-0@auto-2025-12-26_0300 250M 180G
pool/vm-101-disk-0@auto-2025-12-26_0400 200M 180G
Ce que cela signifie : Vous avez des snapshots fréquents. La colonne used suggère un churn actif. Les anciens blocs sont probablement épinglés.
Décision : Si vous espériez que « la charge se réécrive naturellement en nouveau volblocksize », les snapshots vous saboteront.
La migration vers un nouveau ZVOL avec une politique de snapshot propre est la voie sensée.
Task 7: Measure I/O and latency at the pool level
cr0x@server:~$ zpool iostat -v pool 1 5
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
pool 4.20T 3.10T 820 2400 45.2M 110M
mirror 4.20T 3.10T 820 2400 45.2M 110M
nvme0n1 - - 410 1200 22.6M 55M
nvme1n1 - - 410 1200 22.6M 55M
Ce que cela signifie : Vous êtes en écriture lourde. C’est le moment de demander : ces écritures sont-elles sync ? Sont-elles petites et aléatoires ? Sont-elles séquentielles ?
Décision : Si le débit est élevé mais que les plaintes de latence persistent, le problème est probablement la latence sync, la mise en file, ou l’amplification d’écriture,
pas le simple débit brut.
Task 8: Check per-dataset I/O (is the ZVOL really the hot spot?)
cr0x@server:~$ zfs iostat -v pool 1 3
capacity operations bandwidth
dataset alloc free read write read write
----------------------------- ----- ----- ----- ----- ----- -----
pool 4.20T 3.10T 0 0 0 0
pool/vm-101-disk-0 200G 3.10T 120 1600 3.2M 62M
pool/vm-102-disk-0 120G 3.10T 40 300 1.1M 10M
Ce que cela signifie : vm-101 domine les écritures.
Décision : Ne commencez pas à tuner le pool globalement si un seul ZVOL est responsable. Corrigez le coupable.
Task 9: Check compression ratio and whether smaller blocks will explode metadata
cr0x@server:~$ zfs get -H -o property,value compressratio pool/vm-101-disk-0
compressratio 1.45x
Ce que cela signifie : La compression apporte un gain utile. Des blocs plus petits peuvent réduire le read-modify-write sur les petites écritures,
mais peuvent augmenter la surcharge métadonnées et réduire l’efficacité de la compression dans certains schémas.
Décision : Si la charge ressemble à une base de données, privilégiez la justesse et la latence plutôt que des gains théoriques de compression.
Task 10: Confirm TRIM behavior (thin provisioning sanity)
cr0x@server:~$ zfs get -H -o property,value autotrim pool
autotrim on
Ce que cela signifie : Le pool envoie TRIM automatiquement (comportement dépendant de l’implémentation). Pour les ZVOL utilisés par des invités,
vous avez aussi besoin du support discard dans la pile invitée pour récupérer l’espace efficacement.
Décision : Si l’usage d’espace continue d’augmenter même après des suppressions dans l’invité, vérifiez le discard invité et la rétention des snapshots avant d’accuser volblocksize.
Task 11: Estimate rewrite feasibility with a quick logical copy test (offline or on a clone)
cr0x@server:~$ zfs snapshot pool/vm-101-disk-0@pre-migrate
cr0x@server:~$ zfs clone pool/vm-101-disk-0@pre-migrate pool/vm-101-disk-0-clone
Ce que cela signifie : Vous avez maintenant un clone qui partage des blocs. C’est excellent pour tester des procédures, pas pour forcer une réécriture.
Décision : Utilisez le clone pour valider les étapes d’export/attach, pas pour « corriger » la disposition des blocs. Les blocs partagés restent partagés tant qu’ils ne sont pas réécrits.
Task 12: Create the new ZVOL with the desired volblocksize (the real migration step)
cr0x@server:~$ zfs create -V 200G -b 16K -o compression=lz4 -o sync=standard pool/vm-101-disk-0-new
cr0x@server:~$ zfs list -t volume -o name,volsize,volblocksize pool/vm-101-disk-0-new
NAME VOLSIZE VOLBLOCKSIZE
pool/vm-101-disk-0-new 200G 16K
Ce que cela signifie : Vous avez une cible ZVOL propre avec la nouvelle taille de bloc. C’est la seule manière de garantir une politique d’allocation neuve.
Décision : Engagez un plan de basculement. Le reste est mouvement de données et discipline opérationnelle.
Task 13: Block-level copy with progress (offline migration)
cr0x@server:~$ dd if=/dev/zvol/pool/vm-101-disk-0 of=/dev/zvol/pool/vm-101-disk-0-new bs=16M status=progress conv=sync,noerror
21474836480 bytes (21 GB, 20 GiB) copied, 42 s, 511 MB/s
Ce que cela signifie : Vous effectuez une réécriture logique vers le nouveau ZVOL. La destination sera allouée selon sa politique volblocksize
au fur et à mesure que le flux arrive.
Décision : N’utilisez ceci que lorsque la source est mise en quiescence (VM arrêtée, filesystem propre) à moins que vous ne fassiez
volontairement une copie consistante au crash. Le plus souvent, arrêtez la VM.
Task 14: Verify the guest sees the same disk identity expectations (UUIDs, partitions)
cr0x@server:~$ sgdisk -p /dev/zvol/pool/vm-101-disk-0-new
Disk /dev/zvol/pool/vm-101-disk-0-new: 419430400 sectors, 200.0 GiB
Sector size (logical/physical): 512/4096 bytes
Disk identifier (GUID): 5A1B2C3D-4E5F-6789-ABCD-0123456789AB
Partition table holds up to 128 entries
Number Start (sector) End (sector) Size Code Name
1 2048 2099199 1024.0 MiB EF00 EFI System
2 2099200 419428351 199.0 GiB 8300 Linux filesystem
Ce que cela signifie : La table de partitions a été copiée et semble cohérente. La sortie « Sector size » est utile : si votre invité s’attend à du 4K,
vérifiez que ce n’est pas une surprise.
Décision : Si vous voyez des tailles de secteur inattendues ou des partitions manquantes, arrêtez. Ne procédez pas au basculement tant que vous n’avez pas compris pourquoi.
Task 15: Cutover by swapping ZVOL names atomically (with careful sequencing)
cr0x@server:~$ zfs rename pool/vm-101-disk-0 pool/vm-101-disk-0-old
cr0x@server:~$ zfs rename pool/vm-101-disk-0-new pool/vm-101-disk-0
cr0x@server:~$ zfs list -t volume -o name,volblocksize pool/vm-101-disk-0
NAME VOLBLOCKSIZE
pool/vm-101-disk-0 16K
Ce que cela signifie : Le nom canonique pointe maintenant vers le nouveau ZVOL, donc toute automatisation qui référence le dataset continue de fonctionner.
Décision : Gardez l’ancien ZVOL jusqu’à validation. Puis détruisez-le volontairement, pas impulsivement.
Stratégies de migration réellement efficaces
Strategy A: Recreate + block copy (simple, blunt, effective)
C’est l’approche dd ou image. Elle fonctionne bien quand vous pouvez prendre une fenêtre d’arrêt et voulez une réécriture déterministe.
C’est aussi la plus simple à expliquer au change management : « Nous avons créé un nouveau volume avec la géométrie correcte et copié le disque. »
Compromis :
- Pour : Garantie de réécriture, respecte le nouveau
volblocksize, peu de magie ZFS. - Contre : Nécessite une interruption pour la cohérence ; copie aussi l’espace libre ; lent si le disque est majoritairement vide.
Strategy B: Recreate + file-level migration inside the guest (cleaner data, but more moving parts)
Si vous pouvez attacher un second disque à la VM, vous pouvez migrer au niveau du filesystem : créez un nouveau ZVOL, attachez-le à l’invité, formatez-le,
copiez les données (rsync, dump/restore base de données), puis changez la configuration de boot. Cela réécrit uniquement les données utilisées et conduit souvent
à moins de fragmentation. C’est plus long humainement, plus efficace côté stockage.
- Pour : Ne copie pas les blocs inutilisés ; peut améliorer la disposition du filesystem invité ; souvent moins de downtime.
- Contre : Nécessite des modifications dans l’invité ; plus de modes de défaillance ; exige une gestion soigneuse de la cohérence applicative.
Strategy C: ZFS send/receive is for datasets, not direct “volblocksize conversion”
Les gens utilisent zfs send/receive parce que c’est le marteau ZFS. C’est excellent pour déplacer des datasets et préserver les snapshots.
Mais pour changer volblocksize, ce n’est pas la baguette magique qu’on espère. La réplication préserve la structure des blocs telle que représentée
dans le stream. Dans de nombreux cas pratiques, un receive ne « reblocke » pas magiquement vos données selon le nouveau volblocksize.
Utilisez send/receive pour :
- Déplacer le ZVOL vers un autre pool ou hôte.
- Préserver les snapshots/historique.
- Patrons de reprise après sinistre où l’identité et le rollback point-in-time comptent.
Utilisez recréer-et-copier quand :
- Vous voulez un changement de politique d’allocation déterministe.
- Vous voulez couper les chaînes de snapshots héritées et la fragmentation.
- Vous voulez une réinitialisation de performance mesurable.
Strategy D: “Let it rewrite naturally” (usually a trap)
Parfois les équipes changent volblocksize et espèrent que la charge réécrira suffisamment de données avec le temps pour que la nouvelle taille prenne effet.
Cela peut marcher dans des cas étroits : charges éphémères, runners CI, caches, ou templates VM souvent ré-imagés.
Ça échoue quand :
- Les snapshots épinglent les anciens blocs.
- Le disque est majoritairement statique (OS + applications installées) et le churn est faible par rapport au total.
- La charge est « chaude dans une petite zone » (bases de données), réécrivant la même région et augmentant la fragmentation sans changer le reste.
Une citation fiabilité pour rester honnête
La célèbre phrase de Brian Kernighan s’applique malicieusement bien aux changements de stockage : « Debugging is twice as hard as writing the code. »
(idée paraphrasée)
Les migrations de stockage ne sont pas difficiles parce que les commandes sont complexes. Elles sont difficiles parce que les suppositions se multiplient plus vite que les IOPS sur un graphique de benchmark.
Trois mini-récits du monde de l’entreprise
Mini-récit 1 : L’incident causé par une mauvaise hypothèse
Une entreprise de taille moyenne exploitait un cluster de virtualisation avec des disques VM sur ZVOL. Un nouvel ingénieur remarqua que le volblocksize
par défaut était 8K sur certains vieux ZVOL et 128K sur d’autres plus récents. Il supposa « blocs plus gros = meilleur débit », et que « ZFS s’occupera du reste ».
Un ticket de changement fut créé pour mettre tout à 128K.
La première surprise fut que certains volumes refusèrent le changement car ils étaient « busy ». L’ingénieur contourna cela en redémarrant des VM par batchs,
basculant la propriété quand les disques étaient détachés. La seconde surprise fut subtile : quelques VM de bases de données montrèrent des pics de latence périodiques.
Les applis ne plantèrent pas. Elles devinrent simplement assez lentes pour déclencher des tempêtes de retry et saturer des pools de connexions.
L’hypothèse qui les a piégés : changer la propriété convertirait la disposition des données existantes. Ce n’était pas le cas. Ils avaient une disposition mixte : ancien comportement ~8K
dans les vieux blocs, nouvelles allocations 128K dans les blocs récents, plus une longue histoire de snapshots qui épinglait les anciens blocs. Les graphiques de stockage semblaient
normales—jusqu’à ce qu’on regarde la latence tail et les temps d’écriture sync.
La correction n’était pas héroïque. Elle était ennuyeuse. Ils créèrent de nouveaux ZVOL de 16K pour les DB, firent des copies contrôlées hors-ligne au niveau bloc, basculèrent,
et réduisirent la rétention des snapshots pour ces volumes. Les performances se stabilisèrent et le cluster cessa d’avoir des « mardis mystères ».
Leçon : un changement de propriété n’est pas un plan de migration. Si vous avez besoin de migrer, migrez.
Mini-récit 2 : L’optimisation qui a mal tourné
Une équipe d’entreprise exploitait des cibles iSCSI sur ZVOL. Sur le papier la charge semblait séquentielle : dumps ETL nocturnes et gros transferts.
Ils posèrent volblocksize=256K pour « performance de streaming maximale », et sur le benchmark ça semblait excellent.
Puis la production arriva. La charge n’était pas que des dumps ; elle incluait aussi des écritures aléatoires petites faites par un agent d’état, plus un outil de sécurité
qui mettait constamment à jour de petits fichiers. Les initiateurs iSCSI produisaient un mélange de write sync 4K et d’écritures async plus grosses.
La latence monta, puis des pauses burst apparurent. Les jobs ETL commencèrent à rater leurs fenêtres. Les tableaux de bord montraient de la bande passante disponible, ce qui fit chasser
aux premiers intervenants le mauvais problème : « Mais on ne sature pas le pool. »
Ce qui est arrivé : avec un volblocksize important, les petites écritures sync déclenchèrent plus de read-modify-write et de churn métadonnées.
La partie séquentielle s’est accélérée ; la latence tail s’est dégradée. Et la latence tail est ce que les utilisateurs remarquent, et ce que les systèmes distribués amplifient.
Le rollback fut maladroit parce qu’ils essayèrent de « simplement remettre volblocksize ». Ça ne réarrangea pas les allocations existantes ; ça changea seulement les écritures futures.
Ils finirent par recréer les ZVOL à 16K, restaurer depuis des backups applicatifs (pas bloc), et accepter que le gain du benchmark n’était pas représentatif de la production.
Leçon : optimiser pour la moyenne mène aux incidents. Optimisez pour la charge mixte et moche qui tourne réellement à 2h du matin.
Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise
Un environnement régulé avait une règle : chaque ZVOL disque VM devait être créé via un script wrapper fin qui définit volblocksize selon la classe de charge
(VM générale, base de données, log-heavy) et tague le dataset avec une note lisible. Personne n’aimait le script. Tout le monde voulait « juste créer un volume ».
Des années plus tard, un rafraîchissement de stockage les força à migrer des pools. Lors de la planification de la migration, ils découvrirent une dispersion de ZVOL avec
tailles et problèmes de performance. Les tags du script wrapper permirent d’identifier clairement les volumes destinés DB-class, les volumes généraux et les cas particuliers créés manuellement.
Quand une base de facturation sensible montra des pics de latence après le déplacement, l’équipe avait une référence documentée claire : elle devait être en 16K.
Elle l’était. Ils ne perdirent pas une semaine à débattre de la taille de bloc. Ils vérifièrent la latence sync, validèrent la santé du SLOG, trouvèrent un initiateur mal configuré forçant des flushs,
et corrigèrent le vrai problème.
La pratique ennuyeuse n’était pas le script en lui‑même. C’était l’exigence de reproductibilité et de métadonnées : le système décrivait ce qu’il devait être.
Cela a évité une spirale spéculative de tuning sous pression.
Leçon : le meilleur outil de migration est une norme appliquée quand vous n’étiez pas en crise.
Erreurs fréquentes : symptômes → cause → correctif
1) Symptom: “We changed volblocksize and nothing happened”
Cause racine : Les blocs existants n’ont pas été réécrits ; la rétention des snapshots épingle les anciennes allocations.
Correctif : Recréez le ZVOL avec le -b souhaité et effectuez une réécriture logique (copie bloc hors-ligne ou restauration au niveau invité).
Révisez les snapshots et la rétention ; n’amenez pas un musée de snapshots dans une migration de performance à moins que ce soit nécessaire.
2) Symptom: “Random write latency spiked after increasing volblocksize”
Cause racine : Amplification read-modify-write et surcharge métadonnées sur petites écritures sync.
Correctif : Pour des charges DB-like aléatoires, choisissez plus souvent 8K–16K comme volblocksize. Validez avec des tests représentatifs de la charge,
pas des benchmarks séquentiels génériques. Recréez et réécrivez si vous avez besoin d’un layout cohérent.
3) Symptom: “Space usage didn’t go down after deleting data in the VM”
Cause racine : Le discard invité n’est pas activé, les snapshots épinglent les anciens blocs, ou la charge réécrit sans libérer à cause des snapshots.
Correctif : Confirmez le discard/TRIM invité, supprimez les snapshots inutiles, et assurez-vous que la solution de sauvegarde n’effectue pas des snapshots horaires éternels.
4) Symptom: “zfs set volblocksize fails with ‘volume is busy’”
Cause racine : Le périphérique bloc est attaché, ouvert, mappé ou exporté. Beaucoup de plateformes empêchent la modification en usage.
Correctif : Ne planifiez pas une modification risquée en direct. Créez un nouveau ZVOL avec la bonne taille et migrez. Si vous avez besoin d’un downtime quasi-nul,
utilisez la réplication applicative ou le mirroring au niveau invité, puis basculez.
5) Symptom: “Reads are fast, writes are slow, and CPU is low”
Cause racine : Écritures sync frappant le chemin lent (pas de SLOG adapté, réglages sync mal configurés, ou stockage incapable de committer assez vite).
Correctif : Confirmez le comportement sync au niveau applicatif et ZFS. Si vous déployez un SLOG, faites-le correctement (support protégé contre la perte de puissance),
ou ne le faites pas. N’utilisez pas sync=disabled comme panacée sauf si vous acceptez la perte potentielle d’écritures confirmées.
6) Symptom: “After migration, performance improved briefly then degraded”
Cause racine : La fragmentation a augmenté à cause d’écritures petites et aléatoires continues ; la politique de snapshot a épinglé l’état et empêché le nettoyage ;
le filesystem invité peut être fortement fragmenté.
Correctif : Revoyez la politique de snapshot, considérez une maintenance périodique au niveau invité (ex. entretien DB, trim filesystem), et surveillez les indicateurs de fragmentation.
Ne traitez pas volblocksize comme un bouton miracle.
Blague n°2 : Les snapshots, c’est comme la rétention des mails d’entreprise — tout le monde les adore jusqu’à ce qu’il découvre qu’ils conservent chaque mauvaise décision pour toujours.
Listes de contrôle / plan étape par étape
Checklist de décision : devez-vous recréer le ZVOL ?
- La charge est-elle dominée par des I/O aléatoires petits (4K–16K) ? Si oui, vous voudrez probablement un
volblocksizeplus petit. - Avez-vous une longue chaîne de snapshots ? Si oui, la « réécriture naturelle » ne convertira pas proprement les anciens blocs.
- Le volume est-il occupé et ne peut pas changer de propriété ? C’est votre réponse : recréer-et-basculer.
- Avez-vous besoin d’un changement prévisible et mesurable dans une fenêtre de maintenance ? Recréez.
- Le volume est-il éphémère et fréquemment réécrit de bout en bout ? Vous pouvez peut‑être vous contenter de le définir pour les écritures futures.
Étapes : recréer-et-basculer en sécurité (hors-ligne, minimal drama)
- Métriques de référence. Capturez iostat pool et dataset pendant la fenêtre problématique. Confirmez à quoi ressemble le « mauvais » pour pouvoir vérifier « mieux ».
-
Inventaire des propriétés. Enregistrez
volsize,volblocksize,compression,sync,
reservation/refreservation, et la politique de snapshots. - Assurez-vous de pouvoir revenir en arrière. Prenez une snapshot finale et confirmez que les backups sont valides (pas seulement « configurés »).
- Planifiez downtime ou méthode de consistance. Arrêtez la VM ou quiescez l’application. Définissez ce que signifie « consistant ».
-
Créez le ZVOL cible. Utilisez
zfs create -V ... -b ...avec des propriétés explicites. Pas de surprises d’héritage. - Copiez les données. Utilisez la copie bloc pour la simplicité, ou la copie au niveau invité pour l’efficacité. Validez le résultat.
- Basculement par renommage ou rattachement. Préférez le renommage dataset pour la compatibilité avec l’automatisation. Confirmez les chemins de périphérique.
- Démarrez et validez. Vérifiez le filesystem invité, la santé applicative et la latence de stockage.
- Surveillez 24–72 heures. Surveillez la latence tail, les écritures sync et la croissance des snapshots.
- Retirez l’ancien ZVOL. Gardez-le pour une fenêtre de rollback définie, puis détruisez-le intentionnellement. Documentez le changement.
Étapes : si vous insistez pour « changer en place »
Parfois vous ne pouvez pas migrer immédiatement. Si vous allez définir volblocksize sans recréer, faites-le en connaissance de cause :
- Confirmez qu’il n’y a pas de snapshots qui garderont les anciens blocs pour toujours (ou acceptez la conséquence).
- Définissez la propriété uniquement pendant une période calme ; attendez-vous à zéro amélioration immédiate.
- Planifiez un futur « événement de réécriture » (restauration depuis backup, reimage, copie complète de disque) qui forcera réellement le changement de layout.
FAQ
1) Can I change volblocksize on an existing ZVOL?
Parfois vous pouvez définir la propriété, parfois elle refusera si le volume est busy. Même quand cela réussit, cela affecte typiquement seulement les allocations futures.
Cela ne convertit pas de façon fiable la disposition des données existantes.
2) Why does recreating the ZVOL work when changing the property doesn’t?
La recréation force tous les blocs à être alloués à neuf sous la nouvelle politique. Copier les données sur un ZVOL neuf provoque une réécriture logique complète,
qui est ce dont vous avez réellement besoin pour « migrer » le comportement de taille de bloc.
3) Does ZFS send/receive change volblocksize?
Ne le considérez pas comme un outil de conversion. Send/receive est excellent pour la réplication et le déplacement de datasets, mais il ne garantit pas une transformation de reblocking
des allocations existantes. Si vous avez besoin d’un layout déterministe, recréez et réécrivez.
4) What volblocksize should I use for VM disks?
Pour les disques VM généralistes, 8K–16K est un intervalle pratique courant. Les bases de données préfèrent souvent plus petit. Les charges séquentielles peuvent justifier plus grand.
Choisissez selon les tailles d’I/O observées et le comportement sync, pas par dogme.
5) Is smaller volblocksize always faster for random I/O?
Souvent oui, mais pas systématiquement. Les blocs plus petits peuvent réduire le read-modify-write sur les petites écritures, mais augmenter la surcharge métadonnées et réduire l’efficacité de la compression.
Si vous êtes lié par le CPU pour la compression ou les métadonnées, plus petit peut nuire. Mesurez avec des tests proches de la production.
6) How do snapshots interfere with volblocksize migration?
Les snapshots conservent des références aux anciens blocs. Même si l’invité réécrit des données, les anciens blocs restent alloués et la fragmentation perdure.
Vous vous retrouvez avec un layout mixte et moins des bénéfices espérés.
7) What about sync=disabled to “fix latency”?
Ce n’est pas une solution. C’est une décision métier d’accepter la perte possible d’écritures confirmées en cas de crash/perte d’alimentation. Si vous acceptez ce risque, documentez‑le.
Sinon, résolvez le vrai chemin sync (latence des périphériques, design du SLOG, comportement des initiateurs).
8) Can I use zvol “thin provisioning” safely with a migration?
Oui, mais comprenez la récupération d’espace. Assurez-vous que discard/TRIM fonctionne de bout en bout (invité → hyperviseur → ZVOL → pool → SSD). Rappelez-vous aussi que les snapshots peuvent contrecarrer la récupération.
La migration par restauration au niveau invité récupère souvent l’espace mieux que la copie bloc.
9) How do I prove the new volblocksize helped?
Comparez la latence avant/après (en particulier la latence tail), les temps d’écriture sync, et les métriques applicatives. Le seul débit pool est un signal faible.
Utilisez zpool iostat, zfs iostat, et des mesures spécifiques à la charge.
10) If I already changed volblocksize, should I change it back?
Si vous l’avez changé et observé une régression, le remettre en arrière peut ne pas annuler les changements de layout déjà écrits. Cela peut empêcher une dérive supplémentaire,
mais la solution propre reste de recréer-et-réécrire pour le volume affecté.
Prochaines étapes réalisables cette semaine
Si vous avez des plaintes de performance ZVOL et une pile de tentatives de tuning à moitié oubliées, faites ceci dans l’ordre :
- Choisissez un ZVOL problématique et capturez une baseline de 10 minutes pendant la charge réelle :
zpool iostat -v 1etzfs iostat -v 1. - Inventoriez les snapshots et la rétention pour ce ZVOL. Si vous avez un musée de snapshots, admettez-le et planifiez un nettoyage ou une migration sans l’emporter.
- Créez un ZVOL test avec le
volblocksizecible et réalisez une migration contrôlée en fenêtre de maintenance. Mesurez la latence tail et le comportement applicatif. - Standardisez la création : script, documentez, tagguez les datasets. Votre futur vous sera reconnaissant.
L’essentiel n’est pas de vénérer un nombre comme 8K ou 16K. L’essentiel est de faire du layout des blocs un choix délibéré, puis de l’appliquer en recréant quand vous avez besoin d’un vrai changement.
ZFS vous donne des outils tranchants. Utilisez-les comme si vous alliez être d’astreinte quand on les activera.