Quand les outils de « nettoyage » ont causé des dégâts : utilitaires de confiance qui ont mal tourné

Cet article vous a aidé ?

Le disque atteint 92 %. Les alertes commencent à s’affoler. Quelqu’un ouvre un ticket de « nettoyage » qui paraît inoffensif : faire tourner les logs, élaguer les images, supprimer les fichiers temporaires, vacuum des journaux. Le genre de tâche que vous faites entre deux réunions.

Deux heures plus tard, votre base de données est en lecture seule, votre nœud est expulsé, et le postmortem s’intitule quelque chose comme « Incident de suppression n°7 ». L’outil en cause ? Pas un malware. Pas un attaquant. Un utilitaire de confiance, faisant exactement ce qu’on lui a demandé.

Pourquoi le nettoyage est particulièrement dangereux en production

Le nettoyage est destructeur, généralement irréversible, et souvent effectué sous pression temporelle. C’est la trifecta. Ajoutez un quatrième élément : le travail de nettoyage tend à être délégué au contexte le moins privilégié qui possède encore assez de pouvoir pour ruiner votre journée. Root, cluster‑admin, ou le rôle « maintenance stockage » qui a silencieusement accès à tout parce que « il en a besoin ».

Le vrai piège, c’est que le nettoyage ressemble à du ménage, pas à de l’ingénierie. Vous n’avez pas de revue de conception pour « rm old stuff ». Vous ne faites pas de tests de charge pour « vacuum logs ». Vous ne le mettez pas en staging, parce que vous supprimez des données et que le staging paraît inutile. Toutes ces suppositions sont fausses.

Les systèmes modernes ne stockent pas des « fichiers ». Ils stockent des relations : des conteneurs référant des couches overlay, des bases de données référant des segments WAL, des services référant des sockets et des fichiers de verrou, des snapshots référant l’historique des blocs, des expéditeurs de logs référant des positions d’inode, des outils de sauvegarde référant des checksums. Lorsqu’un « nettoyeur » supprime un objet, il peut casser une relation qui n’a jamais été consignée nulle part.

Une citation, parce que l’industrie l’a apprise à la dure : « Idée paraphrasée » de James Hamilton (reliability engineering) : de petits changements opérationnels provoquent une part surprenante des indisponibilités ; traitez‑les comme de vrais déploiements.

Il y a aussi le facteur humain. Quand le disque est plein, vous ressentez de l’urgence. L’urgence engendre des exploits héroïques. Les héros utilisent --force. Et --force est la version adulte de « je suis sûr que c’est OK ».

Blague n°1 : Les scripts de nettoyage sont comme des chats — ils n’obéissent que lorsqu’il est inconvenant, et ils savent toujours où se trouve la chose coûteuse.

Faits intéressants et contexte historique (court, mais utile)

  • Le principe Unix « tout est un fichier » rendait le nettoyage trompeusement simple. Mais il a aussi facilité la suppression de nœuds de périphérique, de sockets et de fichiers d’état qui ne sont pas « des données » jusqu’à ce qu’ils le deviennent.
  • Les premiers administrateurs système utilisaient la rotation des logs bien avant l’existence d’outils standards ; les schémas ad‑hoc de « move and truncate » hantent encore les systèmes dont les démons ne rouvrent pas correctement les logs.
  • Les systèmes de fichiers avec journalisation (ext3/ext4, XFS) ont amélioré la récupération après crash, pas la récupération d’un « oups ». La suppression reste une suppression ; le journal aide la cohérence, pas le pardon.
  • La transition vers les couches de conteneurs a créé de nouveaux garbage collectors (image prune, layer GC). Un « nettoyage de disque » peut maintenant casser la capacité d’ordonnancement d’un cluster entier, pas seulement d’un hôte.
  • Le stockage copy‑on‑write (ZFS, btrfs) a élevé les snapshots au rang d’outil opérationnel de première classe. Il a aussi rendu la notion d’espace libre plus complexe : supprimer des fichiers peut ne pas libérer de blocs si des snapshots les référencent encore.
  • L’épuisement d’inodes est un classique imposteur de « disque plein » : vous pouvez avoir beaucoup d’octets libres mais zéro inode, généralement à cause de petits fichiers dans des répertoires tmp/log.
  • Les sémantiques POSIX permettent aux processus de continuer à écrire dans des fichiers supprimés. L’espace n’est pas récupéré tant que le dernier descripteur de fichier n’est pas fermé, donc « j’ai supprimé le gros fichier » ne signifie pas « le disque a regagné de l’espace ».
  • Systemd a introduit des politiques tmpfiles qui peuvent effacer des répertoires que vous supposiez persistants, surtout si vous avez placé de l’état sous /tmp ou mal déclaré un répertoire runtime.

Comment les outils de « nettoyage » tournent mal : modes de défaillance récurrents

1) La cible s’est élargie : globbing, variables et valeurs par défaut « aidantes »

Un outil de nettoyage supprime rarement « une chose ». Il supprime « ce qui correspond ». Cette correspondance peut s’étendre. Les globs s’étendent. Les variables d’environnement s’étendent. Les liens symboliques s’étendent. Des montages apparaissent/disparaissent. Et soudain votre suppression soigneusement limitée devient un incendie à l’échelle du campus.

Coupables typiques : rm -rf $DIR/*$DIR est vide ; find sans -xdev ; un lien symbolique créé par une étape d’installation ; un bind mount qui a déplacé du contenu dans un chemin « temp ».

2) Espace récupéré ? Pas forcément : descripteurs ouverts et snapshots

Votre disque est plein. Vous supprimez 30 Go. Le disque est toujours plein. Le niveau de panique augmente. Les gens suppriment plus vite. Le vrai problème est souvent soit :

  • Fichiers ouverts mais supprimés : les données restent allouées jusqu’à ce que le processus ferme le descripteur.
  • Snapshots : les données restent référencées par un snapshot, donc les blocs ne peuvent pas être libérés.

Les nettoyeurs qui « suppriment les vieux logs » peuvent en réalité aggraver la situation s’ils suppriment des fichiers qu’un démon de longue durée écrit encore. Vous avez maintenant masqué le chemin des logs, vous n’avez pas libéré d’espace, et vous avez rendu le dépannage plus difficile.

3) Les nettoyeurs « optimisés » qui concurrencent votre charge de travail

Certains outils sont commercialisés comme si le nettoyage était passif. Ce n’est pas le cas. Scanner des répertoires bousille les caches. Hacher des fichiers brûle du CPU. Les passes de déduplication réveillent les disques. Le rééquilibrage des métadonnées provoque des tempêtes d’I/O. Un nettoyeur peut devenir la charge la plus chaude sur la machine.

En termes de stockage : vous venez d’introduire une charge aléatoire de lectures en arrière‑plan avec une faible localité. Si le système était déjà contraint en I/O, félicitations : vous avez construit un benchmark sans limite et l’avez pointé vers la production.

4) Hypothèses « sans état » qui suppriment de l’état

Nombre de systèmes placent de l’état dans des endroits qui ont l’air temporaires :
/var/tmp, /var/lib, /run, un répertoire de cache local, ou « juste un fichier dans /tmp » devenu verrou, file d’attente ou spool.

Les nettoyeurs qui traitent ces chemins comme « sûrs à effacer » provoquent des défaillances étranges : jobs bloqués, traitement en double, métriques perdues, ou démarrages lents pendant que les caches se reconstruisent sous charge.

5) Logique de rétention qui marche jusqu’à ce que le temps bouge

Les politiques de rétention sont de l’arithmétique sur les dates plus des cas limites. Heure d’été. Dérive d’horloge. Secondes intercalaires. Frontières de nouvelle année. Le moment où vous changez le format des logs ou renommez un répertoire, votre « supprimer plus vieux que 7 jours » peut tout supprimer parce qu’il ne sait plus parser les dates.

6) Outils sûrs seuls, dangereux ensemble

Votre expéditeur de logs garde un curseur. Votre nettoyeur fait tourner les logs. Votre job de compression déplace des fichiers. Votre job de sauvegarde les lit. Chaque outil est « ok ». Ensemble, ils créent des courses : doubles rotations, archives tronquées, segments manquants, et ingestion en double.

La plupart des catastrophes de nettoyage ne proviennent pas d’une seule commande foireuse. Ce sont des échecs d’orchestration entre des outils bien intentionnés.

7) Permissions et identité : le mythe « il ne peut pas supprimer ça »

Les gens supposent qu’un outil tournant sous un compte de service ne peut pas faire de gros dégâts. Puis quelqu’un ajoute le compte à un groupe « temporairement », ou il tourne dans un conteneur privilégié, ou le système de fichiers est monté avec une propriété laxiste, ou les ACL accordent plus que prévu.

Les incidents de nettoyage aiment la dérive des privilèges. C’est discret. C’est pratique. C’est catastrophique.

Blague n°2 : « Je vais juste lancer un nettoyage rapide » est la façon dont les incidents font leur cardio.

Playbook de diagnostic rapide : vérifications première/seconde/troisième

Quand un « nettoyage » a mal tourné, vous avez besoin de vitesse, pas d’élégance. L’objectif est d’identifier le vrai goulot d’étranglement avant de supprimer plus de preuves.

Première étape : vérifier quelle ressource est réellement épuisée

  • Octets vs inodes : un système peut être « plein » de deux manières différentes.
  • Système de fichiers vs thin pool vs réserve de snapshot : « df dit 90 % » n’est pas toute l’histoire sur LVM thin, ZFS, ou overlays de conteneurs.
  • Local au nœud vs stockage distant : les évictions Kubernetes tiennent compte de la pression sur le système de fichiers du nœud, pas de votre SAN sophistiqué.

Deuxième étape : identifier les plus gros consommateurs (et vérifier si la suppression libérera l’espace)

  • Top répertoires et fichiers.
  • Fichiers ouverts mais supprimés.
  • Références de snapshots ou rétention copy‑on‑write.

Troisième étape : évaluer le rayon d’impact et arrêter l’hémorragie

  • Désactiver ou mettre en pause le job de nettoyage (cron, timers systemd, runner CI).
  • Geler d’autres rotations/suppressions qui pourraient détruire des artefacts forensiques.
  • Stabiliser le système : récupérer un peu d’espace en sécurité (même 2–5 %) pour rétablir les opérations normales (journald, gestionnaires de paquets, bases de données).

Règle de décision à garder

Si vous ne pouvez pas expliquer pourquoi supprimer une chose va libérer de l’espace, ne la supprimez pas encore. Mesurez d’abord. Puis supprimez avec un plan de rollback (snapshot, backup, ou au moins un répertoire de quarantaine sur le même système de fichiers).

Tâches pratiques : commandes, sorties et décisions (12+)

Voici les tâches que j’utilise quand un « nettoyage » a déraillé. Chacune inclut : une commande, ce que signifie une sortie typique, et la décision à prendre ensuite. Traitez‑les comme des blocs de construction, pas comme un script à copier aveuglément.

Tâche 1 : Vérifier l’utilisation en octets par système de fichiers (triage rapide)

cr0x@server:~$ df -hT
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/nvme0n1p2 ext4   220G  214G  1.8G 100% /
tmpfs          tmpfs   32G  120M   32G   1% /run
/dev/sdb1      xfs    3.6T  2.1T  1.5T  59% /srv

Sens : La racine est effectivement pleine. /srv est correct, mais cela n’aide pas si la charge écrit dans /.

Décision : Concentrez‑vous sur la récupération de quelques Go sur / d’abord pour restaurer la stabilité. Ne « nettoyez pas /srv » simplement parce qu’il est volumineux.

Tâche 2 : Vérifier l’épuisement d’inodes (le moment où « df ment »)

cr0x@server:~$ df -ih
Filesystem     Inodes IUsed IFree IUse% Mounted on
/dev/nvme0n1p2   14M   14M     0  100% /

Sens : Vous êtes à court d’inodes. Supprimer quelques gros fichiers n’aidera pas si le problème est des millions de petits fichiers.

Décision : Identifiez les répertoires avec un nombre massif de fichiers (spools, caches, temp dirs). Évitez les outils récursifs qui prendront des heures et empireront la charge.

Tâche 3 : Trouver quels répertoires consomment de l’espace (octets)

cr0x@server:~$ sudo du -xhd1 /var | sort -h
120M    /var/cache
3.2G    /var/log
14G     /var/lib
18G     /var

Sens : /var/lib est le gros consommateur. C’est généralement de l’état applicatif (bases de données, runtimes de conteneurs), pas des « déchets ».

Décision : Approfondissez avec prudence dans /var/lib ; envisagez un nettoyage conscient des applications plutôt que des suppressions à la hache.

Tâche 4 : Trouver quels répertoires consomment des inodes (nombre de fichiers)

cr0x@server:~$ sudo find /var -xdev -type f -printf '.' | wc -c
12984217

Sens : ~13 millions de fichiers sous /var. C’est énorme. Vous avez probablement des fichiers temporaires en fuite, des fragments de cache, ou un schéma de rotation cassé.

Décision : Identifiez ensuite le répertoire point chaud (ne supprimez pas aveuglément).

Tâche 5 : Localiser les hotspots d’inodes par répertoire

cr0x@server:~$ sudo find /var -xdev -mindepth 1 -maxdepth 3 -type f -printf '%h\n' | sort | uniq -c | sort -nr | head
8420000 /var/lib/app/spool
1960000 /var/log/nginx
510000  /var/tmp/session-cache

Sens : /var/lib/app/spool explose. Les spools sont généralement de la « logique métier », pas des déchets.

Décision : Traitez‑le comme un incident dans la pipeline applicative ; le nettoyage peut n’être qu’un pansement, pas une solution.

Tâche 6 : Vérifier les fichiers ouverts mais supprimés (espace non récupéré)

cr0x@server:~$ sudo lsof +L1 | head
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NLINK NODE NAME
java     2310 app    12w  REG  259,2  8.0G     0  9123 /var/log/app/app.log (deleted)
nginx    1882 www     5w  REG  259,2  1.2G     0  7742 /var/log/nginx/access.log (deleted)

Sens : Ces processus gardent des descripteurs sur des logs supprimés. Les octets sont toujours alloués.

Décision : Redémarrez ou signalez les processus pour qu’ils rouvrent les logs (par ex. systemctl restart ou kill -HUP), puis revérifiez df.

Tâche 7 : Confirmer l’utilisation de journald avant de vacuumer

cr0x@server:~$ sudo journalctl --disk-usage
Archived and active journals take up 4.1G in the file system.

Sens : Les journaux occupent une place non négligeable. Le vacuum peut libérer de l’espace rapidement, mais vous perdrez des logs forensiques.

Décision : Si vous êtes en plein incident, faites un snapshot ou exportez les logs pertinents d’abord ; puis vacuumez jusqu’à un seuil de rétention connu.

Tâche 8 : Vacuum journald en sécurité vers une taille cible

cr0x@server:~$ sudo journalctl --vacuum-size=800M
Vacuuming done, freed 3.3G of archived journals from /var/log/journal.

Sens : Vous avez récupéré 3.3G depuis les journaux.

Décision : Revérifiez la santé du système. Si ce n’était qu’une mesure d’urgence, corrigez la cause racine qui rempli le disque.

Tâche 9 : Valider la configuration de logrotate sans l’exécuter

cr0x@server:~$ sudo logrotate -d /etc/logrotate.conf
reading config file /etc/logrotate.conf
including /etc/logrotate.d
reading config file nginx
error: nginx:12 duplicate log entry for /var/log/nginx/access.log

Sens : Logrotate se comporterait de manière inattendue ou échouerait, laissant les logs croître sans borne.

Décision : Corrigez la configuration et lancez logrotate manuellement une fois (avec précaution) après validation.

Tâche 10 : Lancer logrotate une fois, en mode verbeux, et observer les changements

cr0x@server:~$ sudo logrotate -vf /etc/logrotate.conf
rotating pattern: /var/log/nginx/*.log  after 1 days (14 rotations)
renaming /var/log/nginx/access.log to /var/log/nginx/access.log.1
compressing log with: /bin/gzip

Sens : La rotation a eu lieu ; la compression s’est déclenchée. Si un démon ne rouvre pas les logs, vous pouvez maintenant avoir des fichiers ouverts mais supprimés.

Décision : Assurez‑vous que les actions postrotate signalent correctement les services ; vérifiez avec lsof +L1.

Tâche 11 : Vérifier l’utilisation disque du runtime conteneur (exemple Docker)

cr0x@server:~$ sudo docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          48        12        38.2GB    24.7GB (64%)
Containers      21        6         3.1GB     1.0GB (32%)
Local Volumes   16        10        220GB     0B (0%)
Build Cache     12        0         5.6GB     5.6GB

Sens : Le gros chiffre ce sont les volumes locaux. Le prune des images ne résoudra pas la pression disque ; ce sont des volumes d’état.

Décision : Auditez les volumes et leurs propriétaires. Envisagez une rétention applicative ou déplacer les volumes vers un montage plus grand.

Tâche 12 : Pruner en sécurité (ne pas supprimer des objets en cours d’utilisation)

cr0x@server:~$ sudo docker image prune -a --filter "until=168h"
Deleted Images:
deleted: sha256:3d2b...
Total reclaimed space: 12.4GB

Sens : Vous avez récupéré 12.4G d’images de plus de 7 jours.

Décision : Si c’est un nœud de production, coordonnez‑vous avec le rythme de déploiement ; assurez‑vous de ne pas pruner des images nécessaires pour des rollbacks rapides.

Tâche 13 : Vérifier les symptômes de pression disque sur un nœud Kubernetes

cr0x@server:~$ kubectl describe node worker-3 | sed -n '/Conditions:/,/Addresses:/p'
Conditions:
  Type             Status  LastHeartbeatTime                 Reason              Message
  DiskPressure     True    2026-01-22T10:11:02Z              KubeletHasDiskPressure  kubelet has disk pressure
  Ready            True    2026-01-22T10:11:02Z              KubeletReady         kubelet is posting ready status

Sens : Le nœud est « Ready » mais sous DiskPressure ; des évictions vont commencer et les workloads vont se dégrader.

Décision : Libérez de l’espace sur le système de fichiers du nœud utilisé par kubelet/runtime conteneur ; ne « nettoyez pas à l’intérieur des pods » comme premier réflexe.

Tâche 14 : Réalité des snapshots ZFS (pourquoi les suppressions ne libèrent pas d’espace)

cr0x@server:~$ sudo zfs list -o name,used,avail,refer,mountpoint tank/app
NAME      USED  AVAIL  REFER  MOUNTPOINT
tank/app  980G  120G   240G   /srv/app

Sens : Le dataset « USED » est 980G mais « REFER » est 240G. Le delta provient typiquement de snapshots ou d’enfants dataset.

Décision : Inspectez les snapshots avant de supprimer quoi que ce soit ; le nettoyage peut nécessiter des changements de rétention de snapshot.

Tâche 15 : Lister les snapshots et voir ce qui retient l’espace

cr0x@server:~$ sudo zfs list -t snapshot -o name,used,refer,creation -s used | tail
tank/app@daily-2026-01-15   22G  240G  Mon Jan 15 02:00 2026
tank/app@daily-2026-01-16   27G  240G  Tue Jan 16 02:00 2026
tank/app@daily-2026-01-17   31G  240G  Wed Jan 17 02:00 2026
tank/app@daily-2026-01-18   35G  240G  Thu Jan 18 02:00 2026
tank/app@daily-2026-01-19   39G  240G  Fri Jan 19 02:00 2026
tank/app@daily-2026-01-20   44G  240G  Sat Jan 20 02:00 2026
tank/app@daily-2026-01-21   48G  240G  Sun Jan 21 02:00 2026

Sens : Les snapshots consomment de l’espace significatif. Supprimer des fichiers dans /srv/app ne réduira pas beaucoup USED tant que ces snapshots existent.

Décision : Ajustez la rétention ou répliquez les snapshots ailleurs avant de les élaguer ; faites‑le délibérément, pas dans la panique.

Tâche 16 : Identifier si un nettoyage a traversé des frontières de systèmes de fichiers

cr0x@server:~$ sudo find / -xdev -maxdepth 2 -type d -name 'tmp' -print
/tmp
/var/tmp

Sens : -xdev vous maintient sur un seul système de fichiers. Sans lui, un nettoyage pourrait traverser des volumes montés, y compris des sauvegardes.

Décision : Pour toute suppression basée sur find, ajoutez -xdev sauf si vous pouvez justifier de traverser des systèmes de fichiers par écrit.

Trois mini‑histoires d’entreprise : mauvaise hypothèse, optimisation qui se retourne, victoire ennuyeuse

Mini‑histoire 1 : L’incident causé par une mauvaise hypothèse (« /tmp est toujours sûr »)

Une entreprise de taille moyenne exploitait une pipeline de paiement avec un service Java et un sidecar qui gérait le chiffrement. Le sidecar écrivait des artefacts éphémères dans /tmp. C’était supposé être temporaire : chiffrer, transmettre, supprimer. Simple.

Avec le temps, « temporaire » est devenu « opérationnel ». Le sidecar utilisait aussi /tmp comme file de récupération : si l’API en amont throttlait, il mettait en cache les payloads et réessayait. Personne n’a documenté cela parce que ce n’était pas une fonctionnalité intentionnelle ; c’était un bricolage pragmatique ajouté lors d’un incident passé et jamais revu.

Puis un ingénieur système a activé une politique tmpfiles systemd pour nettoyer les entrées de /tmp plus vieilles qu’un jour. Totalement normal. Cela a réduit le churn d’inodes et gardé les hôtes propres. Le weekend suivant, le trafic a flambé, le sidecar a été plus souvent throttlé, et la file de réessai a grossi. Elle a dépassé le seuil d’un jour. Le nettoyeur a fait son travail.

Le lundi matin, on a eu des « transactions manquantes ». Pas perdues en transit, pas rejetées — supprimées silencieusement de la file de réessai. Les logs du service n’aidaient pas non plus parce qu’ils référenceaient des IDs de requête, mais les payloads avaient disparu.

La correction technique était ennuyeuse : déplacer la file de réessai vers un répertoire dédié sous /var/lib, gérer la rétention explicitement, et ajouter des métriques sur la profondeur de file. La correction culturelle a été plus importante : toute action de « nettoyage » touchant aux politiques tmpfiles OS nécessite désormais la signature du propriétaire applicatif. Parce que la phrase « c’est juste /tmp » est la façon dont l’argent disparaît.

Mini‑histoire 2 : L’optimisation qui s’est retournée contre nous (prune d’images agressif sur runners CI)

Une autre organisation exécutait des runners CI auto‑hébergés sur des machines costaudes. L’utilisation disque augmentait parce que les builds tiraient beaucoup d’images conteneurs. Quelqu’un a eu une idée : un job nocturne pour pruner tout ce qui a plus de 24 heures. L’objectif était noble : arrêter les relances pour « disque à 90 % ».

Ça a marché pendant une semaine. Puis les temps de build ont empiré. Pas un peu. Assez pour que les développeurs relancent des jobs, ce qui a augmenté la charge. Le job de prune tournait la nuit, mais les dégâts n’étaient pas « nocturnes ». Chaque matin, la première vague de builds retéléchargeait les images, martelant le registry et saturant des liens réseau partagés avec des services de production.

Le mode de défaillance n’était pas « nous avons supprimé des choses nécessaires ». C’était « nous avons effacé la localité ». Les caches existent parce que le réseau et le stockage ne sont pas gratuits. En optimisant pour le disque, ils ont créé un déni de service distribué contre leur propre registry et WAN.

La correction : passer d’une suppression basée sur le temps à une rétention basée sur la capacité avec un plancher pour les images de base couramment utilisées. Garder un ensemble chaud. Pruner quand le disque dépasse un seuil, pas selon le calendrier. Aussi : pinner le job de prune dans un cgroup avec limites I/O et CPU, parce que le travail de fond ne doit pas devenir le processus le plus bruyant de l’hôte.

Mini‑histoire 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise (quarantaine, puis suppression)

Une plateforme SaaS avait le problème classique : croissance des logs sur des nœuds gérant du trafic par rafales. Un ingénieur a proposé de supprimer directement les anciens logs dans /var/log. Un autre a insisté sur une « quarantaine »: déplacer les fichiers candidats vers /var/log/.trash sur le même système de fichiers, attendre 24 heures, puis supprimer.

Ça semblait gaspilleur — pourquoi garder des déchets ? Mais l’étape de quarantaine était peu coûteuse. Les opérations de renommage sont rapides. Cela préservait aussi la possibilité de récupérer d’erreurs sans impliquer des backups, des tickets ou des conversations gênantes.

Un jour, un service a mis à jour son format de logs et a commencé à écrire vers un nouveau nom de fichier qui correspondait au glob de nettoyage. Le job de nettoyage a déplacé le log actif en quarantaine. Le service a continué à écrire, mais il a écrit dans un fichier rouvert au chemin original. Pendant ce temps, l’expéditeur de logs a cassé parce que son curseur d’inode suivait le fichier déplacé. Les alertes se sont déclenchées rapidement car l’ingestion avait chuté.

Parce que le fichier était en quarantaine et non supprimé, la récupération a été simple : le remettre, ajuster la correspondance du nettoyage, redémarrer le shipper, et réingérer le trou. Pas de restauration. Pas de perte de données. Le postmortem contenait une phrase rare et agréable : « Aucun impact client. » Cette phrase s’achète presque toujours par des pratiques ennuyeuses que personne ne veut implémenter.

Erreurs courantes : symptôme → cause racine → correctif

Le disque est plein, vous avez supprimé des gros fichiers, mais df ne change pas

Symptôme : df affiche toujours 95–100 % après suppression.

Cause racine : Fichiers ouverts mais supprimés (processus garde le descripteur) ou snapshots retenant des blocs.

Correctif : Vérifiez lsof +L1 et redémarrez/rechargez les services ; pour ZFS/btrfs, inspectez les snapshots et ajustez la rétention délibérément.

Un service plante après un « tmp cleanup », mais le disque semble mieux

Symptôme : Après nettoyage de /tmp ou /var/tmp, un démon ne démarre plus, des jobs disparaissent, ou des pics de taux surviennent.

Cause racine : L’application a détourné les répertoires temporaires pour de l’état (files d’attente, verrous, sockets, caches requis à l’exécution).

Correctif : Déplacez l’état vers un chemin persistant explicite ; codifiez le nettoyage en connaissance de l’application ; ajoutez des tests pour les politiques tmpfiles en staging.

La rotation des logs « fonctionne », mais vous avez perdu des logs ou des trous d’ingestion apparaissent

Symptôme : Des logs compressés existent, mais des trous d’ingestion ou des lignes manquent.

Cause racine : Logs pivotés/tronqués sans signaler le processus ; le shipper suit les inodes et se retrouve confus par les mouvements/troncations.

Correctif : Utilisez les bonnes actions postrotate (HUP/reload), et alignez la configuration du shipper avec la méthode de rotation (copytruncate vs rename).

Le job de nettoyage provoque un pic d’I/O et latence sur l’hôte

Symptôme : La latence monte quand le nettoyage s’exécute ; iowait grimpe ; les bases de données se plaignent.

Cause racine : Le nettoyeur effectue des scans profonds, compression, checksum, ou dédup sans limitation de vitesse.

Correctif : Limitez le débit via ionice/nice, planifiez en heures creuses, réduisez la portée, ou redesign vers un nettoyage incrémental avec métriques.

« On a pruné des images » et maintenant les rollbacks sont lents ou échouent

Symptôme : Le rollback nécessite de tirer des images et expire ; les nœuds churnent.

Cause racine : Un élagage agressif a supprimé des images supposées en cache localement.

Correctif : Gardez un ensemble chaud protégé ; pruniez par capacité avec une rétention minimale ; alignez avec la fréquence de déploiement et la politique de rollback.

Peur de corruption du système de fichiers après une suppression massive

Symptôme : Les applications renvoient des erreurs, des répertoires semblent bizarres, quelqu’un dit « peut‑être corruption ».

Cause racine : Généralement pas de corruption ; il s’agit d’état manquant, de changements de permissions, ou de sockets/verrous supprimés. La vraie corruption est plus rare qu’on le pense.

Correctif : Validez les montages, permissions et l’état applicatif ; vérifiez les logs kernel ; lancez des vérifications de système de fichiers seulement avec un plan et une fenêtre de downtime.

Le nettoyage s’est exécuté sur le mauvais hôte ou le mauvais montage

Symptôme : Un nœud sans rapport avec l’alerte a été « nettoyé », ou un montage de sauvegarde a été vidé.

Cause racine : Absence de garde‑fous : pas de vérification du hostname, pas de vérification de montages, pas de -xdev, automatisation pointée sur le mauvais groupe d’inventaire.

Correctif : Ajoutez des vérifications strictes (UUIDs de montage attendus, marqueurs d’environnement), et exigez une confirmation interactive pour les actions destructrices hors fenêtres de maintenance.

Checklists / plan pas à pas : nettoyer en sécurité sans regrets

Étape 0 : Arrêter d’empirer la situation (5 minutes)

  1. Mettre en pause le job de nettoyage : désactivez cron/timer systemd/job CI temporairement.
  2. Capturer des preuves : usage disque/inodes actuel, top répertoires, lsof +L1, et extraits récents de syslog/journal.
  3. Donner un peu d’air au système : récupérer une petite quantité d’espace en sécurité (vacuum journald ou déplacer des logs en quarantaine).

Étape 1 : Prouver ce qui retient l’espace (15–30 minutes)

  1. Octets vs inodes : lancez df -hT et df -ih.
  2. Localiser les consommateurs : du -xhd1 sur le système plein ; pour les inodes, compter les fichiers par répertoire.
  3. Vérifier les fichiers ouverts supprimés : lsof +L1.
  4. Si vous utilisez du stockage CoW : inspectez les snapshots et l’utilisation des datasets (ZFS/btrfs).

Étape 2 : Choisir la soupape de secours la moins risquée

  • Préférez supprimer des données régénérables : caches de build, caches de paquets, artefacts temporaires recréables.
  • Préférez un nettoyage conscient de l’application : vacuum de base via outils vendor, prune conteneur avec filtres de rétention, logrotate avec signaux corrects.
  • Évitez de supprimer des inconnus : tout ce qui est dans /var/lib sans connaître le propriétaire est un piège.

Étape 3 : Mettre en place des garde‑fous avant de réactiver l’automatisation

Un job de nettoyage sans garde‑fous n’est pas de « l’automatisation ». C’est juste un risque programmé.

  • Quarantaine puis suppression : déplacez les fichiers candidats vers un répertoire caché sur le même système de fichiers ; supprimez après un délai.
  • Vérification des montages : contrôlez les points de montage et types de système attendus avant d’exécuter.
  • Limites de portée : utilisez -xdev, chemins explicites, et profondeur maximale explicite.
  • Exécutions à blanc : enregistrez ce qui serait supprimé. Toujours.
  • Limitation de débit : utilisez nice et ionice pour les jobs de fond.
  • Métriques : alertez sur les tendances de croissance, pas seulement sur des seuils, et traquez les actions de nettoyage comme événements.

Étape 4 : Rendre le processus volontairement ennuyeux

Le meilleur processus de nettoyage est celui dont personne ne parle parce qu’il ne surprend personne. Cela signifie : politiques de rétention documentées, propriétaires assignés, et répertoires « temporaire » traités comme des contrats, pas des impressions.

FAQ

1) Pourquoi supprimer un fichier de log ne libère parfois pas d’espace disque ?

Parce qu’un processus peut garder le fichier ouvert et continuer à y écrire même après son unlink. L’espace n’est libéré que lorsque le dernier descripteur de fichier est fermé. Utilisez lsof +L1 pour les trouver et redémarrez/rechargez le processus.

2) Est‑ce que rm -rf est toujours une mauvaise idée ?

C’est un outil tranchant. Le problème n’est pas rm ; c’est l’ambiguïté. Si vous ne pouvez pas définir précisément la cible et prouver qu’elle est correcte, n’utilisez pas la suppression récursive forcée en production. Préférez des déplacements en quarantaine et un nettoyage conscient des applications.

3) Quel est le « meilleur » espace d’urgence à récupérer rapidement ?

Habituellement les archives journald, les caches des gestionnaires de paquets, ou des caches de build connus — des choses qui se régénèrent. Évitez de supprimer tout ce qui ressemble à de l’état (/var/lib, répertoires de bases de données, montages de volumes) sauf si vous avez confirmé la propriété et la récupération.

4) Pourquoi nettoyer /tmp a‑t‑il cassé une application ?

Parce que l’application stockait de l’état dans un chemin temporaire : sockets, verrous, files d’attente, ou métadonnées cachées nécessaires à l’exécution. Corrigez en déplaçant l’état vers un répertoire persistant explicite et en déclarant correctement les répertoires runtime (surtout avec systemd).

5) Pourquoi ZFS affiche‑t‑il encore une forte utilisation après suppression de fichiers ?

Les snapshots conservent des références aux anciens blocs. Supprimer des fichiers courants peut ne pas libérer d’espace tant que les snapshots ne sont pas détruits. Vérifiez avec zfs list -t snapshot et ajustez la rétention avec précaution — les snapshots sont souvent votre seul rollback rapide.

6) Devons‑nous pruner agressivement les images conteneurs pour garder les disques propres ?

Pas agressivement — stratégiquement. Le prune peut effacer la localité et ralentir les déploiements/rollbacks. Utilisez des seuils de capacité, conservez un ensemble chaud, et coordonnez avec le rythme des releases.

7) Comment empêcher un nettoyage de traverser des volumes montés ?

Utilisez des protections de frontières de système de fichiers comme find -xdev, et validez les points de montage avant d’exécuter. Dans l’automatisation, ajoutez des vérifications du type de système de fichiers et des IDs de périphérique attendus.

8) Est‑ce que « supprimer plus vieux que N jours » est fiable ?

C’est fiable seulement si votre parsing temporel et le nommage des fichiers sont fiables. Les changements DST, les décalages de fuseau, et les renommages cassent la logique de rétention. Préférez la suppression basée sur mtime avec portee explicite et exécutions à blanc, et surveillez le nombre de suppressions.

9) Quel est le plus grand correctif culturel pour les catastrophes de nettoyage ?

Traitez les opérations destructrices comme des déploiements : revue, staging, observabilité, et rollback. Le nettoyage n’est pas du ménage ; c’est un changement en production.

Prochaines étapes concrètes à faire cette semaine

Si vous exploitez des systèmes de production, vous n’avez pas besoin d’un « nettoyeur » meilleur. Vous avez besoin de moins de surprises. La surprise vient de l’ambiguïté : propriété inconnue, rétention mal définie, et outils autorisés à supprimer sans prouver qu’ils suppriment la bonne chose.

  1. Inventoriez vos mécanismes de nettoyage : cron jobs, timers systemd, maintenance des runners CI, GC de conteneurs, rétention de snapshots. Notez les propriétaires.
  2. Ajoutez un motif de quarantaine pour tout ce qui est basé sur des fichiers. Renommez/déplacez d’abord, supprimez ensuite.
  3. Instrumentez la pression disque : octets et inodes, plus les taux de croissance. Les alertes de tendance valent mieux que « 92 % à 3h du matin ».
  4. Codifiez le « diagnostic rapide » dans vos runbooks : octets vs inodes, fichiers ouverts supprimés, snapshots, usage du runtime conteneur.
  5. Bridez les nettoyages de fond : votre nettoyeur ne doit jamais être le consommateur principal sur l’hôte.
  6. Décidez ce qui peut être supprimé et ce qui doit être géré par des outils applicatifs. Si c’est de l’état, traitez‑le comme de l’état.

La propreté en production n’est pas supprimer plus. C’est supprimer avec intention, avec des garde‑fous, et avec un moyen de revenir en arrière lorsque l’intention rencontre la réalité.

← Précédent
Contrôleurs mémoire intégrés : le changement que vous ressentez encore aujourd’hui
Suivant →
ZFS atime : le petit commutateur qui peut résoudre les « écritures lentes »

Laisser un commentaire