Vous ne remarquez pas les internals de ZFS quand tout va bien. Vous les remarquez à 02:17, quand la latence monte en flèche,
les réplicas commencent à expirer, et quelqu’un demande si « ajouter du cache » va régler le problème. (Ça ne le fera pas. Pas comme ça.)
Voici le glossaire que vous auriez aimé avoir avant d’avoir fait en sorte que ce pool « marche », de l’avoir mis en production,
et de découvrir que votre modèle mental était surtout des impressions. Nous allons définir les grands noms — VDEV, TXG, ARC, SPA — puis les utiliser
pour prendre des décisions, diagnostiquer des goulets d’étranglement et éviter les pannes classiques auto-infligées.
Faits intéressants et histoire (les points qui comptent vraiment)
- ZFS a commencé chez Sun au début des années 2000 comme réponse au bazar « système de fichiers + gestionnaire de volumes + outil RAID ». Hypothèse de conception : les piles de stockage doivent former un système cohérent.
- Le copy-on-write n’était pas inédit, mais ZFS l’a rendu opérationnellement courant : chaque modification écrit de nouveaux blocs, puis bascule des pointeurs de façon atomique. C’est pourquoi il peut faire des snapshots cohérents sans geler le système.
- Le nom “Zettabyte” était aspirational à une époque où des pools multi-téra semblaient énormes. Aujourd’hui, le nom ressemble moins à du marketing et plus à un avertissement.
- OpenZFS est une continuation pilotée par la communauté après l’ère d’acquisitions de Sun. Des fonctionnalités comme les special vdevs et L2ARC persistant ont évolué en grande partie en open source, poussées par la douleur des opérateurs réels.
- Le checksum de tout n’était pas un défaut courant dans les systèmes de fichiers grand public à l’époque. ZFS a fait de la « corruption silencieuse = défaut de stockage, pas problème applicatif » une posture opérationnelle.
- ARC est devenu un modèle : un cache adaptatif géré par le système de fichiers qui connaît les blocs, la compression et les métadonnées. Ce n’est pas seulement « la RAM est un cache disque ». C’est un moteur de politique avec des opinions.
- Les TXG sont le compromis entre « tout synchroniser » et « tamponner pour toujours ». Le modèle de transaction group explique pourquoi ZFS peut être rapide et cohérent — jusqu’à ce que votre charge de travail le transforme en embouteillage.
- RAID-Z n’est pas du RAID matériel. La parité est calculée par ZFS, avec conscience des tailles de blocs et des checksums. C’est mieux à bien des égards, mais la mathématique de la parité n’est pas gratuite.
- Le réglage par défaut “recordsize 1M” n’était pas choisi pour les bases de données. C’est un réglage favorisant le débit pour les IO séquentiels importants. Si vous faites des écritures aléatoires 8K et ne changez jamais ce paramètre, vous n’avez pas de malchance — vous êtes mal configuré.
Glossaire central : VDEV, TXG, ARC, SPA (avec les vraies implications)
VDEV (Virtual Device) : l’unité de performance et de défaillance
Un VDEV est l’élément de base de ZFS pour le stockage d’un pool. Les gens disent familièrement « mon pool a 12 disques »,
mais ZFS entend : « mon pool a ces vdevs ». Et ce sont les vdevs qui déterminent :
la IOPS, la latence, et souvent votre rayon d’explosion.
Un vdev peut être un disque unique (ne le faites pas), un miroir, RAID-Z, un fichier (vraiment ne le faites pas), un special vdev pour les métadonnées,
un log vdev (SLOG), ou un périphérique cache (L2ARC).
Règle opérationnelle : les vdevs ajoutent de la performance ; les disques à l’intérieur d’un vdev ajoutent de la redondance (et parfois de la bande passante).
Dans un pool composé de plusieurs vdevs, ZFS stripe les allocations à travers les vdevs. Plus de vdevs signifie généralement plus de parallélisme.
Mais à l’intérieur d’un vdev RAID-Z, les petites écritures aléatoires paient toujours un coût de parité et ont tendance à se sérialiser plus que vous ne le souhaiteriez.
Les mirror vdevs sont la solution de base pour les charges sensibles à la latence. Les vdevs RAID-Z sont destinés à la capacité et au débit séquentiel.
Si vous avez des charges mixtes, choisissez délibérément plutôt que de laisser les achats décider pour vous.
TXG (Transaction Group) : comment ZFS transforme le chaos en commit atomique
Un TXG est un lot de changements en mémoire que ZFS finit par écrire sur le stockage stable. Pensez-y comme
« l’ensemble des blocs sales que nous allons écrire ensemble, puis déclarer durables ».
ZFS fait tourner les TXG à travers des états : open (accepte les changements), quiescing (arrêt des nouveaux changements),
et syncing (écriture sur disque). Les basculements sont périodiques et basés sur la pression.
Si votre pool est sain, c’est invisible. Si votre pool est surchargé, vous le verrez comme :
des pics de latence d’écriture, des sync storms, et des applications bloquées en fsync().
Le comportement des TXG explique pourquoi vous pouvez avoir un haut débit mais de terribles latences de queue. Le pool peut être « occupé à synchroniser »
et votre charge est forcée d’attendre. Votre monitoring doit séparer « nous écrivons » de « nous sommes bloqués en attente de fin d’écriture ».
ARC (Adaptive Replacement Cache) : la RAM comme politique, pas seulement comme cache
L’ARC est le cache en mémoire de ZFS pour les blocs fréquemment et récemment utilisés — données et métadonnées.
Ce n’est pas un simple LRU. Il est adaptatif : il tente d’équilibrer les accès « récents » et « fréquents ».
L’ARC est aussi un acteur politique dans votre système. Il entre en compétition avec les applications pour la mémoire. Si vous le laissez faire,
il mangera volontiers la RAM jusqu’à ce que le noyau l’arrête. Ce n’est pas un bug ; c’est le marché :
la mémoire inutilisée est une performance gaspillée. Mais en production, « inutilisée » est rarement vrai — votre base de données, JVM et cache de pages
ont aussi faim.
L’ARC a plusieurs populations importantes :
les listes MFU/MRU (fréquent/récent),
la métadonnée,
les buffers anonymes,
et les buffers sales en attente de sync TXG.
Quand on dit « le taux de hit ARC est bas », la question utile est : bas pour quelle classe, sous quelle charge ?
SPA (Storage Pool Allocator) : le cerveau du pool
Le SPA est le sous-système interne qui coordonne le pool : gestion des vdevs, allocations,
metaslabs, space maps, et la machine d’état de haut niveau qui fait d’un « pool » une chose cohérente.
Si ZFS était une entreprise, le SPA serait l’équipe opérations qui planifie réellement le travail.
Vous touchez rarement le SPA directement, mais vous voyez ses décisions partout : comment les blocs sont alloués across les vdevs,
comment l’espace libre est suivi, pourquoi la fragmentation arrive, et pourquoi certains pools vieillissent bien tandis que d’autres tournent mal.
Une citation à garder sur votre mur, parce que les pannes de stockage sont presque toujours des échecs de coordination :
« L’espoir n’est pas une stratégie. »
— General Gordon R. Sullivan (souvent cité en ingénierie et opérations)
Glossaire étendu que vous rencontrerez en production
Pool
Un pool est l’objet de stockage de plus haut niveau. Il agrège des vdevs. Vous ne pouvez pas le réduire en retirant
un vdev RAID-Z. Planifiez en conséquence. Votre futur vous ne sera pas impressionné par « on migrera plus tard ».
Dataset
Un dataset est un système de fichiers avec ses propres propriétés : compression, recordsize, quota, réservation,
comportement de sync, et plus. Les datasets sont la façon d’empêcher qu’une charge n’empoisonne une autre — si vous les utilisez réellement.
Zvol
Un zvol est un périphérique bloc pris en charge par ZFS. Utilisez-le pour iSCSI, disques VM, et choses qui demandent
une sémantique de bloc. Réglez volblocksize pour la charge de travail. Laissez-le incorrect, et vous découvrirez de nouvelles façons
excitantes de gaspiller des IOPS.
Recordsize et volblocksize
Le recordsize est la taille maximale de bloc pour les fichiers dans un dataset. Un recordsize large aide le débit séquentiel et la compression. Un recordsize petit aide les IO aléatoires et réduit l’amplification d’écriture sur de petites mises à jour.
Le volblocksize est la taille de bloc pour les zvols. Elle est fixe à la création.
Si vous stockez des pages de base de données 8K dans un zvol volblocksize 128K, vous demandez à ZFS de faire un travail supplémentaire.
Metaslab
Un metaslab est une région d’espace dans un vdev utilisée pour l’allocation. La fragmentation des metaslabs est une
histoire courante « mon pool est à 70% et tout est lent ». Le SPA et les classes de metaslab décident où vont les blocs ;
si vous êtes presque plein, ces décisions deviennent contraintes et coûteuses.
Scrub et resilver
Un scrub vérifie les checksums et répare à partir de la redondance. Un resilver reconstruit
la redondance après le remplacement d’un périphérique. Les deux entrent en concurrence avec votre charge pour l’IO. Limitez-les correctement,
mais ne les sautez pas. Le scrub est la façon de trouver des erreurs latentes avant qu’elles ne deviennent une perte de données.
SLOG et ZIL
Le ZIL est le journal d’intention dans le pool pour les écritures synchrones. Le SLOG est un périphérique de log optionnel
séparé pour accélérer ces écritures synchrones. Le SLOG n’accélère pas les écritures asynchrones. Il rend les écritures sync
moins pénibles en leur donnant une zone d’atterrissage à faible latence.
Le SLOG doit être fiable et sûr en cas de perte d’alimentation. Si vous mettez du flash « rapide mais fragile » comme SLOG, vous construisez
un mensonge dans votre modèle de durabilité. Et ZFS va operationaliser fidèlement ce mensonge.
L2ARC
Le L2ARC est un cache de second niveau sur des périphériques rapides (généralement SSD/NVMe). Il met en cache des lectures, pas des écritures.
Historiquement, il coûtait aussi de la mémoire pour l’indexation ; les implémentations modernes ont amélioré la persistance et le comportement, mais ce n’est toujours
pas gratuit. L2ARC ne remplace pas suffisamment de RAM ni un bon tuning des datasets.
Ashift
ashift est l’exposant de taille de secteur utilisé par ZFS pour un vdev. Le conseil canonique en production :
le définir correctement à la création du pool, parce que le changer plus tard équivaut pratiquement à « reconstruire le pool ».
Un ashift erroné est une fuite lente qui devient un déluge sous charge.
Blague #1 : Mettre ashift à la mauvaise valeur, c’est comme acheter des chaussures trop petites — techniquement vous pouvez marcher, mais vous vous détesterez dans les escaliers.
Compression
La compression économise de l’espace et améliore souvent les performances en transformant de l’IO en CPU, et l’IO est généralement le goulot d’étranglement.
Mais si votre CPU est déjà saturé, la compression peut devenir la goutte qui fait déborder le vase. Mesurez avant de déclarer victoire.
Copy-on-write et fragmentation
Le copy-on-write signifie que les blocs sont réécrits ailleurs, pas sobrescrits en place. C’est excellent pour la cohérence et les snapshots, mais cela peut fragmenter.
La fragmentation empire à mesure que le pool se remplit et que vous faites churn de données avec des snapshots.
« ZFS est lent quand il est plein » est un meme parce que c’est souvent vrai de façons spécifiques.
Un modèle mental utilisable : de l’appel système au spinning rust
Lectures : le chemin heureux (quand tout va bien)
Une lecture arrive. ZFS vérifie l’ARC. Si le bloc est dans l’ARC, vous avez fini rapidement. Sinon, ZFS planifie des lectures vers les vdevs,
récupère les blocs, vérifie les checksums, décompresse (si nécessaire), et éventuellement remplit l’ARC (et peut-être le L2ARC avec le temps).
La latence est déterminée par : le taux de hits du cache, la profondeur de file d’attente des vdevs, la latence des périphériques, et la dispersion des blocs.
Les mirrors peuvent servir les lectures des deux côtés, améliorant souvent le parallélisme. Les lectures RAID-Z peuvent être correctes, mais les petites lectures aléatoires
rivalisent avec la disposition de la parité et souvent une amplification IO plus élevée lors des réparations/scrubs.
Écritures : où TXG et ZIL décident de votre sort
Une écriture asynchrone va en mémoire (buffers sales dans l’ARC). Plus tard, le sync TXG l’écrit sur disque. Si le système plante avant
le sync TXG, ces écritures asynchrones sont perdues. C’est le contrat. Les applis qui s’en soucient appellent fsync() ou utilisent des écritures sync.
Une écriture synchrone doit être engagée d’une façon qui survive à un crash. ZFS utilise le ZIL : il logue rapidement l’intention, accuse réception,
puis plus tard le sync TXG écrit les blocs réels et libère les enregistrements du log. Si vous avez un SLOG, les écritures de log vont là.
Sinon, elles vont dans le pool principal, et votre vdev le plus lent devient votre latence sync.
Conclusion opérationnelle : la latence des écritures sync est souvent un problème « périphérique de log et latence du pool », pas un problème de bande passante brute.
Vous pouvez avoir 5 GB/s en écriture séquentielle et quand même 20 ms de latence fsync qui détruisent une base de données.
Gestion de l’espace : SPA, metaslabs, et pourquoi « 80% plein » n’est pas qu’un chiffre
Le SPA découpe chaque vdev en metaslabs et suit l’espace libre via des space maps. Quand les pools sont plus vides,
les allocations sont bon marché : choisir une grande région libre, écrire. À mesure que les pools se remplissent et se fragmentent, les allocations deviennent :
trouver assez de segments, gérer des extents libres dispersés, mettre à jour les métadonnées, et payer plus de seeks et de bookkeeping.
C’est pourquoi la planification de capacité est de la planification de performance. Si vous traitez « espace libre » comme une simple ligne budgétaire, ZFS finira
par encaisser ses intérêts en latence.
Tâches pratiques : commandes, sens des sorties et décisions
Ce ne sont pas des tours de passe-passe. Ce sont les commandes que vous exécutez quand quelqu’un dit « le stockage est lent », et que vous voulez
répondre avec des preuves plutôt qu’avec des impressions.
Tâche 1 : Identifier la santé du pool et les signaux d’alerte immédiats
cr0x@server:~$ zpool status -v
pool: tank
state: ONLINE
scan: scrub repaired 0B in 02:14:19 with 0 errors on Wed Dec 24 03:00:12 2025
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
/dev/disk/by-id/ata-A ONLINE 0 0 0
/dev/disk/by-id/ata-B ONLINE 0 0 0
errors: No known data errors
Ce que ça signifie : L’état et les compteurs d’erreurs vous indiquent si vous déboguez la performance ou si vous perdez activement de la redondance/intégrité des données. Les résultats de scrub comptent : des octets réparés signifient que vous avez eu de la corruption que la redondance a corrigée.
Décision : Si vous voyez DEGRADED, des augmentations des compteurs READ/WRITE/CKSUM, ou un resilver actif,
arrêtez les réglages et commencez à stabiliser. Le débogage de performance vient après avoir arrêté l’hémorragie.
Tâche 2 : Voir les tendances de débit et de latence au niveau vdev
cr0x@server:~$ zpool iostat -v tank 1 5
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 1.20T 2.40T 320 980 45.2M 110M
mirror-0 1.20T 2.40T 320 980 45.2M 110M
ata-A - - 160 490 22.6M 55.1M
ata-B - - 160 490 22.6M 55.0M
-------------------------- ----- ----- ----- ----- ----- -----
Ce que ça signifie : Vous voyez les opérations et la bande passante par vdev et par disque. Les mirrors répartissent les lectures entre les côtés ;
les écritures vont sur les deux. Si un disque montre une latence nettement plus élevée dans iostat -x (tâche suivante), il peut ralentir le mirror.
Décision : Si un vdev est saturé (ops élevées, faible bande passante, latence croissante), ajoutez des vdevs (plus de parallélisme)
ou changez les caractéristiques de la charge (recordsize, comportement sync). Si un seul disque se comporte mal, remplacez-le.
Tâche 3 : Confirmer la latence des périphériques et l’enqueue au niveau OS
cr0x@server:~$ iostat -x 1 3
Linux 6.8.0 (server) 12/26/2025 _x86_64_ (16 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
6.20 0.00 2.10 18.40 0.00 73.30
Device r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 95.0 280.0 12.3 34.8 352.1 7.80 25.6 8.2 31.4 1.1 41.0
sdb 92.0 275.0 12.1 34.6 353.0 8.10 27.4 8.5 33.2 1.1 43.5
Ce que ça signifie : await et avgqu-sz montrent la latence et la profondeur de file. Un %iowait élevé suggère que le CPU attend le stockage. Un %util élevé signifie que les périphériques sont occupés.
Décision : Si await est élevé et %util est saturé, vous êtes limité par le stockage.
Si %iowait est bas mais que les applis sont lentes, cherchez ailleurs (verrous, réseau, CPU).
Tâche 4 : Vérifier les propriétés du dataset qui changent directement le comportement IO
cr0x@server:~$ zfs get -o name,property,value -s local,received recordsize,compression,atime,sync,logbias tank/app
NAME PROPERTY VALUE
tank/app recordsize 128K
tank/app compression zstd
tank/app atime off
tank/app sync standard
tank/app logbias latency
Ce que ça signifie : Ce sont les réglages qui décident si ZFS fait des IO 128K, compresse, met à jour les atimes, et traite les écritures sync avec une préférence latence.
Décision : Pour les bases de données, envisagez un recordsize plus petit (souvent 16K ou 8K selon la taille de page DB),
gardez atime=off à moins d’en avoir vraiment besoin, et soyez prudent avec les modifications de sync. « sync=disabled » n’est pas un réglage ;
c’est négocier avec la physique en fraudant la comptabilité.
Tâche 5 : Inspecter le comportement de l’ARC (Linux)
cr0x@server:~$ awk 'NR==1 || /^(size|c |c_min|c_max|hits|misses|mfu_hits|mru_hits|prefetch_data_hits|prefetch_data_misses)/' /proc/spl/kstat/zfs/arcstats
13 1 0x01 204 33728 11970458852 6427389332172
size 4.20G
c 6.00G
c_min 1.00G
c_max 24.0G
hits 132948210
misses 21928411
mfu_hits 90128210
mru_hits 42820000
prefetch_data_hits 1428000
prefetch_data_misses 6180000
Ce que ça signifie : size est la taille actuelle de l’ARC, c est la cible, et les compteurs hit/miss
indiquent si les lectures sont favorables au cache. Les prefetch misses peuvent indiquer des charges qui rendent caduques les heuristiques séquentielles.
Décision : Si les misses dominent et que votre charge est lecture-intensive, vous pourriez avoir besoin de plus de RAM, d’une meilleure localité,
ou d’un layout différent (mirrors, special vdev pour métadonnées). Si l’ARC est énorme et que les applications swapent, limitez l’ARC.
Tâche 6 : Vérifier les données sales ZFS et la pression TXG (Linux)
cr0x@server:~$ awk '/(dirty data|max dirty data|dirty data sync)/{print}' /proc/spl/kstat/zfs/arcstats
dirty data 812345678
max dirty data 4294967296
dirty data sync 0
Ce que ça signifie : Les dirty data sont les écritures en attente. Si les dirty data approchent la valeur max et y restent,
le pool ne peut pas flusher assez vite. C’est là que le sync TXG commence à throttler les écrivains.
Décision : Si les dirty data sont chroniquement élevées, vous surchargez le pool. Réduisez le débit d’écriture,
améliorez la latence d’écriture des vdevs (plus de vdevs, périphériques plus rapides), ou ajustez la charge (écritures séquentielles plus grandes, compression).
Tâche 7 : Identifier la douleur des écritures sync et si un SLOG est présent
cr0x@server:~$ zpool status tank
pool: tank
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-A ONLINE 0 0 0
ata-B ONLINE 0 0 0
logs
nvme-SLOG ONLINE 0 0 0
Ce que ça signifie : Une section logs signifie que vous avez un périphérique de log séparé. Sans lui,
les écritures sync touchent les vdevs principaux et héritent de leur latence.
Décision : Si vous avez une charge sync-intense (bases de données, NFS en sync, stockage VM),
envisagez un SLOG sûr en cas de perte d’alimentation. Si vous en avez déjà un et que les sync restent lents, validez qu’il n’est pas le goulot.
Tâche 8 : Voir l’utilisation d’espace par dataset et la pression des snapshots
cr0x@server:~$ zfs list -o name,used,avail,refer,compressratio -r tank
NAME USED AVAIL REFER RATIO
tank 1.20T 2.40T 128K 1.45x
tank/app 620G 2.40T 410G 1.62x
tank/app@daily-1 80G - 390G 1.60x
tank/logs 110G 2.40T 110G 1.05x
Ce que ça signifie : Les snapshots consomment de l’espace via les blocs modifiés. Si used augmente mais refer reste stable,
les snapshots (ou clones) retiennent l’historique.
Décision : Si le pool se remplit et que la performance se dégrade, auditez la rétention des snapshots.
Conservez les snapshots nécessaires, supprimez ceux qui ne le sont pas, et arrêtez de prétendre que la « rétention infinie » est gratuite.
Tâche 9 : Vérifier la fragmentation du pool et la marge de capacité
cr0x@server:~$ zpool list -o name,size,alloc,free,frag,cap,dedup,health
NAME SIZE ALLOC FREE FRAG CAP DEDUP HEALTH
tank 3.60T 1.20T 2.40T 18% 33% 1.00x ONLINE
Ce que ça signifie : frag est heuristique, mais utile directionnellement. cap montre le remplissage.
Quand cap dépasse ~70–80% sur des pools chargés, les allocations deviennent plus difficiles et la latence suit généralement.
Décision : Si vous êtes au-dessus d’environ 80% et que la latence compte, planifiez l’expansion de capacité ou une migration maintenant.
« On attendra jusqu’à 95% » est la manière de finir à déboguer des metaslabs sous pression.
Tâche 10 : Inspecter ashift et le layout des vdev (et repérer les erreurs irréversibles tôt)
cr0x@server:~$ zdb -C tank | egrep 'vdev|ashift|path' | head -n 20
vdev_tree:
type: 'root'
id: 0
guid: 1234567890123456789
children[1]:
type: 'mirror'
id: 0
ashift: 12
children[2]:
type: 'disk'
path: '/dev/disk/by-id/ata-A'
type: 'disk'
path: '/dev/disk/by-id/ata-B'
Ce que ça signifie : ashift: 12 signifie secteurs 4K. Si vous avez des disques natifs 4K/8K mais que ashift est trop petit,
vous avez forcé un comportement read-modify-write qui vous hantera.
Décision : Si ashift est mauvais, budgétez une reconstruction/migration. Il n’y a pas de bouton magique « corriger ashift en place ».
Tâche 11 : Vérifier que la compression aide (et n’est pas juste « activée »)
cr0x@server:~$ zfs get -o name,property,value,source compression,compressratio tank/app
NAME PROPERTY VALUE SOURCE
tank/app compression zstd local
tank/app compressratio 1.62x -
Ce que ça signifie : Le ratio montre les économies réelles. Un ratio proche de 1.00x signifie que vos données sont incompressibles
ou déjà compressées (fichiers média, blobs chiffrés).
Décision : Si le ratio est ~1.00x et que le CPU est sollicité, envisagez une compression plus légère ou aucune. Si le ratio est bon,
la compression vous achète probablement de la marge IO.
Tâche 12 : Détecter un scrub/resilver qui vole votre budget IO
cr0x@server:~$ zpool status -x
pool 'tank' is healthy
cr0x@server:~$ zpool status tank | sed -n '1,12p'
pool: tank
state: ONLINE
scan: scrub in progress since Thu Dec 25 03:00:12 2025
540G scanned at 610M/s, 120G issued at 140M/s, 1.20T total
0B repaired, 9.77% done, 0:02:13 to go
Ce que ça signifie : Un scrub en cours entre en concurrence pour les lectures (et parfois des écritures pour les réparations).
Le débit « issued » est celui d’intérêt ; il reflète ce qui est effectivement poussé vers les périphériques.
Décision : Si vous êtes dans un incident de performance, vous pouvez mettre en pause ou planifier les scrubs hors pointe
(selon les contrôles de la plateforme). Mais ne « résolvez » pas la performance en ne scrubbant plus jamais.
Tâche 13 : Confirmer les mountpoints et éviter des montages doubles accidentels
cr0x@server:~$ zfs get -o name,property,value mountpoint,canmount tank/app
NAME PROPERTY VALUE
tank/app mountpoint /srv/app
tank/app canmount on
Ce que ça signifie : Des datasets mal montés créent le type d’interruption où vous écrivez des données au mauvais endroit,
puis « restaurez » à partir d’un snapshot qui ne les avait jamais capturées.
Décision : Standardisez les mountpoints et imposez-les dans le provisioning. Traitez les montages ad-hoc comme des événements gérés par changement.
Tâche 14 : Surveiller l’IO en temps réel par ZFS et attraper le processus tyran
cr0x@server:~$ zpool iostat -w -v tank 1
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 1.20T 2.40T 110 2200 12.1M 280M
mirror-0 1.20T 2.40T 110 2200 12.1M 280M
ata-A - - 55 1100 6.0M 140M
ata-B - - 55 1100 6.1M 140M
-------------------------- ----- ----- ----- ----- ----- -----
Ce que ça signifie : Le mode -w ajoute des statistiques de latence sur certaines plateformes/builds ; même sans lui,
vous pouvez voir des tempêtes d’écriture. Associez cela à des outils niveau processus (pidstat, iotop) pour trouver la source.
Décision : Si un job inonde d’écritures et pousse le sync TXG, limitez son débit, isolez-le dans son propre dataset,
ou déplacez-le vers un pool d’une autre classe. Les pools partagés récompensent les tyrans et punissent tout le monde.
Blague #2 : L2ARC est comme un « Centre d’Excellence » en entreprise — super sur le papier, cher en réunions, et ça ne réparera pas votre organigramme.
Méthode de diagnostic rapide (premier/deuxième/troisième)
Premier : déterminer si c’est santé, capacité ou contention
- Santé :
zpool status -v. Des erreurs, périphériques dégradés, resilvers ou scrubs ? Réparez la santé avant de tuner. - Marge de capacité :
zpool list. Si vous êtes au-dessus d’environ 80% de capacité sur un pool chargé, supposez que les allocations deviennent coûteuses. - Est-ce vraiment le stockage ?
iostat -xpour la latence et l’utilisation des périphériques. await/queue élevés = contention stockage.
Deuxième : identifier si ce sont les lectures ou les écritures qui font souffrir
- Mix au niveau pool :
zpool iostat -v 1pour voir les opérations et la bande passante read/write. - Suspicion écritures sync : Si les applis bloquent sur commits/fsync, vérifiez la présence d’un SLOG et les propriétés dataset
sync/logbias. - Angle cache : Statistiques ARC pour hits/misses ; si les lectures manquent l’ARC et touchent des disques lents, la latence suit.
Troisième : valider que le layout correspond à la charge
- Type de VDEV : Mirrors pour IO aléatoire basse latence ; RAID-Z pour capacité et débit séquentiel. Si vous avez choisi RAID-Z pour une ferme de VM à écritures aléatoires, le pool fait exactement ce que vous avez demandé.
- Taille des blocs : Vérifiez
recordsizeet (pour les zvols)volblocksize. Le mauvais alignement crée de l’amplification d’écriture et de la pression TXG. - Special vdev : Si les métadonnées sont chaudes et que vous avez du rust lent, un special vdev peut aider — mais seulement si vous comprenez les implications de redondance.
Erreurs courantes : symptômes → cause racine → correction
1) « Tout est lent quand le pool atteint ~85% »
Symptômes : Latence d’écriture en hausse, pauses imprévisibles, scrub/resilver prennent une éternité, opérations métadonnées lentes.
Cause racine : Fragmentation des metaslabs + choix d’allocation contraints à haute capacité ; le copy-on-write amplifie le phénomène.
Correction : Maintenez une marge (expansion de capacité plus tôt), réduisez le churn (discipline de rétention des snapshots), envisagez d’ajouter des vdevs pour le parallélisme. Ne visez pas 95% d’utilisation sur des pools critiques pour la performance.
2) « Les commits DB prennent 20–80 ms, mais le débit semble correct »
Symptômes : Latence p99 élevée, threads bloqués en fsync, TPS qui s’effondre pendant les pics.
Cause racine : Goulot sur le chemin d’écriture sync : pas de SLOG, SLOG lent, ou latence du vdev principal ; écritures de log sérialisées.
Correction : Utilisez un SLOG sûr en cas de perte d’alimentation pour les charges sync-intenses ; validez les propriétés dataset sync et logbias ; assurez-vous que la latence vdev n’est pas pathologique.
3) « On a ajouté L2ARC et c’est pire »
Symptômes : Pression mémoire plus élevée, stalls occasionnels, aucun gain de hit rate.
Cause racine : Overhead d’indexation L2ARC + mise en cache du mauvais working set ; RAM insuffisante donc ARC déjà affamé.
Correction : Ajoutez de la RAM d’abord, optimisez la localité de la charge, mesurez le hit rate ARC avant/après. N’utilisez L2ARC que lorsque le working set dépasse la RAM mais reste cacheable et orienté lecture.
4) « Les écritures aléatoires sont affreuses sur notre RAID-Z tout neuf »
Symptômes : IOPS bien en dessous des attentes, latence élevée à faible bande passante, CPU inactif.
Cause racine : Coût de parité RAID-Z et amplification d’écriture sur petites écritures aléatoires ; sync TXG devient un goulot.
Correction : Utilisez des vdevs mirror pour les charges à écritures aléatoires ; ou isolez la charge, ajustez recordsize/volblocksize, et assurez-vous que vous n’imposez pas d’écritures sync inutilement.
5) « On a désactivé sync pour ‘corriger’ la latence puis on a perdu des données »
Symptômes : La performance s’améliore ; après un crash, des transactions récentes manquent ou sont corrompues côté application.
Cause racine : Vous avez changé les sémantiques de durabilité. ZFS a respecté votre demande et a accusé réception des écritures avant qu’elles ne soient stables.
Correction : Remettez sync à standard ; utilisez un SLOG et du matériel adapté ; corrigez le goulot de latence réel au lieu de réécrire le contrat.
6) « Le scrub tue la performance chaque semaine »
Symptômes : Pics de latence prévisibles pendant les fenêtres de scrub, timeouts dans les services IO-intensifs.
Cause racine : Le scrub entre en concurrence pour l’IO avec des charges sensibles à la latence ; aucune discipline de throttling/planification.
Correction : Planifiez les scrubs hors-heure de pointe, ajustez le comportement de scrub disponible sur votre plateforme, et isolez les charges via pools/vdevs séparés si nécessaire.
Trois mini-histoires d’entreprise (anonymisées, douloureusement réelles)
Incident provoqué par une mauvaise hypothèse : « Un pool est un pool »
Une entreprise de taille moyenne a migré une flotte d’hôtes VM vers un nouvel appliance de stockage ZFS. Le service achats avait optimisé
pour la capacité utile, donc le design était « quelques vdevs RAID-Z larges avec beaucoup de disques ». Sur le papier : parfait.
En pratique : il hébergeait des centaines de disques VM faisant des petites lectures/écritures aléatoires, avec des rafales périodiques sync-intenses.
L’hypothèse qui a causé l’incident était simple : « Plus de disques veut dire plus d’IOPS. » C’est vrai quand vous ajoutez des vdevs,
pas quand vous ajoutez des disques à l’intérieur d’un vdev RAID-Z puis demandez à ce dernier de se comporter comme un ensemble mirror. Pendant la première grande fenêtre de patch,
le pool a subi une pression d’écriture soutenue, les TXGs ont commencé à synchroniser en continu, et la latence des IOs invités est passée de « acceptable » à « appelez le responsable incident ».
Les tableaux de bord ne mentaient pas. Le débit agrégé était élevé. C’est ce qui rendait la situation déroutante : la bande passante semblait saine,
mais les VMs mouraient. La métrique manquante était la latence tail sur les écritures sync. Les charges n’étaient pas liées à la bande passante ;
elles étaient liées à la latence de commit. Chaque petit fsync attendait derrière le travail de parité et la mise en file des vdevs.
La correction n’était pas du « tuning ». C’était de l’architecture. Ils ont ajouté un pool miroir dédié pour le stockage VM sensible à la latence
et ont conservé RAID-Z pour les backups et les données séquentielles. Ils ont aussi revu les defaults des datasets : tailles de bloc plus petites où approprié,
et plus personne n’a touché à sync=disabled sans un accord de gestion de risque écrit.
Optimisation qui a mal tourné : special vdev comme bouton magique
Une autre organisation avait un grand pool sur mirrors HDD qui servait des millions de petits fichiers. Les métadonnées étaient chaudes.
Quelqu’un a lu à propos des special vdevs et proposé : « Mettez les métadonnées sur SSD et tout ira plus vite. » Vrai, avec des mises en garde.
Les mises en garde n’ont pas été discutées. Ils ont ajouté un special vdev avec moins de redondance que le pool principal parce que c’était « juste des métadonnées ».
Cela a marché immédiatement. Les traversées d’arborescence se sont accélérées, les charges stat-heavy se sont calmées, et l’équipe a déclaré victoire.
Un mois plus tard, le périphérique spécial a commencé à lancer des erreurs intermittentes. ZFS a réagi correctement : l’intégrité des métadonnées n’est pas optionnelle.
Si vous perdez le special vdev et qu’il n’est pas suffisamment redondant, vous ne perdez pas juste des performances — vous pouvez perdre le pool.
L’incident n’est pas devenu un titre de presse sur la perte de données parce que le périphérique n’est pas mort complètement. Mais ils ont eu une alerte opérationnelle coûteuse :
fenêtre de maintenance d’urgence, escalation fournisseur, et une conversation très tendue sur « pourquoi avons-nous mis des données critiques du pool sur un point unique de défaillance ? »
L’optimisation qui a mal tourné n’était pas « les special vdevs sont mauvais ». L’erreur était de traiter une fonctionnalité de performance comme si c’était un cache.
Les special vdevs peuvent stocker des métadonnées et parfois de petits blocs. Cela les rend structurels. Structurel signifie que la redondance doit correspondre à l’importance du pool.
Ils ont reconstruit le special vdev en miroir, documenté le domaine de défaillance, puis l’ont déployé à grande échelle.
Pratique ennuyeuse mais correcte qui a sauvé la mise : scrubs cohérents + discipline de remplacement
Une équipe SaaS exploitait des pools ZFS sur serveurs commodity. Rien de glamour : vdevs mirror, marge conservatrice,
et un planning de scrubs réguliers. Ils avaient aussi une habitude qui paraît obsessionnelle jusqu’à ce qu’elle vous sauve :
si un disque montre des compteurs d’erreurs croissants, il est remplacé avant de « tomber complètement ».
Une semaine, un scrub a rapporté des octets réparés sur un pool autrement sain. Aucune application ne s’était plainte.
Personne n’avait remarqué. C’est le point : les erreurs de secteur latentes n’envoient pas d’invitation calendrier.
Le scrub avait trouvé des mismatches de checksum, lu depuis le mirror, réparé, et loggé le tout.
L’équipe a traité les octets réparés comme un système d’alerte précoce matériel. Ils ont vérifié les tendances d’erreurs du périphérique au niveau OS,
remplacé le disque dans une fenêtre planifiée, et resilveré alors que le pool était encore sain et pas sous pression.
Le remplacement était ennuyeux. L’incident qui n’est jamais arrivé aurait été excitant.
Un mois plus tard, un autre disque d’un autre serveur est mort pendant les heures de pointe. Ce pool est resté en ligne parce que mirrors + pratique proactive
signifiaient qu’ils n’ont jamais roulé près du bord. Personne en dehors de l’équipe n’a remarqué.
Voilà à quoi ressemble le « travail de fiabilité » : du succès qu’on ne peut pas montrer dans une capture d’écran.
Listes de contrôle / plan étape par étape
Étape par étape : concevoir un pool qui ne vous ridiculisera pas plus tard
- Classifiez les charges : lecture aléatoire-heavy, écriture aléatoire-heavy, séquentiel, sync-heavy, métadonnées-heavy. Ne les moyennez pas jusqu’à l’inefficacité.
- Choisissez le type de vdev par charge : mirrors pour faible latence ; RAID-Z pour capacité et débit séquentiel. Les charges mixtes méritent séparation via datasets ou pools distincts.
- Planifiez le nombre de vdevs pour les IOPS : besoin de plus d’IOPS ? ajoutez des vdevs, pas des disques dans un seul vdev RAID-Z.
- Décidez du SLOG : seulement si vous avez des écritures sync significatives. Choisissez des périphériques sûrs en cas de perte d’alimentation ; mirror SLOG si votre modèle de risque l’exige.
- Décidez du special vdev : seulement si les métadonnées/les petits blocs sont le goulot. Assortissez la redondance à l’importance du pool.
- Définissez ashift correctement à la création. Traitez-le comme irréversible, car, pour des raisons pratiques, il l’est.
- Définissez les defaults des datasets :
compression=zstd(souvent),atime=off(couramment), recordsize selon la charge, et quotas/réservations quand nécessaire. - Politique de marge de capacité : définissez un seuil dur (par exemple 75–80%) où vous devez étendre ou migrer.
- Cadence opérationnelle : scrubs planifiés, alerting sur erreurs, et procédures documentées de remplacement.
Étape par étape : quand vous héritez d’un pool et que vous ne lui faites pas confiance
- Exécutez
zpool status -vet enregistrez les compteurs d’erreurs de base et l’état du scrub. - Exécutez
zpool listet notez la capacité et la fragmentation. - Exécutez
zpool iostat -v 1 10pendant la charge normale pour comprendre le « normal ». Sauvegardez la sortie. - Audit des propriétés des datasets :
zfs get -rpourrecordsize,sync,compression,atime, quotas/réservations. - Inventaire des périphériques spéciaux : SLOG, L2ARC, special vdev. Confirmez redondance et santé.
- Inspectez ashift via
zdb -C. Si c’est incorrect, consignez-le comme dette technique avec un plan. - Vérifiez la rétention et les patterns de croissance des snapshots. Supprimez de façon responsable, mais ne laissez pas les snapshots consommer silencieusement le pool.
- Implémentez des alertes : changements de santé du pool, deltas des compteurs d’erreurs, seuils de capacité, échecs de scrub, et latence inhabituelle.
FAQ
1) Un VDEV est-il essentiellement un groupe RAID ?
Fonctionnellement, oui : un vdev mirror ressemble à RAID1, RAID-Z ressemble à un RAID parité. Opérationnellement, la différence importante est :
les vdevs sont l’unité sur laquelle ZFS stripe. Ajoutez des vdevs pour ajouter des IOPS/parallélisme.
2) Pourquoi les performances de ZFS chutent-elles quand le pool est plein ?
Parce que les allocations deviennent contraintes et fragmentées. Le SPA a moins de bons choix, les métadonnées augmentent, et les écritures deviennent
des IO plus dispersés. Les pools presque pleins coûtent en performance.
3) Qu’est-ce que le syncing TXG signifie exactement pour mes applications ?
Le sync TXG, c’est quand ZFS flushe les données sales sur disque. Si le pool ne peut pas suivre, ZFS limite les écrivains, et votre appli le ressent comme de la latence.
Les applis sync-heavy le ressentent davantage car elles exigent des commits durables.
4) L’ARC remplace-t-il le page cache Linux ?
Pas exactement. ZFS utilise l’ARC pour le caching géré par ZFS. Le noyau garde encore ses propres mécanismes de page cache, mais ZFS n’est pas un système de fichiers typique
dans la façon dont il gère les blocs mis en cache. La préoccupation pratique est la compétition mémoire : assurez-vous que les applications ont aussi assez de RAM.
5) Quand devrais-je ajouter un SLOG ?
Quand votre charge effectue une quantité significative d’écritures synchrones (bases de données, NFS avec sémantique sync, stockage VM qui fait des flushes),
et que la latence compte. Si votre charge est principalement des écritures asynchrones en streaming, un SLOG n’aidera pas.
6) L2ARC en vaut la peine ?
Parfois. Si votre working set est plus grand que la RAM, orienté lecture, et cacheable, L2ARC peut aider. Si vous êtes write-heavy, à court de RAM,
ou que votre charge est aléatoire avec peu de réutilisation, il ne fera souvent rien ou empirera la situation.
7) Quelle est la différence entre recordsize et volblocksize ?
recordsize s’applique aux fichiers dans les datasets et peut être changé. volblocksize s’applique aux zvols et est fixe à la création.
Choisissez des tailles de bloc qui correspondent aux IO que votre application réalise réellement.
8) Puis-je changer le niveau RAID-Z ou retirer un vdev plus tard ?
Assumez « non » pour la planification production. Certaines fonctionnalités d’expansion existent dans certaines implémentations, mais la suppression d’un vdev et le changement de niveau RAID
ne sont pas des choses sur lesquelles vous devriez parier votre entreprise. Concevez comme si vous alliez vivre avec la décision.
9) Les scrubs abîment-ils les SSD ou réduisent-ils dramatiquement leur durée de vie ?
Les scrubs lisent l’ensemble du pool et peuvent provoquer des écritures si des réparations ont lieu. C’est de l’usure, oui — mais l’alternative est de ne pas savoir que vous avez une corruption latente jusqu’au jour où vous avez besoin des données. La fréquence des scrubs est une décision de risque, pas une superstition.
10) Dois-je activer la déduplication ?
Uniquement si vous avez une charge prouvée favorable à la dédup et suffisamment de mémoire/CPU pour la supporter. Dans la plupart des environnements généralistes, la dédup est un
coût en performance et complexité qui ne rapporte pas.
Conclusion : prochaines étapes à faire cette semaine
ZFS n’est pas « compliqué ». Il est honnête. Il expose la réalité que le stockage est un système coordonné : géométrie des vdevs,
timing des TXG, comportement de l’ARC, et politique d’allocation du SPA finissent tous par apparaître dans vos graphiques de latence.
Étapes pratiques :
- Exécutez les commandes de base :
zpool status -v,zpool list,zpool iostat -v, et enregistrez les sorties comme votre « connu bon ». - Auditez les propriétés des datasets pour vos trois charges principales ; corrigez les incompatibilités évidentes (recordsize, atime, compression).
- Définissez une politique de marge de capacité et appliquez-la avec des alertes.
- Si vous avez des charges sync-heavy, validez votre histoire SLOG : soit vous en avez un bon, soit vous acceptez la latence.
- Planifiez des scrubs, surveillez les réparations, et remplacez les disques suspects tôt. L’ennui est l’objectif.
Si vous ne retenez qu’une chose : le pool n’est pas l’unité de performance. Le vdev l’est. Et les TXG tournent toujours en arrière-plan,
prêts à encaisser les hypothèses que vous avez faites pendant la conception.