Les utilisateurs de ZFS aiment les règles empiriques. Elles rassurent, comme étiqueter un tableau électrique ou se dire « je rangerai cette disposition de datasets plus tard ». La plus célèbre est la « règle ZFS des 80% » : ne laissez pas un pool dépasser 80% d’utilisation, sinon les performances chutent brutalement et les ennuis commencent. En production, on l’entend répétée comme si c’était de la physique.
La vérité est meilleure — et plus utile. La barre des 80% n’est ni une superstition ni une loi universelle. C’est une limite grossière pour quelques mécanismes réels : allocation des metaslabs, fragmentation, comportement copy-on-write, croissance des métadonnées et la mathématique impitoyable du « j’ai besoin d’espace libre à peu près contigu pour écrire efficacement ». La vraie zone de danger n’est pas un chiffre unique ; c’est quand l’espace libre restant cesse d’être de l’espace libre utilisable pour votre charge de travail.
Ce que signifie réellement la « règle des 80% »
La « règle des 80% » est un raccourci pour : l’allocation ZFS devient plus difficile à mesure que le pool se remplit, et une fois que c’est suffisamment difficile, tout ce qui vous importe (latence, débit d’écriture, temps de resilver, suppression de snapshots) peut se dégrader de façon non linéaire.
C’est le point clé : non linéaire. ZFS ne ralentit pas progressivement et poliment comme un ascenseur trop chargé. C’est plutôt comme essayer de se garer en ville quand il ne reste que des places étranges, minuscules ou à moitié bloquées. Vous pouvez toujours vous garer, mais le temps moyen pour trouver une place augmente fortement.
Deux blagues, comme promis, parce que les personnes du stockage gèrent ça avec de l’humour et de la caféine :
Blague n°1 : La règle des 80% ressemble à un régime : tout le monde est d’accord, puis arrive le vendredi.
Blague n°2 : Si vous voulez savoir ce que signifie vraiment « copy-on-write », remplissez un pool à 95% et regardez votre application réécrire son CV.
Alors, 80% est-ce juste ?
Parfois. Pour de nombreuses charges mixtes, « rester en dessous d’environ 80% » est conservateur et vous évite des ennuis. Mais ce n’est pas un seuil magique. Certains pools tournent sans problème à 85–90% parce que la charge est majoritairement en lecture séquentielle et en grosses écritures séquentielles, la fragmentation est maîtrisée et il y a de la marge ailleurs (special vdev rapide pour les métadonnées, RAM suffisante, recordsize adapté). D’autres pools deviennent misérables à 70–75% parce qu’ils subissent des écritures aléatoires sur petits blocs avec une politique de snapshots intensive et beaucoup de petits metaslabs dus à des vdevs étroits.
L’objectif n’est pas de vénérer 80%. L’objectif est de comprendre ce qui rend votre pool « effectivement plein » avant que le chiffre « utilisé » n’atteigne 100%.
Ce qui change réellement quand l’espace libre diminue
De façon générale, ZFS doit trouver des blocs libres pour satisfaire les allocations. À mesure que le pool se remplit, les blocs libres restants sont plus fragmentés et répartis de manière inégale entre les metaslabs. Les décisions d’allocation deviennent plus coûteuses et moins optimales, ce qui peut se traduire par :
- Une amplification d’écriture plus élevée (plus d’E/S par unité d’écriture logique).
- Des écritures plus dispersées (pire pour les HDD, toujours pénalisant pour les SSD).
- Des temps de sync des groupes de transactions (TXG) plus longs (visible comme des pics de latence).
- Des frees plus lents (supprimer des snapshots peut ressembler à pousser un piano en montée).
- Des resilvers et scrubs plus longs, surtout quand le pool est chaud et fragmenté.
Bref historique et faits qui expliquent le folklore
Les règles empiriques de stockage n’apparaissent pas par magie ; elles apparaissent après que suffisamment de gens se sont brûlés au même endroit. Voici des faits concrets et des points de contexte qui donnent du sens à la règle des 80% — sans la traiter comme des Écritures :
- ZFS a été conçu pour le copy-on-write dès le départ. Cela signifie que les réécritures deviennent « allouer du neuf, puis mettre à jour les pointeurs », ce qui nécessite de l’espace libre même pour modifier des données existantes.
- L’allocateur de metaslab favorise les régions peu fragmentées. À mesure que le pool se remplit, les « bons » metaslabs sont utilisés et l’allocateur se retrouve à gérer des restes.
- Les premières déploiements ZFS étaient axés sur les HDD. Les HDD pénalisent les écritures aléatoires et les seeks ; la « falaise » était évidente. Les SSD atténuent la douleur mais ne suppriment pas les coûts d’allocation ni l’agitation des métadonnées.
- RAIDZ change les mathématiques. RAIDZ a la parité et un comportement de stripe variable. Les petites écritures aléatoires peuvent devenir des cycles read-modify-write, et un espace libre fragmenté aggrave le problème.
- Les snapshots sont bon marché jusqu’à ce qu’ils ne le soient plus. Prendre des snapshots est rapide ; les conserver et les supprimer à grande échelle peut transformer « espace libre » en une responsabilité compliquée.
- 128K est devenu un recordsize culturel par défaut. Ce défaut est excellent pour de nombreuses charges séquentielles, mais il interagit mal avec des écritures aléatoires petites et un churn de snapshots si vous ne tunez pas par dataset.
- Les erreurs d’ashift sont définitives (pour ce vdev). Des hypothèses de secteur mal alignées peuvent gaspiller de l’espace et de la marge d’E/S, réduisant votre marge d’espace pratique.
- Les special vdev ont changé l’économie des métadonnées. Placer les métadonnées (et éventuellement les petits blocs) sur un média rapide peut garder les pools utilisables plus longtemps en forte utilisation — si dimensionné correctement. Sinon, il peut devenir le nouveau goulot d’étranglement.
- « df » et « zfs list » disent deux vérités différentes. Les systèmes de fichiers traditionnels laissent faire l’illusion ; ZFS expose plus de réalité : snapshots, réservations, et referenced vs used importent.
La véritable zone de danger : quand l’espace libre cesse d’être utilisable
Si vous voulez une phrase opérationnelle pour remplacer « ne dépassez jamais 80% », utilisez ceci :
La zone de danger commence lorsque l’espace libre restant du pool ne peut plus satisfaire efficacement votre schéma d’allocation, surtout en période de charge d’écriture maximale et avec la rétention des snapshots.
« Utilisé » n’est pas la même chose que « stress »
Deux pools peuvent être tous deux à 85% utilisés et se comporter complètement différemment. Le stress dépend de :
- Fragmentation de l’espace libre : Avez-vous des blocs libres en grands extents, ou une pile de confettis ?
- Taille et localité des écritures : Écrivez-vous des blocs volumineux et séquentiels ou des mises à jour aléatoires de 4K ?
- Géométrie des vdev : Les miroirs se comportent différemment du RAIDZ ; plus de vdevs signifie plus de « voies » d’allocation.
- Churn de snapshots : Snapshots fréquents + réécritures signifient que vos frees sont retardés et que votre ensemble vivant croît en « copies fantômes ».
- Charge de métadonnées : Des millions de petits fichiers, attributs étendus, ACLs et tables de dédup créent des I/O de métadonnées qui n’apparaissent pas comme de « grosses écritures ».
Une définition pratique d’« effectivement plein »
En production, j’appelle un pool « effectivement plein » quand l’une des conditions suivantes est vraie :
- La latence d’écriture applicative devient imprévisible (p99 et p999 explosent), même si les disques ne sont pas saturés en débit brut.
- Le temps de sync des TXG augmente et reste élevé sous une charge d’écriture soutenue.
- Les suppressions de snapshots se bloquent ou prennent des heures de plus que d’habitude.
- Les estimations de temps de resilver deviennent comiques, surtout en heures ouvrées.
- Vous commencez à « réparer » les performances en redémarrant, ce qui signifie que vous êtes passé du déni à l’improvisation.
Pourquoi la falaise semble soudaine
La falaise est une boucle de rétroaction :
- Le pool se remplit et se fragmente.
- Les allocations deviennent plus dispersées ; les écritures prennent plus de temps.
- Des écritures plus longues maintiennent les TXG ouverts plus longtemps ; plus de données sales s’accumulent.
- Plus de données sales signifie un travail de sync plus lourd ; la latence de sync augmente.
- Les applications voient la latence et réessaient ou mettent en file ; la charge augmente.
Ce n’est pas que ZFS « panique à 81% ». C’est que votre charge traverse le point où les choix de l’allocateur cessent d’être peu coûteux.
Schémas de charge qui heurtent le mur en premier
Écritures aléatoires de VM et bases de données sur RAIDZ
C’est le classique. Beaucoup de mises à jour de 8K–16K, écritures synchrones et churn d’overwrites. En RAIDZ, les petites écritures peuvent déclencher des read-modify-write. Ajoutez des snapshots et vous avez construit une machine qui fabrique de la fragmentation.
Partages de fichiers avec snapshots intensifs, renommages fréquents et petits fichiers
Churn de métadonnées et frees retardés. Les utilisateurs ne remarquent pas les 50 000 premiers snapshots parce que les lectures restent fluides. Puis les suppressions, renommages et opérations de répertoire commencent à ralentir, et tout le monde accuse « le réseau ».
Sauvegardes et stockage type objet avec gros flux séquentiels
Ces charges peuvent tolérer une utilisation plus élevée si la charge est majoritairement en append et que vous ne réécrivez pas en place. Mais attention : l’expiration de rétention (suppression massive) peut être une tempête à elle seule.
Conteneurs et pipelines CI
Beaucoup de petits fichiers, durées de vie courtes, couches overlayfs, caches de build et événements « tout supprimer ». ZFS peut très bien gérer cela, mais près de la saturation, le churn constant de création/suppression transforme le travail de l’allocateur en douleur.
Comptabilité de l’espace : pourquoi « df » ment et pourquoi ZFS s’en fiche
ZFS rend les gens furieux parce qu’il refuse de maintenir une illusion simple. Vous pouvez avoir 2 To « libres » dans une vue et être à court d’espace dans une autre. Généralement, personne ne ment ; vous posez juste des questions différentes.
Termes clés qui importent vraiment
- USED : Espace consommé par le dataset et ses descendants, y compris les snapshots (selon l’endroit où vous regardez).
- REFER : Espace référencé uniquement par ce dataset (sans compter les snapshots).
- AVAIL : Espace disponible en tenant compte des quotas/réservations et de l’espace libre du pool.
- Enregistré vs réel : La compression et les copies changent ce que signifient « logique » vs « physique ».
Pourquoi les snapshots donnent l’impression que l’espace est hanté
Avec les snapshots, les suppressions ne libèrent pas nécessairement des blocs. Les réécritures allouent de nouveaux blocs ; les anciens blocs restent référencés par les snapshots. Ainsi votre réflexe « supprimer le gros fichier » ne vous rapporte pas autant qu’avec ext4. Le pool peut sembler avoir de l’espace libre, mais l’allocateur est toujours forcé dans des endroits délicats parce que l’espace libre disponible est fragmenté ou réparti de façon inégale.
Trois mini-histoires du monde corporate (du terrain)
1) Incident causé par une mauvaise hypothèse : « 80% est sûr, donc 79% l’est aussi »
Une entreprise de taille moyenne exploitait un cluster NFS sur ZFS servant des répertoires personnels et quelques fermes de build. L’équipe stockage avait un tableau de bord avec une jolie bande vert/jaune/rouge : vert en dessous de 80%, jaune au-dessus de 80%, rouge au-dessus de 90%. Ça faisait pro, et tout le monde adorait parce que ça réduisait les disputes à une couleur.
Puis le pool a atteint 79% utilisé. Toujours vert. Cette semaine-là, le churn d’artéfacts de la ferme de build a explosé à cause d’un lancement produit, et le partage des répertoires personnels avait une politique de snapshots trimestrielle. Rien d’exotique : juste beaucoup de petits fichiers créés et réécrits, plus des snapshots pris toutes les heures.
Mardi, le helpdesk a commencé à voir des échecs de build « aléatoires ». Mercredi, les clients NFS ont commencé à se bloquer sur les opérations de métadonnées : stat(), listes de répertoires, renommages de fichiers. L’équipe réseau a été appelée parce que « NFS est lent », et elles ont fait ce que font les équipes réseau : prouver que le réseau était innocent.
Jeudi, l’équipe stockage a trouvé la vérité : le pool n’était pas « sûr » à 79%. Il était effectivement plein pour cette charge. Les metaslabs s’étaient suffisamment fragmentés pour que les recherches de l’allocateur et les écritures dispersées martèlent la latence. La ligne des 80% n’était pas la falaise ; c’était un avertissement folklorique. Leurs tableaux restaient verts alors que les utilisateurs étaient en feu.
La correction n’était pas magique. Ils ont libéré de l’espace en expirant d’anciens snapshots, déplacé les artéfacts de build vers un dataset avec recordsize et compression ajustés, et — surtout — changé les alertes pour suivre non seulement le pourcentage utilisé mais aussi la latence d’écriture, le comportement TXG sync et la croissance de l’espace snapshots. La nouvelle bande « verte » se basait sur le comportement, pas seulement sur un chiffre.
2) Optimisation qui s’est retournée contre eux : « On va augmenter recordsize et tout compresser »
Une autre société utilisait ZFS pour la virtualisation. Elles avaient des SSD, beaucoup de RAM, et de la confiance — toujours un ingrédient dangereux. Quelqu’un a remarqué que le recordsize par défaut était 128K et décidé que « plus grand c’est mieux », le passant à 1M sur le dataset VM. Ils ont aussi activé une compression agressive partout parce que ça faisait joli dans le rapport trimestriel de stockage.
Au début, tout allait bien. Les sauvegardes ont rétréci. Le chiffre « used » du pool avait l’air meilleur. Puis, à mesure que l’utilisation augmentait, la latence des écritures aléatoires a commencé à grimper. Les charges VM qui faisaient de petites mises à jour touchaient maintenant de très gros enregistrements, amplifiant les écritures et le travail des métadonnées. La compression ajoutait une charge CPU au moment où le système devait prendre des décisions d’allocation rapides et tenir le rythme des sync.
Le pire : leur monitoring suivait surtout le débit et le pourcentage utilisé. Le débit avait l’air correct. Le pourcentage utilisé était sous 80%. Pendant ce temps, les hyperviseurs échouaient sur des opérations de stockage aux heures de pointe. L’expérience métier était « la plateforme est instable », le type de bug de performance le plus coûteux.
Ils ont fait marche arrière : les disques VM ont été déplacés vers des datasets avec un recordsize plus raisonnable (et, pour les zvols, un volblocksize approprié), la compression a été conservée mais adaptée à la marge CPU, et ils ont séparé les charges par dataset plutôt que d’appliquer un réglage universel. La leçon n’était pas « la compression est mauvaise » ni « le grand recordsize est mauvais ». La leçon : des optimisations qui aident les rapports de capacité peuvent nuire au comportement d’allocation près de la saturation.
3) Pratique ennuyeuse mais correcte qui a sauvé la mise : réservations, marge et procédures testées
Une société financière utilisait ZFS pour un pipeline d’analyse de logs et des services de fichiers internes. Rien de glamour : beaucoup d’écritures en append, des compactages périodiques et des snapshots pour rollback rapide. Le responsable stockage détestait les récupérations héroïques, alors ils ont bâti un plan terne : garder 20–25% de marge, appliquer des quotas, et créer un dataset « casse-glace » avec de l’espace réservé pour les urgences.
C’était impopulaire. Les équipes détestent les quotas comme les chats détestent les bains. Mais elles ont accepté après quelques réunions et des explications calmes sur le copy-on-write et la rétention des snapshots. Ils ont aussi créé un runbook de nettoyage : quels snapshots expirer en premier, quels datasets purger et quoi préserver. Ils l’ont testé trimestriellement comme un exercice d’incendie.
Un an, une boucle de logging incontrôlée a commencé à générer des données massives. Dans un environnement moins discipliné, le pool aurait atteint 95% puis serait devenu un carnaval de latence. Ici, les alertes se sont déclenchées tôt (tendance d’espace + latence), les quotas ont contenu le rayon d’explosion, et l’espace réservé « casse-glace » a assuré que les services critiques pouvaient encore écrire pendant que l’équipe nettoyait. Ils ont exécuté le runbook sans improviser : expirer les snapshots non critiques, arrêter le pipeline fautif, scruber pour vérifier l’intégrité, puis reprendre.
Rien d’héroïque n’est arrivé. C’est le but. La pratique ennuyeuse n’a pas fait un super récit à la réunion générale, mais elle a évité une grosse histoire sur les réseaux sociaux.
Tâches pratiques : commandes, sorties et comment les lire
Ci-dessous se trouvent les tâches pratiques que j’utilise réellement quand un pool est « mystérieusement lent » ou approche de la zone de danger. Les commandes sont montrées comme si elles étaient lancées sur un hôte Linux typique avec OpenZFS. Des interprétations sont incluses — parce qu’une sortie brute sans sens n’est que décorative.
Task 1: Check pool capacity and health (the baseline)
cr0x@server:~$ zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 54.5T 44.1T 10.4T - - 38% 80% 1.00x ONLINE -
Interprétation : CAP à 80% n’est pas automatiquement mauvais, mais c’est le moment de commencer à faire attention. FRAG est un indicateur, pas un verdict. Un FRAG de 38% peut être acceptable ou pénalisant selon la charge.
Task 2: Get detailed vdev layout and spot an obvious bottleneck
cr0x@server:~$ zpool status -v tank
pool: tank
state: ONLINE
scan: scrub repaired 0B in 07:12:33 with 0 errors on Sun Dec 22 02:10:14 2025
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
sdf ONLINE 0 0 0
errors: No known data errors
Interprétation : La santé est bonne. Cela ne signifie pas que les performances sont bonnes. Si un seul disque avait des erreurs READ/WRITE élevées ou tombait périodiquement, vous le verriez ici — les pools presque pleins amplifient la douleur d’un hardware marginal.
Task 3: Identify what’s consuming space (top datasets)
cr0x@server:~$ zfs list -o name,used,refer,avail,compressratio,mountpoint -S used | head -n 12
NAME USED REFER AVAIL COMPRESSRATIO MOUNTPOINT
tank 44.1T 128K 10.4T 1.35x /tank
tank/vm 18.7T 18.2T 10.4T 1.12x /tank/vm
tank/home 12.4T 9.1T 10.4T 1.61x /tank/home
tank/backup 9.8T 9.7T 10.4T 1.05x /tank/backup
tank/containers 2.1T 1.9T 10.4T 1.48x /tank/containers
Interprétation : USED inclut les snapshots selon la hiérarchie ; REFER est les données vivantes. Un grand écart entre USED et REFER signifie souvent que des snapshots retiennent beaucoup d’anciens blocs.
Task 4: Quantify snapshot space impact
cr0x@server:~$ zfs list -t snapshot -o name,used,refer,creation -S used | head -n 10
NAME USED REFER CREATION
tank/home@hourly-2025-12-24-2300 420G 9.0T Wed Dec 24 23:00 2025
tank/home@hourly-2025-12-24-2200 390G 8.9T Wed Dec 24 22:00 2025
tank/vm@daily-2025-12-24 210G 18.1T Wed Dec 24 01:00 2025
tank/home@hourly-2025-12-24-2100 180G 8.8T Wed Dec 24 21:00 2025
Interprétation : Le USED d’un snapshot est l’espace exclusif retenu par ce snapshot. Si quelques snapshots sont énormes, vous avez probablement un fort churn d’overwrites (VMs, bases de données, caches CI) dans ce dataset.
Task 5: Spot reservations and quotas that make “AVAIL” weird
cr0x@server:~$ zfs get -o name,property,value,source quota,refquota,reservation,refreservation tank/home tank/vm
NAME PROPERTY VALUE SOURCE
tank/home quota none default
tank/home refquota none default
tank/home reservation none default
tank/home refreservation none default
tank/vm quota 20T local
tank/vm refquota none default
tank/vm reservation 2T local
tank/vm refreservation none default
Interprétation : Les réservations réservent de l’espace même lorsque le pool est serré. Parfait pour protéger des workloads critiques, déroutant si vous avez oublié que vous les aviez définies.
Task 6: Check pool fragmentation and allocation classes
cr0x@server:~$ zdb -L -bbbs tank | head -n 30
Traversing all blocks to verify metadata...
Metaslabs:
tank: 256 metaslabs, 38% fragmented, 80% capacity
...
Summary:
blocks = 123456789
alloc = 44.1T
free = 10.4T
Interprétation : La fragmentation ici est au niveau pool et grossière, mais elle corrèle avec la douleur de l’allocateur. FRAG en hausse plus une latence d’écriture en hausse est votre alarme de « zone de danger ».
Task 7: Inspect dataset properties that influence near-full behavior
cr0x@server:~$ zfs get -o name,property,value,source recordsize,compression,atime,sync,logbias,primarycache,secondarycache tank/vm
NAME PROPERTY VALUE SOURCE
tank/vm recordsize 128K default
tank/vm compression lz4 local
tank/vm atime off local
tank/vm sync standard default
tank/vm logbias latency local
tank/vm primarycache all default
tank/vm secondarycache all default
Interprétation : Pour les datasets VM, recordsize et le comportement sync importent. Les pools proches de la saturation punissent les écritures aléatoires sync ; logbias et un SLOG correctement déployé peuvent aider, mais ils ne résolvent pas la fragmentation.
Task 8: Check zvol block size (common VM pitfall)
cr0x@server:~$ zfs get -o name,property,value,source volblocksize tank/vm/zvol0
NAME PROPERTY VALUE SOURCE
tank/vm/zvol0 volblocksize 8K local
Interprétation : Un volblocksize raisonnable peut réduire l’amplification d’écriture. Un décalage (comme 128K pour une charge 8K, ou 4K pour du séquentiel large) peut faire sentir la « quasi saturation » plus tôt.
Task 9: Watch real-time latency and IOPS per vdev
cr0x@server:~$ zpool iostat -v tank 1 5
capacity operations bandwidth
pool alloc free read write read write
---------- ----- ----- ----- ----- ----- -----
tank 44.1T 10.4T 820 1600 110M 95.2M
raidz2-0 44.1T 10.4T 820 1600 110M 95.2M
sda - - 120 250 17.0M 15.8M
sdb - - 118 260 16.5M 16.2M
sdc - - 130 245 17.2M 15.4M
sdd - - 112 270 16.1M 16.8M
sde - - 160 300 22.0M 18.5M
sdf - - 180 275 21.2M 17.0M
Interprétation : Repérez un disque anormalement peu actif (ou montrant des erreurs). Notez aussi : la bande passante peut sembler correcte alors que la latence ne l’est pas. Utilisez iostat et les métriques applicatives, pas seulement le débit.
Task 10: Check ARC health and whether you’re caching what matters
cr0x@server:~$ arcstat 1 3
time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
12:00:01 890 120 13 10 1 40 4 70 8 96G 112G
12:00:02 910 140 15 15 2 50 5 75 8 96G 112G
12:00:03 870 110 12 8 1 38 4 64 7 96G 112G
Interprétation : Les misses ARC ne sont pas automatiquement mauvaises, mais si les misses de métadonnées augmentent pendant des charges orientées répertoires, les pools près de la saturation souffrent davantage car chaque opération de métadonnées déclenche plus d’I/O dispersé.
Task 11: See if sync writes are dominating (and whether a SLOG is helping)
cr0x@server:~$ cat /proc/spl/kstat/zfs/zil
8 1 0x01 107 8880 1234567890 987654321
name type data
zil_commit_count 4 152340
zil_commit_writer_count 4 152338
zil_itx_count 4 9832451
zil_itx_indirect_count 4 0
Interprétation : Une forte activité de commit suggère des charges sync-intensives. Si vous êtes proche de la saturation et sync-heavy, vous le sentirez. Un SLOG peut réduire la latence des écritures sync, mais il ne guérira pas la fragmentation ni l’amplification d’écriture induite par les snapshots.
Task 12: Confirm ashift (capacity and IO alignment implications)
cr0x@server:~$ zdb -C tank | grep -E "ashift|vdev_tree" -n | head
109: vdev_tree:
174: ashift: 12
231: ashift: 12
Interprétation : ashift=12 (4K) est courant. Si vous avez construit accidentellement avec un ashift trop petit pour des disques 4K-natifs, vous pouvez obtenir des inefficiences de performance et d’espace qui réduisent votre marge réelle.
Task 13: Measure delete pain (snapshot destruction) safely
cr0x@server:~$ time zfs destroy -nvp tank/home@hourly-2025-12-24-2100
would destroy tank/home@hourly-2025-12-24-2100
would reclaim 180G
Interprétation : Le dry-run montre l’espace récupérable. Si les destructions prennent une éternité en pratique, c’est souvent un signe que vous êtes profondément fragmenté et/ou que le churn de métadonnées est élevé. Planifiez les suppressions en heures creuses et évitez les suppressions massives pendant les pics d’écriture.
Task 14: Spot small-block workload candidates for special vdev (metadata/small blocks)
cr0x@server:~$ zfs get -o name,property,value,source special_small_blocks tank/home tank/containers
NAME PROPERTY VALUE SOURCE
tank/home special_small_blocks 0 default
tank/containers special_small_blocks 0 default
Interprétation : Si vous avez un special vdev et activez les petits blocs pour y atterrir, vous pouvez réduire les I/O aléatoires sur les vdevs HDD. Mais c’est un choix d’architecture, pas un pansement : sous-dimensionner le special vdev et vous créez un nouveau mode d’échec « pool plein » quand il se remplit.
Mode opératoire de diagnostic rapide (quoi vérifier en premier, deuxième, troisième)
Quand quelqu’un dit « ZFS est lent » et que le pool se remplit, vous avez besoin d’une séquence reproductible qui trouve le goulot avant que les invitations aux réunions ne se multiplient.
Premier : confirmer si c’est une pression de capacité ou autre chose
- CAP et FRAG du pool : CAP > ~80% ? FRAG augmente-t-il dans le temps ?
- Latence d’écriture côté appli : Voyez-vous des pics p99 corrélés à la charge d’écriture ou aux opérations de snapshot ?
- Erreurs/périphériques dégradés : Des disques ont-ils des erreurs, des périphériques lents, ou un resilver en cours ?
cr0x@server:~$ zpool list -o name,size,alloc,free,frag,cap,health
NAME SIZE ALLOC FREE FRAG CAP HEALTH
tank 54.5T 44.1T 10.4T 38% 80% ONLINE
Deuxième : déterminer si vous êtes contraint par IOPS, bande passante, sync ou CPU
- IOPS et bande passante par vdev :
zpool iostat -v 1pendant la fenêtre de plainte. - Latence disque : Utilisez les outils OS pour voir await/service times ; un pool près de la saturation peut ressembler à « I/O aléatoire partout ».
- Pression sync : NFS, bases de données et hyperviseurs peuvent forcer des écritures sync. Confirmez avec l’activité ZIL et les politiques
syncdes datasets. - CPU : La compression et le checksum valent généralement le coût, jusqu’à ce que la machine manque de CPU pendant le sync TXG.
cr0x@server:~$ iostat -x 1 3
avg-cpu: %user %nice %system %iowait %steal %idle
12.30 0.00 6.10 22.40 0.00 59.20
Device r/s w/s rkB/s wkB/s await svctm %util
sda 21.0 240.0 1800 16400 28.1 2.8 73.4
sdb 18.0 255.0 1600 17100 31.5 2.9 79.2
Interprétation : Await élevé et %util élevé impliquent que les disques sont le goulot. La fragmentation d’un pool presque plein a tendance à pousser vers de l’I/O aléatoire, augmentant l’await.
Troisième : identifier le dataset ou le comportement qui cause la pression
- Quels datasets croissent le plus vite ?
zfs list -o used,referet listes de snapshots. - Quels snapshots sont énormes ? Trier les snapshots par USED.
- Une charge unique fait-elle du churn d’overwrites ? VMs, caches CI, bases de données.
cr0x@server:~$ zfs list -t snapshot -o name,used -S used | head
NAME USED
tank/home@hourly-2025-12-24-2300 420G
tank/home@hourly-2025-12-24-2200 390G
tank/vm@daily-2025-12-24 210G
Erreurs courantes, symptômes spécifiques et correctifs
Mistake 1: Treating 80% as a hard line instead of watching behavior
Symptôme : Le pool est « seulement » à 75–80% utilisé, mais des pics de latence d’écriture et des suppressions qui stagnent apparaissent.
Correctif : Ajoutez des alertes sur la latence d’écriture, le temps de sync des TXG (via les métriques système) et le taux de croissance des snapshots. Gardez une marge basée sur la charge observée. Si votre pool devient malheureux à 75%, votre règle est 75%.
Mistake 2: Keeping a snapshot policy that grows without a deletion plan
Symptôme : « On a supprimé 2 To mais on n’a récupéré que 50 Go. » Le USED des snapshots est important ; les suppressions ne libèrent pas l’espace rapidement.
Correctif : Auditez la rétention des snapshots par dataset, plafonnez la rétention et supprimez les plus anciens en heures creuses. Envisagez de séparer les workloads churny dans leur propre dataset avec un calendrier de snapshots adapté.
Mistake 3: Mixing incompatible workloads in one dataset
Symptôme : Le réglage pour une charge casse une autre ; recordsize/compression semblent être un compromis.
Correctif : Séparez les datasets par charge : VMs, sauvegardes, home dirs, containers. Affinez par dataset (recordsize/volblocksize, compression, atime, logbias).
Mistake 4: Over-optimizing for capacity reports
Symptôme : Excellents ratios de compression, latence épouvantable sous charge d’écriture.
Correctif : Gardez la compression sensée (lz4 est généralement le « gain gratuit »), mais mesurez la marge CPU. Ne gonflez pas le recordsize pour des charges d’écriture aléatoire.
Mistake 5: Assuming a SLOG fixes “near full” performance
Symptôme : Ajout d’un SLOG rapide ; la latence d’écriture aléatoire est toujours épouvantable ; les suppressions de snapshots sont toujours lentes.
Correctif : Le SLOG aide la latence des écritures sync ; il ne résout pas la fragmentation, la pression des métadonnées ou le coût des recherches d’allocation. Concentrez-vous sur la marge et la disposition des datasets.
Mistake 6: Running RAIDZ for IOPS-heavy VM workloads without enough vdev width/count
Symptôme : Performances acceptables à 50% utilisé ; douloureuses à 75% ; scrubs/resilvers dévastent la latence.
Correctif : Les miroirs (plus de vdevs) offrent souvent de meilleures IOPS pour petits accès aléatoires. Si vous restez en RAIDZ, planifiez plus de vdevs, envisagez un special vdev pour les métadonnées et gardez plus d’espace libre.
Mistake 7: Ignoring rebuild/resilver dynamics
Symptôme : Un remplacement de disque prend une éternité ; performance catastrophique pendant le resilver.
Correctif : Gardez de la marge, scrubez régulièrement et planifiez les jobs lourds autour des maintenances. Les pools proches de la saturation rendent les resilvers plus lents car les patterns d’allocation et d’espace libre sont pires.
Listes de vérification / plan pas à pas
Étape par étape : décider de votre véritable objectif de marge
- Mesurez votre « normal » : Enregistrez latence p95/p99 d’écriture, comportement TXG sync (indirectement via les pics de latence) et temps de scrub de référence à 50–60% d’utilisation.
- Mesurez à plus haute utilisation : Au fur et à mesure que vous passez 70%, 75%, 80%, comparez ces métriques chaque semaine.
- Trouvez le genou : Le point où la variance de latence et les tâches opérationnelles (suppression de snapshots, scrub) se dégradent plus vite que la croissance de la capacité.
- Définissez la politique : Votre « règle » est l’endroit où votre charge reste ennuyeuse. Pour certains pools c’est 80%. Pour d’autres c’est 70%. Pour des pools de sauvegarde append-only, on peut aller plus haut avec une gestion stricte.
Étape par étape : récupération d’espace d’urgence sans chaos
- Arrêtez l’hémorragie : Identifiez le plus gros écrivain et mettez-le en pause si possible (cache CI, boucle de logs, job de backup incontrôlé).
- Supprimez avec intention : Préférez supprimer les snapshots qui récupèrent le plus d’espace d’abord (mais ne faites pas de suppressions massives en période de pointe).
- Protégez les datasets critiques : Assurez-vous qu’ils ont des réservations ou quotas appropriés pour qu’une équipe ne prive pas tout le monde.
- Vérifiez après récupération : Confirmez l’espace libre du pool et que la latence se stabilise ; planifiez un scrub si vous avez eu des problèmes hardware.
Étape par étape : rendre le « presque plein » moins effrayant à long terme
- Séparez les workloads en datasets et ajustez-les (recordsize/volblocksize, compression, atime, logbias).
- Revisitez la conception vdev (miroirs vs RAIDZ, nombre de vdevs, dimensionnement du special vdev si utilisé).
- Implémentez des alertes basées sur la tendance (taux de croissance d’espace + latence), pas seulement des seuils.
- Entraînez-vous au nettoyage (application des rétentions de snapshots, exercice de récupération d’urgence).
FAQ
1) La règle ZFS des 80% est-elle réelle ?
C’est réel en tant qu’avertissement, pas en tant que seuil universel. Beaucoup de pools deviennent nettement plus difficiles à allouer efficacement en dépassant ~80%, mais le véritable « genou » dépend de la charge, de la disposition des vdevs et de la fragmentation.
2) Pourquoi les performances se dégradent tant près de la saturation ?
Parce que ZFS doit allouer de nouveaux blocs pour écrire (copy-on-write), et quand l’espace libre diminue il devient plus fragmenté et réparti de manière inégale. L’allocateur travaille plus et fait des placements moins optimaux, augmentant l’I/O et la latence.
3) Les pools SSD ignorent-ils la règle des 80% ?
Les SSD masquent certains symptômes ( pénalité de seek ) mais n’enlèvent pas les coûts d’allocation, l’agitation des métadonnées ou l’impact des réécritures lourdes liées aux snapshots. De plus, les SSD ont leurs propres falaises de performance quand l’espace interne libre (overprovisioning) devient serré.
4) Le FRAG de ZFS est-il un indicateur fiable ?
C’est utile mais pas suffisant. Une valeur FRAG modérée peut aller pour des charges séquentielles et être pénalisante pour des écritures aléatoires. Utilisez FRAG avec des métriques de latence et une compréhension de la charge.
5) Ajouter plus de RAM résoudra-t-il les performances d’un pool presque plein ?
Plus d’ARC aide les lectures et le cache de métadonnées, et peut réduire une partie des I/O. Mais cela ne rendra pas l’espace fragmenté contigu, et n’empêchera pas la douleur de l’allocateur sous de fortes écritures. Considérez la RAM comme un multiplicateur, pas comme un remède.
6) Un SLOG me permet-il d’exploiter le pool plus rempli ?
Un SLOG peut améliorer la latence des écritures sync pour des charges comme NFS ou des bases de données avec fsync. Il ne corrige pas l’inefficacité générale d’allocation ni l’amplification d’écriture induite par les snapshots. Il peut vous aider à survivre, pas à violer les lois de la géométrie.
7) Quelle est la façon la plus sûre de récupérer de l’espace rapidement ?
Arrêtez ou limitez le plus gros écrivain, puis récupérez l’espace là où il est réellement récupérable — souvent en supprimant les snapshots à fort USED. Utilisez le destroy en dry-run pour estimer l’espace récupérable et évitez les opérations massives destructrices en pleine charge.
8) Puis-je défragmenter un pool ZFS ?
Pas au sens traditionnel « lancer un defrag ». Vous pouvez réduire la fragmentation sur le long terme en réécrivant les données (send/receive vers un nouveau pool, ou réplication vers de nouveaux vdevs) et en gardant de la marge pour que les choix de l’allocateur restent bons.
9) Pourquoi la suppression de fichiers n’a-t-elle pas libéré d’espace ?
Parce que des snapshots peuvent encore référencer les anciens blocs. Supprimer le fichier vivant retire une référence, mais les snapshots préservent une autre. L’espace est libéré quand la dernière référence disparaît — souvent en expirant les snapshots.
10) Quel objectif d’utilisation devrais-je choisir ?
Choisissez l’utilisation la plus élevée qui garde votre système ennuyeux sous la charge maximale. Pour de nombreux pools généralistes, c’est 70–80%. Pour les workloads VM/DB churny, viser plus bas est souvent plus sûr. Pour les pools de sauvegarde append-only, vous pouvez pousser plus haut avec une surveillance et une gestion stricte de la rétention.
Conclusion
La règle ZFS des 80% n’est ni un mythe ni un évangile. C’est une vieille cicatrice transformée en slogan. La vraie vérité d’ingénierie est que ZFS a besoin d’espace libre utilisable pour garder les allocations copy-on-write efficaces, et « utilisable » dépend de la fragmentation, de la disponibilité des metaslabs, des schémas d’écriture et du churn des snapshots.
Si vous gérez du stockage en production, la meilleure manœuvre n’est pas de débattre des 80%. C’est de définir la zone de danger de votre pool en fonction du comportement : variance de latence, dynamique de récupération de snapshots, impact des scrub/resilver et tendances de croissance. Gardez suffisamment de marge pour simplifier l’allocation, maintenez des politiques ennuyeuses (quotas, réservations, rétention) et vous passerez moins de temps à négocier avec un système de fichiers qui a manqué de bons choix.