Comptabilité de l’espace ZFS : pourquoi du et zfs list divergent

Cet article vous a aidé ?

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 :

  1. 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.
  2. 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 ».
  3. La restitution d’espace dans ZFS a évolué : OpenZFS expose désormais des propriétés comme usedbydataset, usedbysnapshots et logicalused pour réduire les approximations.
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. Les snapshots sont peu coûteux pour la création, pas pour la conservation ; la facture arrive quand les données churnent.
  9. 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 du ignore l’espace épinglé par les snapshots à moins que vous ne traversiez explicitement .zfs/snapshot (si exposé).
  • Métadonnées et overhead du dataset : du rapporte 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 : du rapporte 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-size vs défaut).
  • Réservations : Si un dataset a une réservation, le pool a de la capacité mise de côté, mais du ne vous le dira pas.
  • Trous/régions creuses : du compte 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 -l affiche 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 list USED est l’utilisation physique (avec les réserves/snapshots en tête).
  • zfs get logicalused montre 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)

  1. Exécuter zfs list -o usedbydataset,usedbysnapshots,usedbyrefreservation pour le dataset.
  2. Si usedbysnapshots est large, lister les snapshots triés par used et identifier la politique de rétention.
  3. Vérifier le taux de churn avec zfs get written entre intervalles de snapshot.
  4. Confirmer que personne n’autosnapshote trop fréquemment (propriétés d’automatisation, cron, outils d’orchestration).
  5. Vérifier les fichiers ouverts-supprimés avec lsof +L1.
  6. 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”

  1. Vérifier si vous avez utilisé du --apparent-size (logique) tandis que REFER est physique.
  2. Vérifier les réglages de compression et compressratio.
  3. Pour les fichiers creux, comparer ls -l taille logique vs du alloué.
  4. S’assurer que du ne 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”

  1. Vérifier quota/refquota et reservation/refreservation du dataset.
  2. Vérifier l’utilisation du pool (zpool list) et considérer le comportement du slop space.
  3. Rechercher d’autres datasets avec de grandes réservations qui épinglent la capacité.
  4. 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.

← Précédent
WireGuard : configuration client la plus simple sur Windows/macOS/Linux (et les pièges habituels)
Suivant →
Docker « bind: address already in use » : trouver le processus et corriger proprement

Laisser un commentaire