Analyse des logs ZFS : détecter les ralentissements avant qu’ils ne deviennent des incidents

Cet article vous a aidé ?

ZFS ne « tombe » que rarement dans un grand fracas. Il ralentit. Silencieusement. Le graphe oscille. La latence s’étire.
Les applications commencent à dépasser leurs délais. Quelqu’un ouvre un ticket sur une « lenteur intermittente ». Et puis — parce que l’univers déteste l’humilité — votre
prochaine mise en production atterrit sur ce problème et se fait accuser de tout.

L’astuce consiste à attraper la dégradation des performances ZFS tant que c’est encore une fenêtre de maintenance, pas un post-mortem.
Ceci est un guide terrain pour lire les logs et les vérités adjacentes (messages du noyau, erreurs de périphérique, flux d’événements ZFS)
afin de repérer les ralentissements tôt et décider quoi faire ensuite — rapidement, précisément, et sans rituels de cargo-cult.

Attitude : les logs sont une chronologie, pas une ambiance

Les « logs » ZFS sont au pluriel. Il y a le flux d’événements ZFS, le ring buffer du noyau, le journal systemd, les logs SMART/périphériques,
et la propre vision de ZFS sur la santé du pool. L’objectif n’est pas de collecter plus de texte. L’objectif est d’aligner les chronologies :
qu’est-ce qui est devenu plus lent, quand, et qu’est-ce qui a changé d’autre.

Voici la posture opérationnelle qui vous évite des ennuis :

  • Privilégiez la latence plutôt que le débit. Les utilisateurs ressentent la latence au 99e percentile. Les tableaux de bord qui n’affichent que MB/s vous mentiront.
  • Supposez que ZFS est honnête sur l’intégrité des données et conservateur sur les performances. Quand il ralentit, il vous protège généralement de quelque chose de pire.
  • Soyez méfiant envers les narratifs « ça a commencé après X ». Les problèmes ZFS incubent souvent pendant des semaines : un disque faiblard, un recordsize mal dimensionné, un chemin d’écriture sync oublié.
  • Corrélez au niveau du périphérique. La plupart des « problèmes de performance ZFS » sont soit la latence du périphérique, de l’ordonnancement, soit un chemin d’écriture sync qui fait exactement ce que vous lui avez demandé.

Une ligne de log est un indice, pas un verdict. Il faut toujours la confronter à la réalité : zpool iostat, arcstat, iostat,
et ce que font réellement vos applications.

Faits intéressants et contexte historique (pour arrêter de deviner)

  1. ZFS est né à l’époque de Solaris avec un modèle d’intégrité de bout en bout — checksums partout — parce que la « corruption silencieuse » existait déjà, simplement pas très populaire.
  2. Le journal d’intention (ZIL) n’est pas un cache d’écriture. C’est un mécanisme pour rejouer la sémantique synchrone après un crash. La plupart des écritures ne restent jamais « sur le log » à long terme.
  3. SLOG est un périphérique, pas une fonctionnalité magique. Ajouter un dispositif de log séparé (SLOG) n’aide que les écritures synchrones et peut vous nuire s’il est lent ou mal configuré.
  4. Les scrubs ont été conçus comme un audit proactif, pas comme un outil « réparer quand c’est cassé ». Ils servent à prouver que vos données sont toujours vos données.
  5. Le comportement du resilver a évolué. Les resilvers modernes d’OpenZFS peuvent être séquentiels et plus intelligents sur ce qu’il faut copier, mais vous payez toujours en contention d’I/O.
  6. Le tuning ARC/L2ARC a une longue histoire de mauvais conseils. Beaucoup de « guides de performance » d’il y a dix ans optimisaient pour des charges de travail différentes et des ratios RAM/disque plus faibles.
  7. ashift est pour toujours. Une mauvaise hypothèse sur la taille de secteur à la création du pool peut vous enfermer dans une amplification d’écriture — coûteuse discrètement, douloureuse bruyamment.
  8. La compression est devenue courante en opérations ZFS parce que le CPU est devenu bon marché et pas l’I/O. Mais le bénéfice dépend de la forme de vos données, pas de vos espoirs.

Ce que signifie réellement « ZFS lent » : la carte des goulets d’étranglement

« ZFS est lent » revient à dire « la ville est encombrée ». Quelle rue ? Quelle heure ? Quelle fermeture de voie ?
En pratique, les ralentissements ZFS se regroupent en quelques catégories. Vos logs pointeront généralement vers l’une d’elles :

1) Latence du périphérique et récupération d’erreur

Un disque marginal peut bloquer un vdev. En RAIDZ et en miroirs, l’enfant le plus lent devient souvent la voiture de rythme.
Les logs du noyau Linux peuvent montrer des réinitialisations de lien, des timeouts de commande, ou des événements de « file d’attente gelée ». ZFS peut afficher des erreurs de lecture/écriture/checksum.
Même si le disque « récupère », le coût des retries est payé en temps réel par votre application.

2) Chemin d’écriture synchrone : douleur ZIL/SLOG

Si votre charge effectue des écritures synchrones (bases de données, NFS, certains stockages de VM, tout ce qui appelle souvent fsync),
alors la latence ZIL compte. Avec un SLOG, votre latence sync est fréquemment la latence du SLOG.
Sans SLOG, les écritures synchrones frappent le pool et héritent de sa latence. Les logs ne diront pas « fsync est votre problème » en ces termes,
mais le schéma apparaît : augmentation d’await, pics alignés sur les sync de txg, et beaucoup de plaintes pendant les périodes de commits intensifs.

3) Pics du temps de sync des transaction groups (txg)

ZFS regroupe les changements en transaction groups. Lorsqu’un txg est commité (« sync »), le système peut voir de courtes tempêtes d’I/O d’écriture.
Si le temps de sync augmente, tout ce qui dépend de ces commits devient plus lent. Cela peut se manifester par des pauses périodiques, des NFS « not responding »,
ou des pics de latence applicative toutes les quelques secondes.

4) Métadonnées et problèmes de fragmentation

La fragmentation n’est pas une faute morale ; c’est de la physique plus du temps. Certaines charges (images de VM, bases de données, petits écritures aléatoires)
peuvent transformer le pool en un festival de seeks coûteux. Les logs ZFS n’afficheront pas « vous êtes fragmenté », mais vos patterns iostat le feront,
et vos temps de scrub/resilver empireront.

5) Pression mémoire : thrash ARC

Lorsque le hit rate de l’ARC chute, les lectures vont sur disque. Ce n’est pas automatiquement mauvais — parfois l’ensemble de travail dépasse la RAM.
Mais un effondrement soudain de l’ARC peut survenir après un déploiement gourmand en mémoire, un changement de densité de conteneurs, ou une configuration L2ARC mal pensée.
Le signal habituel est : plus de lectures disque, latence plus élevée, et un noyau qui a l’air… occupé.

Une idée paraphrasée souvent attribuée à John Allspaw convient ici : La fiabilité vient de l’apprentissage et de l’adaptation, pas de la prétention à tout prévoir. ZFS est adaptable. Votre travail est d’apprendre ce qu’il vous dit avant qu’il ne commence à crier.

Playbook de diagnostic rapide (premiers/second/troisièmes contrôles)

Si vous êtes d’astreinte, vous n’avez pas le temps pour une danse interprétative. Vous avez besoin d’une séquence qui réduit l’espace de recherche.
Ce playbook suppose Linux + OpenZFS, mais la logique se transporte.

Premier : le pool est-il sain maintenant ?

  • Exécutez zpool status -x. S’il affiche autre chose que « all pools are healthy », arrêtez et enquêtez d’abord.
  • Vérifiez zpool events -v pour des fautes récentes de périphérique, réinitialisations de lien, ou erreurs de checksum.
  • Recherchez des scrubs/resilvers en cours. Un pool « sain » peut quand même être lent s’il est en reconstruction.

Second : est-ce un problème de périphérique ou de charge/sync ?

  • Exécutez zpool iostat -v 1 et observez la distribution de la latence par vdev. Un disque lent ? Un miroir lent ? Voilà votre suspect.
  • Exécutez iostat -x 1 et vérifiez await, svctm (si présent), et %util. Await élevé + util élevé = saturation périphérique/file d’attente.
  • Vérifiez si la latence corrèle avec des rafales d’écritures sync : cherchez des écritures élevées avec un débit relativement bas mais un await élevé.

Troisième : confirmez le mode de défaillance avec logs et compteurs

  • Journal/noyau : journalctl -k pour timeouts, réinitialisations, erreurs NCQ, erreurs de transport, commandes avortées.
  • SMART : smartctl pour secteurs réalloués, secteurs en attente, erreurs CRC (souvent câble/backplane).
  • Statistiques ZFS : comportement ARC (arcstat si disponible), messages de sync txg (selon votre build), et historique d’événements.

Règle en une phrase : si vous pouvez nommer le composant le plus lent, vous pouvez généralement réparer l’incident.
Si vous ne le pouvez pas, vous devinez encore — continuez à réduire le périmètre.

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

Voici les tâches que j’exécute réellement en production lorsque ZFS ralentit. Chacune inclut ce que la sortie signifie et quelle décision prendre ensuite.
Copier/coller est autorisé. Panique interdite.

Tâche 1 : Vérification rapide de l’état du pool

cr0x@server:~$ sudo zpool status -x
all pools are healthy

Sens : Pas de fautes connues, pas de vdev dégradé, pas d’erreurs actives. Cela ne garantit pas la performance, mais élimine une grande catégorie d’urgences.
Décision : Passer au diagnostic de latence (zpool iostat, iostat) plutôt qu’aux opérations de réparation.

Tâche 2 : État complet avec compteurs d’erreurs et travaux en cours

cr0x@server:~$ sudo zpool status
  pool: tank
 state: ONLINE
status: One or more devices has experienced an unrecoverable error.  An
        attempt was made to correct the error.  Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
        using 'zpool clear' or replace the device with 'zpool replace'.
  scan: scrub repaired 0B in 02:14:33 with 0 errors on Mon Dec 23 03:12:18 2025
config:

        NAME                        STATE     READ WRITE CKSUM
        tank                        ONLINE       0     0     0
          mirror-0                  ONLINE       0     0     0
            ata-SAMSUNG_SSD_860-1   ONLINE       0     0     0
            ata-SAMSUNG_SSD_860-2   ONLINE       0     0     3

errors: No known data errors

Sens : Le pool est en ligne, mais un périphérique a des erreurs de checksum. ZFS les a corrigées grâce à la redondance, mais vous avez maintenant un signal de fiabilité et de performance.
Décision : Enquêter sur le chemin du périphérique (SMART, câblage, backplane, HBA). Ne pas utiliser « zpool clear » comme thérapie ; n’effacez qu’après avoir compris pourquoi les erreurs sont apparues.

Tâche 3 : Surveiller la latence par vdev en direct

cr0x@server:~$ sudo zpool iostat -v 1
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        4.12T  3.15T    210    980  23.1M  61.4M
  mirror-0                  2.06T  1.57T    105    510  11.6M  30.7M
    ata-SAMSUNG_SSD_860-1      -      -     60    250  6.7M  15.2M
    ata-SAMSUNG_SSD_860-2      -      -     45    260  4.9M  15.5M
--------------------------  -----  -----  -----  -----  -----  -----

Sens : La charge du miroir semble à peu près symétrique au fil du temps. Si un membre affiche beaucoup moins d’opérations mais une latence plus élevée (non montré ici),
ou si les ops d’un vdev s’effondrent alors que la demande du pool reste, c’est un indice que le périphérique cale ou relance des retries.
Décision : Si le déséquilibre persiste, corrélez avec les logs du noyau et SMART ; envisagez de mettre hors ligne/remplacer le périphérique suspect si les erreurs s’alignent.

Tâche 4 : Ajouter des colonnes de latence (là où supporté)

cr0x@server:~$ sudo zpool iostat -v -l 1
                              capacity     operations     bandwidth    total_wait     disk_wait
pool                        alloc   free   read  write   read  write   read  write    read  write
--------------------------  -----  -----  -----  -----  -----  -----  ----- -----    ----- -----
tank                        4.12T  3.15T    220   1020  24.0M  63.2M   3ms   28ms     2ms   24ms
  mirror-0                  2.06T  1.57T    110    520  12.0M  31.6M   2ms   30ms     2ms   27ms
    ata-SAMSUNG_SSD_860-1      -      -     55    260  6.1M  15.8M   2ms   8ms      2ms   7ms
    ata-SAMSUNG_SSD_860-2      -      -     55    260  5.9M  15.8M   2ms   90ms     2ms   85ms
--------------------------  -----  -----  -----  -----  -----  -----  ----- -----    ----- -----

Sens : Un disque a des pics de disk_wait (85–90ms) tandis que l’autre reste bas. C’est votre « voiture de rythme ».
Décision : Récupérez les preuves noyau + SMART. Si c’est le câblage/chemin HBA, corrigez cela. Si c’est le SSD lui-même, planifiez le remplacement avant qu’il ne « récupère » dans votre prochain incident.

Tâche 5 : Vérifier la contention scrub/resilver

cr0x@server:~$ sudo zpool status tank
  pool: tank
 state: ONLINE
  scan: resilver in progress since Thu Dec 26 08:11:02 2025
        312G scanned at 1.24G/s, 48.2G issued at 192M/s, 7.11T total
        48.2G resilvered, 0.68% done, 10:27:11 to go
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

errors: No known data errors

Sens : Un resilver est en cours. Votre pool effectue des lectures/écritures supplémentaires, et la latence va généralement empirer.
Décision : Si c’est un système de production orienté utilisateur, décidez s’il faut limiter le resilver/scrub (là où c’est possible),
ou déplacer temporairement la charge. Confirmez également que la défaillance initiale est totalement résolue — ne laissez pas un deuxième disque vaciller pendant le resilver.

Tâche 6 : Lire le flux d’événements ZFS récent

cr0x@server:~$ sudo zpool events -v | tail -n 30
TIME                           CLASS
Dec 26 2025 08:10:58.123456789 ereport.fs.zfs.vdev.io
    pool = tank
    vdev_path = /dev/disk/by-id/ata-SAMSUNG_SSD_860-2
    vdev_guid = 1234567890123456789
    errno = 5
    size = 131072
    offset = 9876543210
    flags = 0x180

Dec 26 2025 08:10:58.223456789 ereport.fs.zfs.vdev.checksum
    pool = tank
    vdev_path = /dev/disk/by-id/ata-SAMSUNG_SSD_860-2
    vdev_guid = 1234567890123456789

Sens : ZFS enregistre des erreurs I/O et des problèmes de checksum contre un périphérique spécifique.
Décision : Traitez cela comme du triage chemin matériel : SMART, câbles, HBA, boîtier. Si cela se répète, remplacez le périphérique.
Si ça s’arrête après avoir reseaté un câble, continuez à surveiller ; les erreurs CRC intermittentes aiment revenir.

Tâche 7 : Vérifier les logs du noyau pour réinitialisations et timeouts de transport

cr0x@server:~$ sudo journalctl -k --since "2 hours ago" | egrep -i "ata|nvme|scsi|reset|timeout|error" | tail -n 40
Dec 26 09:01:14 server kernel: ata7.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6 frozen
Dec 26 09:01:14 server kernel: ata7.00: failed command: READ FPDMA QUEUED
Dec 26 09:01:14 server kernel: ata7: hard resetting link
Dec 26 09:01:18 server kernel: ata7: link is slow to respond, please be patient (ready=0)
Dec 26 09:01:20 server kernel: ata7: SATA link up 6.0 Gbps (SStatus 133 SControl 300)
Dec 26 09:01:20 server kernel: ata7.00: configured for UDMA/133

Sens : Événements de réinitialisation de lien. Même lorsqu’ils « récupèrent », le temps de retry crée des pics de latence et peut bloquer un vdev.
Décision : Vérifiez le câblage/backplane, l’alimentation, et le firmware HBA. Si c’est une baie de disque unique, changez le disque de slot pour isoler le chemin d’enclosure.

Tâche 8 : Triage SMART (SATA/SAS)

cr0x@server:~$ sudo smartctl -a /dev/sdb | egrep -i "Reallocated|Pending|Offline_Uncorrectable|CRC_Error_Count|Power_On_Hours"
  9 Power_On_Hours          0x0032   094   094   000    Old_age   Always       -       23874
197 Current_Pending_Sector  0x0012   100   100   000    Old_age   Always       -       8
198 Offline_Uncorrectable   0x0010   100   100   000    Old_age   Offline      -       2
199 UDMA_CRC_Error_Count    0x003e   200   200   000    Old_age   Always       -       0

Sens : Les secteurs en attente et les offline uncorrectables sont des problèmes médias réels. Un compte CRC à zéro suggère que ce n’est pas « juste un câble ».
Décision : Planifiez le remplacement. Si le pool est redondant, remplacez de manière proactive. Si c’est un disque unique (ne le faites pas), sauvegardez d’abord puis remplacez hier.

Tâche 9 : Santé NVMe et log d’erreurs

cr0x@server:~$ sudo nvme smart-log /dev/nvme0 | egrep -i "critical_warning|media_errors|num_err_log_entries|percentage_used"
critical_warning                    : 0x00
media_errors                        : 12
num_err_log_entries                 : 398
percentage_used                     : 87%

Sens : Erreurs médias et pourcentage d’usure élevé peuvent corréler avec une latence croissante et une défaillance imminente.
Décision : Si ce NVMe est un SLOG ou un vdev spécial, traitez-le en urgence — ces rôles peuvent dégrader fortement la performance quand le périphérique se comporte mal.

Tâche 10 : Identifier les charges sync via les propriétés de dataset

cr0x@server:~$ sudo zfs get -o name,property,value -s local sync,logbias,primarycache,recordsize tank/app tank/vm
NAME      PROPERTY      VALUE
tank/app  sync          standard
tank/app  logbias       latency
tank/app  primarycache  all
tank/app  recordsize    128K
tank/vm   sync          always
tank/vm   logbias       latency
tank/vm   primarycache  metadata
tank/vm   recordsize    16K

Sens : sync=always force la sémantique synchrone même si l’application ne le demande pas. Cela peut être correct, ou c’est un incident de performance auto-infligé.
Décision : Vérifiez pourquoi sync=always est défini. Si c’est pour une base de données qui gère déjà la durabilité, vous payez peut-être deux fois. Si c’est pour la sécurité NFS/VM, conservez-le et investissez dans un SLOG adapté.

Tâche 11 : Confirmer la présence et la disposition de base du SLOG

cr0x@server:~$ sudo zpool status tank | sed -n '1,80p'
  pool: tank
 state: ONLINE
config:

        NAME                        STATE     READ WRITE CKSUM
        tank                        ONLINE       0     0     0
          mirror-0                  ONLINE       0     0     0
            sda                     ONLINE       0     0     0
            sdb                     ONLINE       0     0     0
        logs
          nvme-SAMSUNG_MZVLB1T0-1   ONLINE       0     0     0

errors: No known data errors

Sens : Un SLOG sur un seul périphérique existe. C’est courant, mais aussi un point unique de performance et (selon votre tolérance) de risque pour la latence des écritures synchrones.
Décision : Pour les charges sync critiques, préférez des SLOG en miroir. Et assurez-vous que le SLOG est vraiment à faible latence en conditions de protection contre coupure de courant.

Tâche 12 : Vérifier si le système est noyé par le queueing I/O

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

Device            r/s     w/s   rkB/s   wkB/s  avgrq-sz avgqu-sz   await  r_await  w_await  %util
sda              12.0   340.0    480   14560      83.2     18.4    52.6     3.1     54.4   99.2
sdb              10.0   332.0    420   14400      85.7      1.2     3.7     2.8      3.8   34.5
nvme0n1           0.0    25.0      0    2048     163.8      0.4    15.8     0.0     15.8   40.1

Sens : sda est saturé à ~99% util avec une file profonde et un await élevé, tandis que sdb va bien. Dans un miroir, cela peut ralentir le vdev.
NVMe montre un await modéré ; si c’est votre SLOG, 15ms peut être trop lent pour des attentes fsync « rapides ».
Décision : Enquêter pourquoi sda est lent : erreurs, firmware, throttling thermique, problèmes de contrôleur. Si c’est un membre de miroir, envisagez de le mettre hors ligne brièvement pour voir si la latence s’améliore (avec conscience des risques).

Tâche 13 : Vérifier le comportement ARC (si arcstat est disponible)

cr0x@server:~$ arcstat 1 5
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsz     c
09:12:01  3120   980     31   220    7   710   23    50    1  96.2G  96.0G
09:12:02  2980   940     31   240    8   650   22    50    1  96.2G  96.0G
09:12:03  3050   970     32   210    7   710   23    50    1  96.2G  96.0G
09:12:04  3105   995     32   230    7   715   23    50    1  96.2G  96.0G
09:12:05  3002   960     32   220    7   690   23    50    1  96.2G  96.0G

Sens : Un miss rate ~31–32% peut être acceptable ou catastrophique selon votre stockage et workload. Si miss% bondit soudainement par rapport à la baseline,
les disques verront plus de lectures et la latence montera.
Décision : Comparez à la baseline de la semaine passée. Si ARC est capé (c égal à arcsz) et que vous avez de la RAM libre, envisagez d’augmenter le max ARC.
Si l’ARC est comprimé par autre chose, résolvez la pression mémoire plutôt que de « tuner ZFS » dans un coin.

Tâche 14 : Vérifier compression et I/O logique vs physique

cr0x@server:~$ sudo zfs get -o name,property,value compression,compressratio tank/app
NAME      PROPERTY       VALUE
tank/app  compression    lz4
tank/app  compressratio  1.62x

Sens : La compression fonctionne et économise probablement de l’I/O. Si compressratio est ~1.00x, vous payez un surcoût CPU pour aucun bénéfice I/O (généralement faible avec lz4, mais pas zéro).
Décision : Si le CPU est un goulot et que les données sont incompressibles, envisagez de désactiver la compression sur ce dataset. Sinon, laissez lz4 ; c’est un des rares choix par défaut qui rapporte.

Tâche 15 : Trouver qui bombardent le pool maintenant

cr0x@server:~$ sudo iotop -oPa
Total DISK READ: 45.20 M/s | Total DISK WRITE: 112.30 M/s
  PID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
18342 be/4  postgres    2.10 M/s   65.40 M/s  0.00 %  84.21 % postgres: checkpointer
20111 be/4  root        0.00 B/s   28.20 M/s  0.00 %  62.10 % zfs send -w tank/app@snap
 9321 be/4  libvirt-qemu 1.10 M/s  12.80 M/s  0.00 %  20.33 % qemu-system-x86_64

Sens : Vous avez un checkpointer qui écrit fortement, un zfs send qui pousse des données, et des VM qui lisent/écrivent. C’est une carte de contention.
Décision : Si la latence est visible par les utilisateurs, mettez en pause ou replanifiez le transfert massif (zfs send) ou limitez son débit. Ne discutez pas avec la physique.

Blague #1 : Le stockage est le seul endroit où « c’est bon en moyenne » est accepté jusqu’au moment où ça ne l’est plus.

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

Mini-récit 1 : L’incident causé par une mauvaise hypothèse

Une entreprise SaaS de taille moyenne gérait Postgres clients sur du stockage VM sur ZFS. Tout était stable depuis des mois, et l’équipe en était fière :
SSDs en miroir, compression activée, scrubs hebdomadaires, monitoring basique. La seule chose qu’ils ne surveillaient pas était la latence des écritures synchrones. Parce que, dans leur tête,
« les SSD sont rapides ».

Une nouvelle exigence de conformité est arrivée : garantir la sémantique de durabilité pour un sous-ensemble de charges. Un ingénieur a activé sync=always sur le dataset qui contenait
les images VM. L’hypothèse était simple : « Ce sera plus sûr et seulement un peu plus lent. » Elle était à moitié vraie.

Le lendemain matin, les clients ont signalé des timeouts sporadiques. Le pool semblait sain. Le CPU allait bien. Le réseau allait bien. Les graphiques de débit allaient bien.
Mais la latence d’écriture au 99e percentile avait explosé. Les logs du noyau n’affichaient rien de dramatique. Les logs ZFS n’affichaient pas d’erreurs. Tout le monde a commencé à regarder la couche applicative,
parce que c’est ce qu’on fait quand le stockage ne confesse pas.

Le coupable était dans zpool iostat -l : le dispositif SLOG (un NVMe grand public sans protection contre la coupure de courant) avait une latence d’écriture élevée et instable sous une charge sync soutenue.
Il n’était pas « cassé ». On lui demandait juste de fournir des commits à faible latence constants et il a poliment refusé.

La correction a été ennuyeuse et coûteuse : remplacer le SLOG par un dispositif conçu pour une latence d’écriture sync stable et le mettre en miroir.
Le postmortem a livré une leçon à retenir : ne changez pas la sémantique sync sans mesurer le chemin sync.

Mini-récit 2 : L’optimisation qui a mal tourné

Une équipe plateforme interne d’entreprise gérait un pool ZFS pour des artefacts CI et des images de conteneur. C’était surtout de gros fichiers, beaucoup de lectures parallèles,
et des écritures massives occasionnelles. Le système était « correct », mais une initiative de performance bien intentionnée exigeait « plus de débit ».

Quelqu’un a trouvé une vieille note de tuning et a décidé que le pool devait utiliser un « special vdev » séparé pour les métadonnées afin d’accélérer les traversées de répertoires et les petites lectures.
Ils ont ajouté une paire de petits SSD rapides comme special vdev. Les benchmarks initiaux semblaient excellents. La direction a souri. Tout le monde est passé à autre chose.

Des mois plus tard, la performance est devenue bizarre. Pas seulement plus lente — saccadée. Pendant les heures de pointe CI, les builds se bloquaient pendant des secondes.
zpool status restait vert. Mais zpool iostat -v -l racontait une histoire plus laide : le special vdev était devenu le goulet de latence.
Ces « petits SSD rapides » étaient fortement sollicités, s’usant, et parfois se throttleant.

Le retour de bâton n’était pas la fonctionnalité. C’était le dimensionnement et la réflexion sur le cycle de vie. Les métadonnées et les petits blocs peuvent attirer énormément d’I/O.
Quand le special vdev cale, tout le pool en subit les conséquences. Les logs noyau comportaient des avertissements NVMe légers, pas assez pour déclencher des alertes,
mais suffisants pour expliquer les blocages quand on les corrélait aux pics de latence.

Le plan de remédiation : remplacer le special vdev par des périphériques durables appropriés, augmenter la capacité pour réduire l’amplification d’écriture,
et ajouter du monitoring spécifique pour la latence et l’usure du special vdev. La morale : toute structure d’accélération devient une dépendance.

Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Une société de services financiers utilisait ZFS pour un backend NFS servant des répertoires personnels et des sorties de build partagées. Rien de sexy. Aucun tuning héroïque.
Ce qu’ils avaient, c’était de la discipline : scrubs mensuels, alertes sur les changements de zpool status, et un runbook qui obligeait les ingénieurs à vérifier
les erreurs de transport noyau avant de toucher aux réglages ZFS.

Un mardi, la latence a augmenté. Les utilisateurs l’ont remarquée. L’astreinte a suivi le runbook : vérifier l’état du pool, les événements, les logs du noyau.
En quelques minutes ils ont trouvé des réinitialisations de lien SATA répétées sur une baie de disques. Pas encore d’erreurs ZFS — juste des retries.

Ils ont remplacé le câble/composant backplane dans une micro-fenêtre planifiée, avant que le disque ne commence à lancer des erreurs de checksum.
La latence est revenue à la normale. Pas de resilver nécessaire. Aucun risque de données. Aucun week-end consommé par le regret.

La pratique qui les a sauvés n’était pas du génie. C’était la constance : scrubs pour détecter les problèmes latents, et corrélation des logs pour attraper la dégradation du chemin matériel tôt.
L’ennui est sous-estimé en ingénierie stockage parce que ça marche.

Blague #2 : Si vous voulez une carrière stockage excitante, ignorez votre planning de scrub ; le pager vous créera de l’excitation.

Erreurs courantes : symptôme → cause racine → correction

1) « Le pool est ONLINE mais la latence est terrible »

Symptôme : zpool status semble propre ; les applications expirent ; iostat montre un await élevé.

Cause racine : Retries de périphérique, réinitialisations de lien, ou un disque lent tirant un miroir/RAIDZ.

Correction : Vérifiez journalctl -k pour réinitialisations/timeouts ; vérifiez SMART/NVMe. Remplacez le périphérique suspect ou réparez le chemin transport. Ne tunez pas ZFS pour compenser un matériel défaillant.

2) « Toutes les quelques secondes nous avons une pause »

Symptôme : Pics périodiques de latence ; saccades NFS ; commits de base de données bloqués.

Cause racine : Txg sync trop long, souvent parce que le pool est saturé, la fragmentation est élevée, ou un périphérique lent bloque les flushes.

Correction : Utilisez zpool iostat -l pour identifier le vdev lent, et réduisez la charge d’écriture concurrente. Si c’est sync-heavy, corrigez la latence SLOG ou reconsidérez sync=always.

3) « Nous avons ajouté un SLOG et la performance a empiré »

Symptôme : Charge sync ralentit après ajout d’un périphérique de log.

Cause racine : Le SLOG a une latence pire que le pool ou subit du throttling ; un SLOG unique devient un goulet.

Correction : Vérifiez avec iostat -x et zpool iostat -l. Remplacez par un dispositif basse-latence, protégé contre la perte de puissance, idéalement en miroir. Si la charge est surtout async, retirez le SLOG et cessez d’attendre un miracle.

4) « Les erreurs de checksum apparaissent sans cesse, mais les scrubs les réparent »

Symptôme : Le compteur CKSUM augmente ; les scrubs réparent ; pas d’erreur de données visible — encore.

Cause racine : Souvent câblage/backplane/HBA (erreurs CRC), parfois défaillance média du disque.

Correction : Vérifiez les compteurs CRC SMART et les logs de transport noyau. Reseat/remplacez câble/backplane ; mettez à jour le firmware ; remplacez le disque si les indicateurs média sont mauvais. Ensuite scrub à nouveau et surveillez si les compteurs restent stables.

5) « Le resilver va finir en 2 heures… pendant les 3 jours suivants »

Symptôme : L’ETA du resilver augmente ; le pool est lent.

Cause racine : Charge concurrente + pool fragmenté + périphérique lent. Le resilver concurrence pour l’I/O et peut être dépriorisé ou affamé par vos applications.

Correction : Réduisez la charge, planifiez le resilver hors heures de pointe si possible, et vérifiez qu’un périphérique faible ne prolonge pas le processus. Confirmez qu’ashift et le design des vdevs ne provoquent pas d’amplification d’écriture pathologique.

6) « Le hit rate ARC s’est effondré après un déploiement non lié »

Symptôme : Augmentation soudaine des lectures disque ; latence en hausse ; changements d’utilisation mémoire.

Cause racine : Pression mémoire due à de nouveaux services, à la densité de conteneurs, ou au comportement du page cache ; ARC limité par la config ou comprimé par d’autres consommateurs.

Correction : Mesurez la mémoire, ne devinez pas. Si vous avez de la RAM disponible, augmentez le cap ARC. Sinon, réduisez la pression mémoire ou déplacez la charge. N’ajoutez pas de L2ARC à la place d’une RAM suffisante à moins de comprendre les patterns read/write.

7) « Nous avons réglé recordsize et maintenant les écritures sont plus lentes »

Symptôme : Après modification de recordsize, le débit chute et la latence monte.

Cause racine : Inadéquation entre recordsize et workload (par ex. trop grand pour des blocs DB random, trop petit pour du streaming séquentiel).

Correction : Définissez recordsize par dataset et par type de workload. Les images VM et bases de données préfèrent souvent des blocs plus petits (ex. 16K), tandis que les gros fichiers séquentiels bénéficient de plus grand (128K–1M selon l’usage). Validez avec de vraies traces I/O, pas des impressions.

Checklists / plan étape par étape

Checklist A : Quand les utilisateurs signalent une « lenteur intermittente »

  1. Confirmez s’il s’agit de latence de stockage : vérifiez p95/p99 côté application et I/O wait sur les hôtes.
  2. Exécutez zpool status -x. Si pas sain, traitez comme incident.
  3. Exécutez zpool status et cherchez un scrub/resilver en cours.
  4. Exécutez zpool iostat -v -l 1 pendant 60–120 secondes. Identifiez le vdev/périphérique le plus lent par latence.
  5. Exécutez journalctl -k filtré pour réinitialisations/timeouts. Confirmez si le périphérique lent a des erreurs correspondantes.
  6. Vérifiez la santé SMART/NVMe du périphérique suspect.
  7. Décidez : isoler (offline/remplacer), réparer le transport (câble/backplane/HBA), ou réduire la contention de workload.

Checklist B : Quand les écritures sync sont suspectes (bases de données/NFS/VM)

  1. Vérifiez les propriétés dataset sync et logbias pour les datasets concernés.
  2. Confirmez si vous avez un SLOG et quelle est sa configuration (single vs mirror).
  3. Mesurez la latence SLOG avec iostat -x sur le périphérique SLOG pendant la fenêtre de ralentissement.
  4. Si la latence SLOG est pire que le pool, ne débattez pas : remplacez ou retirez selon les besoins sync.
  5. Si aucun SLOG n’existe et que la latence sync est douloureuse, envisagez d’ajouter un SLOG miroir approprié — après validation que la charge est vraiment sync-heavy.

Checklist C : Quand des erreurs apparaissent mais le pool « continue de fonctionner »

  1. Capturez les sorties zpool status et zpool events -v pour le dossier d’incident.
  2. Vérifiez les logs noyau autour des mêmes timestamps pour des problèmes de transport.
  3. Vérifiez les indicateurs médias SMART/NVMe et les compteurs d’erreurs.
  4. Corrigez le chemin ou remplacez le matériel. Ensuite seulement, effacez les erreurs avec zpool clear.
  5. Exécutez un scrub après la remédiation et confirmez que les compteurs d’erreurs restent plats.

Checklist D : Baseline pour détecter les régressions

  1. Enregistrez la baseline zpool iostat -v -l pendant des heures « connues saines ».
  2. Enregistrez les stats ARC (hit rate, taille ARC, indicateurs de pression mémoire).
  3. Suivez la durée des scrubs et resilvers (ils sont des signaux précoces de fragmentation et de vieillissement des périphériques).
  4. Alertez sur les erreurs de transport noyau, pas seulement sur les fautes ZFS.

FAQ

1) Les logs ZFS suffisent-ils pour diagnostiquer les problèmes de performance ?

Non. ZFS vous informera des signaux d’intégrité (erreurs, fautes, événements), mais le diagnostic de performance nécessite le contexte matériel et noyau.
Associez toujours les événements ZFS aux logs noyau et à iostat/zpool iostat.

2) Si zpool status est propre, puis-je écarter le matériel ?

Absolument pas. Beaucoup de problèmes matériel/transport se manifestent par des retries et des réinitialisations bien avant que ZFS n’incrémente un compteur.
Les logs noyau et SMART montrent souvent les « pré-symptômes ».

3) Ajouter un SLOG améliore-t-il toujours la performance ?

Seulement pour les écritures synchrones. Pour les workloads async, c’est surtout neutre. Et un SLOG lent peut rendre la performance sync pire.
Traitez le SLOG comme un composant critique pour la latence, pas comme une case à cocher.

4) Quel est le moyen le plus rapide pour repérer un disque défaillant dans un miroir ?

Utilisez zpool iostat -v -l 1 et cherchez un membre avec une latence disk wait beaucoup plus élevée.
Puis confirmez avec journalctl -k et les logs SMART/NVMe.

5) Les erreurs de checksum signifient-elles toujours que le disque est en train de mourir ?

Souvent c’est le chemin : câble, backplane, HBA, firmware. Les erreurs CRC SMART et les réinitialisations de transport noyau sont vos indicateurs.
Les erreurs média (pending/reallocated/uncorrectable) impliquent le disque plus directement.

6) Pourquoi le pool ralentit-il pendant un scrub si les scrubs sont « en arrière-plan » ?

Les scrubs sont background dans l’intention, pas dans la physique. Ils consomment de l’I/O réelle et peuvent augmenter la latence.
Si les scrubs gênent les utilisateurs, planifiez-les mieux, bridez-les si possible, et vérifiez que votre pool a suffisamment de marge de performance.

7) Dois-je régler sync=disabled pour résoudre la latence ?

Ce n’est pas une réparation ; c’est une négociation avec la réalité en espérant qu’elle ne remarque pas. Vous échangez des garanties de durabilité contre de la vitesse.
Si les données comptent, corrigez le chemin sync (latence SLOG/périphérique) à la place.

8) Une forte fragmentation est-elle toujours la cause des ralentissements ?

Non. La fragmentation est courante, mais le premier coupable habituel est la latence périphérique ou un pool dégradé/en reconstruction.
La fragmentation se manifeste plutôt comme une tendance à long terme : scrubs/resilvers plus longs, I/O aléatoire plus coûteux, et latence plus facile à déclencher.

9) Quand dois-je effacer les erreurs ZFS avec zpool clear ?

Après avoir corrigé la cause sous-jacente et capturé les preuves. Effacer trop tôt efface votre piste et invite les incidents répétés.

10) Si ZFS est lent mais que iostat montre un %util faible ?

Alors le goulet peut être ailleurs : CPU (compression/chiffrement), pression mémoire, throttling, ou un blocage du chemin sync.
Confirmez aussi que vous mesurez les bons dispositifs (multipath, couches dm-crypt, HBA).

Conclusion : prochaines étapes pratiques

Les pannes de performance ZFS sont généralement des défaillances matérielles en mode ralenti, des surprises du chemin d’écriture sync, ou de la contention due à des resilvers/scrubs que personne n’a traités comme un événement de production.
La bonne nouvelle : vous pouvez les voir venir — si vous regardez aux bons endroits et conservez une baseline.

Faites ceci ensuite :

  1. Baseliner zpool iostat -v -l et iostat -x pendant des heures saines, puis conservez ces chiffres quelque part que votre futur vous pourra trouver.
  2. Alerter sur les erreurs de transport noyau (réinitialisations, timeouts) en plus des changements d’état du pool ZFS.
  3. Auditer les datasets pour les réglages sync et identifier quelles charges sont vraiment sync-heavy.
  4. Décider si votre SLOG (le cas échéant) est réellement adapté : faible latence, sûr en cas de coupure de courant, et idéalement en miroir pour les environnements critiques.
  5. Maintenir les scrubs planifiés et surveillés. Pas parce que c’est amusant, mais parce que c’est ainsi que l’on attrape tôt la « corruption silencieuse et le matériel faible ».

Votre objectif n’est pas de créer le système ZFS parfait. C’est de rendre les ralentissements prévisibles, diagnostiquables et réparables — avant qu’ils ne deviennent des incidents qui nécessitent une réunion.

← Précédent
Docker : secrets sans fuites — arrêtez de mettre des mots de passe dans .env
Suivant →
WireGuard : configuration client la plus simple sur Windows/macOS/Linux (et les pièges habituels)

Laisser un commentaire