Priorité de resilver ZFS : reconstruire rapidement sans écraser les E/S de production

Cet article vous a aidé ?

Rien ne met autant votre conception de stockage à l’épreuve que le moment où un disque tombe en panne à 14h un mardi et que votre pool commence à resilver alors que l’activité bat son plein. Vous voulez que la reconstruction se termine rapidement — parce que le risque augmente à chaque minute passée en état dégradé — mais vous ne voulez pas non plus que vos bases de données aient l’air de fonctionner sur une disquette.

La « priorité » du resilver dans ZFS est en réalité un ensemble de réglages : ordonnancement, simultanéité, profondeur de file d’attente et agressivité avec laquelle ZFS parcourt les zones modifiées et les métadonnées. Bien réglé, le resilver est un feu contrôlé. Mal réglé, vous vous créez votre propre incident, poliment, de l’intérieur.

Ce que signifie réellement la priorité de resilver (et ce qu’elle n’est pas)

En termes ZFS, un resilver est le processus de reconstruction de la redondance après le remplacement ou la reconnexion d’un périphérique, ou après qu’un périphérique ait temporairement disparu puis réapparu. C’est lié à un scrub, mais ce n’est pas la même tâche.

Les gens disent « augmenter la priorité du resilver » comme s’il existait un unique curseur appelé Rendre plus rapide. Ce n’est pas le cas. La vitesse du resilver et son impact sur la production dépendent de :

  • Ce que ZFS choisit de copier : un resilver est typiquement incrémental, guidé par les métadonnées ZFS sur ce qui doit être reconstruit, pas une copie aveugle intégrale du disque (même si certaines topologies et conditions peuvent le rendre plus proche d’une copie complète).
  • Combien d’E/S de reconstruction concurrentes ZFS émet : trop peu et vous sous-utilisez les disques ; trop et vous surchargez les files et tuez la latence.
  • Où se situe réellement le goulot d’étranglement : souvent ce n’est pas la « vitesse du disque » mais l’amplification des E/S aléatoires, la contention sur les métadonnées, la fragmentation, ou un vdev unique saturé.
  • Ordonnanceur IO et comportement des files dans l’OS : le comportement diffère entre Linux et FreeBSD ; les ordonnanceurs modernes, NVMe et couches de virtualisation changent la donne.
  • Travail concurrent : scrubs, écritures lourdes, charges synchrones et lectures aléatoires petites se disputent les mêmes plateaux.

La priorité, en pratique, signifie décider qui a le droit d’être gênant : le resilver ou vos clients. On trouve généralement un compromis où le resilver reste assez agressif pour réduire le risque, tandis que la production garde sa latence p99 en dessous du seuil « on appelle le PDG ».

Une citation à garder sur son écran

Idée paraphrasée (Werner Vogels, ingénierie axée sur la fiabilité) : « Tout échoue, tout le temps — concevez et exploitez en supposant que cela arrivera. »

Faits et historique qui expliquent le comportement actuel

Le comportement du resilver n’est pas arbitraire ; il résulte de choix de conception et de quelques cicatrices accumulées sur plusieurs décennies. Voici des faits courts et concrets qui vous aident à raisonner sur ce que vous observez.

  1. ZFS a été conçu autour de checksums de bout en bout et du copy-on-write, ce qui signifie que « reconstruire » n’est pas un clonage naïf de secteurs ; c’est une reconstruction basée sur ce que le pool considère comme vivant et valide.
  2. Les reconstructions RAID traditionnelles lisaient historiquement tout le disque, ce qui explique pourquoi les administrateurs plus anciens supposent encore qu’un resilver doit lire chaque secteur. ZFS peut souvent en faire moins.
  3. Le scrub prédate beaucoup de disques modernes haute-capacité et peu coûteux ; les taux d’URE et les disques multi-TB modernes ont transformé « dégradé pendant un jour » en « dégradé pendant une semaine » si vous ne faites pas de réglages.
  4. Les RAIDZ larges sont devenus populaires en partie pour économiser des baies ; le compromis est des temps de reconstruction plus longs et plus de pression d’E/S pendant le resilver, surtout sous charges d’écritures aléatoires.
  5. Des améliorations comme le « resilver séquentiel » (implémentation variable selon plateforme/version) visent à réduire les tempêtes de seeks en émettant les E/S dans un ordre plus favorable aux disques.
  6. ZFS doit reconstruire correctement les métadonnées, pas seulement les blocs. Les pools riches en métadonnées (petits fichiers, snapshots, nombreux datasets) peuvent resilver selon un schéma qui paraît « aléatoire et lent » même sur des disques rapides.
  7. Les dispositifs spéciaux (métadonnées/petits blocs) peuvent rendre un pool bruyant quand il est sain — et bruyant d’une autre manière quand il est dégradé, car les lectures critiques se concentrent.
  8. La compression et le choix de recordsize changent la forme des E/S de resilver. Les gros records et les données compressées peuvent réduire les lectures physiques ; les petits records peuvent faire paraître le resilver comme un million de petites coupures.

Blague #1 : Un resilver, c’est comme un ascenseur : si vous le regardez, il va plus lentement. Si vous le mettez en graphique, il va encore plus lentement.

Modèle de risque : pourquoi « le plus rapide possible » n’est pas toujours le plus sûr

La vitesse du resilver est un réglage de contrôle du risque. Votre pool est dégradé ; une autre défaillance peut entraîner une perte de données (ou au moins une récupération forcée). Donc oui, finir rapidement compte. Mais « finir rapidement » ne signifie pas « saturer tout jusqu’à l’effondrement de la production ».

Voici le triangle de risque que vous jonglez :

  • Temps en risque : combien de temps vous restez avec la redondance réduite.
  • Impact client : latence et budget d’erreurs pendant la reconstruction.
  • Stress matériel : les reconstructions agressives peuvent maintenir les disques à plein régime pendant des jours, augmentant la probabilité de panne — surtout sur des spinners plus âgés.

La posture correcte dans la plupart des environnements de production est : agressif mais borné. Vous voulez que le resilver progresse même sous charge, tout en empêchant que l’attente d’E/S et la latence ne tombent dans une spirale infernale.

Un modèle mental utile : un resilver est un job batch en arrière-plan avec une date limite de sécurité. Traitez-le comme un job batch que vous pouvez prioriser temporairement — mais pas au prix de rendre le système inutilisable.

Feuille de route pour un diagnostic rapide

Si votre resilver est lent ou si vos applications souffrent, ne commencez pas par tripoter des réglages. Commencez par trouver le goulot. C’est le chemin le plus court pour faire les bonnes actions.

First: confirm what job you’re running and where the pool stands

  • Est-ce réellement un resilver, un scrub, ou les deux ?
  • Le pool est-il dégradé à cause d’un disque manquant, faulté ou d’un remplacement en cours ?
  • Le nouveau disque est-il plus lent (surprise SMR, pont USB, mauvais firmware) ?

Second: identify the limiting vdev and IO shape

  • Quel vdev réalise le plus de travail ?
  • Êtes-vous limité par des lectures aléatoires, des écritures aléatoires ou des écritures sync ?
  • Les métadonnées dominent-elles (IOPS élevées, débit faible) ?

Third: check queueing and latency, not just bandwidth

  • Quelle est la profondeur de file des disques et le temps d’attente (await) ?
  • Êtes-vous en train de saturer un chemin HBA unique ?
  • Le taux de hit de l’ARC chute-t-il, faisant tout passer au disque ?

Fourth: decide the trade you’re making

  • Avez-vous besoin du resilver le plus rapide possible (risque métier élevé, redondance pauvre), même si cela nuit ?
  • Ou devez-vous protéger la latence p99 (systèmes orientés client), en acceptant un resilver plus long ?

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

Voici les commandes que j’exécute réellement quand un pool est dégradé et que tout le monde se rappelle subitement que le stockage existe. Chaque tâche inclut : commande, sortie d’exemple, ce que cela signifie, et la décision que vous prenez.

Task 1: See whether you’re resilvering, scrubbing, or both

cr0x@server:~$ zpool status -v tank
  pool: tank
 state: DEGRADED
status: One or more devices is currently being resilvered.
action: Wait for the resilver to complete.
  scan: resilver in progress since Wed Dec 25 09:12:04 2025
        1.24T scanned at 1.10G/s, 412G issued at 365M/s, 3.80T total
        412G resilvered, 10.57% done, 0 days 02:31:18 to go
config:

        NAME                        STATE     READ WRITE CKSUM
        tank                        DEGRADED     0     0     0
          mirror-0                  DEGRADED     0     0     0
            ata-WDC_WD80...         ONLINE       0     0     0
            replacing-1             DEGRADED     0     0     0
              ata-WDC_WD80...       OFFLINE      0     0     0
              ata-ST8000...         ONLINE       0     0     0
errors: No known data errors

Signification : C’est un resilver, pas seulement un scrub. « Issued » est le travail réellement effectué ; « scanned » peut être plus élevé car ZFS peut parcourir les métadonnées plus vite qu’il ne peut reconstruire les blocs.

Décision : Si l’ETA est raisonnable et que la production est stable, ne touchez à rien. Si la latence grimpe ou que « issued » stagne, poursuivez le diagnostic.

Task 2: Check if a scrub is also running (and stop it if needed)

cr0x@server:~$ zpool status tank | sed -n '1,25p'
  pool: tank
 state: DEGRADED
  scan: resilver in progress since Wed Dec 25 09:12:04 2025
        1.24T scanned at 1.10G/s, 412G issued at 365M/s, 3.80T total

Signification : Seul le resilver est actif. Si vous voyez « scrub in progress » en même temps (possible dans certaines séquences opérationnelles), vous effectuez du travail en doublon.

Décision : Si un scrub concurrence pendant un incident, arrêtez le scrub et laissez le resilver se terminer en priorité.

cr0x@server:~$ sudo zpool scrub -s tank

Task 3: Show per-vdev IO to find the hot spot

cr0x@server:~$ zpool iostat -v tank 2 3
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        22.1T  13.5T  18.2K  6.4K   520M   140M
  mirror-0  7.40T  5.10T  12.1K  3.1K   340M    70M
    sda         -      -  6.1K   1.6K   170M    35M
    sdb         -      -  6.0K   1.5K   170M    35M
  mirror-1  7.40T  4.90T  3.9K   1.7K   110M    40M
    sdc         -      -  2.0K     850   55M    20M
    sdd         -      -  1.9K     840   55M    20M
  mirror-2  7.40T  3.50T  2.2K   1.6K    70M    30M
    sde         -      -  1.1K     820   35M    15M
    sdf         -      -  1.1K     810   35M    15M

Signification : mirror-0 réalise la plupart des lectures. C’est probablement le vdev en cours de resilver ou le vdev contenant le plus de blocs référencés.

Décision : Concentrez-vous sur le vdev chaud. Régler le mauvais vdev n’est que du cosmétique de performance.

Task 4: Confirm the replacement disk isn’t the slow one (or SMR)

cr0x@server:~$ lsblk -o NAME,MODEL,SIZE,ROTA,TRAN,SERIAL
NAME  MODEL            SIZE ROTA TRAN SERIAL
sda   WDC WD80...      7.3T    1 sata WD-AAA
sdb   WDC WD80...      7.3T    1 sata WD-BBB
sdc   WDC WD80...      7.3T    1 sata WD-CCC
sdd   WDC WD80...      7.3T    1 sata WD-DDD
sde   WDC WD80...      7.3T    1 sata WD-EEE
sdf   ST8000DM004      7.3T    1 sata ZDHFFF

Signification : Un disque est d’un modèle différent. Cela peut être acceptable — ou bien il peut s’agir d’un disque SMR qui transforme les reconstructions en mélasse sous écritures soutenues.

Décision : Si le remplacement est un modèle SMR dans une charge qui écrit pendant le resilver, arrêtez et remplacez-le par un CMR. Oui, même si les achats protestent.

Task 5: Check disk health quickly (SMART)

cr0x@server:~$ sudo smartctl -H /dev/sdf
smartctl 7.4 2023-08-01 r5530 [x86_64-linux-6.8.0] (local build)
SMART overall-health self-assessment test result: PASSED

Signification : « PASSED » n’est pas synonyme de « en bonne santé », c’est « pas manifestement mort ». Vous voulez quand même vérifier les compteurs d’erreurs.

Décision : Si SMART échoue ou si les attributs sont mauvais (secteurs réalloués/pending), ne faites pas confiance au disque pour terminer un resilver. Remplacez-le à nouveau.

Task 6: Watch OS-level latency and queue depth during resilver

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

avg-cpu:  %user %nice %system %iowait  %steal   %idle
           6.02  0.00    3.11   18.40    0.00   72.47

Device            r/s     w/s   rkB/s   wkB/s  rrqm/s  wrqm/s %util aqu-sz  await
sda            320.1   110.4 165000   42000     0.0     2.1  99.0  41.3  110.2
sdf            310.6   115.2 160000   45000     0.0     2.0  98.7  39.8  105.9

Signification : %util ~99, profondeur de file ~40, await ~100ms. Sur des spinners, c’est « nous les saturons et tout le reste attendra ».

Décision : Si la production souffre, vous devez réduire la concurrence d’E/S ou la lisser (régler le resilver, limiter le débit ou déplacer la charge). Sur SSD/NVMe, 100ms est un signal d’alarme.

Task 7: Check ARC pressure (a hidden source of “everything got slow”)

cr0x@server:~$ grep -E 'c_max|c_min|size|arc_meta_used|hits|misses' /proc/spl/kstat/zfs/arcstats | head
c_max                           4    25769803776
c_min                           4    6442450944
size                            4    24191070208
arc_meta_used                   4    4246732800
hits                            4    392004112
misses                          4    48122103

Signification : L’ARC est proche de c_max ; l’utilisation des métadonnées est élevée. Pendant un resilver, les parcours de métadonnées peuvent expulser le cache utile et augmenter les lectures disques pour la production.

Décision : Si l’ARC thrash (misses augmentant vite) et que vous avez de la RAM disponible, envisagez d’augmenter le max de l’ARC (avec prudence) ou de réduire d’autres pressions mémoire. Sinon, vous devez régler les E/S, pas la mémoire.

Task 8: Confirm your pool layout and ashift (resilver time is partly geometry)

cr0x@server:~$ zdb -C tank | grep -E 'vdev|ashift' -n | head -n 20
45:        vdev_tree:
46:            type: 'root'
47:            id: 0
58:                    type: 'mirror'
59:                    ashift: 12
78:                    type: 'mirror'
79:                    ashift: 12

Signification : ashift=12 (secteurs 4K). Si vous avez ashift=9 sur des disques 4K-natifs, vous paierez une taxe d’amplification d’écritures indéfiniment, et les resilvers seront pires.

Décision : Si ashift est incorrect, corrigez-le en reconstruisant le pool (oui, pénible). N’essayez pas de compenser un mauvais paramétrage de géométrie par des réglages.

Task 9: See if you’re bottlenecked on a single HBA or link

cr0x@server:~$ lsscsi -t
[0:0:0:0]    disk    ata:WDC_WD80...   /dev/sda  sata:0:0:0
[0:0:1:0]    disk    ata:WDC_WD80...   /dev/sdb  sata:0:0:1
[0:0:2:0]    disk    ata:WDC_WD80...   /dev/sdc  sata:0:0:2
[0:0:3:0]    disk    ata:WDC_WD80...   /dev/sdd  sata:0:0:3
[1:0:0:0]    disk    ata:WDC_WD80...   /dev/sde  sata:1:0:0
[1:0:1:0]    disk    ata:ST8000DM004   /dev/sdf  sata:1:0:1

Signification : Les disques sont répartis sur deux contrôleurs. Si tout est sur un seul HBA (ou un seul lien d’expander), vous pouvez le saturer pendant le resilver.

Décision : Si vous trouvez un goulot unique, réduisez la concurrence ou planifiez une correction matérielle. Le tuning ne créera pas une bande passante inexistante.

Task 10: Observe ZFS internal IO patterns via zpool iostat with latency (OpenZFS feature dependent)

cr0x@server:~$ zpool iostat -l -v tank 2 2
                           capacity     operations     bandwidth    total_wait     disk_wait
pool                     alloc   free   read  write   read  write   read  write   read  write
-----------------------  -----  -----  -----  -----  -----  -----  -----  -----  -----  -----
tank                     22.1T  13.5T  18.0K  6.5K   510M   145M   12ms   18ms    8ms   15ms
  mirror-0               7.40T  5.10T  12.0K  3.2K   335M    72M   14ms   21ms   10ms   18ms
    sda                      -      -  6.0K   1.6K   168M    36M    0ms    0ms    0ms    0ms
    sdb                      -      -  6.0K   1.6K   167M    36M    0ms    0ms    0ms    0ms

Signification : « total_wait » inclut le temps d’attente dans ZFS ; « disk_wait » est le temps au niveau du périphérique. Un total_wait élevé avec un disk_wait faible indique une contention côté ZFS ; un disk_wait élevé signifie que les périphériques sont la limite.

Décision : Si disk_wait domine, limitez la charge. Si total_wait domine, cherchez un problème CPU, une contention de verrous, ou des charges métadonnées pathologiques.

Task 11: Adjust resilver aggressiveness on Linux (module parameters)

Sur Linux OpenZFS, le comportement du resilver est influencé par des paramètres de module comme zfs_resilver_delay et des tranches de temps min/max de scan. La disponibilité exacte dépend de la version ; vérifiez d’abord, puis changez.

cr0x@server:~$ modinfo zfs | grep -E 'resilver|scan' | head -n 20
parm:           zfs_resilver_delay:How long to delay resilvering next extent (int)
parm:           zfs_scan_idle:Idle scan delay (int)
parm:           zfs_scan_min_time_ms:Minimum scan time per txg (ulong)
parm:           zfs_scan_max_time_ms:Maximum scan time per txg (ulong)

Signification : Les boutons existent sur ce système. Bien. Maintenant vous pouvez régler en connaissance de cause au lieu de copier-coller des sysctls d’un article écrit à l’ère jurassique des disques rotatifs.

Décision : Si la latence de production souffre, augmentez les délais ou réduisez le temps de scan. Si le resilver est trop lent et que vous avez de la marge IO, faites l’inverse.

cr0x@server:~$ cat /sys/module/zfs/parameters/zfs_resilver_delay
2

Signification : Le délai actuel est 2 (les unités sont définies par l’implémentation ; pensez « back off entre extents »). Des valeurs plus basses poussent plus fort.

Décision : En production diurne, gardez un délai non nul. Hors heures ou en urgence « finir maintenant », réduisez prudemment en surveillant la latence.

Task 12: Temporarily throttle ZFS scan work (Linux)

cr0x@server:~$ cat /sys/module/zfs/parameters/zfs_scan_max_time_ms
30000

Signification : ZFS peut consacrer jusqu’à 30 secondes au scan par cycle de transaction group. Une valeur plus élevée signifie un scan/resilver plus agressif ; une valeur plus basse cède plus souvent la place au travail normal.

Décision : Si la production est en timeout, baissez cette valeur par petites étapes et validez avec les métriques. Ne la changez pas brutalement de 30000 à 1000 puis ne vous étonnez pas que l’ETA du resilver affiche « à un moment donné le trimestre prochain ».

cr0x@server:~$ echo 10000 | sudo tee /sys/module/zfs/parameters/zfs_scan_max_time_ms
10000

Task 13: Set up a stable, low-noise watch of progress

cr0x@server:~$ watch -n 10 'zpool status tank | sed -n "1,20p"'
Every 10.0s: zpool status tank

  pool: tank
 state: DEGRADED
  scan: resilver in progress since Wed Dec 25 09:12:04 2025
        1.46T scanned at 1.05G/s, 501G issued at 360M/s, 3.80T total
        501G resilvered, 13.01% done, 0 days 02:12:03 to go

Signification : Vous suivez issued et l’ETA, pas seulement scanned. C’est ce chiffre qui tend à corréler avec « combien de temps jusqu’au rétablissement de la redondance ».

Décision : Si « scanned » avance mais que « issued » stagne, vous êtes probablement bloqué sur les E/S réelles de reconstruction ou sur une contention, pas sur le parcours du scan.

Task 14: Verify you’re not creating a self-inflicted sync storm

cr0x@server:~$ zfs get -o name,property,value -r sync tank | head
NAME           PROPERTY  VALUE
tank           sync      standard
tank/db        sync      standard
tank/vmstore   sync      always

Signification : Un dataset avec sync=always forcera plus d’écritures synchrones. Pendant un resilver, cela peut plomber les spinners.

Décision : Si sync=always est défini pour de bonnes raisons (bases de données sans barrières appropriées, conformité), ne « corrigez » pas en changeant sync. Au lieu de cela : assurez-vous que le SLOG est sain et rapide, ou déplacez la charge pendant le resilver.

Task 15: Check if a SLOG device is missing or slow (and making sync writes hurt)

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

        NAME                        STATE     READ WRITE CKSUM
        tank                        DEGRADED     0     0     0
          mirror-0                  DEGRADED     0     0     0
            sda                     ONLINE       0     0     0
            sdb                     ONLINE       0     0     0
          logs
            nvme0n1p2               ONLINE       0     0     0

Signification : Le SLOG est présent et online. S’il était manquant/faulted, les charges sync déverseraient sur le pool principal, concurrençant plus fortement le resilver.

Décision : Si le SLOG est dégradé, réparez-le en priorité pour les charges sync-heavy. Un resilver rapide est vain si votre journal de transactions est en sursis.

Stratégie de réglage : reconstruire vite sans écraser la latence

Soyons réalistes : la « meilleure » priorité de resilver dépend de ce que vous protégez. Pour une cible de sauvegarde, vous pouvez envoyer à fond. Pour un pool principal de bases de données, vous avez besoin de garde-fous.

Commencez par des leviers opérationnels, pas des réglages

Le réglage le plus propre est celui que vous ne faites pas via sysfs du tout.

  • Déplacez ou réduisez la charge : throttlez les jobs batch, mettez en pause le reindex, déplacez l’analytique hors de la machine, retardez les snapshot send/receive.
  • Arrêtez le travail de fond optionnel : scrubs, grosses suppressions de snapshots, réplications, grands zfs destroy.
  • Privilégiez les fenêtres d’achèvement du resilver : si possible, planifiez les remplacements pour la nuit. Ce n’est pas de la triche ; c’est de la maturité opérationnelle.

Comprenez ce que ZFS optimise pendant un resilver

ZFS doit maintenir la correction des données. Il essaie aussi de garder le pool utilisable. Certains choix par défaut sont conservateurs parce que le pire cas est horrible : le resilver peut générer d’énormes E/S aléatoires, surtout sur des pools fragmentés avec beaucoup de snapshots.

Deux conséquences pratiques :

  • Le débit n’est pas le seul indicateur. Vous pouvez afficher 800MB/s « scanned » tandis que la latence de production meurt parce que vous effectuez en réalité des lectures/écritures aléatoires petites et de l’enfilage.
  • Incrémental n’est pas toujours bon marché. Si un pool est très fragmenté ou a un fort turnover, la stratégie « ne copier que les blocs vivants » touche quand même beaucoup de régions dispersées.

Choisissez une politique : heures ouvrables vs mode urgence

Je recommande de définir deux modes et de les pratiquer :

  • Mode heures ouvrables : agressivité de resilver modérée, latence prévisible, ETA plus long.
  • Mode urgence : lorsque la redondance est critique (deuxième disque montrant des erreurs, RAIDZ sous pression, lot de disques connu défectueux), acceptez un impact plus élevé pour finir plus vite.

Blague #2 : Le réglage du resilver ressemble à la caféine — il y a une dose productive, puis il y a « j’entends les couleurs » et rien ne se fait.

Knobs Linux OpenZFS : ce qu’ils font en pratique

Les noms et la sémantique exacts varient selon la version d’OpenZFS, mais voici des thèmes communs :

  • Delais (comme zfs_resilver_delay) : introduisent une petite pause entre les chunks du resilver. Cela réduit souvent beaucoup la latence extrême sur les pools HDD car ça casse la monopolisation des files.
  • Tranches temporelles (comme zfs_scan_min_time_ms, zfs_scan_max_time_ms) : combien de temps par cycle ZFS consacre au scan/resilver. Des valeurs plus faibles cèdent plus souvent aux E/S normales.
  • Comportement d’idle scan (comme zfs_scan_idle) : tente de détecter l’inactivité et d’augmenter le scan quand le système est calme.

À éviter : pousser la concurrence tellement haut que les files disques sont toujours pleines. C’est ainsi que vous transformez un « resilver plus lent » en « resilver qui n’aboutit jamais parce que tout timeout et se réinitialise ».

Knobs FreeBSD et approche générale

Sur FreeBSD, vous utiliserez typiquement des contrôles via sysctl et vous vous reposerez sur le comportement d’ordonnancement IO du noyau. La philosophie est la même : façonnez le travail de scan/resilver pour qu’il cède aux IO de premier plan. Les détails diffèrent ; le workflow ne change pas : mesurer, changer une chose, observer la p99 et le taux d’issued du resilver.

Quand plus rapide est en réalité plus lent : le piège des tempêtes de seek

Sur les pools HDD, le resilver peut devenir un générateur d’E/S aléatoires. Si vous montez l’agressivité, vous augmentez les E/S en cours et le disque effectue plus de seeks, ce qui réduit le débit effectif. Vous verrez le taux d’issued plafonner tandis que l’await grimpe. C’est le signe que vous avez atteint le mur des seeks.

Sur pools SSD/NVMe, le piège est différent : vous pouvez saturer les files du contrôleur et voler le budget d’E/S des lectures sensibles à la latence. Ici, un throttling modéré peut préserver la p99 avec un impact limité sur le temps de reconstruction.

Scrub vs resilver : arbitrage et ordonnancement

Un scrub lit les données et vérifie les checksums ; un resilver reconstruit la redondance. Les deux appartiennent à la classe « scan » dans ZFS. Les lancer ensemble, c’est demander aux mêmes disques d’exécuter deux gros jobs en arrière-plan tout en servant la production. Ce n’est pas de la bravoure. C’est des heures sup non rémunérées pour votre sous-système IO.

Règles que je suis

  • Ne lancez jamais un scrub pendant un resilver actif sauf raison très spécifique (par ex. enquêter sur une corruption silencieuse sur un pool avec hardware connu défectueux) et en acceptant l’impact perf.
  • Après un resilver, envisagez un scrub si votre politique opérationnelle l’exige, mais planifiez-le quand la charge est plus faible.
  • Ne laissez pas l’automatisation empiler les jobs : si vous avez des scrubs hebdomadaires, assurez-vous qu’ils se mettent en pause quand le pool est dégradé ou en résilver.

Pourquoi ZFS peut paraître « occupé » même si le débit est faible

Scrub/resilver peut être lié aux métadonnées : beaucoup de petites E/S, vérification des checksums et gestion. Sur un pool fragmenté, cela peut être un job IOPS-intensive avec des MB/s peu impressionnants. C’est normal. Ce qui n’est pas normal, c’est de laisser cela priver vos lectures de premier plan.

Trois mini-récits d’entreprise tirés du terrain

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

L’entreprise avait une flotte mixte : certains nœuds de stockage étaient en mirror vdev sur SSD, d’autres en RAIDZ2 sur HDD. Les opérations les traitaient comme « le même ZFS ». Le tableau de bord montrait même un panneau unique « taux de resilver » pour tous les nœuds. C’était propre. C’était aussi trompeur.

Un après-midi, un disque d’un vdev RAIDZ2 HDD a lâché. L’ingénieur on-call l’a remplacé et a décidé d’« accélérer » en appliquant les mêmes paramètres de resilver qui fonctionnaient bien sur les nœuds SSD. Les profondeurs de file ont monté, mais le débit « scanned » avait l’air fantastique, donc tout le monde s’est détendu.

En une heure, l’API exposée aux clients a commencé à timeouter de façon intermittente. La base de données n’était pas tombée ; elle était juste assez lente pour déclencher des timeouts en amont. La cause racine n’était pas un manque de bande passante. C’était une tempête de seeks. Les HDD étaient bloqués à une utilisation quasi-constante, avec des await élevés. Les lectures de premier plan étaient mises en queue derrière des E/S de reconstruction et des écritures synchrones petites.

L’hypothèse erronée était subtile : « Si le SSD supporte plus de concurrence, le HDD aussi. » Le HDD non. Le HDD aime la séquentialité, de l’air pour respirer et ne pas être forcé de faire 40 choses à la fois.

La correction était ennuyeuse : revenir à des limites de scan conservatrices, arrêter le scrub programmé, et déplacer temporairement un job batch vers un autre cluster. Le resilver a pris plus de temps qu’en « mode rapide », mais l’incident s’est terminé parce que la latence p99 est redevenue acceptable.

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

Une autre organisation avait l’habitude : dès qu’un pool était dégradé, ils « aidaient » immédiatement en mettant en pause le traitement normal et en laissant le resilver tourner à fond. La logique : minimiser le temps à risque. Sur le papier, c’est sensé.

Puis ils sont devenus plus malins. Ils ont construit une automatisation pour détecter un pool dégradé, augmenter l’agressivité du resilver, et déclencher en parallèle un nettoyage massif de datasets (« libérer de l’espace pour faciliter ZFS »). Ce nettoyage impliquait de lourdes suppressions de snapshots — beaucoup de travail métadonnées et de frees — pendant que le resilver parcourait les mêmes structures métadonnées.

Le résultat a été une tempête parfaite : le pool a passé beaucoup de temps CPU dans la gestion des métadonnées, tandis que les disques étaient martelés d’E/S aléatoires. Le taux d’issued du resilver a en fait chuté, même si le système « semblait occupé ». L’automatisation a maintenu l’état des choses pendant des heures parce qu’elle ne s’arrêtait que lorsque le resilver était terminé.

Ils n’ont pas causé de perte de données, mais ils ont provoqué une douleur client évitable et allongé la fenêtre dégradée. L’optimisation a échoué parce qu’elle a combiné deux opérations lourdes en I/O et métadonnées pendant la période où le pool était le moins à même de le supporter.

La correction a été une politique : pendant un resilver, ne lancez pas de suppressions massives de snapshots, de grands zfs destroy ou d’opérations de rééquilibrage lourdes. Si vous devez libérer de l’espace, faites-le avant d’être dégradé, pas pendant.

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

Une équipe de services financiers utilisait ZFS pour le stockage VM. Leur SLO de performance était simple : garder la latence de stockage dans une bande étroite pendant les heures de trading. Ils avaient aussi une règle de fiabilité : ne jamais laisser un pool rester dégradé plus longtemps que nécessaire. Ces objectifs entrent en conflit. Ils l’ont donc formalisé en playbook opérationnel.

Quand un disque est tombé, l’on-call a fait trois choses machinalement. D’abord : confirmer s’il s’agissait d’un problème de chemin transitoire ou d’une véritable défaillance disque. Ensuite : lancer le remplacement et le resilver immédiatement. Troisième : basculer le pool en réglage « mode heures ouvrables » et geler le travail batch non essentiel.

Ils avaient aussi une procédure : si la p99 dépasse un seuil pendant plus de 10 minutes, réduire le scan max time par étapes et réévaluer. C’est tout. Pas d’héroïsme. Pas d’archéologie sysctl à 2h du matin.

Le resilver a pris plus de temps qu’en mode pleine puissance, mais les systèmes de trading sont restés stables. Après les heures, ils sont passés en « mode urgence » et ont laissé le resilver finir plus agressivement pendant la nuit.

La pratique ennuyeuse consistait en procédures documentées, des bascules répétées et la discipline de ne pas changer cinq choses à la fois. Cela les a empêchés de transformer une panne matérielle en manquement SLA.

Erreurs courantes : symptômes → cause racine → correction

Ce ne sont pas des théories. Ce sont les façons dont les gens déclenchent involontairement des incendies dans leur stockage puis blâment l’incendie pour avoir été chaud.

1) Symptom: “Resilver is stuck at 0% issued but scanned keeps moving”

  • Cause racine : le parcours des métadonnées continue, mais les E/S de reconstruction réelles sont bloquées par des erreurs de périphérique, un disque de remplacement lent ou une contention extrême.
  • Correction : vérifiez zpool status -v pour des erreurs ; vérifiez la santé et le lien du périphérique de remplacement ; regardez iostat -x await ; réduisez l’agressivité du scan et arrêtez les jobs concurrents.

2) Symptom: “Apps are timing out; disks show 99% util; resilver ‘speed’ looks high”

  • Cause racine : monopolisation de la file/seek storm ; la métrique de scan est trompeuse ; les E/S de premier plan attendent derrière les E/S de reconstruction.
  • Correction : augmentez le délai de resilver / réduisez le scan max time ; arrêtez le scrub ; réduisez les écritures batch ; surveillez la p99, pas les MB/s.

3) Symptom: “Replacement disk keeps faulting during resilver”

  • Cause racine : disque défectueux, câble/backplane marginal, ou problèmes d’alimentation ; le resilver est le premier stress soutenu qu’il subit.
  • Correction : remplacez à nouveau le disque, changez de slot/câble, consultez les logs SMART, et vérifiez les logs du contrôleur. N’essayez pas plusieurs fois avec le même chemin instable.

4) Symptom: “Resilver is painfully slow on a nearly full pool”

  • Cause racine : forte fragmentation et stress de l’allocateur ; ZFS a moins de liberté pour placer les blocs reconstruits efficacement ; la surcharge de métadonnées augmente.
  • Correction : gardez les pools sous une utilisation raisonnable (règle pratique : évitez de vivre au-dessus d’environ 80% pour de nombreuses charges) ; ajoutez des vdevs avant d’être désespéré ; ne lancez pas de frees massifs pendant le resilver.

5) Symptom: “Resilver speed varies wildly hour to hour”

  • Cause racine : modèles de charge concurrents (fenêtre de sauvegarde, compaction, envoi de snapshots, checkpoints base de données) et ramping de la détection d’inactivité ZFS.
  • Correction : corrélez avec le calendrier des charges ; fixez l’agressivité du scan sur des paramètres prévisibles pendant les heures ouvrables ; augmentez éventuellement l’agressivité pendant des fenêtres calmes connues.

6) Symptom: “Resilver got slower after we added a special device”

  • Cause racine : le device spécial concentre métadonnées/petits blocs ; s’il est plus lent, surutilisé ou dégradé, il devient le goulot.
  • Correction : assurez-vous que les devices spéciaux sont redondants et rapides ; surveillez leur latence séparément ; évitez de les laisser se remplir ; traitez-les comme du stockage de première classe, pas comme un « SSD bonus ».

7) Symptom: “We tuned for fast resilver, but the resilver took longer”

  • Cause racine : la concurrence excessive provoque du thrash ; pénalité de seek HDD ; augmentations des retries ; contention de l’ordonnanceur IO.
  • Correction : réduisez l’agressivité jusqu’à ce que le taux d’issued augmente et que l’await baisse ; mesurez, ne devinez pas.

Listes de contrôle / plan étape par étape

Plan étape par étape : quand un disque tombe en panne en production

  1. Confirmez le mode de défaillance. Est-ce une vraie panne disque, ou un hic de chemin/contrôleur ? Vérifiez zpool status -v et les logs OS.
  2. Remplacez le disque et lancez le resilver. N’attendez pas une réunion pour approuver la physique.
  3. Arrêtez les tâches d’arrière-plan concurrentes. Mettez en pause scrubs, réplication lourde, suppressions de snapshots et maintenance en masse.
  4. Mesurez l’impact sur la production. Utilisez la latence applicative et l’await disque ; ne vous fiez pas seulement aux MB/s du resilver.
  5. Choisissez un mode : réglage heures ouvrables vs mode urgence, selon le risque de redondance et les SLO clients.
  6. Changez un seul réglage à la fois. Modifiez scan max time ou zfs_resilver_delay par petites étapes ; observez 10–15 minutes.
  7. Vérifiez le progrès. Les bytes issued et resilvered doivent avancer ; les compteurs d’erreurs doivent rester discrets.
  8. Quand terminé, validez la santé. Le pool doit être ONLINE, sans nouvelles erreurs ; planifiez un scrub si la politique l’exige.

Checklist : mode heures ouvrables (protéger la latence)

  • Scrub arrêté ou différé
  • Jobs batch mis en pause ou limités
  • Resilver delay non nul
  • Scan max time réduit modérément
  • Surveiller p95/p99, await disque et taux d’issued

Checklist : mode urgence (finir vite)

  • Confirmer que le risque de redondance le justifie (multiples avertissements, RAIDZ sous pression, lot défectueux)
  • Augmenter scan max time et réduire les délais
  • Optionnel : mettre brièvement en pause services non critiques pour accélérer la fin
  • Assurer un refroidissement adéquat ; surveiller températures et erreurs contrôleur

FAQ

1) Is a ZFS resilver always incremental?

Souvent, oui : ZFS peut reconstruire seulement les blocs pertinents d’après les métadonnées. Mais la topologie du pool, la fragmentation et la façon dont le périphérique a été retiré peuvent le faire fonctionner plus proche d’une opération plein-disque en pratique.

2) Why does “scanned” move faster than “issued” during resilver?

Le scan est un parcours de métadonnées ; issuing est l’E/S réelle de reconstruction. Si issuing est en retard, vous êtes limité par les E/S disques, la contention ou des problèmes de périphérique.

3) Should I pause production workload to speed up resilver?

Pour un système exposé aux clients, privilégiez d’abord le lissage du resilver. Mettre la production en pause peut aider, mais c’est une mesure brutale. Utilisez-la quand le risque de redondance est élevé ou que vous pouvez drainer le trafic en toute sécurité.

4) Is it safe to tune zfs_scan_max_time_ms and zfs_resilver_delay live?

Typiquement oui sur Linux via les paramètres de module sysfs, mais traitez cela comme un changement contrôlé : incréments petits, mesure d’impact, et enregistrement des modifications pour pouvoir revenir en arrière.

5) Why did resilver get slower when the pool is >80% full?

La flexibilité de l’allocateur diminue et la fragmentation tend à augmenter, ce qui accroît les E/S aléatoires et la surcharge métadonnées. Ce n’est pas une faute morale ; c’est de la géométrie et de l’entropie.

6) Do mirrors resilver faster than RAIDZ?

Habituellement. Les mirrors ont une reconstruction plus simple et souvent de meilleures caractéristiques de parallélisme. Le resilver RAIDZ peut impliquer plus de calcul de parité et plus d’amplification d’E/S, selon la charge et la fragmentation.

7) Should I run a scrub right after resilver completes?

Si votre politique opérationnelle exige des scrubs périodiques, planifiez-le — simplement pas immédiatement si le système est encore chaud et que la charge de production est élevée. Donnez un peu de repos au pool.

8) What’s the single best metric to watch?

Pour le risque : le temps restant jusqu’au rétablissement de la redondance (progrès issued/resilvered). Pour l’impact client : la latence p99 et l’await/ profondeur de file disque.

9) Can I make resilver fast by adding L2ARC?

Pas de manière fiable. L2ARC aide le cache de lecture mais peut ajouter du trafic d’écriture et de la surcharge métadonnées. Pendant un resilver, votre goulot est généralement les E/S disque et la reconstruction, pas « plus de cache ».

10) Does a SLOG make resilver faster?

Indirectement. Un bon SLOG peut protéger la latence des écritures synchrones afin que la production souffre moins, ce qui vous permet de garder un resilver plus agressif sans casser les apps. Il n’accélère pas magiquement la reconstruction elle-même.

Conclusion : prochaines étapes à réaliser cette semaine

La priorité de resilver n’est pas un réglage magique ; c’est de l’exploitation sous limite de vitesse. L’objectif est simple : restaurer la redondance assez vite pour réduire le risque, tout en gardant les E/S de production prévisibles pour éviter de créer un incident secondaire.

Prochaines étapes qui rapportent immédiatement :

  1. Formulez deux modes (heures ouvrables vs urgence) avec vos réglages de scan/resilver choisis et quand les utiliser.
  2. Ajoutez du monitoring qui trace le progrès issued/resilvered aux côtés de la p99 et de l’await disque.
  3. Auditez votre flotte pour les surprises SMR, les pools presque pleins et les programmes de scrub qui ignorent les états dégradés.
  4. Exercez-vous une fois sur un pool non critique : remplacez un disque, observez le comportement, ajustez un seul paramètre et notez les résultats.
← Précédent
Docker « too many open files » : augmenter correctement les limites (systemd + conteneur)
Suivant →
Le transfert d’e-mails casse DMARC — Corrigez-le avec SRS (et autres options)

Laisser un commentaire