Ça arrive toujours au pire moment : fenêtre de déploiement, téléphone d’astreinte qui sonne, tableaux de bord qui hurlent, et quelqu’un annonce « Le disque est à 100 % ». Cette affirmation est à la fois utile et terriblement incomplète. Quel disque ? Quel système de fichiers ? Espace réel, espaces réservés, inodes, pools à provisionnement fin, ou un montage factice qui n’est même pas l’endroit où votre application écrit ?
Se tromper ici ne fait pas que perdre du temps. Ça crée de nouveaux incidents : suppression des mauvais fichiers, corruption de bases de données, ou « correction » temporaire qui conduit à un nouveau page dans une heure. Faisons la version mature : identifiez ce qui est vraiment plein, pourquoi c’est arrivé, et comment réparer sans jouer avec vos données.
Quand « 100 % disque » ne veut pas dire ce que vous croyez
« Utilisation du disque 100 % » peut signifier au moins huit choses différentes. Certaines sont simples (« le système de fichiers n’a plus de blocs libres »). D’autres sont sournoises (« des blocs libres existent mais vous ne pouvez pas les utiliser »). D’autres encore sont trompeuses (« l’espace est libre, mais le noyau le garde parce qu’un processus a le fichier ouvert »). Si vous ne faites pas la distinction, vous ferez le geste classique : supprimer un fichier, ne pas récupérer d’espace, paniquer, et supprimer davantage. Ce n’est pas de l’ingénierie. C’est de l’agitation.
Commencez par l’unité de vérité : système de fichiers vs périphérique bloc vs pool
Au minimum, vous devez savoir quelle couche est pleine :
- Système de fichiers (ext4/xfs/btrfs/dataset ZFS) : fichiers et répertoires, inodes, blocs réservés, snapshots, quotas.
- Périphérique bloc (LVM LV, NVMe, volume EBS) : la capacité sous-jacente ; il peut être sain pendant que le système de fichiers ne l’est pas (ou l’inverse).
- Pool de stockage (pool ZFS, thin pool LVM, Ceph) : provisionnement fin, métadonnées, snapshots, et comptabilité « logique vs physique ».
- Couche conteneur/overlay : Docker overlay2, snapshotters containerd, stockage éphémère Kubernetes ; les écritures ne sont pas forcément là où vous croyez.
Les trois mauvaises interprétations les plus courantes
- Espace vs inodes : « df dit plein » n’est pas la même chose que « df -i dit plein ». Les corrections diffèrent.
- Fichiers supprimés mais ouverts : vous avez supprimé le fichier, mais l’espace ne revient pas tant que le processus qui le tient ne le ferme pas.
- Snapshots et copy-on-write : vous avez « supprimé » des données mais des snapshots référencent encore les blocs, donc le pool reste plein.
Blague #1 : Le disque est comme un hôtel. « Nous avons des chambres vides » n’aide pas si chaque clé de chambre est toujours cochée.
Méthode de diagnostic rapide (premier/deuxième/troisième)
Ceci est la version pour l’astreinte. Elle priorise : arrêter l’hémorragie, identifier la contrainte réelle, éviter d’aggraver la situation.
Premier : confirmez ce qui est plein, à quelle couche
- Vérifiez l’utilisation du système de fichiers sur le(s) point(s) de montage suspect(s) :
df -hT. - Vérifiez l’utilisation des inodes :
df -i. - Vérifiez le périphérique bloc sous-jacent :
lsblk -fetpvs/vgs/lvssi LVM est impliqué. - Si ZFS : vérifiez dataset et pool :
zfs list,zpool list. - Si conteneurs : vérifiez le stockage overlay/conteneurs :
docker system dfoucrictl df.
Deuxième : trouvez rapidement le consommateur (l’étape « qu’est‑ce qui a grossi ? »)
- Taille des répertoires de premier niveau :
du -xhd1 /mount(restez sur un seul système de fichiers). - Croissance récente : triez par date de modification :
find ... -printf '%T@ %s %p\n'. - Journaux :
journalctl --disk-usage, vérifiez/var/loget les répertoires de logs applicatifs. - Fuite d’espace supprimé mais ouvert :
lsof +L1.
Troisième : choisissez un correctif sûr basé sur le mode de défaillance
- Fichiers occupant réellement de l’espace : supprimer/archiver/déplacer les données en toute sécurité, puis ajouter de la capacité ou réduire la rétention.
- Inodes épuisés : supprimer des millions de petits fichiers (cache/temp), repenser ou reconstruire le système de fichiers avec plus d’inodes (rarement plaisant).
- Snapshots : élaguer les snapshots ou changer la politique de snapshot. Ne supprimez pas des « fichiers au hasard » en espérant de la magie.
- Pool thin plein : étendre le pool ou supprimer des snapshots ; traitez cela comme un événement à haut risque.
- Supprimés mais ouverts : redémarrer/faire tourner le service fautif proprement (ou le tuer, si vous aimez les postmortems).
Tâches pratiques : commandes, sorties, décisions
Ce ne sont pas des « essayez ça ». Chaque tâche inclut : une commande exécutable, ce que la sortie vous dit, et la décision suivante. Supposons Linux sauf indication contraire. Exécutez en root quand nécessaire, mais ne transformez pas chaque problème de disque plein en hobby d’élévation de privilèges.
Tâche 1 : Identifier le système de fichiers plein (et son type)
cr0x@server:~$ df -hT
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/vg0-root ext4 80G 79G 0.6G 99% /
/dev/nvme0n1p1 vfat 511M 7.2M 504M 2% /boot/efi
tmpfs tmpfs 32G 96M 32G 1% /run
/dev/mapper/vg0-var xfs 200G 200G 20M 100% /var
Ce que cela signifie : /var est plein, et c’est du XFS. Vos journaux de base de données, couches de conteneurs et journaux systemd se trouvent souvent ici.
Décision : Concentrez-vous sur /var. Ne supprimez pas des fichiers dans / en espérant aider. Notez aussi le type de système de fichiers : XFS se comporte différemment d’ext4 (pas de redimensionnement à la baisse, comportement des blocs réservés différent).
Tâche 2 : Vérifier l’épuisement des inodes (le tueur silencieux)
cr0x@server:~$ df -i /var
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/mapper/vg0-var 13107200 13107190 10 100% /var
Ce que cela signifie : Vous n’avez pratiquement plus d’inodes. Vous pouvez encore avoir des octets libres et être bloqué. Beaucoup de petits fichiers ont causé cela.
Décision : Arrêtez de chercher des « gros fichiers ». Trouvez des répertoires avec des millions d’entrées (caches, tmp, spool mail, couches de conteneurs) et supprimez-les en toute sécurité.
Tâche 3 : Trouver les plus grands répertoires sans traverser de montages
cr0x@server:~$ sudo du -xhd1 /var | sort -h
12M /var/tmp
220M /var/lib
1.6G /var/cache
48G /var/log
150G /var/lib/docker
Ce que cela signifie : /var/lib/docker est énorme. Ce n’est pas rare. C’est aussi souvent sous-estimé.
Décision : Inspectez le stockage des conteneurs avant de supprimer des journaux. Les journaux peuvent être le symptôme, les couches Docker la cause, ou l’inverse.
Tâche 4 : Obtenir la vérité côté Docker
cr0x@server:~$ sudo docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 47 12 62.3GB 44.8GB (71%)
Containers 36 8 9.1GB 7.9GB (86%)
Local Volumes 18 11 81.4GB 12.6GB (15%)
Build Cache 119 0 24.7GB 24.7GB (100%)
Ce que cela signifie : Le cache de build est entièrement récupérable. Les images et conteneurs arrêtés sont aussi récupérables. Les volumes locaux cachent souvent « des données qui comptent ».
Décision : Nettoyez d’abord le cache de build (sûr), puis les images/containers inutilisés, et touchez les volumes seulement si vous êtes certain qu’ils sont jetables.
Tâche 5 : Récupérer en toute sécurité le cache Docker et les artefacts inutiles
cr0x@server:~$ sudo docker builder prune -af
Deleted build cache objects:
m1r4nd4d1g3st:sha256:0c5b... 215.3MB
m1r4nd4d1g3st:sha256:8e21... 112.9MB
Total reclaimed space: 24.7GB
Ce que cela signifie : Vous avez récupéré de l’espace réel sans toucher aux volumes persistants.
Décision : Revérifiez df. Si c’est encore serré, lancez docker image prune et docker container prune. Planifiez ensuite une politique de rétention d’images pour éviter que cela ne se reproduise chaque semaine.
Tâche 6 : Trouver les fichiers supprimés mais encore ouverts (espace non libéré)
cr0x@server:~$ sudo lsof +L1 | head
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME
java 2214 app 12w REG 253,1 4294967296 0 90122 /var/log/app/server.log (deleted)
rsyslogd 912 syslog 7w REG 253,1 2147483648 0 72311 /var/log/syslog (deleted)
Ce que cela signifie : Des processus tiennent des fichiers journaux supprimés. Le système de fichiers ne peut pas libérer les blocs tant que ces descripteurs ne sont pas fermés.
Décision : Redémarrez proprement les services incriminés ou déclenchez une rotation de logs correcte. Tuer des processus est l’instrument brutal ; utilisez‑le seulement si vous êtes coincé.
Tâche 7 : Mesurer l’usage du journal systemd et le vacuumer
cr0x@server:~$ sudo journalctl --disk-usage
Archived and active journals take up 18.0G in the file system.
cr0x@server:~$ sudo journalctl --vacuum-size=2G
Deleted archived journal /var/log/journal/4c.../system@0005b1d2....journal (8.0G).
Deleted archived journal /var/log/journal/4c.../system@0005b1d9....journal (6.0G).
Vacuuming done, freed 16.0G of archived journals.
Ce que cela signifie : Journald accumulait l’historique. Ça arrive sur les nœuds très actifs, et ce n’est pas une faute morale.
Décision : Définissez une politique persistante (SystemMaxUse= dans la configuration journald) après l’incident. Ne faites pas du vacuum manuel un mode de vie.
Tâche 8 : Trouver rapidement les plus gros fichiers (par taille)
cr0x@server:~$ sudo find /var -xdev -type f -size +1G -printf '%s %p\n' | sort -nr | head
8589934592 /var/lib/docker/containers/1b.../1b...-json.log
4294967296 /var/log/app/server.log
2147483648 /var/lib/postgresql/15/main/pg_wal/000000010000000A000000FE
Ce que cela signifie : Les logs JSON des conteneurs sont énormes, plus un répertoire de segments WAL PostgreSQL qui grossit. Plusieurs consommateurs en cause.
Décision : Ajoutez des limites de logs pour le driver de logging Docker ; pour PostgreSQL, vérifiez la réplication/archivage et la rétention. Ne supprimez pas les fichiers WAL à la légère sauf si vous aimez reconstruire à partir de sauvegardes.
Tâche 9 : Vérifier la pression sur les WAL PostgreSQL et l’archivage
cr0x@server:~$ sudo -u postgres psql -c "select now(), pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),'0/0')) as wal_since_boot;"
now | wal_since_boot
------------------------------+---------------
2026-02-05 12:44:19.121+00 | 87 GB
(1 row)
Ce que cela signifie : Beaucoup de WAL ont été générés. Ce n’est pas automatiquement mauvais, mais c’est un indice.
Décision : Vérifiez si l’archivage/réplication est bloqué et cause la rétention des WAL. Si vous ne savez pas, arrêtez‑vous et faites intervenir le DBA. Disque plein + « improvisation sur les WAL » est une combinaison qui rend les carrières palpitantes.
Tâche 10 : Vérifier la santé du thin pool LVM (le provisionnement fin peut mordre)
cr0x@server:~$ sudo lvs -a -o +devices,seg_monitor,metadata_percent,data_percent
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert Devices
thinpool vg0 twi-aotz-- 500.00g 99.80 92.10 /dev/sdb(0)
vm-01 vg0 Vwi-aotz-- 80.00g thinpool 74.20 thinpool(0)
vm-02 vg0 Vwi-aotz-- 120.00g thinpool 68.15 thinpool(0)
Ce que cela signifie : Le thin pool est pratiquement plein. Quand un thin pool atteint 100 %, les écritures échouent de façon brutale et surprenante.
Décision : Étendez immédiatement le thin pool ou libérez de l’espace à l’intérieur (supprimez des snapshots/volumes thin inutilisés). Traitez cela en urgence ; ce n’est pas du « ménage ».
Tâche 11 : Confirmer les contraintes du pool/dataset ZFS (quotas, snapshots, réservation)
cr0x@server:~$ sudo zpool list
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 3.62T 3.55T 72.0G - - 39% 98% 1.00x ONLINE -
cr0x@server:~$ sudo zfs list -o name,used,avail,refer,mountpoint
NAME USED AVAIL REFER MOUNTPOINT
tank 3.55T 72.0G 128K /tank
tank/app 2.40T 20.0G 2.10T /tank/app
tank/app@daily-1 300G - 2.10T -
Ce que cela signifie : Le pool est à 98 % d’utilisation. Le dataset tank/app n’a que 20G disponibles. Un snapshot existe et peut maintenir l’espace bloqué.
Décision : Évaluez la rétention des snapshots et supprimez-les en toute sécurité s’ils sont la raison pour laquelle l’espace ne revient pas. Aussi : ne laissez pas les pools ZFS tourner à 98 % si vous aimez les chutes de performance.
Tâche 12 : Vérifier les blocs réservés ext4 (root a de l’espace, les utilisateurs non)
cr0x@server:~$ sudo tune2fs -l /dev/mapper/vg0-root | egrep 'Block count|Reserved block count|Reserved block percentage'
Block count: 20971520
Reserved block count: 1048576
Reserved block percentage: 5%
Ce que cela signifie : 5 % du système de fichiers est réservé (historique pour protéger root et réduire la fragmentation). Sur de grands volumes, cela peut représenter plusieurs Go.
Décision : Si c’est un volume de données (pas la racine système), envisagez de réduire les blocs réservés, mais faites‑le délibérément. Ne « libérez » pas l’espace en supprimant des garde‑fous sur des volumes critiques sans plan.
Tâche 13 : Identifier la création de fichiers incontrôlée (brûlage d’inodes) par répertoire
cr0x@server:~$ sudo find /var -xdev -type d -printf '%p\n' | while read -r d; do echo "$(find "$d" -maxdepth 1 -type f 2>/dev/null | wc -l) $d"; done | sort -nr | head
1200345 /var/cache/myapp
410221 /var/lib/docker/overlay2
99521 /var/spool/postfix/maildrop
Ce que cela signifie : Un répertoire de cache génère un nombre absurde de fichiers. C’est votre coupable pour les inodes.
Décision : Purgez le cache et corrigez la politique de cache de l’application (TTL, nombre max d’entrées, hachage de répertoire). Envisagez aussi de déplacer les caches vers tmpfs si c’est sûr, ou vers un fichier système dédié en planifiant les inodes.
Tâche 14 : Vérifier les points de montage (éviter de nettoyer au mauvais endroit)
cr0x@server:~$ mount | egrep ' /var | /var/lib/docker | / '
/dev/mapper/vg0-root on / type ext4 (rw,relatime)
/dev/mapper/vg0-var on /var type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)
Ce que cela signifie : Docker est sous /var sur cet hôte. Si vous pensiez qu’il vivait sur un LV différent, vous auriez nettoyé le mauvais système de fichiers et n’auriez rien appris.
Décision : Confirmez les montages avant d’agir. C’est ainsi que vous évitez « j’ai supprimé 20G et rien n’a changé » parce que vous avez supprimé sur le mauvais montage.
Tâche 15 : Suivre ce qui croit en ce moment (quand le disque se remplit en direct)
cr0x@server:~$ sudo bash -lc 'while true; do date; df -h /var; du -xhd1 /var/log | sort -h | tail -n 5; sleep 10; done'
Thu Feb 5 12:46:00 UTC 2026
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg0-var 200G 199G 380M 100% /var
1.3G /var/log/apt
4.8G /var/log/nginx
16G /var/log/journal
48G /var/log
Thu Feb 5 12:46:10 UTC 2026
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg0-var 200G 200G 120M 100% /var
Ce que cela signifie : L’utilisation augmente encore. Ce n’est pas « nettoyer et terminé ». Quelque chose écrit activement.
Décision : Identifiez l’écrivain (journaux, base de données, uploads). Envisagez d’arrêter temporairement le service ou de limiter le débit d’ingestion. Nettoyer sans arrêter la source, c’est passer la serpillière face à une inondation.
Les vraies causes (avec des corrections durables)
Cause 1 : Les journaux ont grossi parce que le système est suffisamment sain pour continuer à fonctionner
Les journaux sont le mange-disque classique car ils sont conçus pour ne jamais bloquer la charge principale. C’est bien… jusqu’à ce que ça ne le soit plus. Déclencheurs courants :
- Niveau de log debug laissé activé après un incident.
- Journaux d’accès sur un endpoint public lors d’une « scan storm ».
- Applications journalisant le corps complet des requêtes (oui, cela arrive en production).
- Journal systemd non borné sur des nœuds très occupés.
Corrections réelles :
- Définir des rétentions et des plafonds de taille (
logrotate, journaldSystemMaxUse). - Exporter les logs hors hôte, mais ne pas utiliser « on les envoie » comme excuse pour conserver des logs illimités sur disque.
- Rendre les niveaux de log configurables à l’exécution et par défaut sur une verbosité raisonnable.
Cause 2 : Les fichiers supprimés n’ont pas libéré d’espace (descripteurs ouverts)
La sémantique Unix est élégante : supprimer un nom de fichier ne supprime pas le fichier tant que personne ne l’utilise. Sur des hôtes très actifs, « personne » peut prendre beaucoup de temps.
Corrections réelles :
- Utiliser
lsof +L1pour trouver les fichiers supprimés mais ouverts. - Redémarrer proprement le processus (ou le forcer si nécessaire).
- Corriger la rotation des logs : assurer que le service rouvre ses logs (par ex. via SIGHUP) après rotation.
Cause 3 : Les inodes sont épuisés (l’espace existe, mais vous ne pouvez pas créer de fichiers)
Les inodes sont les « emplacements de fichiers » du système de fichiers. Si vous créez des millions de petits fichiers — fragments de cache, artefacts temporaires, couches d’images, files d’attente mail — vous pouvez atteindre 100 % d’utilisation des inodes alors que df -h semble correct. Le symptôme est souvent « No space left on device » avec une utilisation d’octets ridiculement basse.
Corrections réelles :
- Supprimer les répertoires à grand nombre de fichiers (cache, temp) et corriger le producteur.
- Utiliser moins de fichiers : empaqueter les objets, utiliser SQLite/LMDB, ou repenser la disposition du cache.
- Pour les cas extrêmes : reconstruire le système de fichiers avec plus d’inodes (planification ext4
-N) ou changer de système de fichiers adapté à la charge.
Cause 4 : Les snapshots maintiennent les blocs (surtout sur les systèmes CoW)
Sur ZFS et btrfs, les snapshots ne sont pas « gratuits ». Ils sont bon marché, mais pas gratuits. Supprimer un fichier ne libère pas forcément ses blocs si un snapshot les référence. C’est le comportement attendu. C’est aussi déroutant à 3h du matin.
Corrections réelles :
- Revoir les politiques de snapshot : fréquence, rétention et quels datasets sont inclus.
- Élaguer les snapshots pour libérer l’espace.
- Conserver un seuil de marge libre ; les systèmes CoW deviennent capricieux lorsqu’ils sont presque pleins (pression métadonnées, fragmentation).
Cause 5 : Le provisionnement fin a épuisé l’espace réel
Les thin pools LVM, datastores VM et beaucoup de SAN permettent d’allouer plus d’espace « virtuel » que ce que vous avez physiquement. C’est acceptable… jusqu’à ce que ce ne le soit plus. Quand le pool atteint la limite, les écritures échouent et les applications interprètent cela comme de la corruption, des timeouts, ou des « disque plein » au mauvais endroit.
Corrections réelles :
- Surveiller l’usage des données et métadonnées des thin pools et alerter tôt.
- Étendre le pool avant qu’il n’atteigne 100 %. À 99 % vous êtes déjà en retard.
- Limiter la prolifération des snapshots. Les snapshots sont un instrument de dette avec intérêts composés.
Cause 6 : Le stockage overlay/conteneurs a grossi discrètement
Les conteneurs rendent l’utilisation disque abstraite. Images, couches, caches de build et logs JSON s’accumulent. Kubernetes aggrave le problème en répartissant la responsabilité entre nœuds, namespaces, et « ce n’est pas mon problème ».
Corrections réelles :
- Définir des limites de taille pour les drivers de logging des conteneurs.
- Garbage collecter images et caches de build selon un calendrier.
- Utiliser des partitions dédiées pour le stockage des conteneurs afin qu’il ne suffoque pas le système.
- Définir des requests/limits d’espace éphémère dans Kubernetes et les faire respecter.
Cause 7 : Espaces réservés et quotas (c’est plein pour vous, pas pour root)
Sur ext4, des blocs réservés existent pour de bonnes raisons. Sur ZFS, quotas et réservations peuvent faire apparaître un dataset comme plein alors que le pool a de l’espace, ou l’inverse. Sur XFS, des quotas projet peuvent silencieusement plafonner des répertoires. Ce n’est pas un bug. C’est une politique.
Corrections réelles :
- Vérifiez les paramètres de quota et d’espace réservé avant de supprimer quoi que ce soit.
- Ajustez la politique avec intention : qui doit pouvoir remplir le disque, et qui doit être protégé ?
Cause 8 : « df dit plein » mais « du ne trouve rien » (mismatch de comptabilité)
C’est le cas casse‑tête : df rapporte des blocs utilisés, mais du ne montre pas de fichiers correspondants. Raisons courantes :
- Fichiers supprimés mais ouverts (encore).
- Croissance des métadonnées et du journal du système de fichiers.
- Snapshots (ZFS/btrfs).
- Allocation de blocs dans des fichiers creux ou fichiers préalloués de bases de données.
Correction réelle : Utilisez le bon outil pour la bonne couche. Si vous traitez toute l’utilisation disque comme « fichiers dans des répertoires », vous êtes aveugle à la moitié du système.
Une citation, parce qu’elle a sa place ici : Everything fails, all the time.
— Werner Vogels
Trois courtes histoires d’entreprise du terrain
Mini-histoire 1 : L’incident causé par une mauvaise hypothèse
Ils avaient une flotte de serveurs applicatifs avec un « gros disque données » attaché. Tout le monde connaissait la règle : les logs vont sur le gros disque. Le runbook le disait même. L’équipe fit ce qui semblait sensé pendant un incident : elle tail‑ait les logs, vit une tempête d’erreurs, et fit tourner un log massif. Le disque resta à 100 %.
Quelqu’un monta l’incident vers le stockage. Le support stockage regarda df -hT et soupira. Le gros disque était monté sur /data, mais le fichier de service de l’application avait été modifié des mois auparavant. Le chemin de log avait silencieusement changé vers /var/log/app — sur la racine. Le « gros disque » était inoccupé et innocent.
La mauvaise hypothèse était sociale, pas technique : « la config ne peut pas dériver parce que le runbook existe ». Elle a dérivé quand même. La correction n’a pas été un script héroïque de nettoyage. Ce fut : corriger la config du service, redémarrer proprement, et ajouter un contrôle de démarrage qui refuse d’exécuter si le montage attendu n’est pas présent.
Ils ont aussi modifié le runbook : la première étape devint « vérifier les montages et chemins », pas « tourner les logs ». La fois suivante que le symptôme apparut, le diagnostic prit quelques minutes, pas un après‑midi d’hypothèses confiantes.
Mini-histoire 2 : L’optimisation qui s’est retournée
Un ingénieur soucieux de performance décida d’accélérer les builds en mettant tout en cache sur les runners CI. Cache de build Docker, caches de paquets, artefacts de test — si ça pouvait être mis en cache, c’était mis en cache. Les builds furent plus rapides. Tout le monde applaudit. Puis les runners commencèrent à échouer par vagues.
Ce n’était ni le CPU ni la RAM. C’était le disque. Mais pas des « gros fichiers ». Les inodes. Des millions de petits objets de cache répartis dans des répertoires conçus par des personnes qui n’avaient jamais géré une ferme de runners partagés.
La première réponse fut prévisible : « Ajoutez des disques plus gros ». Ça a aidé une semaine. Puis les inodes atteignirent 100 % à nouveau, car le nombre d’inodes ne s’augmente pas automatiquement avec « ajoutez juste un volume plus grand » comme on le suppose. Ils augmentaient la capacité et manquaient toujours de slots de fichiers.
L’optimisation qui s’est retournée a appris une leçon ennuyeuse : le caching nécessite des budgets. La correction finale fut terne mais efficace — tailles de cache bornées, élagage périodique, et empaquetage de certains caches en tarballs au lieu d’une tempête de fichiers. Les builds restèrent assez rapides et les runners arrêtèrent de mourir d’une multitude de petites coupures.
Mini-histoire 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise
Une autre organisation gérait un cluster de bases de données avec des disques dimensionnés de manière conservatrice et des alertes à 70 %, 80 % et 85 %. Les gens se plaignaient que les alertes étaient bruyantes. La direction voulait les « moins sensibles ». L’équipe SRE n’a pas cédé.
Un week‑end, un consommateur avala et la réplication prit du retard. Les WAL commencèrent à s’accumuler. L’alerte 70 % déclencha. L’astreinte regarda, vit la tendance, et ouvrit un incident avant que les clients ne remarquent quoi que ce soit.
L’équipe eut le temps de faire les choses sûres : diagnostiquer pourquoi le consommateur était bloqué, augmenter temporairement la capacité, et ajuster les boutons de rétention sans improviser. Personne ne supprima des fichiers aléatoires de la base de données. Personne ne « libéra » de l’espace en supprimant la seule copie de quelque chose d’important.
Au moment où le disque aurait pu atteindre 100 %, le système était déjà stable. La politique d’alerte paraissait ennuyeuse sur un tableau de bord. En pratique, elle fit la différence entre une réponse contrôlée et un séminaire nocturne de récupération de données.
Erreurs courantes : symptôme → cause racine → correctif
1) « J’ai supprimé 20 Go, mais df n’a pas bougé »
Symptôme : du montre moins, mais df rapporte toujours plein.
Cause racine : Fichiers supprimés mais ouverts (ou snapshots sur systèmes CoW).
Correctif : lsof +L1, redémarrez le processus qui tient les fichiers ; pour les snapshots, élaguer et valider la libération d’espace au niveau pool/dataset.
2) « No space left on device » mais df montre beaucoup d’espace libre
Symptôme : Échecs d’écriture ; df -h affiche des Go libres.
Cause racine : Inodes épuisés, ou quota atteint.
Correctif : df -i ; identifier les répertoires à grand nombre de fichiers ; nettoyer les caches ; vérifier et ajuster les quotas.
3) « Seul / est plein, mais le disque de données est vide »
Symptôme : Le système de fichiers racine atteint 100 % ; le stockage attaché a de l’espace.
Cause racine : Mauvais chemin, montage manquant, ou application écrivant vers l’emplacement par défaut après échec de montage.
Correctif : Vérifier les montages (mount, findmnt), faire refuser le démarrage du service si le montage requis est absent, utiliser des chemins absolus, et tester le comportement au reboot.
4) « L’utilisation disque augmente pendant les sauvegardes/snapshots et ne redescend jamais »
Symptôme : L’utilisation augmente après des sauvegardes basées sur snapshots.
Cause racine : Rétention des snapshots trop longue, ou sauvegardes qui conservent des snapshots ; rétention des blocs CoW.
Correctif : Auditer la planification/rétention des snapshots, s’assurer que les sauvegardes expirent les snapshots, garder de la marge, et surveiller référencé vs utilisé (les propriétés ZFS aident).
5) « Après activation du debug, les disques se remplissent tous les jours »
Symptôme : Croissance continue des logs ; l’application est par ailleurs stable.
Cause racine : Volume de logs non borné ; rotation de logs manquante ou mal configurée.
Correctif : Limiter les logs, implémenter la rotation, et exporter les logs centralement avec une rétention locale raisonnable.
6) « Nous avons étendu le volume mais il est toujours à 100 % »
Symptôme : Volume cloud redimensionné ; df inchangé.
Cause racine : Le périphérique bloc a augmenté mais le système de fichiers n’a pas été étendu, ou la couche redimensionnée est la mauvaise (par ex. PV mais pas LV, LV mais pas FS).
Correctif : Confirmer avec lsblk ; étendre PV/LV/FS de manière appropriée (par ex. pvresize, lvextend, xfs_growfs / resize2fs).
7) « Un thin pool provisionné à la demande a atteint 100 % et tout est devenu bizarre »
Symptôme : Échecs d’écriture aléatoires, erreurs système de fichiers, pauses VM.
Cause racine : Thin pool à court de données ou de métadonnées.
Correctif : Étendre immédiatement le thin pool ; réduire les snapshots ; mettre en place des alertes bien avant 90 %.
Blague #2 : Si vous faites tourner un système de fichiers à 100 % et qu’il « va bien », c’est seulement parce qu’il n’a pas encore consulté ses mails.
Listes de contrôle / plan étape par étape
Checklist A : Incident en direct (le disque est à 100 % maintenant)
- Arrêtez l’hémorragie : Si un seul service écrit sans contrôle, limitez son débit ou arrêtez‑le. Gardez l’hôte en vie.
- Confirmez la cible pleine :
df -hTetdf -isur le point de montage. - Identifiez la couche : système de fichiers vs thin pool vs pool ZFS vs overlay conteneur.
- Trouvez les principaux consommateurs :
du -xhd1etfindciblés pour fichiers volumineux. - Vérifiez les supprimés mais ouverts :
lsof +L1. - Appliquez d’abord la récupération la plus sûre :
- Vacuum des journaux
- Prune du cache de build
- Rotation/compression des logs correctement
- Suppression des caches connus comme sûrs
- Revérifiez :
dfet l’état des services après chaque changement. - Uniquement ensuite envisagez d’étendre la capacité ou de déplacer des données.
Checklist B : Après l’incident (prévenir la récidive)
- Rédigez en une phrase ce qui a rempli le disque (exemple : « Cache de build Docker et logs JSON sans limites »).
- Ajoutez de la surveillance et des alertes pour :
- Espace et inodes des systèmes de fichiers
- Données et métadonnées des thin pools
- Capacité et fragmentation des pools ZFS
- Utilisation du stockage conteneurs
- Définissez des budgets de rétention : logs, artefacts, sauvegardes, snapshots, caches.
- Rendre les montages obligatoires : le service refuse de démarrer si le système de fichiers requis n’est pas monté.
- Organisez un game day : simulez la pression disque et validez le runbook.
Checklist C : Choix de conception de stockage qui réduisent les incidents disque-plein
- Placez
/var, le stockage des conteneurs et les bases de données sur des systèmes de fichiers séparés quand c’est possible. La surface d’impact compte. - Privilégiez des trajectoires de croissance prévisibles : la planification de capacité vaut mieux que le nettoyage d’urgence.
- Conservez une marge : visez 20–30 % libres sur les systèmes chargés ; plus pour CoW et charges riches en métadonnées.
- Considérez les snapshots comme des données de production. Traitez‑les avec le même sérieux que des sauvegardes.
- Ne thin‑provisionnez pas sans surveillance de premier ordre et procédures d’extension testées.
Faits intéressants et contexte historique
- Blocs réservés sur les systèmes ext ont été introduits pour garder le système utilisable pour root et réduire la fragmentation quand les disques se remplissent.
- Les inodes sont préalloués sur beaucoup de systèmes de fichiers traditionnels (comme ext4). Vous pouvez manquer d’entrées de fichiers indépendamment des octets.
- Le comportement « supprimé mais ouvert » est un choix de conception Unix : les noms de fichiers sont des entrées de répertoire ; le fichier vit jusqu’à la dernière référence.
- XFS a été conçu pour du big iron (haut débit, grands systèmes de fichiers). Il est rapide, mais le réduire n’est pas une chose à faire un mardi.
- Les snapshots copy-on-write (ZFS/btrfs) échangent la facilité de snapshot pour une comptabilité d’espace plus compliquée sous pression.
- La rotation des logs existe parce que les disques sont finis, fait aussi vrai sur des disques de 40 Mo qu’aujourd’hui sur des volumes multi‑To.
- Le thin provisioning est devenu courant car il améliore l’utilisation, mais il transforme aussi la « capacité » en problème de surveillance et gouvernance.
- Le comportement d’un système de fichiers plein est non linéaire : la performance et les taux d’échec peuvent se dégrader fortement près du plein, surtout avec de l’espace libre fragmenté et du churn métadonnées.
FAQ
Pourquoi mon système ralentit quand le disque est presque plein ?
L’espace libre se fragmente, les opérations sur les métadonnées deviennent plus coûteuses, et les systèmes CoW peuvent amplifier les écritures. Près du plein, les hypothèses du « cas moyen » se cassent.
Pourquoi du ne correspond pas à ce que df affiche ?
du parcourt les arbres de répertoires et additionne les tailles de fichiers visibles. df rapporte les blocs alloués. Les fichiers supprimés mais ouverts, les snapshots et les métadonnées peuvent les faire diverger.
Est‑ce sûr de supprimer des fichiers dans /var/log ?
Parfois. Préférez la rotation et la compression via les outils de logging du système. Si vous supprimez un log qu’un processus a ouvert, vous ne pourrez peut‑être pas récupérer l’espace tant que le processus ne rouvre pas le fichier.
Puis‑je simplement supprimer les fichiers WAL PostgreSQL pour libérer de l’espace ?
Non, pas comme tactique opérationnelle normale. WAL fait partie de la durabilité et de la réplication. L’approche sûre est de corriger l’archivage/réplication, ajuster la rétention, ou ajouter de la capacité. Si vous êtes déjà en situation de catastrophe, faites intervenir un expert base de données.
Quelle est la manière la plus rapide et sûre de récupérer de l’espace sur un hôte Docker ?
Commencez par le cache de build : docker builder prune -af. Ensuite, supprimez images et conteneurs inutilisés. Soyez prudent avec les volumes ; ils contiennent souvent des données réelles.
Comment savoir si c’est un problème d’inodes ?
Exécutez df -i sur le montage affecté. Si IUse% est proche de 100 %, vous devez supprimer beaucoup de petits fichiers ou repenser la charge, pas chercher des gros fichiers.
Pourquoi ZFS montre de l’espace utilisé même après suppression de gros répertoires ?
Les snapshots peuvent encore référencer ces blocs, donc le pool ne peut pas les libérer. Vérifiez la liste des snapshots et la rétention. Gardez également une marge ; ZFS performe mal quand il est très plein.
Quels seuils d’alerte devrions‑nous utiliser pour l’utilisation disque ?
Ça dépend du taux de croissance et du temps de récupération. Une base pratique : avertir à 70–80 %, pager à 85–90 % pour les systèmes critiques. Les systèmes CoW et pools thin provisionnés méritent des alertes plus précoces.
Devons‑nous séparer /var de / ?
Oui pour la plupart des hôtes de production. /var est l’endroit où la croissance se produit (logs, caches, données de conteneurs). Le séparer réduit le risque qu’une charge bruyante bloque le système.
Quelle est la cible de suppression d’urgence la plus sûre ?
Les caches récupérables que vous pouvez régénérer : cache de build, caches de paquets, fichiers temporaires, logs archivés, anciens journaux. Évitez de toucher aux fichiers de base de données en direct ou à des répertoires inconnus sous pression.
Prochaines étapes pour éviter les récidives
Corriger une utilisation disque à 100 % n’est pas une question d’héroïsme. Il s’agit d’identifier la couche pleine, d’utiliser les bons outils pour trouver le vrai consommateur, et d’appliquer des changements qui ne reviendront pas en boomerang.
- Adoptez la méthode de diagnostic rapide et rendez‑la réflexe :
df -hT,df -i,du -x,lsof +L1, puis vérifications spécifiques par couche (Docker/ZFS/LVM thin). - Mettez des budgets partout : rétention des logs, limites journald, rétention des snapshots, tailles de cache, politiques de cycle de vie des images.
- Concevez pour la surface d’impact : systèmes de fichiers séparés pour OS, logs, conteneurs et bases de données ; exigez les montages au démarrage.
- Surveillez ce qui compte tôt : espace, inodes, données/métadonnées des thin pools, croissance des snapshots, et répertoires principaux par consommation.
- Gardez une marge libre volontaire : « nous tournons à 95 % tout le temps » n’est pas de l’économie ; c’est de la dette opérationnelle différée.
Les incidents « disque plein » sont rarement mystérieux. Ce sont en général des dettes opérationnelles impayées, qui arrivent avec des intérêts et exigent un paiement immédiat.