Bases de zpool iostat : transformer les chiffres en goulet d’étranglement

Cet article vous a aidé ?

Votre application est « lente ». L’équipe base de données jure que rien n’a changé. Le CPU va bien. Les graphiques réseau sont ennuyeux.
Et puis quelqu’un pointe du doigt le stockage : « ZFS a l’air occupé. » Félicitations, vous êtes entré·e dans la partie de l’incident
où les gens commencent à faire des affirmations assurées basées sur des impressions.

zpool iostat est l’endroit où les impressions prennent fin. C’est aussi l’endroit où des ingénieur·e·s compétent·e·s se font piéger,
parce que la sortie a l’air simple et pleine de chiffres qui semblent confirmer n’importe quelle théorie que vous aviez déjà.
Voici comment transformer ces chiffres en un goulet d’étranglement que vous pouvez nommer, mesurer et corriger.

Ce qu’est ZFS iostat (et ce qu’il n’est pas)

ZFS vous propose plusieurs « lunettes » iostat. Celle que la plupart des gens entendent est zpool iostat, qui rapporte
les débits et taux d’E/S par pool et par vdev. Selon les options, il peut aussi afficher la latence, la taille de la file d’attente et
des répartitions par périphérique. C’est la vision ZFS du travail, pas la vue du périphérique de blocs, et pas nécessairement ce
que votre application pense avoir demandé.

Ce que ce n’est pas : ce n’est pas un profileur de performance complet, il ne vous dira pas « la base de données n’a pas d’index »,
et il ne séparera pas magiquement « workload inadapté » de « mauvais design de stockage ». Mais il vous dira où le pool dépense
du temps : quel vdev, quel périphérique, lectures vs écritures, bande passante vs IOPS vs latence, et si vous êtes limité par le
disque le plus lent ou par vos propres choix de configuration.

Règle utile : si vous ne pouvez pas expliquer un incident en termes de quelques métriques stables (IOPS, bande passante, latence),
vous n’avez pas fini de déboguer ; vous êtes juste en train de raconter une histoire.

Faits intéressants et contexte historique

  • ZFS a commencé chez Sun au début des années 2000 pour résoudre la complexité des systèmes de fichiers et du gestionnaire de volumes en en faisant un seul système, avec checksums de bout en bout.
  • L’idée de « pool de stockage » était radicale dans un monde de partitions et de tableaux de LUN ; elle a changé la façon dont les équipes ops pensaient la gestion de capacité.
  • Les vdevs sont l’unité de performance : ZFS stripe entre les vdevs de niveau supérieur, pas entre les disques individuels comme beaucoup le supposent à tort.
  • La mathématique de la parité RAIDZ explique pourquoi les petites écritures aléatoires souffrent plus sur RAIDZ que sur des mirrors ; « amplification d’écriture » n’est pas du marketing, c’est de l’arithmétique.
  • OpenZFS a divergé puis convergé : plusieurs plateformes ont porté ZFS après Oracle, et les fonctionnalités et outils ont évolué de façon inégale selon les OS pendant des années.
  • Le SLOG est apparu parce que les écritures synchrones sont un contrat ; le ZIL existe pour le satisfaire, et iostat est l’un des moyens les plus rapides de voir si ce contrat coûte cher.
  • Les special vdevs ont été introduits pour gérer les métadonnées/petits blocs sur des médias plus rapides ; ce sont des gains de performance et une dette opérationnelle.
  • Les batailles ashift ont eu lieu parce que les disques mentent (ou sont mal compris) sur la taille des secteurs physiques ; le mauvais ashift peut taxer la performance de façon permanente.
  • « L2ARC résout tout » est un mythe récurrent depuis que les premiers admins ont découvert le caching ; ça ne règle pas la latence d’écriture, et ça peut voler la mémoire dont vous aviez besoin ailleurs.

Guide de terrain : lire zpool iostat sérieusement

Commencez par la sortie par défaut, mais ne vous arrêtez pas là

La sortie par défaut de zpool iostat est une introduction douce : ops de lecture/écriture et bande passante par pool et
éventuellement par vdev. C’est utile pour « est-ce que c’est occupé ? » et mauvais pour « pourquoi c’est lent ? » parce que les goulets
d’étranglement concernent généralement la distribution de la latence et un chemin lent, pas le débit agrégé.

Ce que signifient réellement les colonnes

Les noms de colonnes varient légèrement selon la plateforme et la version d’OpenZFS, mais les concepts sont stables :

  • r/s, w/s : opérations de lecture/écriture par seconde telles que ZFS les voit à ce niveau (pool/vdev/périphérique).
  • rkB/s, wkB/s : bande passante de lecture/écriture par seconde.
  • await (quand disponible) : temps moyen qu’un I/O a passé en attente + service (mise en file + périphérique).
  • r_await, w_await : même idée, séparée par lectures/écritures (très utile quand les écritures synchrones mordent).
  • sqd (parfois affiché) : profondeur moyenne de la file d’attente. File élevée avec latence croissante est un signal classique de « périphérique saturé ».
  • util n’est habituellement pas une colonne ZFS comme dans Linux iostat ; n’importez pas mentalement les sémantiques Linux. ZFS utilise sa propre instrumentation.

La phrase qui vous sauve des heures

La performance ZFS est dominée par le vdev le plus lent impliqué dans l’opération, et zpool iostat est le moyen le plus rapide pour identifier lequel joue le rôle de maillon faible dans le groupe.

Un modèle mental pratique : où passe le temps

Quand une application dit « écrire ceci », ZFS le transforme en une chorégraphie : transaction groups (TXGs), copy-on-write (COW),
checksumming, compression optionnelle, allocation de metaslab, puis E/S sur le périphérique. Les lectures ont leur propre histoire :
hits ARC, hits L2ARC, prélecture, reconstruction RAIDZ, et enfin disques.

zpool iostat ne vous montrera pas directement le temps de commit TXG, mais il vous montrera les symptômes :
rafales d’écritures, pics de latence, un seul vdev effectuant plus de travail que les autres, ou un périphérique SLOG qui encaisse toute la
chaleur des écritures synchrones.

Si vous avez besoin d’un mappage rapide symptôme → « quelle couche souffre », voici la version franche :

  • w_await élevé, faible bande passante : petites écritures, écritures synchrones, surcharge parité RAIDZ, ou latence périphérique.
  • rkB/s élevé, r/s modéré, r_await en hausse : grosses lectures saturant la bande passante.
  • r/s élevé, rkB/s faible, r_await élevé : lectures aléatoires, mauvais caching, ou contention de métadonnées.
  • Un vdev de niveau supérieur saturé : allocation inégale, un vdev plus petit/plein, ou un périphérique réellement défaillant.

Une citation à garder au mur :
L’espoir n’est pas une stratégie. — Jim Lovell

Tâches pratiques : commandes, sorties, décisions (12+)

Voici ce que vous faites réellement à 02h17 quand quelqu’un dit « le stockage est lent ». Chaque tâche a : une commande,
ce que vous regardez, et la décision qu’elle soutient. Exécutez-les dans l’ordre si vous êtes débutant·e ; sautez si vous avez déjà
une intuition et une cicatrice de pager.

Task 1: Obtenez une image en mouvement, pas un instantané

cr0x@server:~$ zpool iostat -v 1 5
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        3.12T  2.88T    420    310   42.1M  18.7M
  mirror    1.56T  1.44T    210    155   21.0M   9.4M
    sda         -      -    110     78   10.4M   4.9M
    sdb         -      -    100     77   10.6M   4.5M
  mirror    1.56T  1.44T    210    155   21.1M   9.3M
    sdc         -      -    105     77   10.5M   4.6M
    sdd         -      -    105     78   10.6M   4.7M

Sens : Vous obtenez cinq échantillons d’une seconde avec détail vdev et disque. Cherchez le déséquilibre
(un disque ou un mirror faisant beaucoup plus), et regardez la forme du workload : grosse bande passante vs beaucoup d’opérations.

Décision : Si un périphérique est constamment derrière son homologue dans un mirror, vous suspectez la santé du périphérique,
le câblage, des problèmes de contrôleur ou un problème de chemin. Si les deux côtés correspondent mais la latence du pool est mauvaise,
vous cherchez le workload ou la configuration.

Task 2: Activez la vue latence (si prise en charge)

cr0x@server:~$ zpool iostat -v -l 1 5
                              capacity     operations     bandwidth    total_wait
pool                        alloc   free   read  write   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----  -----  -----
tank                        3.12T  2.88T    430    320   43.2M  19.1M    4ms   28ms
  mirror                    1.56T  1.44T    215    160   21.5M   9.6M    3ms   26ms
    sda                         -      -    112     81   10.7M   5.0M    3ms   25ms
    sdb                         -      -    103     79   10.8M   4.6M    3ms   28ms
  mirror                    1.56T  1.44T    215    160   21.7M   9.5M    4ms   31ms
    sdc                         -      -    109     80   10.8M   4.8M    4ms   32ms
    sdd                         -      -    106     80   10.9M   4.7M    4ms   30ms

Sens : « total_wait » (ou similaire) est votre signal rapide et grossier de latence.
Ici les écritures sont bien plus lentes que les lectures, et elles sont lentes partout, pas seulement sur un disque.

Décision : Si le temps d’attente d’écriture est élevé sur tous les vdevs, demandez-vous : écritures synchrones ? parité RAIDZ ?
un SLOG lent ? un blocage TXG ? Si c’est seulement un vdev/disque, traitez-le comme un problème matériel/chemin jusqu’à preuve du contraire.

Task 3: Ciblez le pool coupable quand vous avez plusieurs pools

cr0x@server:~$ zpool iostat -v tank 1 3
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        3.12T  2.88T    440    330   44.1M  19.8M
  mirror    1.56T  1.44T    220    165   22.0M   9.9M
    sda         -      -    112     83   10.8M   5.1M
    sdb         -      -    108     82   11.2M   4.8M
  mirror    1.56T  1.44T    220    165   22.1M   9.9M
    sdc         -      -    110     82   11.0M   4.9M
    sdd         -      -    110     83   11.1M   5.0M

Sens : Évitez le bruit entre pools. Surtout sur des machines multi-tenant, votre « appli lente »
n’est peut-être pas la seule à faire des E/S.

Décision : Si le pool occupé n’est pas celui qui supporte la plainte, vous ne touchez pas au stockage ;
vous gérez les attentes et vous enquêtez sur la contention des ressources ailleurs (ou la facturation).

Task 4: Confirmez l’état du pool avant de courir après des fantômes de performance

cr0x@server:~$ zpool status -v tank
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 06:41:12 with 0 errors on Mon Dec 23 03:12:01 2025
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          mirror    ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
          mirror    ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0

errors: No known data errors

Sens : Si vous voyez des erreurs READ/WRITE/CKSUM en hausse, les « problèmes » de performance peuvent provenir du système
qui réessaie, remappe et souffre. ZFS gardera vos données correctes et votre latence piquante.

Décision : Tout compteur d’erreurs non nul et en tendance : arrêtez les optimisations. Commencez par remplacer le matériel,
vérifier les câbles/HBA, et examiner les données SMART.

Task 5: Vérifiez si un scrub ou un resilver vous vole des ressources

cr0x@server:~$ zpool status tank
  pool: tank
 state: ONLINE
  scan: scrub in progress since Tue Dec 24 11:02:09 2025
        1.43T scanned at 1.21G/s, 820G issued at 694M/s, 3.12T total
        0B repaired, 26.18% done, 00:52:14 to go
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          mirror    ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
          mirror    ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0

errors: No known data errors

Sens : Les scrubs sont des consommateurs légitimes d’E/S. Ils sont aussi une bonne hygiène.
Mais pendant les heures de pointe, ils peuvent pousser une latence déjà tendue au-delà du point de rupture.

Décision : Si le système est sensible à la latence, programmez les scrubs hors des pics et/ou ajustez
la priorité de scrub. Si vous ne pouvez pas tolérer les scrubs, vous ne pouvez pas tolérer l’exploitation du stockage.

Task 6: Voyez si vous êtes limité par les IOPS ou la bande passante

cr0x@server:~$ zpool iostat -v 2 3
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        3.12T  2.88T   4200    180   32.1M   6.2M
  mirror    1.56T  1.44T   2100     90   16.0M   3.1M
    sda         -      -   1050     45    8.0M   1.6M
    sdb         -      -   1050     45    8.0M   1.5M
  mirror    1.56T  1.44T   2100     90   16.1M   3.1M
    sdc         -      -   1050     45    8.1M   1.6M
    sdd         -      -   1050     45    8.0M   1.5M

Sens : 4200 lectures/sec mais seulement 32 MB/s : ce sont des E/S aléatoires à petits blocs. Si la latence est élevée,
ajouter plus de plateaux (plus de vdevs) aide plus que « des disques plus rapides » isolément.

Décision : Les workloads limités en IOPS veulent des mirrors, plus de vdevs et des tailles d’enregistrement raisonnables ; les workloads limités par la bande passante veulent une disposition séquentielle, moins de pénalités de parité, et souvent des blocs plus grands.

Task 7: Validez si les écritures sync sont le coupable

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

Sens : sync=standard signifie que les écritures synchrones sont honorées quand les applications les demandent.
Les bases de données le font souvent.

Décision : Si la latence d’écriture est terrible et que vous voyez beaucoup d’écritures synchrones, votre SLOG (si présent) doit
être rapide et protégé contre la perte d’alimentation. Si vous « corrigez » cela en mettant sync=disabled, soyez au moins honnête et appelez cela
« choisir la perte de données comme fonctionnalité ».

Task 8: Vérifiez la présence d’un SLOG et s’il est réellement utilisé

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

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          mirror    ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
          mirror    ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0
        logs
          nvme0n1   ONLINE       0     0     0

errors: No known data errors

Sens : Il y a un dispositif de log séparé. C’est le SLOG (separate intent log).
Il n’accélère que les écritures synchrones, pas les écritures normales.

Décision : Si vous n’avez pas de workloads lourds en sync, un SLOG n’aidera pas et peut compliquer les domaines de panne. Si vous en avez, le SLOG doit avoir une faible latence et une protection contre les pertes d’alimentation.

Task 9: Surveillez le dispositif de log sous charge (est-ce qu’il explose ?)

cr0x@server:~$ zpool iostat -v 1 5
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        3.12T  2.88T    120   1800    3.1M  22.4M
  mirror    1.56T  1.44T     60    900    1.5M  11.1M
    sda         -      -     30    450  760K     5.5M
    sdb         -      -     30    450  740K     5.6M
  mirror    1.56T  1.44T     60    900    1.6M  11.3M
    sdc         -      -     30    450  780K     5.7M
    sdd         -      -     30    450  820K     5.6M
logs
  nvme0n1       -      -      0   5200      0  41.6M

Sens : De grosses opérations d’écriture sur nvme0n1 sous « logs » suggèrent fortement que le trafic d’écritures synchrones
est engagé sur le SLOG. Si le pool a un write wait élevé et que le dispositif de log montre beaucoup d’opérations, vous avez un workload dominé par les écritures sync.

Décision : Si les ops du dispositif de log sont élevées et la latence aussi, améliorez/remplacez le SLOG, vérifiez la PLP,
et confirmez que vous n’utilisez pas accidentellement un NVMe grand public qui se transforme en citrouille sous des écritures synchrones soutenues.

Task 10: Vérifiez recordsize du dataset et inadéquation du workload

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

Sens : Beaucoup de bases de données préfèrent des blocs plus petits (par ex., 8K–16K) pour éviter de lire/écrire des données supplémentaires.
Un recordsize de 128K peut fonctionner, mais il peut amplifier les E/S sur des workloads aléatoires.

Décision : Si votre iostat montre beaucoup d’IOPS avec faible bande passante (petit aléatoire), envisagez de régler le recordsize plus près de la taille de page de la BD (après avoir confirmé la recommandation spécifique de la BD).

Task 11: Vérifiez la compression (elle peut réduire les E/S ou coûter du CPU)

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

Sens : lz4 est généralement un gain : moins de données écrites, moins lues depuis le disque, souvent plus rapide.
Mais sur des systèmes à CPU saturé ou des données déjà compressées, ça peut être neutre ou légèrement pire.

Décision : Si iostat montre saturation disque mais CPU disponible, la compression est votre alliée.
Si le CPU est saturé et le disque inactif, n’« optimisez » pas le stockage avec plus de compression.

Task 12: Vérifiez ashift (alignement) parce que c’est pour toujours

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

Sens : ashift=12 implique des secteurs 4K. Si vous avez construit le pool avec ashift=9
sur des disques 4K, les petites écritures peuvent devenir des cauchemars de read-modify-write.

Décision : Un ashift incorrect est une erreur nécessitant une reconstruction. S’il est incorrect et que la performance compte, planifiez une migration.
Il n’existe pas de bouton magique pour réécrire la géométrie du pool en place sans risque.

Task 13: Identifier un remplissage inégal des vdev (biais d’allocation)

cr0x@server:~$ zpool list -v tank
NAME         SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH
tank        6.00T  3.12T  2.88T        -         -    19%    52%  1.00x  ONLINE
  mirror    3.00T  2.40T   600G        -         -    28%    80%      -  ONLINE
  mirror    3.00T   720G  2.30T        -         -     8%    24%      -  ONLINE

Sens : Un mirror est rempli à 80% et plus fragmenté ; l’autre est à 24% seulement. ZFS tente d’équilibrer,
mais l’historique du pool, l’expansion et le comportement des metaslabs peuvent conduire à un skew. Le skew peut rendre un vdev le point chaud.

Décision : Si iostat montre que le vdev le plus rempli fait plus de travail ou montre plus de latence, la stratégie de rééquilibrage compte :
envisagez d’ajouter des vdevs plus tôt, gardez les pools en dessous de seuils de capacité agressifs, et évitez de « planifier une expansion plus tard » comme stratégie de performance.

Task 14: Corréler ZFS iostat avec les stats périphériques au niveau OS

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

Device            r/s     w/s   rkB/s   wkB/s  await  aqu-sz  %util
sda             110.2    81.4  10960.0  5092.0   4.2    0.8   42.1
sdb             105.9    79.6  11010.0  4780.0   4.0    0.7   41.7
sdc             109.8    80.2  11030.0  4960.0   4.6    1.0   44.9
sdd             108.8    80.7  11080.0  5030.0   4.4    0.9   44.1
nvme0n1           0.0  5200.3      0.0 41600.0   0.3    0.6   62.0

Sens : ZFS voit le travail logique ; l’OS voit les files réelles et l’utilisation des périphériques.
Si ZFS dit qu’un disque est occupé mais que l’OS dit qu’il est inactif, vous pourriez être limité au-dessus du périphérique (verrous, CPU, TXG).
Si l’OS montre un await élevé et un %util élevé, le périphérique est vraiment le limiteur.

Décision : Utilisez iostat au niveau OS pour confirmer si le problème est « ordonnancement ZFS » vs « le périphérique ne suit pas ».
Cela vous évite de remplacer des disques quand il fallait ajuster les écritures synchrones, ou inversement.

Task 15: Vérifiez la pression ARC et la mémoire disponible (parce que les lectures mentent)

cr0x@server:~$ arcstat 1 3
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsz     c
12:10:01  8420  1120     13   620   55   410   36    90    8   58G    64G
12:10:02  9010  1460     16   780   53   590   40    90    6   58G    64G
12:10:03  8770  1310     14   700   53   520   40    90    7   58G    64G

Sens : Un taux de miss de 13–16% peut être acceptable ou catastrophique selon le workload.
Si les misses montent en flèche et que les disques s’allument dans zpool iostat, votre « latence stockage » peut être juste le cache qui fonctionne comme prévu.

Décision : Si l’ARC est plafonné et le taux de miss élevé, ajoutez de la RAM avant d’acheter plus de disques. Si l’ARC est énorme mais que les misses restent élevés,
votre ensemble de travail dépasse la mémoire ou vous faites des lectures en streaming qui ne se cachent pas bien.

Blague #1 : Si vous regardez iostat assez longtemps, les chiffres ne clignent pas en premier. C’est vous.

Playbook de diagnostic rapide

Quand vous avez besoin d’un goulet d’étranglement rapidement, faites ceci dans l’ordre. L’objectif n’est pas une compréhension parfaite ; c’est une première correction correcte
et une timeline d’incident nette.

Première étape : est-ce un problème de santé qui se fait passer pour un problème de performance ?

  • Exécutez zpool status -v. Cherchez des erreurs, des vdevs dégradés, des resilvers lents ou un périphérique qui clignote.
  • Exécutez les stats périphériques au niveau OS (iostat -x) pour voir si un périphérique souffre.

Si vous voyez des erreurs ou des resets : arrêtez. Remplacez/réparez le chemin. Optimiser des performances sur du matériel malade revient à régler une voiture de course alors que le pneu est en train de se détacher.

Deuxième étape : identifiez l’étendue et la forme des E/S

  • zpool iostat -v 1 5 : quel pool, quel vdev, quel périphérique est le plus chaud ?
  • Regardez IOPS vs bande passante : beaucoup d’ops avec peu de MB/s crie « I/O aléatoire/petit ».
  • Si disponible, ajoutez -l pour des indices de wait/latence : les lectures sont-elles correctes mais les écritures affreuses ?

Troisième étape : décidez si le goulet d’étranglement est les écritures sync, la parité RAIDZ, ou la capacité/fragmentation

  • Vérifiez zfs get sync sur les dataset affectés.
  • Vérifiez la présence d’un SLOG dans zpool status, puis regardez les stats du vdev de log dans zpool iostat -v.
  • Vérifiez zpool list -v pour des indices de déséquilibre de remplissage et de fragmentation.

Quatrième étape : validez avec une métrique de contre-vérification

  • Utilisez iostat -x pour confirmer le comportement réel des files/await du périphérique.
  • Utilisez arcstat (ou équivalent plateforme) pour inclure/exclure le caching comme raison des disques occupés.

À la fin de ce playbook vous devriez pouvoir dire avec assurance une de ces phrases :
« Nous sommes saturés en IOPS de lecture aléatoire », « Les écritures synchrones sont limitées par le dispositif de log », « Un vdev est surchargé » ,
« Nous payons la taxe de fragmentation/capacité », ou « Un périphérique/chemin est en train d’échouer et de réessayer. »

Trois mini-histoires d’entreprise du terrain

Incident causé par une fausse hypothèse : « C’est en miroir, donc c’est rapide »

Une entreprise SaaS de taille moyenne a migré un cluster PostgreSQL client sur un nouveau serveur de stockage avec ZFS.
Le pool était construit en quelques mirrors. Propre, simple, rassurant. Tout le monde dormait mieux.

Quelques semaines plus tard, la latence a commencé à monter pendant les pics de trafic. Les graphiques étaient frustrants : le CPU n’était pas saturé, le réseau allait bien.
L’astreinte a lancé zpool iostat -v et a vu qu’un mirror montrait un write wait nettement supérieur à l’autre.
L’hypothèse a été immédiate : « ZFS devrait équilibrer entre les mirrors ; un mirror ne peut pas être le goulet d’étranglement, il est redondant. »
Ils ont commencé à chercher ailleurs.

Le vrai problème était un remplissage inégal des vdev causé par un flux d’expansion antérieur. Un mirror était significativement plus plein et plus fragmenté.
Ce mirror est devenu le point chaud d’allocation, donc il a fait plus de travail, donc il est devenu plus lent, donc le pool paraissait plus lent.
La sortie zpool list -v essayait de tout avouer depuis le début.

La correction n’a pas été exotique : ils ont réévalué les seuils de capacité, modifié le plan d’expansion pour ajouter des vdevs entiers plus tôt, et migré
les données vers un pool fraîchement construit conçu avec des tailles de vdev cohérentes. Le plus grand changement a été culturel : « mirrors » ne sont pas une seule unité.
Dans ZFS, ce sont les vdevs qui comptent.

Une optimisation qui s’est retournée contre eux : « Désactiver sync, on met en prod »

Une équipe plateforme de données avait un pipeline d’ingestion qui écrivait beaucoup de petites transactions. Lors d’un test de charge, la latence d’écriture semblait mauvaise.
Quelqu’un a découvert zfs set sync=disabled et a lancé un benchmark rapide. La latence a chuté. Le débit est monté.
La demande de changement s’est écrite d’elle-même.

En production, les premières semaines furent excellentes. Puis un événement d’alimentation a frappé une armoire. Les serveurs ont redémarré. Le pipeline a redémarré proprement.
Et une incohérence silencieuse des données est apparue quelques heures plus tard : des jobs en aval ont vu des doublons et des enregistrements manquants. L’équipe a passé des jours
à « déboguer Kafka », puis « la base de données », et a finalement retracé le problème jusqu’aux écritures acquittées qui n’avaient jamais été sécurisées sur disque.

Le post-mortem a été gênant parce que personne n’avait « fait la mauvaise chose » dans son propre cadre.
Le benchmark avait été réel. L’amélioration avait été réelle. Le workload était réel.
L’erreur a été de traiter un contrat de durabilité comme une préférence modifiable.

La correction n’a pas été « ne touchez jamais sync ». Ce fut « construire la bonne voie d’écriture ». Ils ont ajouté un vrai dispositif SLOG avec protection contre la perte d’alimentation,
l’ont validé sous charge via les stats de logs de zpool iostat, et ont laissé sync=standard en place.
La performance s’est améliorée, et tout le monde a mieux dormi.

La pratique ennuyeuse mais correcte qui a sauvé la mise : échantillonnage de référence

Une équipe plateforme interne exécutait ZFS sur une flotte d’hôtes de virtualisation. Ils avaient une politique dont personne ne s’enthousiasmait :
capturer un échantillon de 60 secondes de zpool iostat -v -l 1 pendant les heures normales chaque semaine et le stocker avec les métadonnées de l’hôte.
Pas de tableaux de bord, pas de battage—juste des fichiers texte horodatés. Le genre de chose que l’on supprime par accident lors du ménage de printemps.

Un après-midi, des plaintes sur la latence VM sont arrivées. Les hôtes semblaient « corrects » au premier abord. Le pool n’était pas plein.
Il n’y avait pas d’erreurs. Pourtant l’UI de l’hyperviseur montrait des blocages périodiques.

L’astreinte a comparé l’échantillon iostat actuel à la baseline et a vu la différence immédiatement : le write wait avait doublé
pour le même niveau d’IOPS. Ce n’était pas « plus de charge ». C’était « même charge, temps de service plus lent. »
Cela a resserré la recherche sur « quelque chose a changé dans le chemin I/O », pas « quelqu’un a ajouté des locataires ».

Le coupable était une mise à jour de firmware sur un HBA qui avait changé le comportement des files sous workloads mixtes lecture/écriture.
Ils ont rollbacké le firmware sur les hôtes affectés, confirmé que la latence retournait à la baseline, puis travaillé avec le fournisseur
sur une version corrigée. Des baselines ennuyeuses les ont sauvés d’une semaine de chasse aux fantômes et de pinball de blâme.

Blague #2 : La latence du stockage, c’est comme les validations corporate—personne n’y fait attention jusqu’à ce que ça devienne soudainement le problème de tout le monde.

Erreurs courantes : symptôme → cause racine → correction

1) « Les IOPS du pool sont élevés, donc les disques sont lents »

  • Symptôme : r/s ou w/s élevés dans zpool iostat ; latence appli augmente.
  • Cause racine : Le workload est passé à des I/O plus petits ou plus aléatoires ; la bande passante agrégée peut être modeste.
  • Correction : Vérifiez la taille des I/O (IOPS vs MB/s), ajustez le recordsize du dataset, ajoutez des vdevs (plus de plateaux/mirrors), ou déplacez les données chaudes vers SSD/special vdev.

2) « Un disque dans un mirror fait moins, donc tout va bien »

  • Symptôme : Dans un mirror, un disque montre moins d’ops et/ou un wait plus élevé.
  • Cause racine : Le périphérique est lent, en train de réessayer des erreurs, a un problème de chemin, ou est throttlé par le contrôleur.
  • Correction : Vérifiez les compteurs zpool status, regardez les logs OS, vérifiez SMART, reseate/remplacez les câbles, migrez le disque vers un autre port/HBA, remplacez le périphérique si nécessaire.

3) « On a ajouté un SLOG ; les écritures restent lentes ; le SLOG est inutile »

  • Symptôme : SLOG présent ; latence d’écriture toujours élevée.
  • Cause racine : Le workload n’est pas sync-heavy, ou le SLOG est lent/grand public, ou sync est désactivé/activé de manière inattendue.
  • Correction : Confirmez le comportement sync (zfs get sync), observez l’activité du vdev « logs » dans zpool iostat -v, utilisez un dispositif basse latence avec PLP, et n’attendez pas du SLOG qu’il accélère les écritures asynchrones.

4) « RAIDZ devrait aller ; c’est comme un RAID matériel »

  • Symptôme : Les petites écritures aléatoires ont un wait élevé ; la bande passante semble faible ; le CPU va bien.
  • Cause racine : Surcharge de parité RAIDZ et comportement read-modify-write sur petites mises à jour.
  • Correction : Utilisez des mirrors pour les workloads sensibles aux IOPS, ou changez les tailles de bloc/workload, ou ajoutez des vdevs, ou isolez les workloads d’écriture aléatoire vers des pools mirror/SSD.

5) « La latence est élevée, donc le pool est surchargé »

  • Symptôme : total_wait élevé ; appli bloquée ; mais %util du périphérique n’est pas élevé.
  • Cause racine : Le goulet peut être au-dessus des disques : commit TXG, contention CPU, pression mémoire, ou contention de verrous.
  • Correction : Contrevérifiez avec iostat -x, observez le comportement ARC, vérifiez le steal/interrupts CPU, et cherchez des blocages liés à TXG via les logs système et les tunables ZFS (spécifiques à la plateforme).

6) « La perf s’est dégradée après activation d’un special vdev ; ZFS est cassé »

  • Symptôme : Les lectures deviennent en rafales ; les opérations lourdes en métadonnées bloquent.
  • Cause racine : Le special vdev est sous-dimensionné, saturé, ou sur un périphérique à mauvaise cohérence de latence ; en outre, la concentration des métadonnées augmente la dépendance à ce périphérique.
  • Correction : Assurez-vous que le special vdev a une capacité et une redondance suffisantes, surveillez-le comme un niveau critique, et n’utilisez pas un seul périphérique bon marché comme colonne vertébrale des métadonnées.

7) « On est à seulement 80% ; la capacité ne peut pas affecter la perf »

  • Symptôme : La latence augmente progressivement à mesure que le pool se remplit ; l’allocation devient inégale ; la fragmentation augmente.
  • Cause racine : L’espace libre devient plus difficile à allouer efficacement ; la fragmentation des metaslabs croît ; certains vdevs deviennent plus chauds.
  • Correction : Gardez les pools confortablement en dessous des seuils hauts pour votre workload, ajoutez des vdevs plus tôt, et évitez les expansions de dernière minute pendant les pics d’utilisation.

Checklists / plan pas à pas

Étape par étape : de « lent » à « goulet » en 15 minutes

  1. Confirmez le pool et le dataset impliqués.
    Vérifiez mountpoints/volumes et mappez-les aux pools. Ne diagnostiquez pas la mauvaise machine.
  2. Vérifiez la santé d’abord.
    Lancez zpool status -v. Des erreurs, des périphériques dégradés, des resilvers, ou des scrubs ? Traitez cela en priorité.
  3. Capturez un court run iostat.
    Lancez zpool iostat -v 1 10 (et -l si disponible). Sauvegardez-le. Les incidents sans artefacts deviennent des disputes.
  4. Classifiez la forme du workload.
    IOPS-heavy (ops élevées, MB/s faibles) vs bandwidth-heavy (ops modérées, MB/s élevés). Décidez du type de matériel utile.
  5. Identifiez le vdev chaud.
    Si un vdev est plus chaud, demandez « pourquoi » : déséquilibre de remplissage, type de disque différent, chemin différent, erreurs, ou saturation du special/log device.
  6. Vérifiez le comportement sync.
    Lancez zfs get sync sur le(s) dataset(s). Si sync-heavy, confirmez le SLOG et son comportement dans iostat.
  7. Contrevérifiez au niveau OS.
    Lancez iostat -x 1 5. Confirmez await et queue au niveau périphérique. Si les périphériques sont inactifs, arrêtez de blâmer les disques.
  8. Décidez la première mitigation sûre.
    Exemples : mettre en pause/rééchelonner un scrub, déplacer le workload, limiter le débit d’un job batch, ajouter un dispositif de log, ajouter des vdevs, ou migrer le dataset.

Checklist : quoi capturer pour un postmortem

  • Au moins 60 secondes d’échantillons zpool iostat -v, plus la vue latence si disponible.
  • La sortie zpool status -v au moment de l’incident.
  • Stats périphériques OS (iostat -x) pour corrélation.
  • Propriétés du dataset : sync, recordsize, compression, atime, et toute configuration de special vdev.
  • Si un scrub/resilver était actif et son taux.
  • Une déclaration claire : IOPS-bound, bandwidth-bound, sync-bound, ou single-vdev-bound.

FAQ

1) Quelle est la différence entre zpool iostat et iostat Linux ?

zpool iostat rapporte la vue logique de ZFS par pool/vdev, incluant des dispositifs virtuels comme logs et special vdevs.
iostat Linux rapporte le comportement des périphériques blocs (file, await, utilisation). Utilisez les deux : ZFS pour trouver le vdev chaud,
iostat OS pour confirmer la saturation du périphérique ou un problème de chemin.

2) Pourquoi un vdev devient-il le goulet d’étranglement si ZFS « stripe » les données ?

ZFS stripe entre les vdevs de niveau supérieur. Si un vdev est plus plein, plus lent, se comporte mal, ou contient moins de disques, il peut devenir
le facteur limitant. La vitesse agrégée du pool est tirée vers le vdev le plus lent impliqué dans le workload.

3) Un SLOG accélère-t-il toutes les écritures ?

Non. Un SLOG accélère les écritures synchrones (écritures qui doivent être engagées en sécurité avant de revenir).
Les écritures asynchrones sont tamponnées et engagées via les TXGs ; le SLOG ne change pas ce chemin de façon significative.

4) Pourquoi mes écritures sont-elles plus lentes que les lectures dans iostat ?

Causes communes : écritures sync sans bon SLOG, surcharge de parité RAIDZ pour les petites écritures, pool presque plein/fragmenté,
ou périphérique avec latence d’écriture inconsistente. Si les lectures vont bien et les écritures sont affreuses, vérifiez sync et le comportement du vdev de logs.

5) De fortes IOPS sont-elles toujours mauvaises ?

De fortes IOPS sont juste une caractéristique du workload. Cela devient mauvais quand la latence augmente ou que le système ne respecte pas les SLO.
La bonne question est : sommes-nous IOPS-bound (petit aléatoire) ou bandwidth-bound (gros séquentiel) ?

6) Combien d’échantillons devrais-je prendre avec zpool iostat ?

Pour le triage, 5–10 secondes à intervalles d’une seconde suffisent. Pour diagnostiquer la gigue, prenez au moins 60 secondes et capturez
la même chose pendant les heures normales pour comparaison. Les problèmes de stockage aiment se cacher dans la variance.

7) La fragmentation peut-elle expliquer des pics de latence ?

Elle peut contribuer, surtout lorsque les pools se remplissent. La fragmentation tend à augmenter le coût moyen d’une I/O et la variance.
Si vous voyez des temps d’attente croissants avec des IOPS similaires, et que le pool se remplit, la fragmentation/taxe de capacité est un suspect réel.

8) Quelle est la « correction rapide » la plus sûre pendant un incident ?

La plus sûre est de réduire les E/S concurrentes : mettre en pause/rééchelonner un scrub, limiter le débit des jobs batch, ou déplacer un locataire bruyant.
Changer les paramètres sync ou reconstruire la géométrie du pool n’est pas une correction en temps d’incident à moins que vous soyez prêt·e à assumer le risque.

9) Pourquoi zpool iostat affiche une faible bande passante alors que l’app dit qu’elle écrit beaucoup ?

Les applications « écrivent » à un niveau logique ; ZFS peut compresser, fusionner, différer, ou satisfaire les écritures via le caching et le batching TXG.
La bande passante au niveau périphérique est ce qui frappe réellement les disques. Si votre appli écrit de petits blocs aléatoires, la bande passante peut sembler faible même si le système lutte.

10) Dois-je faire confiance aux chiffres de latence moyens ?

Faites-le en tant qu’indice, pas comme verdict. Les moyennes cachent la latence tail, et la latence tail est celle que subissent les utilisateurs.
Utilisez des échantillons dans le temps, corrélez avec les phases du workload, et confirmez avec les métriques de file au niveau OS.

Prochaines étapes à faire aujourd’hui

Si vous exploitez ZFS en production, faites ces trois choses avant que le prochain incident ne vous les impose :

  1. Créez une baseline. Capturez chaque semaine zpool iostat -v (et la vue latence si disponible) pour chaque hôte important.
    Conservez-la quelque part ennuyeux et durable.
  2. Documentez votre contrat d’écriture prévu. Pour chaque dataset critique : la sync est-elle requise ? Si oui, quel est le SLOG et comment le validez-vous sous charge ?
    Si non, pourquoi pas—et qui a signé ce risque ?
  3. Cessez de traiter « pool plein » comme un événement de capacité uniquement. Décidez votre ligne d’eau de performance (souvent bien en dessous de 90%),
    et planifiez l’ajout de vdevs tant que le pool est encore confortable.

Une fois que vous pouvez nommer le goulet d’étranglement avec des preuves — IOPS-bound, bandwidth-bound, sync-bound, ou un vdev unique qui traîne le pool —
les corrections deviennent simples. Pas toujours bon marché. Mais simples. C’est l’accord.

← Précédent
Introduction à zdb de ZFS : l’outil que vous craignez jusqu’au jour où vous en avez besoin
Suivant →
Docker : Limiter le bruit des logs à la source — modèles de journalisation applicative qui économisent les disques

Laisser un commentaire