Les problèmes de désalignement sont du genre à rendre les SRE superstitieux. Les graphiques ont l’air hantés : des pics de latence alors que rien n’a changé, des IOPS qui refusent de monter, des SSD qui se comportent comme des disques durs lors des benchmarks. Puis vous trouvez la cause : ashift est incorrect, et le pool a effectué du travail supplémentaire à chaque écriture depuis le jour un.
Ceci n’est pas un article « lisez le man ». C’est le guide de terrain que vous auriez aimé avoir avant de créer ce pool — ce que ashift contrôle vraiment, pourquoi c’est collant, comment prouver que ça vous nuit, et les moyens les moins risqués de retrouver des performances raisonnables en production.
Ce qu’est ashift (et ce que ce n’est pas)
ashift est la façon dont ZFS dit : « Quand j’alloue des blocs sur le disque, je traiterai la taille d’écriture minimale du périphérique comme 2^ashift octets. » Si ashift=12, ZFS alloue en secteurs de 4096 octets. Si ashift=9, il alloue en secteurs de 512 octets. Cette seule décision détermine si beaucoup de vos écritures sont propres, opérations en un seul IO — ou des cycles coûteux de lecture-modification-écriture qui transforment les charges d’écriture aléatoires en soupe de latence.
L’« ashifness » n’est pas un réglage que vous pouvez changer à la légère un mardi après-midi. Il est défini au moment de la création du vdev et est effectivement intégré dans la façon dont le pool dispose les blocs. Vous pouvez parfois remplacer un vdev par un nouveau avec un ashift différent lors d’une migration de reconstruction, mais vous ne pouvez pas « basculer ashift » en place et faire que les blocs existants se réalignent magiquement. ZFS est puissant ; ce n’est pas une machine à remonter le temps.
Ce que ashift contrôle
- Unité minimale d’allocation sur chaque vdev : la « taille de secteur » que ZFS suppose pour ce périphérique.
- Alignement des écritures ZFS sur des limites favorables au périphérique.
- Risque d’amplification pour les petites écritures : un mauvais ashift peut forcer plus d’IO que prévu.
Ce que ashift ne contrôle pas
- Taille de bloc du dataset (c’est
recordsizepour les systèmes de fichiers etvolblocksizepour les zvols). - Compression, checksum ou le calcul de parité RAIDZ.
- La vitesse de votre CPU — bien que des erreurs d’ashift puissent être si graves qu’elles ressemblent à des problèmes CPU parce que tout attend l’IO.
Une nuance importante : ashift est par vdev, pas « par pool » dans un sens abstrait. Quand vous dites « mon pool ashift est 12 », vous voulez généralement dire « tous les vdevs du pool ont ashift=12 ». Des vdevs avec ashift mixte peuvent exister, et ce n’est rarement une fête que vous voudriez organiser.
Première blague (restez concis) : La bonne nouvelle avec ashift, c’est que c’est une décision prise une fois. La mauvaise nouvelle avec ashift, c’est que c’est une décision prise une fois.
Pourquoi un mauvais ashift fait tant de dégâts
Le clif de performance vient de la façon dont les périphériques de stockage écrivent réellement les données. Beaucoup de disques et SSD exposent des secteurs logiques de 512 octets pour compatibilité, mais leur unité d’écriture « physique » interne est de 4K (ou plus). Si ZFS croit pouvoir écrire des blocs de 512B (ashift=9) sur un périphérique qui préfère des écritures 4K, le périphérique peut devoir effectuer un cycle de lecture-modification-écriture (RMW) :
- Lire tout le bloc physique de 4K dans le cache interne
- Modifier la portion de 512B qui a changé
- Écrire le bloc complet de 4K
Ce sont trois opérations là où vous en attendiez une. Et parce que ces opérations sont sérialisées à l’intérieur du périphérique, votre queue de latence devient moche même si la moyenne paraît « correcte ». Dans des systèmes réels, il n’est pas rare de voir une chute d’environ ~2× du débit ou bien pire sur les petites écritures aléatoires, plus une augmentation dramatique de la latence p99.
Pourquoi « moitié des performances » n’est pas une exagération
Quand ashift est trop petit, ZFS émettra des écritures plus petites. Les périphériques qui ne peuvent pas écrire nativement ces tailles paient une taxe RMW. Si votre charge est :
- très orientée synchrone (bases de données, NFS avec sync, virtualisation avec barrières d’écriture),
- des écritures aléatoires petits-blocs (métadonnées VM, WAL/redo logs de BD, journalisation),
- ou RAIDZ au-dessus d’un désalignement (parité + RMW est une douleur particulière),
alors cette taxe se manifeste en profondeur de file d’attente, puis en latence, puis en « pourquoi notre service commence à timeout ».
Ashift trop grand : le compromis plus discret
L’erreur opposée existe : choisir un ashift plus grand que nécessaire, comme ashift=13 (8K) sur un périphérique réellement 4K. Cela ne tue généralement pas les performances ; cela augmente « seulement » l’espace utilisé et peut réduire l’efficacité pour les très petits blocs. C’est en général la direction la plus sûre d’un point de vue opérationnel : l’espace gaspillé est gênant, mais la latence imprévisible est ce qui vous réveille la nuit.
Deuxième blague : Si vous réglez mal ashift, ZFS ne se fâchera pas — il deviendra juste lent. C’est probablement le système de fichiers le plus passif-agressif possible.
Faits et contexte historique à connaître
Ce ne sont pas des anecdotes pour le plaisir. Ils expliquent pourquoi ashift reste un piège en 2025.
- Les secteurs de 512 octets ont dominé pendant des décennies, car les contrôleurs, systèmes de fichiers et firmwares initiaux se sont standardisés dessus. L’inertie de compatibilité est réelle.
- Les disques « Advanced Format » (4K) sont devenus courants pour réduire les frais généraux et augmenter l’efficacité de capacité ; beaucoup exposent toujours du 512e (émulation 512) à l’OS.
- Certains périphériques mentent — intentionnellement. Ils rapportent des secteurs logiques 512 même quand leur taille interne de programme/effacement est 4K ou plus, parce que certains OS et chargeurs d’amorçage supposaient historiquement du 512.
- ZFS a été conçu pour l’intégrité des données d’abord ; l’allocateur et le modèle de transaction supposent que l’alignement compte, mais ils ne peuvent pas toujours faire confiance aux rapports des disques.
- Ashift est devenu « collant » par conception. Permettre de changer la taille de secteur sous un pool actif risquerait de corrompre les hypothèses sur la disposition sur disque.
- Les SSD ont introduit de nouvelles « réalités physiques » : les pages NAND et blocs d’effacement ne correspondent pas parfaitement à 512 ou 4K, mais l’alignement 4K reste une base solide pour éviter l’amplification d’écriture.
- RAIDZ rend l’alignement plus sensible. Le calcul de parité et la largeur de stripe interagissent avec les limites de secteur ; le désalignement peut multiplier la douleur.
- La virtualisation a ajouté une autre couche de tromperie : un disque virtuel peut annoncer du 512 alors que le stockage sous-jacent est natif 4K ; ashift doit correspondre au fond réel.
- Aux débuts de l’adoption d’OpenZFS sur Linux, beaucoup d’admins migrés d’ext4/mdadm ont traité ZFS comme « juste une autre couche RAID », manquant complètement ashift.
Trois mini-histoires du monde de l’entreprise
Mini-histoire n°1 : Un incident causé par une mauvaise hypothèse
Tout a commencé comme une remise à neuf de plateforme : nouveaux hosts hyperviseurs, nouveaux « SSD d’entreprise », et un nouveau pool ZFS pour servir le stockage VM. L’équipe a fait ce que font les équipes sous pression temporelle : elle a copié la commande zpool create de l’année précédente depuis une page wiki, l’a exécutée, a vu le pool monter, et est passée à autre chose. Personne n’a regardé ashift parce que « les SSD sont rapides ».
Deux semaines plus tard, le volume de tickets a grimpé : lenteurs intermittentes sur une API client. Les graphiques étaient confus. Le CPU allait bien. Le réseau allait bien. Les nœuds de base de données avaient l’air inactifs. Mais la plateforme VM montrait des pics de latence stockage — des rafales courtes, juste assez longues pour déclencher des timeouts.
Le premier on-call a pensé à un voisin bruyant. Le second a supposé un SSD défectueux. Le troisième a fait quelque chose d’inesthétique : comparer les propriétés ZFS du nouveau cluster à l’ancien. Là ça a sauté aux yeux : l’ancien pool avait ashift=12. Le nouveau était ashift=9.
Les disques déclaraient des secteurs logiques 512, donc ZFS a « gentiment » choisi un alignement 512 octets. Sous une charge VM d’écritures aléatoires, ces « SSD d’entreprise » faisaient des cycles RMW internes. L’incident n’était pas une panne catastrophique unique ; c’était la lenteur par latence queue. La correction ne fut pas rapide : ils ne pouvaient pas changer ashift en place. Ils ont construit un nouveau pool avec ashift=12, migré les VM à chaud quand c’était possible, migré les autres à froid, et en ont fait une leçon sur le fait de faire confiance mais de vérifier les rapports matériels.
Ce qui a changé après ? Leur checklist de construction a reçu une nouvelle ligne : « Enregistrer ashift par vdev avant d’y stocker des données. » C’était ennuyeux. Ça a aussi empêché la répétition de ce type d’incident.
Mini-histoire n°2 : Une optimisation qui s’est retournée contre eux
Une autre organisation avait un problème de performance, et elle a fait ce que font les organisations qui chassent la performance : elles ont optimisé. Elles avaient lu que des secteurs plus grands pouvaient être bénéfiques, alors elles ont décidé de standardiser sur ashift=13 (8K) « pour coller aux internes des SSD modernes ». Elles ont reconstruit un pool, en ont été fières, et l’ont mis en production pour une charge mixte : petits fichiers de configuration, couches de conteneurs, et un système CI bavard et riche en métadonnées.
Les benchmarks initiaux semblaient bons — parce que leur test était surtout du débit séquentiel. Puis le système CI a commencé à ralentir. La plainte n’était pas la vitesse brute ; c’était l’amplification : beaucoup de petits fichiers et petites écritures faisaient que ZFS allouait en chunks minimum de 8K. L’utilisation de l’espace a augmenté plus vite que prévu, les snapshots ont grossi agressivement, et le pool a déclenché des alarmes de capacité plus tôt que l’ancien.
Le côté amusant : la pression de capacité déclenche des changements de comportement. L’espace libre diminue, les metaslabs se fragmentent, l’allocation devient plus coûteuse, et le système qui « benchmarquait mieux » a commencé à paraître pire sous charge réelle. Leur optimisation n’a pas causé d’erreurs d’intégrité, mais elle a transformé un projet performance en projet de gestion de capacité. C’est comme ça qu’on finit en réunion avec la finance, ce qui n’améliore jamais la latence.
Ils n’ont pas abandonné ashift=13 totalement. Ils ont appris à l’appliquer intentionnellement : datasets à gros blocs, certaines cibles de sauvegarde, et des types de vdev où le compromis avait du sens. Pour les pools polyvalents, ils sont revenus à la base ennuyeuse : ashift=12 sur des périphériques de classe 4K.
Mini-histoire n°3 : Une pratique ennuyeuse mais correcte qui a sauvé la mise
Une équipe stockage avec laquelle j’ai travaillé avait une habitude qui semblait paranoïaque : à chaque provisionnement de nouveaux disques, ils exécutaient un petit script de « vérification de la vérité » avant de construire les pools. Il collectait les tailles de secteur avec lsblk, interrogeait la topologie HBA, et sauvegardait des résumés smartctl dans le ticket. Il forçait aussi ashift=12 sauf motif fort contraire.
Un jour, l’approvisionnement a remplacé un modèle de disque à cause de contraintes de chaîne d’approvisionnement. Même marque, même capacité, mêmes revendications marketing. Mais le lot de remplacement se comportait différemment : il exposait des secteurs logiques 512 et « masquait » son comportement physique 4K. L’OS avait l’air content dans les deux cas.
La vérification a signalé l’incohérence comparée aux lots précédents. L’équipe n’a pas paniqué ; elle a juste fait ce que la checklist disait : créer un petit pool test, confirmer la sélection d’ashift, et benchmarker des écritures aléatoires sync. Les chiffres étaient incorrects d’une manière qui sentait le désalignement.
Ils ont forcé ashift=12 pendant la création du pool, relancé les tests, et les performances sont revenus. Aucun incident. Aucun impact client. Juste une demande de changement tranquille avec une preuve jointe. C’est le genre d’ennui qui rend les systèmes fiables.
Tâches pratiques : commandes + interprétation (12+)
Toutes les tâches ci-dessous supposent OpenZFS sur Linux sauf mention contraire, mais la plupart des commandes s’appliquent de façon similaire sur illumos/FreeBSD avec de petites différences de chemin. Utilisez-les comme une boîte à outils : vérifiez ashift, détectez les symptômes de désalignement, et planifiez la remédiation.
Task 1: List vdev ashift values (the ground truth)
cr0x@server:~$ sudo zdb -C tank | sed -n '/vdev_tree/{:a;n;/}/q;p;ba}'
Interprétation : Cherchez les entrées ashift sous chaque leaf vdev. Si vous voyez ashift: 9 sur un SSD/HDD moderne de classe 4K, vous avez probablement un problème. Si certains vdevs montrent 12 et d’autres 9, vous avez une incohérence qui peut compliquer les attentes de performance et les extensions futures.
Task 2: Quick ashift check with a one-liner (leaf vdevs)
cr0x@server:~$ sudo zdb -C tank | awk '/path:|ashift:/{printf "%s ",$0} /ashift:/{print ""}'
Interprétation : Ceci imprime les chemins des périphériques avec ashift. Utile en réponse à incident quand vous avez besoin de réponses rapides, pas de beauté.
Task 3: Check what the OS thinks the sector sizes are
cr0x@server:~$ lsblk -o NAME,MODEL,SIZE,PHY-SeC,LOG-SeC,ROTA,TYPE
NAME MODEL SIZE PHY-SEC LOG-SEC ROTA TYPE
sda INTEL SSDPE2KX040T 3.7T 4096 512 0 disk
sdb INTEL SSDPE2KX040T 3.7T 4096 512 0 disk
Interprétation : Si PHY-SEC est 4096 et LOG-SEC est 512 (512e), le périphérique est un piège classique pour ashift. ZFS peut choisir 9 s’il fait confiance à la taille logique. Vous voulez généralement ashift=12 ici.
Task 4: Verify device-reported logical/physical blocks via sysfs (Linux)
cr0x@server:~$ for d in /sys/block/sd*/queue; do \
dev=$(basename "$(dirname "$d")"); \
printf "%s logical=%s physical=%s\n" \
"$dev" \
"$(cat "$d/logical_block_size")" \
"$(cat "$d/physical_block_size")"; \
done | head
sda logical=512 physical=4096
sdb logical=512 physical=4096
Interprétation : Même histoire que lsblk, mais scriptable et fiable. Capturez ceci dans les logs de construction ; ça accélère les enquêtes futures.
Task 5: Confirm pool topology and spot mixed vdev types
cr0x@server:~$ zpool status -v tank
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
sde ONLINE 0 0 0
sdf ONLINE 0 0 0
Interprétation : Ceci n’affiche pas ashift, mais il montre la topologie. RAIDZ + erreurs d’ashift ont tendance à apparaître comme « pourquoi la latence d’écriture petite est horrible ». Les vdevs mirror sont plus tolérants mais souffrent aussi avec un mauvais ashift sur SSD.
Task 6: Check dataset properties that interact with ashift symptoms
cr0x@server:~$ zfs get -o name,property,value -s local,default recordsize,compression,atime,sync tank/vmstore
NAME PROPERTY VALUE
tank/vmstore recordsize 128K
tank/vmstore compression zstd
tank/vmstore atime off
tank/vmstore sync standard
Interprétation : Les problèmes d’ashift sont les plus visibles sur les petites écritures synchrones. Si vous hébergez des images VM dans un dataset filesystem, recordsize n’est peut‑être pas le principal coupable, mais il affecte la forme des IO. Pour les zvols, vérifiez volblocksize à la place.
Task 7: For zvol-backed storage, check volblocksize (and accept the pain)
cr0x@server:~$ zfs get -o name,property,value volblocksize,compression,sync tank/zvol0
NAME PROPERTY VALUE
tank/zvol0 volblocksize 8K
tank/zvol0 compression zstd
tank/zvol0 sync standard
Interprétation : Si volblocksize est plus petit que la taille d’écriture minimale effective du périphérique, un mauvais ashift aggrave le problème. Vous voulez un alignement propre jusqu’au bas niveau.
Task 8: Observe real-time IO and latency (ZFS-level)
cr0x@server:~$ sudo zpool iostat -v tank 1 5
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 2.10T 1.50T 250 900 12.0M 85.0M
raidz2-0 2.10T 1.50T 250 900 12.0M 85.0M
sda - - 40 150 2.0M 14.0M
sdb - - 38 145 1.9M 13.8M
...
Interprétation : Si les opérations d’écriture sont élevées mais le débit modeste, vous êtes probablement en territoire petites IO. C’est là que le mauvais ashift peut transformer une charge raisonnable en moulinette de latence.
Task 9: Observe real-time IO and latency (device-level)
cr0x@server:~$ iostat -x 1 5
Device r/s w/s r_await w_await aqu-sz %util
sda 55.0 220.0 0.70 18.50 3.10 98.0
sdb 52.0 215.0 0.65 19.10 3.05 97.5
Interprétation : Un w_await élevé avec une utilisation proche de 100% sur des SSD lors d’un débit modeste est une odeur classique. Cela ne prouve pas qu’ashift est mauvais, mais indique que la douleur est sous ZFS, pas dans l’appli.
Task 10: Measure sync write behavior (the workload that exposes misalignment)
cr0x@server:~$ sudo fio --name=sync4k --directory=/tank/test \
--rw=randwrite --bs=4k --iodepth=16 --numjobs=4 --size=2G \
--fsync=1 --direct=1 --time_based --runtime=30 --group_reporting
sync4k: (groupid=0, jobs=4): err= 0: pid=1234: Fri Dec 1 12:00:00 2025
write: IOPS=4200, BW=16.4MiB/s (17.2MB/s), lat (usec): min=180, avg=3100, max=55000
Interprétation : Si vous attendiez beaucoup plus d’IOPS des SSD et voyez une latence moyenne en millisecondes, vous avez un problème de pile de stockage. Un mauvais ashift est une cause fréquente, surtout si les mêmes disques performent bien hors de ZFS.
Task 11: Compare with larger block writes to separate “small write tax” from general slowness
cr0x@server:~$ sudo fio --name=write128k --directory=/tank/test \
--rw=write --bs=128k --iodepth=32 --numjobs=1 --size=8G \
--direct=1 --time_based --runtime=30 --group_reporting
write128k: (groupid=0, jobs=1): err= 0: pid=1301: Fri Dec 1 12:01:00 2025
write: IOPS=2400, BW=300MiB/s (315MB/s), lat (usec): min=250, avg=400, max=8000
Interprétation : Si les écritures séquentielles larges semblent correctes mais que les écritures 4K sync sont affreuses, suspectez l’alignement et l’amplification d’écriture plus que « le pool est juste lent ».
Task 12: Check ZFS sync behavior and whether your workload is forcing it
cr0x@server:~$ zfs get -o name,property,value sync tank
NAME PROPERTY VALUE
tank sync standard
Interprétation : Beaucoup de charges production dépendent des sémantiques sync pour la correction. Désactiver sync pour « réparer les performances » est comment on achète de la vitesse au prix de la perte de données. Si ashift est mauvais, sync=disabled peut masquer le problème jusqu’au prochain incident.
Task 13: Check if you have special vdevs and confirm their ashift too
cr0x@server:~$ zpool status tank | sed -n '/special/,$p'
special
mirror-1
nvme0n1p2
nvme1n1p2
cr0x@server:~$ sudo zdb -C tank | awk '/special|path:|ashift:/{print}'
Interprétation : Les vdevs special stockent des métadonnées (et éventuellement des petits blocs). Si leur ashift diffère ou est mauvais pour les NVMe, vous pouvez créer des goulots metadata qui ressemblent à « ZFS est lent », mais en réalité « IO metadonnées mal alignées et triste ».
Task 14: Confirm what ashift ZFS would pick before you commit (test pool)
cr0x@server:~$ sudo zpool create -o ashift=12 testpool mirror /dev/sdg /dev/sdh
cr0x@server:~$ sudo zdb -C testpool | awk '/path:|ashift:/{print}'
path: '/dev/sdg'
ashift: 12
path: '/dev/sdh'
ashift: 12
cr0x@server:~$ sudo zpool destroy testpool
Interprétation : C’est le moment le plus sûr pour « corriger ashift » : avant qu’il n’y ait des données. Créez un petit pool test, vérifiez l’ashift dans la config, puis détruisez-le. C’est une assurance peu coûteuse.
Task 15: Prove to yourself that ashift is fixed only by rebuilding/migrating
cr0x@server:~$ sudo zpool get ashift tank
NAME PROPERTY VALUE SOURCE
tank ashift - -
Interprétation : Beaucoup de gens s’attendent à une propriété au niveau pool. Cette sortie en est la démonstration : ashift n’est pas une simple propriété de pool que vous pouvez basculer. Il faut inspecter la config des vdevs.
Mode d’emploi pour un diagnostic rapide
Voici la version « vous êtes en on-call et la base de données timeoute ». L’objectif est de rapidement séparer le désalignement ashift des autres dizaines de façons dont le stockage peut vous pourrir la journée.
Étape 1 : Confirmez que vous traitez une latence de stockage, pas CPU ou réseau
- Vérifiez les symptômes côté application : timeouts, blocages fsync, pics d’« IO wait » des VM.
- Sur Linux, cherchez IO wait et croissance de la file d’attente de run.
cr0x@server:~$ uptime
12:03:22 up 10 days, 4:11, 2 users, load average: 8.20, 7.10, 6.80
cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
3 7 0 123456 7890 987654 0 0 120 9800 500 900 10 8 40 42 0
Interprétation : Un wa élevé (IO wait) plus des processus bloqués (b) est un indice fort : le kernel attend du stockage.
Étape 2 : Identifiez si la douleur vient des petites écritures et du comportement synchrone
cr0x@server:~$ sudo zpool iostat -v tank 1 3
Interprétation : Des opérations d’écriture élevées avec un débit relativement bas suggèrent des petites écritures. C’est là que le désalignement apparaît en premier.
Étape 3 : Vérifiez la latence et l’utilisation des périphériques
cr0x@server:~$ iostat -x 1 3
Interprétation : Si des SSD montrent une utilisation élevée et un w_await élevé pendant un débit modeste, suspectez l’amplification d’écriture sous ZFS.
Étape 4 : Vérifiez ashift par vdev (ne devinez pas)
cr0x@server:~$ sudo zdb -C tank | awk '/path:|ashift:/{print}'
Interprétation : Si vous voyez ashift: 9 sur des périphériques de classe 4K, vous avez trouvé un suspect de premier plan.
Étape 5 : Corrélez avec les revendications de taille de secteur
cr0x@server:~$ lsblk -o NAME,PHY-SeC,LOG-SeC,MODEL /dev/sda
Interprétation : Si physical est 4096 et logical est 512, et ashift est 9, votre pile est désalignée par conception.
Étape 6 : Décidez : atténuer maintenant vs corriger correctement
- Atténuations : réduire la pression sync (avec prudence), déplacer les datasets écritures lourdes, ajouter un SLOG si approprié, réduire la fragmentation.
- Correction correcte : reconstruire/migrer vers un pool avec ashift correct.
Interprétation : Si c’est en production et que les données comptent, la correction correcte est presque toujours « construire un nouveau pool et migrer ». Le reste est du triage.
Erreurs courantes : symptômes et corrections
Mistake 1: Trusting drive-reported logical sector size
Symptôme : Nouveau pool sur des disques « modernes » a des performances étranges sur écritures aléatoires 4K ; les SSD montrent une utilisation élevée à faible bande passante.
Pourquoi ça arrive : Les périphériques 512e rapportent 512 de logique pour compatibilité ; ZFS peut choisir ashift=9 à moins que vous ne forciez 12.
Correction : Pour la plupart des périphériques modernes, utilisez explicitement -o ashift=12 lors de zpool create, et vérifiez avec zdb -C. Si le pool est déjà créé et incorrect, planifiez une reconstruction/migration.
Mistake 2: Assuming you can change ashift later
Symptôme : Quelqu’un essaie zpool set ashift=12 tank et soit ça échoue soit rien ne change ; les performances restent mauvaises.
Pourquoi ça arrive : Ashift est intégré dans la config du vdev et le comportement d’allocation sur disque.
Correction : Créez un nouveau pool avec ashift correct et migrez les données. Pour certaines topologies, vous pouvez remplacer les périphériques/vdevs un par un (les mirrors sont plus amicaux que RAIDZ), mais c’est toujours une reconstruction.
Mistake 3: Overcorrecting with too-large ashift everywhere
Symptôme : Les performances semblent correctes, mais l’usage d’espace est anormalement élevé ; les snapshots grossissent plus vite ; le pool déclenche des alarmes de capacité plus tôt.
Pourquoi ça arrive : Un ashift plus grand augmente la taille minimale d’allocation.
Correction : Utilisez ashift=12 comme baseline par défaut ; considérez des valeurs supérieures seulement pour des périphériques/charges mesurées où vous avez accepté l’overhead.
Mistake 4: “Fixing” performance by disabling sync
Symptôme : La latence s’améliore immédiatement, la direction déclare victoire, puis un événement d’alimentation ou un panic kernel crée de désagréables surprises.
Pourquoi ça arrive : Les écritures sync sont coûteuses ; désactiver sync privilégie la vitesse au détriment de la sécurité des données.
Correction : Gardez sync=standard sauf si vous pouvez accepter formellement le risque de perte de données. Si la charge sync est lourde, envisagez un vrai périphérique SLOG, affinez la charge, ou corrigez le désalignement ashift sous-jacent.
Mistake 5: Mixing vdevs with different ashift or device classes
Symptôme : Les performances du pool varient de manière imprévisible ; les extensions changent le profil de latence ; certains datasets deviennent « aléatoirement » plus lents.
Pourquoi ça arrive : ZFS répartit les allocations sur les vdevs ; des vdevs plus lents ou mal alignés peuvent dominer la latence queue.
Correction : Gardez les vdevs homogènes en performance et en ashift autant que possible. Si vous devez mélanger, isolez les charges dans des pools séparés.
Checklists / plan pas à pas
Checklist A: Building a new pool (do it right the first time)
- Inventoriez les périphériques et capturez les tailles de bloc physiques/logiques.
- Décidez d’un ashift de base (généralement 12 pour HDD/SSD modernes).
- Créez un pool test temporaire, vérifiez ashift via
zdb -C, détruisez-le. - Créez le pool réel avec ashift explicite.
- Validez les performances avec des écritures aléatoires petites et le comportement sync avant que des données de production n’arrivent.
cr0x@server:~$ lsblk -o NAME,MODEL,PHY-SeC,LOG-SeC,ROTA,SIZE
cr0x@server:~$ sudo zpool create -o ashift=12 tank raidz2 /dev/sda /dev/sdb /dev/sdc /dev/sdd /dev/sde /dev/sdf
cr0x@server:~$ sudo zdb -C tank | awk '/path:|ashift:/{print}'
cr0x@server:~$ zpool status tank
Interprétation : L’important n’est pas la commande ; c’est la vérification. Si vous ne vérifiez pas ashift immédiatement, vous ne le ferez que plus tard quand ça fera mal.
Checklist B: Migrating off a wrong-ashift pool with minimal drama
- Construisez un nouveau pool avec ashift correct, idéalement sur du matériel neuf ou des périphériques nouvellement découpés.
- Répliquez les datasets avec ZFS send/receive pour préserver les snapshots et les propriétés.
- Basculez les clients pendant une fenêtre de maintenance contrôlée (ou une coupure progressive si votre environnement le permet).
- Gardez l’ancien pool en lecture seule pendant une courte fenêtre de rollback si vous pouvez vous le permettre.
cr0x@server:~$ sudo zpool create -o ashift=12 tank2 mirror /dev/sdg /dev/sdh
cr0x@server:~$ sudo zfs snapshot -r tank@pre-migrate
cr0x@server:~$ sudo zfs send -R tank@pre-migrate | sudo zfs receive -F tank2
cr0x@server:~$ zfs list -r tank2
Interprétation : C’est la correction « propre » : déplacer les données vers un pool correctement aligné. C’est opérationnellement simple, testable et réversible si vous conservez la source un moment.
Checklist C: If you’re stuck with the wrong ashift for now (triage, not a cure)
- Identifiez les pires coupables : datasets ou zvols faisant beaucoup d’écritures sync petites.
- Déplacez ces charges en premier (même vers un petit pool correctement aligné) pour réduire la latence queue.
- Vérifiez que vous n’êtes pas proche de la saturation du pool ; la pression de capacité aggrave tout.
- Mesurez avant/après avec le même job fio, la même fenêtre, et capturez
zpool iostat.
cr0x@server:~$ zfs list -o name,used,avail,refer,mountpoint -r tank
cr0x@server:~$ zpool list -o name,size,alloc,free,capacity,health tank
cr0x@server:~$ sudo fio --name=triage --directory=/tank/test --rw=randwrite --bs=4k --fsync=1 --iodepth=8 --numjobs=2 --size=1G --runtime=20 --time_based --direct=1 --group_reporting
Interprétation : Si vous ne pouvez pas reconstruire immédiatement, isolez les charges les plus sensibles à la latence et réduisez leur exposition au pool mal aligné. Traitez cela comme une stratégie de confinement temporaire.
FAQ
1) What ashift should I use for modern disks?
Pour la plupart des HDD et SSD modernes, ashift=12 est la valeur par défaut raisonnable. Elle aligne les allocations sur 4K et évite les pires pénalités de désalignement sur les périphériques 512e.
2) When would ashift=9 be correct?
Rarement, sur des périphériques véritablement 512-natifs où vous avez une preuve solide que les écritures 512B sont supportées efficacement de bout en bout. En pratique, la plupart des admins choisissent 12 pour éviter de se faire tromper par des rapports de compatibilité.
3) Can I change ashift after creating the pool?
Pas en place pour des vdevs/données existants. Vous pouvez migrer en construisant un nouveau pool et en déplaçant les données, ou dans certaines conceptions remplacer des périphériques/vdevs comme partie d’une stratégie de reconstruction. Mais il n’existe pas de « bascule » qui réaligne les blocs existants.
4) How do I check ashift on a live pool?
Utilisez zdb -C <pool> et cherchez ashift sous chaque leaf vdev. Il n’y a pas une simple propriété zpool get qui le rapporte de façon fiable comme une seule valeur.
5) If I set ashift=12 on a 512-native device, will it break anything?
Ça ne casse pas la cohérence, mais ça peut gaspiller de l’espace et réduire légèrement l’efficacité pour les très petits blocs. Habituellement, la sécurité opérationnelle d’éviter le désalignement l’emporte sur le coût en espace.
6) Why does wrong ashift show up more with virtualization and databases?
Parce que ces charges génèrent beaucoup de petites écritures aléatoires et exigent souvent des sémantiques sync. Cette combinaison magnifie les pénalités RMW et la latence queue.
7) Does recordsize/volblocksize matter if ashift is correct?
Oui. Ashift évite les pires pathologies d’alignement à la frontière du périphérique, mais la taille de bloc de votre charge détermine encore les motifs d’IO, l’amplification et le comportement de cache. Considérez ashift comme « ne pas marcher sur un râteau », et recordsize comme « marcher efficacement ».
8) I have a special vdev (metadata) on NVMe. Do I need to care about ashift there too?
Absolument. Les vdevs special peuvent devenir la porte de latence pour des charges riches en métadonnées. S’ils sont mal alignés ou non appariés, ils peuvent gouloter l’ensemble du pool d’une manière qui ne ressemble pas à « un disque est lent », mais plutôt à « tout est saccadé ».
9) Is ashift the only reason ZFS can be slow?
Non. La fragmentation, un pool surchargé, un mauvais choix de SLOG, des particularités de contrôleur, des disques SMR, des problèmes de profondeur de file, et un mauvais appariement de charge peuvent tous nuire. La raison pour laquelle ashift attire l’attention est qu’il peut silencieusement handicaper les performances dès le départ et ne peut pas être corrigé par un simple changement de propriété.
10) What’s the safest operational approach?
Standardisez : inventairez les tailles de secteur, par défaut utilisez ashift=12, vérifiez immédiatement après la création du pool, et conservez les preuves. Traitez ashift comme un niveau RAID : une décision de conception, pas un paramètre de tuning.
Conclusion
Ashift est un de ces détails qui paraît trop petit pour avoir de l’importance — jusqu’à ce qu’il compte plus que le modèle de votre CPU, votre fabric réseau, et la moitié de vos travaux de tuning réunis. Le côté silencieux est le danger : un mauvais ashift ne crie pas. Il sape simplement les performances et transforme des charges prévisibles en loteries de latence.
L’état d’esprit en production est simple : ne faites pas confiance au marketing du périphérique, ne faites pas confiance à l’autodétection par défaut, et ne mettez pas en production un pool que vous n’avez pas interrogé avec zdb -C. Si vous avez déjà un pool au mauvais ashift, ne passez pas des semaines à polir les symptômes. Construisez le pool correctement aligné et migrez selon un plan. Le pager vous en remerciera, même s’il ne le dira jamais.