Si vous avez exploité ZFS en production — sur un hôte de base de données, une ferme de VM, ou un serveur de fichiers qui est devenu un lac de données — vous l’avez remarqué : du jure qu’un dataset fait 2,1T, mais zfs list insiste sur 3,4T. Quelqu’un demande « Alors… d’où vient ce téraoctet supplémentaire ? » et soudain vous faites de la réponse à incident avec une calculatrice.
Ce n’est pas un bug ZFS. C’est de la comptabilité. ZFS rapporte plusieurs « vérités » selon la question que vous posez. du est une traversée du système de fichiers. zfs list est une comptabilité de propriété des blocs à travers snapshots, réservations, métadonnées et politiques au niveau du pool comme l’espace de slop. Quand vous alignez les questions, les chiffres s’alignent — en grande partie. Quand vous ne le faites pas, vous obtenez des surprises qui ressemblent à des fuites.
Le décalage fondamental : fichiers vs blocs vs historique
du répond : « Combien de blocs disque sont actuellement alloués aux fichiers que je peux atteindre en parcourant cet arbre de répertoires maintenant ? »
zfs list répond : « Combien de blocs dans le pool sont attribuables à ce dataset et à ses snapshots, plus quelques subtilités comme les réservations ? » Selon les colonnes demandées, il peut répondre « blocs uniques », « blocs partagés » ou « octets logiques avant compression ».
Même système de stockage, question différente. Cette différence est amplifiée par les caractéristiques définissantes de ZFS :
- Le copy-on-write fait que les anciens blocs persistent tant que des snapshots y référencent.
- La compression signifie que « octets dans les fichiers » et « octets sur disque » sont deux monnaies différentes.
- Pointeurs de blocs, métadonnées et overhead de spacemap existent même quand votre répertoire semble « vide ».
- Le comportement au niveau du pool (espace de slop) cache de la capacité pour maintenir le système en vie.
Blague #1 : Demander « pourquoi du et zfs list divergent » revient à demander « pourquoi mon solde bancaire ne correspond pas à mon tracker de dépenses » — l’un inclut les transactions en attente et l’autre inclut votre optimisme.
Faits et contexte historique qui comptent vraiment
Le comportement du stockage est politique plus physique, mais ZFS a aussi une histoire. Quelques points de contexte courts qui aident à raisonner sur les chiffres d’aujourd’hui :
- ZFS a popularisé les snapshots copy-on-write dans les systèmes de fichiers à usage général ; ce choix rend l’utilisation d’espace intrinsèquement dépendante du temps.
- La lignée originale de ZFS vient de Solaris, où l’objectif opérationnel n’était pas « un portable » ; c’était « un serveur de stockage qui ne doit pas corrompre les données quand tout va mal ».
- La restitution d’espace dans ZFS a évolué : OpenZFS expose désormais des propriétés comme
usedbydataset,usedbysnapshotsetlogicalusedpour réduire les approximations. - Le comportement « espace de slop 1/8 » existe pour réduire les modes d’échec catastrophiques près des pools pleins ; ce n’est pas une plaisanterie d’interface.
- Historiquement, les administrateurs remplissaient les systèmes de fichiers à 99% parce qu’outils de l’ère ext leur avaient appris qu’ils pouvaient ; ZFS punit cette habitude car l’allocation et le comportement des metaslabs se dégradent fortement quand on approche du plein.
- La compression est passée de « hack de performance de niche » à « recommandation par défaut » pour de nombreux déploiements ZFS parce que les CPU modernes sont bon marché et le disque ne l’est pas.
- Les special vdevs (métadonnées/petits blocs sur SSD/NVMe) ont changé le profil de performance des charges « petits fichiers », mais ont aussi introduit de nouvelles façons d’épuiser le mauvais type d’espace.
- Les snapshots sont peu coûteux pour la création, pas pour la conservation ; la facture arrive quand les données churnent.
- Les images VM et couches de conteneurs ont rendu « fichier creux + churn + snapshots » un cocktail d’échec courant ; ce phénomène n’existait pas à cette échelle quand ZFS est né.
Un modèle mental pratique de l’espace ZFS
Quand vous lisez les statistiques d’espace ZFS, gardez trois seaux mentaux :
1) Octets logiques (ce que les applications croient avoir écrit)
Ce sont les tailles de fichiers, pages de bases de données, capacité virtuelle d’images VM. C’est ce avec quoi les humains veulent raisonner. ZFS peut l’exposer via logicalused et logicalreferenced.
2) Octets physiques (ce qui occupe réellement le pool)
C’est ce qui détermine si vous atteignez 80%, 90%, puis « tout est en feu ». Compression, copies, overhead de parité/RAIDZ et métadonnées tombent ici. ZFS l’expose via used, referenced et des champs usedby* plus détaillés.
3) Propriété/attribution (qui « possède » les blocs à travers le temps)
Avec les snapshots, des blocs peuvent être partagés par plusieurs « vues » de données. Votre filesystem actif peut ne plus référencer un bloc, mais un snapshot le fait, donc le pool le conserve. du ne peut pas le voir parce qu’il parcourt l’arbre vivant, pas l’arbre historique.
Ce que du mesure (et ce qu’il ignore)
du parcourt les répertoires et additionne les blocs alloués pour les fichiers accessibles. C’est utile, mais il a des angles morts sur ZFS :
- Snapshots : Un snapshot ne fait pas partie de l’arbre de répertoire vivant, donc
duignore l’espace épinglé par les snapshots à moins que vous ne traversiez explicitement.zfs/snapshot(si exposé). - Métadonnées et overhead du dataset :
durapporte les allocations de fichiers, pas les métadonnées ZFS comme les pointeurs de blocs, l’overhead des spacemaps et les blocs indirects qui augmentent avec la fragmentation et le churn. - Véracité de la compression :
durapporte typiquement les blocs alloués vus par l’OS. Sur ZFS, il peut être plus proche du « physique » que du « logique », mais le comportement exact dépend de la plateforme et des options (--apparent-sizevs défaut). - Réservations : Si un dataset a une réservation, le pool a de la capacité mise de côté, mais
dune vous le dira pas. - Trous/régions creuses :
ducompte les blocs alloués ; les zéros creux ne comptent pas sauf s’ils sont écrits.
Ce que zfs list mesure (et pourquoi ça paraît « plus gros »)
zfs list est de la comptabilité de blocs, pas une traversée de répertoire. Ses colonnes par défaut sont trompeuses de simplicité :
USED: espace physique consommé par le dataset et ses descendants (selon le contexte), incluant l’espace référencé par des snapshots.AVAIL: ce que ZFS vous permettra d’allouer, en tenant compte de l’espace libre du pool, des quotas, des réservations et du slop space.REFER: espace physique accessible par ce dataset (n’inclut pas les descendants).
Ces mots sont exacts mais incomplets. En production, vous voulez presque toujours les colonnes détaillées, car USED est une figure composite.
Snapshots : le suspect habituel
La plupart des désaccords entre du et zfs list sont « les snapshots retiennent des blocs supprimés/écrasés ». Le copy-on-write signifie que les modifications allouent de nouveaux blocs, et les snapshots conservent les anciens. Si vous supprimez un répertoire de 500G aujourd’hui, et que le snapshot d’hier soir existe toujours, ces blocs sont toujours dans le pool.
Cela empire avec les charges à fort churn : bases de données, images VM, couches de conteneurs et tout ce qui réécrit de gros fichiers en place. Le dataset actif peut paraître petit (du), mais son jeu de snapshots préserve silencieusement l’historique en blocs physiques (zfs list).
Blague #2 : Les snapshots sont comme ce canal Slack « temporaire » — peu coûteux à créer, cher à conserver, et personne ne veut être celui qui le supprime.
Compression, espace logique et pourquoi on se fait piéger
La compression est l’endroit où l’intuition meurt. Sur un dataset compressé :
ls -laffiche la taille logique du fichier.du(par défaut) montre souvent l’espace alloué, qui peut suivre l’utilisation physique de plus près.zfs listUSEDest l’utilisation physique (avec les réserves/snapshots en tête).zfs get logicalusedmontre l’utilisation logique (ce qui a été écrit avant compression).
Donc vous pouvez voir du plus petit que zfs list parce que les snapshots épinglent des blocs anciens, mais vous pouvez aussi voir l’inverse : du --apparent-size peut afficher « plus grand » que la réalité physique à cause de la compression.
Opérationnellement : pour la planification de capacité, vous vous souciez des octets physiques dans le pool. Pour la recharge ou les attentes des locataires, vous vous souciez des octets logiques. Choisissez-en un, étiquetez-le et ne mélangez pas les deux dans le même tableau.
Fichiers creux, zvols et « alloué » vs « écrit »
Les fichiers creux sont un générateur classique de décalage : une image de disque VM peut avoir une taille logique « 1T » mais seulement 80G alloués. du et les statistiques physiques de ZFS auront tendance à s’accorder sur « alloué », tandis que les équipes applicatives continuent de citer la taille logique et se demandent pourquoi « ça ne rentre pas ».
Les zvols ajoutent une couche : ce sont des périphériques bloc vivant à l’intérieur de ZFS. Ils peuvent être thick ou thin selon les réglages (volmode, comportement de provisionnement, et patrons d’écriture de la machine invitée). Snapshotter des zvols est courant dans les piles VM ; c’est aussi un excellent moyen de préserver une quantité impressionnante de churn.
Métadonnées, xattrs, ACL et taxe sur petits fichiers
Certaines charges sont majoritairement des métadonnées : millions de petits fichiers, xattrs lourds, arbres riches en ACL, ou motifs de type maildir. L’overhead des métadonnées ZFS n’est pas gratuit, et il n’apparaît pas comme « octets de fichier ». du peut sous-estimer l’empreinte parce qu’il additionne les allocations de fichiers, pas tous les blocs indirects, dnodes et structures métadonnées nécessaires pour garder le système de fichiers cohérent et rapide.
Si vous avez déjà vu un dataset de « petits fichiers » manger un pool, vous apprenez à ne plus faire confiance aux moyennes comme « les fichiers font seulement 4K ». Ils ne le sont pas. Le fichier fait 4K ; l’écosystème autour du fichier représente le reste de votre week-end.
Réservations, quotas, refreservations et slop space
Les réservations créent une « utilisation fantôme » du point de vue de du. ZFS peut mettre de l’espace de côté pour un dataset (reservation ou refreservation) même si les fichiers ne l’utilisent pas. ZFS rapporte cet espace réservé comme utilisé/indisponible parce qu’il est promis à quelqu’un.
Les quotas (quota, refquota) contraignent l’allocation. Ils n’expliquent pas directement les écarts du vs zfs list, mais ils expliquent « pourquoi AVAIL est plus petit que prévu ».
Puis il y a le slop space : ZFS retient typiquement une portion de l’espace libre du pool pour éviter que les allocations et mises à jour de métadonnées n’échouent de manière catastrophique près de 100%. Donc même si vous « avez » de l’espace libre, ZFS peut refuser de le distribuer.
copies=2, special vdevs et autres pièges
La propriété copies est un multiplicateur silencieux : copies=2 stocke deux copies des données utilisateur (dans le même pool). Super pour certains besoins de fiabilité ; terrible si vous l’oubliez et puis comparez avec du.
Les special vdevs (métadonnées/petits blocs sur SSD/NVMe) peuvent faire ressentir ZFS comme un autre système de fichiers. Mais ils créent aussi un second domaine de capacité : vous pouvez manquer d’espace sur le special vdev alors que le pool principal semble correct. Votre « problème d’espace » devient un « mauvais vdev plein », et les symptômes sont subtils jusqu’à ce qu’ils ne le soient plus.
Trois mini-histoires du monde corporate
Mini-histoire 1 : Un incident causé par une mauvaise hypothèse
Le ticket a commencé comme une plainte financière : « Le stockage nous facture 40% de plus que ce que nous stockons. » L’équipe a lancé du sur le répertoire du projet et s’est sentie confiante. Les chiffres étaient petits. Les chiffres de facturation étaient gros. Quelqu’un a conclu que les rapports de l’équipe stockage étaient gonflés et a escaladé.
Nous avons regardé le dataset et vu le schéma habituel : un système CI générant des artefacts, les supprimant, en générant d’autres, et faisant cela toute la journée. Le dataset avait aussi une politique « snapshots horaires, conservation 30 jours » copiée d’une charge plus stable. L’arbre vivant était modeste ; les snapshots étaient essentiellement un registre archéologique des sorties de build.
L’erreur immédiate n’était pas « les snapshots existent ». C’était de supposer que du mesurait la même chose que la consommation du pool. La sortie du du projet était vraie pour « ce qui existe maintenant ». Elle était hors sujet pour « les blocs que le pool doit conserver ».
Nous n’avons pas supprimé tous les snapshots ; c’est ainsi qu’on se fait des ennemis. Nous avons adapté la rétention pour ce dataset au profil de churn, puis introduit un dataset séparé pour les artefacts avec une rétention plus courte et sans snapshots longue durée. La facturation a cessé d’être un débat parce que les chiffres étaient désormais alignés avec l’intention.
L’élément de postmortem qui a compté : chaque dataset a reçu une étiquette de classe de données explicite (artefacts de build éphémères, répertoires personnels, bases de données, images VM) et des politiques de snapshot ont été attachées à la classe, pas aux humeurs.
Mini-histoire 2 : Une optimisation qui s’est retournée contre eux
Une équipe axée performance a activé une compression agressive et ajusté le recordsize sur un dataset à charge mixte. Leur bench avait l’air super : moins d’IO disque, plus de hits en cache, meilleur débit. Ils l’ont déployé largement et ont déclaré victoire.
Puis les fenêtres de sauvegarde ont commencé à déraper. Pas parce que ZFS était devenu plus lent, mais parce que les snapshots ont commencé à retenir beaucoup plus de blocs uniques que prévu. La charge incluait de gros fichiers fréquemment modifiés sur de petites régions. Un choix de recordsize qui était « bien pour le débit séquentiel » a augmenté l’amplification d’écriture pour les mises à jour aléatoires. Chaque petit changement a provoqué plus de churn de blocs, que les snapshots ont fidèlement préservé. L’utilisation physique a grimpé plus vite que le modèle de quiconque.
L’ironie : l’« optimisation » a amélioré la performance en direct tout en augmentant silencieusement le coût de stockage à long terme de la stratégie de snapshots. Et parce que le pool avait été dimensionné pour l’ancien profil de churn, la croissance ressemblait à une fuite.
La correction n’a pas été d’abandonner la compression. C’était de segmenter les charges : datasets séparés avec recordsize approprié, rétention de snapshots ajustée au churn, et surveillance de written par intervalle de snapshot. La leçon était ennuyeuse : l’optimisation sans comptabilité de cycle de vie ne fait que déplacer le coût d’un axe à un autre.
Mini-histoire 3 : Une pratique ennuyeuse mais correcte qui a sauvé la mise
Une autre organisation avait une règle barbante : chaque dataset doit avoir un rapport mensuel de « comptabilité d’espace » incluant usedbydataset, usedbysnapshots, et une liste des principaux consommateurs de snapshots. Les gens se plaignaient que c’était de la paperasserie. Ce n’était pas de la paperasserie ; c’était de la reconnaissance.
Un trimestre, un pool a commencé à tendre vers 85% malgré des métriques business stables. Personne n’a paniqué parce que les rapports mensuels montraient un changement : usedbysnapshots augmentait, mais usedbydataset non. Ce n’est pas « plus de données » ; c’est « plus d’historique par unité de données », ce qui signifie généralement que le churn a augmenté ou que la rétention a changé.
Ils l’ont détecté tôt : une application était passée de logs en append-only à des réécritures périodiques d’un gros fichier d’état, augmentant fortement le churn. Parce que l’équipe surveillait déjà l’espace de snapshot comme métrique de premier plan, ils ont pu réagir avant que le pool n’atteigne la zone dangereuse.
La correction a été presque insultante de simplicité : changer l’application pour écrire de nouveaux fichiers et faire de la rotation, et raccourcir la rétention des snapshots pour ce dataset. Pas de migration héroïque des données. Pas d’achat d’urgence de capacité. La pratique ennuyeuse — mesurer la bonne ventilation — a sauvé la mise.
Tâches pratiques : commandes et interprétation
Voici les gestes de terrain que j’utilise quand quelqu’un dit « ZFS utilise plus d’espace que du. » Chaque tâche inclut quoi rechercher et comment l’interpréter.
Task 1: Get a truthful dataset breakdown (usedby*)
cr0x@server:~$ zfs list -o name,used,refer,usedbydataset,usedbysnapshots,usedbychildren,usedbyrefreservation tank/proj
NAME USED REFER USEDBYDATASET USEDBYSNAPSHOTS USEDBYCHILDREN USEDBYREFRESERV
tank/proj 3.40T 1.95T 1.80T 1.55T 50.0G 0B
Interprétation : Le décalage est là : les snapshots représentent 1,55T. du reflète majoritairement le ~1,8T du dataset vivant (plus ou moins compression/métadonnées), pas l’historique des snapshots.
Task 2: Compare du “allocated” vs “apparent” sizes
cr0x@server:~$ du -sh /tank/proj
1.9T /tank/proj
cr0x@server:~$ du -sh --apparent-size /tank/proj
2.6T /tank/proj
Interprétation : du par défaut se rapproche des blocs alloués ; la taille apparente est la taille logique des fichiers. Si la compression est activée, le logique peut être beaucoup plus grand que le physique.
Task 3: Check compression ratio and logical space at the dataset level
cr0x@server:~$ zfs get -o name,property,value -H compressratio,compression,logicalused,logicalreferenced tank/proj
tank/proj compressratio 1.37x
tank/proj compression lz4
tank/proj logicalused 4.65T
tank/proj logicalreferenced 2.70T
Interprétation : Les octets logiques sont plus élevés que les physiques. Si quelqu’un compare des totaux logiques à l’occupation physique du pool, vous aurez une dispute au lieu d’un plan.
Task 4: List snapshots and see which ones are expensive
cr0x@server:~$ zfs list -t snapshot -o name,used,refer,creation -s used tank/proj
NAME USED REFER CREATION
tank/proj@daily-2025-12-01 120G 1.95T Mon Dec 1 00:00 2025
tank/proj@daily-2025-11-30 118G 1.95T Sun Nov 30 00:00 2025
tank/proj@hourly-2025-12-24-23 22G 1.95T Wed Dec 24 23:00 2025
Interprétation : USED du snapshot est « l’espace unique attribuable à ce snapshot » (changements depuis le snapshot précédent de cette lignée). De grands nombres indiquent un fort churn pendant cet intervalle.
Task 5: Find the “written since snapshot” signal (great for churn)
cr0x@server:~$ zfs get -H -o name,property,value written tank/proj
tank/proj written 0B
cr0x@server:~$ zfs snapshot tank/proj@now
cr0x@server:~$ zfs get -H -o name,property,value written tank/proj
tank/proj written 18.4G
Interprétation : written est la quantité de données écrites depuis le dernier snapshot. Si c’est énorme chaque heure, une rétention longue coûtera cher.
Task 6: Confirm whether .zfs snapshots are visible and whether du is walking them
cr0x@server:~$ zfs get -H -o value snapdir tank/proj
hidden
cr0x@server:~$ ls -la /tank/proj/.zfs
ls: cannot access '/tank/proj/.zfs': No such file or directory
Interprétation : Si snapdir=visible, un du imprudent pourrait traverser les snapshots et « compter en double » d’un point de vue humain. Si c’est hidden, du ignorera complètement les snapshots.
Task 7: Look for reservations and refreservations
cr0x@server:~$ zfs get -H -o name,property,value reservation,refreservation tank/proj
tank/proj reservation 0B
tank/proj refreservation 500G
Interprétation : Un refreservation peut rendre le dataset « gros » du point de vue de ZFS même si les fichiers sont petits. C’est de l’espace promis aux données référencées par ce dataset.
Task 8: Inspect quotas and refquotas (why AVAIL looks wrong)
cr0x@server:~$ zfs get -H -o name,property,value quota,refquota,avail,used tank/proj
tank/proj quota 2T
tank/proj refquota none
tank/proj avail 120G
tank/proj used 1.88T
Interprétation : Même si le pool a de l’espace libre, un quota limite la croissance. Les gens confondent souvent cela avec « capacité mystérieusement manquante ». C’est la politique qui fait son travail.
Task 9: Check pool health and slop-space reality via zpool list
cr0x@server:~$ zpool list -o name,size,alloc,free,capacity,health tank
NAME SIZE ALLOC FREE CAPACITY HEALTH
tank 20.0T 17.2T 2.80T 86% ONLINE
Interprétation : À ~86% plein, vous êtes dans la zone où la fragmentation et le comportement d’allocation peuvent devenir mauvais. Attendez-vous aussi à ce que zfs list AVAIL soit plus petit que « FREE » à cause du slop space et des contraintes au niveau du dataset.
Task 10: Find datasets with heavy snapshot overhead across the pool
cr0x@server:~$ zfs list -o name,used,usedbydataset,usedbysnapshots -r tank | head
NAME USED USEDBYDATASET USEDBYSNAPSHOTS
tank 17.2T 2.10T 14.7T
tank/proj 3.40T 1.80T 1.55T
tank/vm 8.90T 2.40T 6.30T
tank/home 2.10T 1.95T 120G
Interprétation : Quand usedbysnapshots domine, le pool paye pour l’historique. Cela peut être voulu — mais cela doit être intentionnel.
Task 11: Spot “deleted but still used” space: open file handles
cr0x@server:~$ sudo lsof +L1 | head
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME
java 2114 app 123w REG 0,119 1048576 0 912345 /tank/proj/logs/app.log (deleted)
Interprétation : Ce n’est pas spécifique à ZFS, mais c’est un coupable fréquent. Le fichier est supprimé, du ne le compte pas, mais l’espace reste alloué jusqu’à ce que le processus le ferme.
Task 12: Estimate small-file pressure and metadata-heavy trees
cr0x@server:~$ find /tank/proj -xdev -type f -size -16k | wc -l
4821931
cr0x@server:~$ du -sh /tank/proj
1.9T /tank/proj
Interprétation : Des millions de petits fichiers impliquent de l’overhead métadonnées et une pression possible sur le special-vdev (si configuré). Si vos « données » sont petites mais que vous avez un énorme nombre de fichiers, attendez-vous à ce que le pool se comporte différemment qu’avec une charge de gros fichiers.
Task 13: Check recordsize and volblocksize choices (write amplification clues)
cr0x@server:~$ zfs get -H -o name,property,value recordsize tank/proj
tank/proj recordsize 1M
cr0x@server:~$ zfs get -H -o name,property,value volblocksize tank/vm/zvol01
tank/vm/zvol01 volblocksize 128K
Interprétation : Un grand recordsize peut être excellent pour l’IO en flux, mais peut augmenter le coût de churn sous snapshots pour des mises à jour aléatoires. Le volblocksize des zvols importe de la même façon.
Task 14: Detect copies property multiplying usage
cr0x@server:~$ zfs get -H -o name,property,value copies tank/proj
tank/proj copies 2
Interprétation : Vous payez double pour les blocs de données (plus les métadonnées). Si personne n’avait l’intention de ça, c’est une explication claire du « pourquoi ZFS est plus gros que du ».
Task 15: Show refreservation impact on referenced space specifically
cr0x@server:~$ zfs list -o name,refer,usedbyrefreservation tank/proj
NAME REFER USEDBYREFRESERV
tank/proj 1.95T 500G
Interprétation : Même si REFER est stable, le dataset a 500G réservés pour lui. Cela réduit la flexibilité du pool et explique « pourquoi l’espace libre a disparu ».
Méthode de diagnostic rapide
Voici la méthode « j’ai 10 minutes avant un appel de revue de capacité ». Elle ne résoudra pas tout, mais vous dira dans quelle direction courir.
First: determine if the discrepancy is snapshots, reservations, or something else
cr0x@server:~$ zfs list -o name,used,refer,usedbydataset,usedbysnapshots,usedbyrefreservation tank/target
NAME USED REFER USEDBYDATASET USEDBYSNAPSHOTS USEDBYREFRESERV
tank/target 3.4T 1.9T 1.8T 1.6T 0B
Si usedbysnapshots est important : c’est la rétention historique + churn.
Si usedbyrefreservation est important : c’est la politique/la réservation.
Si usedbydataset est important mais que du est petit : suspectez des fichiers ouverts-supprimés, des cas spéciaux comme copies, ou un du qui parcourt le mauvais point de montage.
Second: check whether du is measuring logical or physical, and whether it’s crossing boundaries
cr0x@server:~$ du -sh /tank/target
cr0x@server:~$ du -sh --apparent-size /tank/target
cr0x@server:~$ mount | grep 'tank/target'
Ce que vous apprenez : si vous comparez des octets alloués vs apparents, et si le chemin que vous scannez est réellement le dataset que vous pensez.
Third: identify churn rate and the snapshot retention policy
cr0x@server:~$ zfs get -H -o name,property,value written,com.sun:auto-snapshot tank/target
tank/target written 220G
tank/target com.sun:auto-snapshot true
Ce que vous apprenez : Si written bondit de centaines de gigaoctets par intervalle, une rétention longue dominera l’utilisation physique.
Fourth: confirm pool fullness and whether you’re hitting the “near full” pain curve
cr0x@server:~$ zpool list -o name,alloc,free,capacity tank
NAME ALLOC FREE CAPACITY
tank 17.2T 2.8T 86%
Ce que vous apprenez : À haute utilisation, tout devient plus difficile : les libérations n’apparaissent pas rapidement (parce qu’elles sont détenues par des snapshots), les allocations se fragmentent, les performances peuvent chuter, et « AVAIL » devient politique.
Erreurs courantes, symptômes et corrections
Mistake 1: Using zfs list USED as “live data size”
Symptôme : USED du dataset est énorme, mais du est plus petit et les équipes applicatives jurent que rien n’a changé.
Cause : USED inclut l’espace référencé par les snapshots (et potentiellement les réservations).
Correction : Utilisez usedbydataset pour les données actives et usedbysnapshots pour l’overhead historique ; ajustez la rétention des snapshots ou le comportement de churn.
Mistake 2: Treating “deleted files” as immediately freed space
Symptôme : rm -rf s’exécute, du baisse, mais l’espace du pool ne récupère pas.
Cause : Les snapshots référencent encore ces blocs ; ou un processus garde le fichier ouvert (supprimé-mais-ouvert).
Correction : Vérifiez les consommateurs de snapshots ; lancez lsof +L1 ; redémarrez/relancez les processus mal configurés ; expirez les snapshots intentionnellement.
Mistake 3: Comparing du –apparent-size to zfs USED
Symptôme : du --apparent-size indique 10T, ZFS indique 4T ; quelqu’un appelle cela « données manquantes ».
Cause : La compression (et parfois les fichiers creux) réduit l’utilisation physique.
Correction : Décidez si vous voulez une comptabilité logique ou physique. Utilisez logicalused avec used et étiquetez clairement les graphiques.
Mistake 4: Ignoring refreservation and then wondering where capacity went
Symptôme : L’espace libre du pool diminue plus vite que la croissance des données actives ; AVAIL semble bas partout.
Cause : refreservation épingle de l’espace même s’il n’est pas utilisé par des fichiers.
Correction : Auditez refreservation/reservation sur les datasets ; supprimez ou redimensionnez. Gardez des réservations pour les workloads qui ont vraiment besoin d’un garanti.
Mistake 5: Snapshotting high-churn VM images like they’re home directories
Symptôme : L’espace des snapshots croît de façon explosive ; les rollbacks fonctionnent bien, la capacité non.
Cause : Écritures aléatoires + COW + snapshots fréquents = beaucoup de blocs uniques retenus.
Correction : Ajustez fréquence/retention des snapshots ; considérez le rythme de réplication ; séparez les datasets VM ; assurez-vous que recordsize/volblocksize correspondent au pattern IO.
Mistake 6: copies=2 enabled “temporarily” and forgotten
Symptôme : L’espace utilisé est à peu près le double de ce à quoi vous vous attendiez ; pas de coupable évident dans les snapshots.
Cause : La propriété copies duplique les blocs.
Correction : Auditez avec zfs get copies -r. Si vous la retirez, comprenez que cela affecte les nouvelles écritures ; les blocs existants peuvent rester jusqu’à réécriture.
Mistake 7: Running the pool too full, then calling it a capacity bug
Symptôme : Les écritures ralentissent, les libérations ne semblent pas aider, erreurs d’allocation près de « encore du libre ».
Cause : Haute fragmentation + slop space + contraintes des metaslabs.
Correction : Gardez les pools en dessous d’un seuil raisonnable (beaucoup d’équipes visent en dessous d’environ ~80% pour des workloads générales). Agrandissez la capacité ou migrez les données avant d’atteindre la falaise.
Listes de vérification / plan étape par étape
Checklist: “du smaller than zfs list USED” (most common)
- Exécuter
zfs list -o usedbydataset,usedbysnapshots,usedbyrefreservationpour le dataset. - Si
usedbysnapshotsest large, lister les snapshots triés parusedet identifier la politique de rétention. - Vérifier le taux de churn avec
zfs get writtenentre intervalles de snapshot. - Confirmer que personne n’autosnapshote trop fréquemment (propriétés d’automatisation, cron, outils d’orchestration).
- Vérifier les fichiers ouverts-supprimés avec
lsof +L1. - Décider : changer la rétention, changer le comportement de churn, ou acheter de la capacité. Ne « supprimez pas juste des snapshots au hasard » sans comprendre les dépendances de réplication/sauvegarde.
Checklist: “zfs list REFER smaller than du”
- Vérifier si vous avez utilisé
du --apparent-size(logique) tandis queREFERest physique. - Vérifier les réglages de compression et
compressratio. - Pour les fichiers creux, comparer
ls -ltaille logique vsdualloué. - S’assurer que
dune traverse pas des points de montage ou ne scanne pas un chemin différent du montage du dataset.
Checklist: “AVAIL is much smaller than pool free”
- Vérifier
quota/refquotaetreservation/refreservationdu dataset. - Vérifier l’utilisation du pool (
zpool list) et considérer le comportement du slop space. - Rechercher d’autres datasets avec de grandes réservations qui épinglent la capacité.
- Si le pool est proche du plein, cessez de traiter « FREE » comme utilisable ; planifiez extension/migration.
FAQ
1) Which number should I trust: du or zfs list?
Faites confiance à celui qui correspond à votre question. Pour « quelle est la taille de l’arbre de répertoire vivant », utilisez du (alloué) ou du --apparent-size (logique). Pour « quelle capacité du pool est consommée », utilisez la comptabilité physique ZFS (zfs list plus la ventilation usedby*).
2) Why does deleting files not free space in the pool?
Parce que les snapshots conservent les anciens blocs. La suppression enlève seulement la référence vivante. L’espace revient quand aucun snapshot (et aucune clone) ne référence ces blocs. Vérifiez aussi les fichiers supprimés-mais-ouverts avec lsof +L1.
3) What does zfs list REFER mean?
REFER est la quantité d’espace physique référencée par le dataset lui-même (pas ses descendants). C’est plus proche de la « vue vivante » que USED, mais cela ne correspondra toujours pas à du --apparent-size sur des datasets compressés.
4) What does “snapshot USED” actually represent?
Le USED d’un snapshot est la quantité d’espace qui serait libérée si ce snapshot était détruit, en supposant qu’aucun autre snapshot/clone ne référence les mêmes blocs. C’est une estimation de « contribution unique », pas la « taille du snapshot » comme les gens l’imaginent.
5) Why is AVAIL smaller than zpool FREE?
Parce que AVAIL est contraint par les quotas/réservations du dataset et par le comportement du pool (y compris le slop space). ZFS est conservateur volontairement près des pools pleins.
6) Can du ever be larger than zfs list?
Oui, si vous utilisez du --apparent-size (tailles logiques) sur un dataset compressé, ou quand des fichiers creux rapportent une grande taille logique. L’utilisation physique ZFS peut être bien plus petite dans ce cas.
7) How do I find what’s consuming snapshot space?
Commencez par identifier les datasets où usedbysnapshots est élevé, puis listez les snapshots triés par used. Ensuite, mesurez le churn avec written par intervalle de snapshot. Enfin, corrélez avec les changements de charge (churn VM, opérations de maintenance DB, patterns d’artefacts CI).
8) Does compression make snapshots cheaper or more expensive?
Les deux, selon la charge. La compression réduit la taille physique de chaque bloc, donc conserver d’anciens blocs peut coûter moins cher. Mais si la compression change l’empaquetage des enregistrements ou le comportement de la charge, elle peut aussi augmenter le churn et donc les blocs uniques retenus par les snapshots. Mesurez written et used des snapshots plutôt que de deviner.
9) Are reservations “wasted space”?
Ce sont des espaces réservés — capacité retenue pour qu’un dataset puisse continuer à écrire sous contention. Ce n’est pas du gaspillage si cela évite des pannes pour des services critiques. C’est du gaspillage si vous la définissez et l’oubliez partout.
10) Is it safe to just delete snapshots to get space back?
Mécaniquement, oui ; opérationnellement, « ça dépend ». Les snapshots peuvent faire partie de votre chaîne de sauvegarde/réplication, ou être requis pour des objectifs de récupération. Supprimez intentionnellement : choisissez une politique de rétention, validez le comportement de réplication, et supprimez les snapshots dans le bon ordre si des outils l’attendent.
Conclusion
du et zfs list divergent parce qu’ils mesurent des réalités différentes : l’arborescence du système de fichiers atteignable vs la propriété des blocs du pool à travers le temps, la politique et les métadonnées. ZFS ne ment pas ; il vous dit l’historique, les promesses (réservations) et la physique (compression, tailles de blocs, overhead).
Le mouvement opérationnel est d’arrêter de se disputer sur « le bon chiffre » et de standardiser quel chiffre vous utilisez pour quelle décision : octets logiques pour les attentes utilisateur, octets physiques pour la capacité, et une ventilation snapshot/churn pour tout ce qui concerne la rétention. Une fois cela fait, la divergence cesse d’être mystérieuse — et devient un levier sur lequel agir.