Détection d’un mauvais ashift ZFS : comment vérifier des pools existants

Cet article vous a aidé ?

Vous ne remarquez pas un problème d’ashift quand un pool est neuf. Tout est vide, les benchs paraissent bons, la vie est belle.
Puis le pool se remplit, la latence augmente, les scrubs prennent une éternité, et soudain votre grappe SSD « rapide » se comporte comme si elle répondait depuis une cave.

Le plus embêtant : vous ne pouvez pas « corriger » un ashift incorrect en place. La détection est le travail. La prise de décision est le travail.
Ce guide porte sur la vérification des pools existants, la preuve qu’il y a (ou pas) un mismatch, et le choix de la voie la moins douloureuse pour en sortir.

Ce qu’est vraiment ashift (et ce que ce n’est pas)

ashift est la taille d’unité d’allocation sur disque de ZFS, exprimée comme une puissance de deux.
Si ashift=12, ZFS alloue en 212 octets : 4096 octets (4K).
Si ashift=9, c’est 512 octets.

Ce n’est pas la même chose que les tailles de secteur « logiques » et « physiques » rapportées par le disque, mais c’est lié.
ZFS choisira un ashift au moment de la création du vdev en fonction de ce qu’il pense être la taille de secteur minimale du périphérique.
Une fois défini, il est effectivement permanent pour ce vdev. Vous pouvez remplacer des disques, étendre, resilver—ashift reste.

Voici la traduction opérationnelle :

  • Ashift trop petit (par ex., 512B sur secteurs physiques 4K) provoque du read-modify-write, amplification d’écriture, pics de latence, et des scrubs/resilvers qui semblent maudits.
  • Ashift trop grand (par ex., 8K ou 16K sur des périphériques 4K) gaspille de l’espace et peut augmenter l’overhead pour des petits blocs, mais cela ne génère généralement pas le profil « tout est en feu ».

Ce que ashift n’est pas :

  • Ce n’est pas la même chose que recordsize ou volblocksize. Ce sont des tailles logiques de plus haut niveau utilisées pour les systèmes de fichiers et les zvols.
  • Ce n’est pas un réglage que l’on peut « définir plus tard » sans reconstruire. Si un article de blog vous dit le contraire, il vous vend de l’espoir.

Une chose de plus : ashift est par vdev, pas strictement par pool. Les pools contiennent des vdevs. Les vdevs contiennent des disques.
La plupart des pools sont créés avec un ashift cohérent sur tous les vdevs, mais des pools à ashift mixte existent—souvent lors d’extensions ou quand quelqu’un a ajouté « juste un vdev de plus » d’une époque différente.

Faits intéressants et petite histoire

Les problèmes de stockage se répètent parce que les fabricants changent les règles tout en gardant les noms marketing. Quelques faits aident à comprendre pourquoi ashift existe :

  1. Les secteurs de 512 octets étaient la valeur par défaut pendant longtemps. Des décennies de logiciels ont supposé des blocs de 512B. ZFS est né dans ce monde.
  2. « Advanced Format » (secteurs physiques 4K) est devenu courant au début des années 2010. Beaucoup de disques présentaient des secteurs logiques 512B pour compatibilité tout en écrivant physiquement en 4K.
  3. Certains périphériques mentent. Les ponts USB-SATA, certains contrôleurs RAID, et quelques disques virtuels ont historiquement rapporté 512B même si le backend était en 4K.
  4. ZFS a choisi ashift une fois parce que le format sur disque compte. ZFS se soucie de cohérence et de vérifiabilité ; changer la granularité d’allocation plus tard serait une migration de format, pas un « réglage ».
  5. Les outils OpenZFS anciens ne rendaient pas toujours ashift évident. Vous pouviez créer un pool et ne découvrir le mismatch que lorsque les performances chutaient à grande échelle.
  6. Les blocs d’effacement des SSD et les pages NAND sont beaucoup plus grands que 4K. Même avec un ashift correct, les couches FTL peuvent créer leur propre amplification d’écriture—un mauvais ashift aggrave la situation.
  7. 4Kn (secteurs logiques natifs 4K) existe. Certains disques d’entreprise rapportent 4096 logique et physique. Ils se comportent mieux, principalement parce qu’ils sont plus difficiles à mal détecter.
  8. Certaines solutions de virtualisation « normalisent » les tailles de bloc. Votre invité peut voir du 512B tandis que le datastore utilise du 4K ou plus. ZFS à l’intérieur de l’invité prendra ses décisions en fonction de la taille visible par l’invité.

Pourquoi un mauvais ashift fait mal (modes de défaillance)

Le mismatch classique est ashift=9 sur des disques avec secteurs physiques 4K. ZFS écrit des blocs alignés sur 512B, mais le disque ne peut mettre à jour que des tranches de 4K.
Ainsi un « petit write » devient :

  1. Lire le secteur physique 4K contenant la région de 512B.
  2. Modifier la portion de 512B en mémoire.
  3. Écrire de nouveau le secteur complet de 4K.

Ce cycle read-modify-write gonfle la latence et transforme vos IOPS en une blague pratique.

Façons courantes dont cela se manifeste en production :

  • Le temps de scrub/resilver explose parce que le système effectue plus d’opérations IO par quantité logique de données.
  • Les charges d’écriture aléatoire souffrent (bases de données, images VM, petits fichiers, builds très orientés métadonnées).
  • L’utilisation CPU peut augmenter parce que le chemin IO travaille plus, les interactions compression/dedup deviennent plus bruyantes, et la latence augmente les context switches.
  • L’amplification d’écriture détériore l’endurance des SSD—pas toujours catastrophiquement, mais suffisamment pour passer de « confortable sous garantie » à « on changera des disques plus souvent que prévu ».

« Mais mon pool semble correct. » D’accord. Un mismatch peut être masqué par :

  • Des écritures majoritairement séquentielles
  • Beaucoup de hits dans l’ARC
  • Une faible utilisation du pool
  • Des charges dominées par de grands blocs (médias, sauvegardes)

Puis vous ajoutez des VM, activez des écritures sync, atteignez 70% d’occupation, ou commencez beaucoup de mises à jour de métadonnées. Le mismatch cesse d’être théorique.

Une citation opérationnelle (idée paraphrasée) : Le mantra de fiabilité de Gene Kranz—« failures are not an option »—se traduit bien : planifiez comme si le mismatch était réel jusqu’à preuve du contraire.

Blague #1 : Si le stockage pouvait parler, il dirait « je ne suis pas lent, je m’exprime ». Puis il ferait timeout votre base de données.

Playbook de diagnostic rapide

Vous voulez le chemin le plus court entre « ça semble lent » et « c’est ashift, ou ça ne l’est pas ». Voici l’ordre qui fait gagner le plus de temps.

Premier : confirmer ashift sur chaque vdev de premier niveau

  • Si ashift est correct et cohérent, arrêtez d’en faire le coupable et passez à autre chose.
  • Si ashift est trop petit (9 sur du matériel 4K), considérez-le comme suspect n°1.
  • Si ashift est mixte entre vdevs, attendez-vous à des performances inégales et des latences de queue étranges.

Deuxième : confirmer ce que l’OS pense des disques (logique/physique)

  • Vérifiez les tailles de secteur via lsblk et blockdev.
  • Surveillez les périphériques « 512/4096 ». C’est là que naissent les erreurs d’ashift.
  • Ne faites pas confiance aux ponts USB ou aux HBA RAID qui virtualisent les secteurs sans le dire.

Troisième : vérifier les signatures de performance évidentes

  • zpool iostat -v pour les petits writes et la latence élevée au niveau vdev
  • iostat -x pour un await élevé et un débit faible malgré une forte utilisation
  • zpool status -v pour erreurs ou progression lente de resilver/scrub (pas une preuve, mais une odeur)

Quatrième : valider le comportement d’alignement avec un test d’écriture contrôlé

  • Utilisez un dataset scratch ou une machine de test si possible.
  • Exécutez un test d’écriture aléatoire en petits blocs et observez latence/IOPS. Un pool avec mismatch ashift « tombe souvent d’un coup » sur des charges 4K-ish.

Cinquième : décider de la voie

  • Ashift correct : concentrez-vous sur recordsize, les réglages sync, le SLOG, les vdevs spéciaux, la fragmentation et l’occupation du pool.
  • Ashift incorrect : arrêtez d’ajuster autour du problème. Planifiez migration ou reconstruction.

Tâches pratiques : commandes, sorties, décisions

Ci‑dessous des vérifications réelles que vous pouvez exécuter aujourd’hui. Chaque tâche contient : la commande, ce que signifie la sortie, et la décision à prendre.
Utilisez-les comme une checklist, pas comme de la divination.

Task 1: List pools and confirm you’re looking at the right one

cr0x@server:~$ zpool list
NAME   SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tank  21.8T  17.2T  4.60T        -         -    32%    78%  1.00x  ONLINE  -

Signification : Vous avez un pool, tank, rempli à 78% et modérément fragmenté. L’occupation et la fragmentation peuvent amplifier les problèmes d’ashift.

Décision : Si le pool est >80% plein, considérez tout problème de performance comme multifactoriel. Vérifiez quand même ashift, mais ne vous arrêtez pas là.

Task 2: Get the vdev layout (you need it for per-vdev ashift checks)

cr0x@server:~$ zpool status -P tank
  pool: tank
 state: ONLINE
config:

        NAME                                      STATE     READ WRITE CKSUM
        tank                                      ONLINE       0     0     0
          raidz2-0                                ONLINE       0     0     0
            /dev/disk/by-id/ata-ST12000NM0008-1JH101_ZA1A2B3C  ONLINE       0     0     0
            /dev/disk/by-id/ata-ST12000NM0008-1JH101_ZA1A2B3D  ONLINE       0     0     0
            /dev/disk/by-id/ata-ST12000NM0008-1JH101_ZA1A2B3E  ONLINE       0     0     0
            /dev/disk/by-id/ata-ST12000NM0008-1JH101_ZA1A2B3F  ONLINE       0     0     0
            /dev/disk/by-id/ata-ST12000NM0008-1JH101_ZA1A2B3G  ONLINE       0     0     0
            /dev/disk/by-id/ata-ST12000NM0008-1JH101_ZA1A2B3H  ONLINE       0     0     0

errors: No known data errors

Signification : Un vdev RAIDZ2 avec six disques.

Décision : Vous vérifierez ashift pour ce vdev et confirmerez que tous les périphériques sous-jacents ont des caractéristiques de secteur correspondantes.

Task 3: Check ashift via zdb (the most direct, least wishful method)

cr0x@server:~$ sudo zdb -C tank | sed -n '/vdev_tree/,/features_for_read/p'
        vdev_tree:
            type: 'root'
            id: 0
            guid: 12345678901234567890
            children[0]:
                type: 'raidz'
                id: 0
                guid: 11111111111111111111
                nparity: 2
                ashift: 12
                children[0]:
                    type: 'disk'
                    id: 0
                    guid: 22222222222222222222
                    path: '/dev/disk/by-id/ata-ST12000NM0008-1JH101_ZA1A2B3C'
                children[1]:
                    type: 'disk'
                    id: 1
                    guid: 33333333333333333333
                    path: '/dev/disk/by-id/ata-ST12000NM0008-1JH101_ZA1A2B3D'

Signification : ashift: 12 signifie des allocations en 4K. C’est généralement correct pour des HDD/SSD modernes.

Décision : Si vous voyez ashift: 9 sur un vdev construit sur des disques physiques 4K, marquez-le pour planification de migration.

Task 4: Spot mixed ashift across vdevs (expansions are where this happens)

cr0x@server:~$ sudo zdb -C tank | grep -E 'children\[[0-9]+\]:|ashift'
            children[0]:
                ashift: 12
            children[1]:
                ashift: 9

Signification : Vous avez au moins deux vdevs de premier niveau avec des valeurs ashift différentes. C’est une taxe sur les performances et la prévisibilité.

Décision : Traitez le plus petit ashift comme le coupable probable. Prévoyez de retirer ce vdev (via migration) ou de reconstruire le pool.

Task 5: Check what the OS reports for logical/physical sector sizes

cr0x@server:~$ lsblk -d -o NAME,MODEL,SIZE,ROTA,LOG-SEC,PHY-SEC /dev/sd[a-f]
NAME MODEL            SIZE ROTA LOG-SEC PHY-SEC
sda  ST12000NM0008  10.9T    1     512    4096
sdb  ST12000NM0008  10.9T    1     512    4096
sdc  ST12000NM0008  10.9T    1     512    4096
sdd  ST12000NM0008  10.9T    1     512    4096
sde  ST12000NM0008  10.9T    1     512    4096
sdf  ST12000NM0008  10.9T    1     512    4096

Signification : Ce sont des disques 512e : 512 logique, 4096 physique. Si votre vdev ashift est 9, vous êtes mal aligné pour les IO physiques.

Décision : Avec du 512e, préférez ashift=12 pour les nouveaux vdevs. Pour des vdevs existants avec ashift=9, planifiez une migration plutôt que d’essayer de « régler » le problème.

Task 6: Confirm sector sizes with blockdev (helps detect odd reporting)

cr0x@server:~$ sudo blockdev --getss /dev/sda
512
cr0x@server:~$ sudo blockdev --getpbsz /dev/sda
4096

Signification : Le noyau voit secteur logique 512B, physique 4096B. Cohérent avec la vue lsblk.

Décision : Si les outils divergent (ex. 512/512 alors que vous savez que c’est 4K), considérez la couche périphérique comme peu fiable et supposez qu’il vous faut au moins ashift=12.

Task 7: Check pool-wide IO behavior during real load

cr0x@server:~$ zpool iostat -v tank 1 5
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        17.2T  4.60T    210    980  54.3M  22.1M
  raidz2-0                  17.2T  4.60T    210    980  54.3M  22.1M
    ata-ST12000NM...B3C         -      -     35    165  9.10M  3.80M
    ata-ST12000NM...B3D         -      -     35    165  9.05M  3.75M
    ata-ST12000NM...B3E         -      -     35    165  9.07M  3.78M
    ata-ST12000NM...B3F         -      -     35    165  9.02M  3.76M
    ata-ST12000NM...B3G         -      -     35    160  9.03M  3.70M
    ata-ST12000NM...B3H         -      -     35    160  9.06M  3.72M
--------------------------  -----  -----  -----  -----  -----  -----

Signification : Des stats par disque équilibrées suggèrent que le vdev se comporte normalement. Cela ne prouve pas la correction d’ashift, mais exclut un disque unique défaillant.

Décision : Si les écritures par disque sont élevées alors que le débit est faible, suspectez des petits writes et de l’amplification—le mismatch ashift est un candidat, avec les écritures sync et la fragmentation.

Task 8: Correlate with device-level latency using iostat

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

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           6.12    0.00    3.41    8.55    0.00   81.92

Device            r/s     w/s   rkB/s   wkB/s  rrqm/s  wrqm/s  %util  await  r_await  w_await
sda              35.0   160.0  9320.0  3860.0     0.0     2.0   92.0   27.4     9.2     31.1
sdb              35.0   160.0  9300.0  3840.0     0.0     1.0   91.5   26.9     9.0     30.6

Signification : Une utilisation élevée et un await élevé sur les écritures peuvent être normaux sous charge pour un RAIDZ HDD, mais si vous voyez un await extrême avec un faible débit, quelque chose cloche.

Décision : Si vous poussez des petits writes et observez un grand await, vérifiez ashift et aussi la voie d’écriture sync (SLOG), les propriétés du dataset et les patterns de workload.

Task 9: Validate volblocksize/recordsize expectations (don’t confuse them with ashift)

cr0x@server:~$ zfs get -o name,property,value,source recordsize,compression tank
NAME  PROPERTY     VALUE     SOURCE
tank  recordsize   128K      default
tank  compression  lz4       local

Signification : recordsize est 128K. C’est typique pour des systèmes de fichiers généralistes. Cela ne change pas ashift, mais affecte les patterns IO.

Décision : Si votre pool héberge des VM/bases de données, vous pouvez tuner recordsize/volblocksize. Mais si ashift est mauvais, régler cela est du vernis sur un camion.

Task 10: Check zvol block size (common in virtualization stacks)

cr0x@server:~$ zfs get -o name,property,value,source volblocksize tank/vmdata
NAME         PROPERTY      VALUE  SOURCE
tank/vmdata  volblocksize  8K     local

Signification : Le zvol utilise des blocs 8K. Si ashift est 9 sur des périphériques physiques 4K, 8K peut rester mal aligné de façon subtile lors d’écritures partielles.

Décision : Maintenez le volblocksize aligné au workload (souvent 8K–16K pour VM/BD), mais priorisez la correction du mismatch ashift si présent.

Task 11: Check for 4Kn vs 512e vs “mystery devices” using udev IDs

cr0x@server:~$ for d in /dev/disk/by-id/ata-ST12000NM0008-*; do echo "== $d =="; udevadm info --query=property --name="$d" | grep -E 'ID_MODEL=|ID_SERIAL=|ID_BUS='; done
== /dev/disk/by-id/ata-ST12000NM0008-1JH101_ZA1A2B3C ==
ID_BUS=ata
ID_MODEL=ST12000NM0008-1JH101
ID_SERIAL=ST12000NM0008-1JH101_ZA1A2B3C

Signification : Les disques sont des périphériques ATA directs, pas derrière de l’USB. Bien : moins de mensonges sur les secteurs.

Décision : Si vous voyez de l’USB ou des couches de transport inhabituelles pour des pools de production, supposez que le reporting des secteurs est douteux et soyez conservateur (ashift=12 ou 13 pour les nouveaux pools).

Task 12: Confirm ZFS is using native paths and not stale device names

cr0x@server:~$ zpool status -P tank | grep /dev/sd

Signification : Pas de chemins /dev/sdX dans la sortie de config (bien). Utiliser by-id limite les pièges opérationnels lors du remplacement de disques.

Décision : Si votre pool utilise /dev/sdX, corrigez cela lors de votre prochaine fenêtre de maintenance (export/import avec by-id) avant de faire quoi que ce soit de risqué comme des migrations.

Task 13: Check ashift on a per-leaf basis (useful when vdev_tree output is long)

cr0x@server:~$ sudo zdb -l /dev/disk/by-id/ata-ST12000NM0008-1JH101_ZA1A2B3C | grep -i ashift
    ashift: 12

Signification : L’étiquette du périphérique leaf indique ashift 12 pour le vdev auquel il appartient. C’est un contrôle rapide quand vous ne voulez pas tout le dump de config.

Décision : Si le label indique ashift: 9 et que le secteur physique du périphérique est 4096, vous avez confirmé un mismatch. Commencez la planification de rebuild/migration.

Task 14: Measure a small-block sync write signature (don’t guess)

cr0x@server:~$ sudo zfs create -o sync=always -o recordsize=16K tank/ashift-test
cr0x@server:~$ dd if=/dev/zero of=/tank/ashift-test/blob bs=4K count=250000 oflag=dsync status=progress
1024000000 bytes (1.0 GB, 954 MiB) copied, 54 s, 19.0 MB/s
cr0x@server:~$ sync

Signification : Ce test brut force le comportement sync. Des blocs 4K plus sync peuvent exposer rapidement des problèmes d’alignement et de latence.

Décision : Si le débit s’effondre et que la latence monte alors que votre matériel devrait mieux faire, investiguez le mismatch ashift et aussi votre histoire SLOG/PLP. N’« optimisez » pas avant de savoir quel goulet vous atteignez.

Trois mini-histoires d’entreprise (ce qui a mal tourné, ce qui nous a sauvés)

Mini-story 1: The incident caused by a wrong assumption

Une équipe a hérité d’une plateforme VM sur ZFS qui était « stable depuis des années ». Elle avait aussi été construite à une époque où la moitié des disques de la chaîne d’approvisionnement étaient 512e,
et la moitié des outils traitaient encore la taille de secteur comme une trivia.

L’astreinte a commencé à recevoir des alertes : latence IO des VM en pic, profondeurs de file d’attente stockage en hausse, et timeouts applicatifs périodiques.
La première hypothèse de l’équipe—aussi corporate soit-elle—était que « la nouvelle charge est plus bruyante », parce qu’une nouvelle plateforme microservice s’était installée.
Ils ont limité les tenants, touché les knobs du planificateur IO, et déplacé quelques VM. Les symptômes ont bougé, mais le problème est resté.

Puis un scrub est passé. Il a débordé sur les heures ouvrables, comme toujours, et il devenait chaque mois plus lent. Cette fois il a déclenché une cascade :
la latence a monté, les timeouts ont augmenté, des tempêtes de retry ont commencé, et le monitoring a félicité tout le monde en les appelant plus fort.

La cause racine était douloureusement ennuyeuse : un vdev de premier niveau avait ashift=9 depuis la création initiale du pool,
alors que les disques en dessous étaient physiques 4K. Ça « marchait » quand le pool était presque vide et quand la charge était majoritairement séquentielle.
Des années plus tard, c’est devenu un impôt sur chaque écriture aléatoire et mise à jour de métadonnées.

La correction n’était pas brillante. Elle était coûteuse : créer un nouveau pool avec ashift=12, migrer les datasets, faire tourner les tenants, et mettre hors service l’ancien vdevs.
La leçon a marqué parce que ça a fait mal : ne supposez pas que vos prédécesseurs ont choisi le bon ashift, même si le système est ancien et « correct ».

Mini-story 2: The optimization that backfired

Un autre service a décidé de « standardiser les performances » en créant de nouveaux pools avec un ashift plus grand parce que « des blocs plus gros sont plus rapides ».
Quelqu’un a choisi ashift=13 (8K) pour tout, y compris des volumes base de données à petites IO et des workloads CI très orientés métadonnées.

Au début, cela semblait correct. Les écritures séquentielles massives étaient saines, et les graphes d’espace n’étaient pas horribles.
Puis ils ont remarqué que certains workloads zvol lourds devenaient étranges : de petites mises à jour produisaient plus de churn backend que prévu, les snapshots grossissaient plus vite,
et l’équipe a commencé à se plaindre du « overhead ZFS ».

Le retour de bâton n’était pas que ashift=13 soit toujours mauvais. C’est qu’ils l’avaient appliqué universellement sans le faire correspondre au matériel et aux charges.
Sur des SSD à secteurs 4K, une allocation 8K augmentait l’amplification interne pour certains patterns et gaspillait de l’espace pour les petits blocs et métadonnées.
Ils ont aussi aggravé des compromis compression/dedup dans des cas limites en forçant une taille minimale d’allocation plus grande.

Le plan de reprise a été, encore une fois, peu glamour : garder ashift=13 uniquement là où cela avait du sens (certaines grappe et cas spéciaux),
et revenir à ashift=12 par défaut. Ils ont documenté la décision et exigé une justification pour les écarts.
La « standardisation des performances » est devenue une pratique standard : ne choisissez pas ashift à la vibe.

Blague #2 : Rien ne dit « optimisation entreprise » comme empirer les choses de façon standardisée.

Mini-story 3: The boring but correct practice that saved the day

Un environnement réglementé utilisait ZFS pour des archives de logs et des sauvegardes VM. Rien d’excitant. L’équipe avait une checklist de changement qui incluait :
relever la taille des secteurs des périphériques, noter l’ashift prévu, et stocker la sortie de zdb -C lors de la création du pool.
C’était assez ennuyeux pour que les ingénieurs s’en plaignent—discrètement, comme des professionnels.

Des années plus tard, un rafraîchissement de stockage a introduit un nouveau firmware HBA et un nouveau lot de disques. Une extension de pool était prévue :
ajouter un autre vdev RAIDZ. Lors des vérifications préalables, l’ingénieur a comparé le reporting des secteurs des nouveaux disques avec ceux des anciens.
Le nouveau chemin (via un autre boîtier) rapportait 512 logique et 512 physique, malgré un modèle de disque connu pour être 4K physique.

Parce que l’équipe disposait des artefacts ennuyeux des builds précédents, ils ont détecté l’incohérence avant d’ajouter le vdev.
Ils ont déplacé les disques sur un autre emplacement d’enclosure, obtenu le bon reporting 512/4096, et poursuivi avec ashift=12.
Pas de pool à ashift mixte, pas de falaise de performance latente, pas de scrubs « mystérieux ».

Le gain n’était pas seulement d’éviter une erreur ; c’était d’éviter une erreur lente qui serait apparue des mois plus tard, quand personne ne se souviendrait du changement.
La documentation ne les a pas rendus plus rapides. Elle les a rendus moins surpris. C’est l’essentiel.

Erreurs courantes : symptômes → cause racine → correction

Cette section est volontairement spécifique. « Vérifiez votre hardware » n’est pas une correction ; c’est de la procrastination avec une meilleure posture.

1) Scrubs sont douloureusement lents, mais les disques semblent sains

  • Symptômes : progression du scrub qui avance au pas de tortue ; zpool status n’affiche pas d’erreurs ; IO occupé mais débit décevant.
  • Cause racine : ashift=9 sur disques physiques 4K provoquant des IO supplémentaires (visible surtout sur métadonnées et petits blocs).
  • Correction : Confirmez avec zdb -C. Si mismatch, planifiez migration/rebuild du pool avec ashift=12. N’essayez pas d’« accélerer » le scrub autour d’un mauvais ashift.

2) Les écritures aléatoires sont catastrophiques; le séquentiel va bien

  • Symptômes : workloads VM qui se plaignent ; latence fsync DB élevée ; écritures de sauvegarde semblent correctes.
  • Cause racine : écritures petites mal alignées ; souvent mismatch ashift, parfois charges sync sans SLOG adéquat, parfois les deux.
  • Correction : Vérifiez ashift et tailles de secteur en premier. Si ashift est correct, évaluez les réglages sync et le SLOG (et la protection contre perte de puissance si SSD).

3) Un vdev « paraît plus lent » après une extension

  • Symptômes : Après ajout d’un vdev, la distribution de latence se dégrade ; les performances deviennent incohérentes selon le temps et la charge.
  • Cause racine : ashift mixte entre vdevs ou nouveau vdev derrière une couche reportant des tailles de secteur différentes.
  • Correction : Vérifiez zdb -C pour chaque vdev de premier niveau. Si mixte, envisagez de migrer les datasets chauds hors du vdev lent ou de reconstruire.

4) Vous avez remplacé des disques et attendu que ashift change

  • Symptômes : « On est passé à des disques 4Kn ; pourquoi zdb affiche-t-il encore ashift=9 ? »
  • Cause racine : Ashift est fixé à la création du vdev et ne change pas lors des remplacements/resilverings.
  • Correction : Rebuild/migrate vers un nouveau vdev/pool créé avec l’ashift voulu.

5) Les benchs ne reproduisent pas la douleur en production

  • Symptômes : fio sur un pool vide paraît correct ; les workloads réels saccadent quand le pool est occupé.
  • Cause racine : le benchmark ne correspond pas à la taille IO, aux sémantiques sync, à la concurrence ou à l’occupation du pool ; le mismatch ashift amplifie particulièrement les petits IO sous contention.
  • Correction : Benchmez avec des écritures aléatoires 4K/8K, des settings sync réalistes, et plusieurs jobs. Confirmez ashift avant de vous fier à un résultat de benchmark.

6) Les boîtiers USB/JBOD produisent des comportements de performance « aléatoires »

  • Symptômes : les tailles de secteur semblent incohérentes ; ashift choisi diffère pour des disques identiques ; les performances changent après replug/reboot.
  • Cause racine : le firmware du bridge ment ou change le reporting ; ZFS verrouille ashift selon ce qu’il a vu à la création.
  • Correction : Évitez les bridges USB pour des pools ZFS sérieux. Si vous devez, forcez ashift à la création via zpool create -o ashift=12 et validez immédiatement avec zdb -C.

Listes de contrôle / plan pas à pas

Checklist A: “Do I have an ashift mismatch right now?”

  1. Identifier le pool et les vdevs : zpool status -P.
  2. Dump de config et trouver ashift : sudo zdb -C poolname.
  3. Enregistrer ashift par vdev de premier niveau (mirror/raidz/draid/special).
  4. Vérifier les tailles de secteur de chaque disque leaf : lsblk -d -o NAME,LOG-SEC,PHY-SEC.
  5. Si un vdev a un ashift plus petit que la taille de secteur physique, vous avez un mismatch qui compte.
  6. Si ashift est mixte, vous avez un mismatch qui mordra de façon irrégulière.

Checklist B: “Is ashift actually the bottleneck?”

  1. Confirmez la taille IO et le comportement sync du workload (VM et bases de données impliquent souvent petits IO aléatoires + sync).
  2. Pendant la charge, lancez zpool iostat -v 1 et iostat -x 1 côte à côte.
  3. Cherchez ops/s élevé avec faible bande passante et latence élevée—signature classique d’amplification petit IO.
  4. Si ashift est correct, vérifiez :
    • occupation/fragmentation du pool (zpool list FRAG/CAP)
    • propriétés des datasets (sync, recordsize, volblocksize)
    • pression sur vdevs spéciaux metadata (si utilisés)
    • conception SLOG (si loads sync dominent)

Checklist C: “Migration/rebuild plan when ashift is wrong”

  1. Arrêtez de discuter avec la physique. Décidez de reconstruire/migrer plutôt que d’ajuster en rond.
  2. Provisionnez un nouveau stockage (nouveau pool ou nouveaux vdevs) avec explicitement -o ashift=12 (ou une valeur supérieure justifiée).
  3. Vérifiez le nouvel ashift immédiatement avec sudo zdb -C et enregistrez-le.
  4. Répliquez les datasets :
    • zfs snapshot
    • zfs send | zfs receive
    • ou utilisez vos outils de réplication existants
  5. Basculez les workloads progressivement ; mesurez latence et vitesse de scrub.
  6. Mettez hors service l’ancien pool/vdevs seulement après avoir :
    • validé les restaurations
    • validé le scrub sur le nouveau pool
    • validé les performances sous charge proche du pic

FAQ

1) Can I change ashift on an existing vdev or pool?

Pas en place. Ashift est intégré à la façon dont les blocs ont été alloués sur le disque. La correction pratique est de créer un nouveau vdev/pool avec le bon ashift et migrer les données.

2) Where do I reliably see ashift for an existing pool?

Utilisez sudo zdb -C poolname et cherchez ashift: N sous chaque vdev de premier niveau dans vdev_tree.
zpool get ne vous dira pas ashift de façon fiable car ce n’est pas une propriété de pool de la même manière.

3) If my disks are 512e (512 logical / 4096 physical), what ashift should I want?

En général ashift=12. Cela aligne les allocations ZFS sur des frontières 4K et évite le read-modify-write côté disque.

4) Is ashift=13 “better” than ashift=12?

Pas automatiquement. Cela peut avoir du sens pour certaines grappes et caractéristiques flash, mais augmente aussi la taille minimale d’allocation.
Par défaut, préférez 12 sauf raison spécifique et tests sur votre workload.

5) I replaced every disk with 4Kn drives. Why didn’t ashift update?

Parce qu’ashift est déterminé lors de la création du vdev, pas lors des remplacements de disques. Les remplacements héritent de l’ashift existant du vdev.

6) If ashift is wrong, why didn’t ZFS detect it?

ZFS utilise les caractéristiques rapportées par le périphérique au moment de la création. Si la couche périphérique a rapporté 512B (même faussement), ZFS l’a cru.
ZFS est sceptique sur la corruption, pas sur l’honnêteté des vendeurs.

7) What are the most reliable sector-size checks on Linux?

lsblk -o LOG-SEC,PHY-SEC et blockdev --getss/--getpbsz. Si ces outils divergent ou semblent suspects derrière des bridges/controllers, considérez-le comme un avertissement.

8) Can mixed ashift vdevs exist in one pool?

Oui. Cela arrive souvent après des extensions ou l’ajout de vdevs depuis du matériel différent. Ça peut fonctionner, mais complique les performances et la prévisibilité.

9) Does recordsize/volblocksize “fix” ashift mismatch?

Non. Ils influencent les patterns IO et peuvent réduire la douleur dans certains cas, mais ils ne changent pas la granularité d’allocation sur disque des vdevs existants.

10) What’s the safest operational response once I confirm ashift=9 on 4K physical drives?

Planifiez une migration/rebuild. Gardez le pool stable, évitez les « réglages héros », et programmez un déplacement contrôlé vers un pool créé correctement.

Conclusion : étapes concrètes à entreprendre

La détection d’un mismatch ashift n’est pas un exercice académique. C’est la différence entre « ce pool est vieux mais correct » et « ce pool nous vole silencieusement notre budget de latence ».
Si vous suspectez un mismatch, ne discutez pas—mesurez.

Prochaines étapes pratiques :

  1. Exécutez sudo zdb -C et enregistrez ashift par vdev.
  2. Confirmez les tailles de secteur des disques avec lsblk et blockdev.
  3. Si vous trouvez ashift=9 sur des périphériques physiques 4K, arrêtez de tuner et commencez à planifier une reconstruction/migration.
  4. Si ashift est correct, passez vite à autre chose : vérifiez le comportement sync, l’occupation/fragmentation du pool, et les tailles IO du workload.
  5. Ajoutez une pratique ennuyeuse pour l’avenir : capturez la sortie zdb -C lors de la création du pool et stockez-la avec les enregistrements de changement.
← Précédent
Quand la référence bat la personnalisation : le mythe parfois vrai
Suivant →
Debian 13 : « Device busy » avec umount — trouvez le processus bloquant instantanément (workflow lsof/fuser)

Laisser un commentaire