Aller au contenu
Disques et systèmes de fichiers au quotidien

Disques et systèmes de fichiers au quotidien

200 Compagnon ⏱ 1 h 20 linuxubuntudebiansystemdscaleway

À la fin, vous saurez

  • Identifier un périphérique bloc par un identifiant stable (UUID, LABEL, /dev/disk/by-id) plutôt que par son nom noyau
  • Partitionner, formater et monter un volume Block Storage Scaleway en choisissant ses options de montage
  • Écrire une ligne de /etc/fstab, la vérifier avec findmnt --verify et mount -a, et expliquer l'unité .mount qui en résulte
  • Agrandir un volume Scaleway puis sa partition et son système de fichiers sans arrêter le service
  • Diagnostiquer un disque plein, par l'espace, par les inodes ou par la réserve de root
  • Ajouter un fichier d'échange, démonter proprement un système de fichiers occupé et vérifier comment /tmp est monté

Prérequis

Testé avec cloud-guest-utils 0.33 debian 13 e2fsprogs 1.47.0 / 1.47.2 gdisk 1.0.10 ncdu 1.19 / 1.22 parted 3.6 psmisc 23.7 systemd 255 / 257 ubuntu 24.04 util-linux 2.39.3 / 2.41 xfsprogs 6.6.0 / 6.13.0 , vérifié le 7 octobre 2026

Pourquoi

Lundi matin, l'export CSV nocturne de la mairie n'est pas parti. Le journal de sig-outils contient une seule ligne utile : No space left on device. Vous découvrez en quelques minutes que Camille faisait tout tenir sur le volume système de 20 Go : les exports, les journaux reçus de sig-app-1 et sig-app-2, les archives en attente d'envoi vers le bucket de sauvegarde. Le disque système s'est rempli, et avec lui tout ce qui avait besoin d'écrire, y compris le journal de systemd et les mises à jour automatiques.

La réparation d'urgence consiste à faire de la place. La réparation durable consiste à séparer : un volume dédié aux données, dimensionné pour elles, monté avec des options adaptées, surveillé, et que l'on peut agrandir sans arrêter le service. C'est un geste d'administration courant, et pourtant il concentre une bonne part des pannes de démarrage que l'on rencontre en exploitation : une ligne de /etc/fstab qui désigne un disque par un nom qui change, un volume détaché qui bloque le démarrage, un mkfs lancé sur le mauvais périphérique.

Cette leçon couvre ce quotidien : reconnaître un disque, le préparer, le monter durablement, l'agrandir, le surveiller, le démonter. Le cours Le stockage : bloc, fichier, objet a montré le parcours minimal côté Scaleway ; on descend ici dans ce que fait le système, et dans ce qui casse. Les volumes logiques (LVM), le RAID logiciel et le choix détaillé d'un système de fichiers relèvent du cours Stockage sous Linux, qui n'est pas encore publié.

Les concepts

Périphérique bloc, système de fichiers, montage

Trois notions s'empilent, et il faut les tenir séparées pour diagnostiquer quoi que ce soit.

Un périphérique bloc (block device) est une suite numérotée de blocs que l'on peut lire et écrire dans n'importe quel ordre. C'est ce que le noyau présente pour un disque physique, un SSD, ou un volume réseau comme le stockage bloc de Scaleway. Il apparaît dans /dev (/dev/sdb) et ne sait rien des fichiers.

Un système de fichiers est une structure écrite sur ce périphérique : un superbloc (superblock, l'en-tête qui décrit le système de fichiers : taille, type, UUID, état), des tables d'inodes, des répertoires et des blocs de données. mkfs écrit cette structure ; c'est ce qui la rend destructrice.

Un montage rattache un système de fichiers à un répertoire de l'arborescence unique (vue dans L'arborescence et les chemins), le point de montage (mount point). Tant que le montage est actif, le contenu antérieur de ce répertoire est masqué, pas effacé. On y reviendra, car ce détail explique une panne classique.

Entre le périphérique et le système de fichiers peut s'intercaler une table de partitions, qui découpe le disque en zones. Sur un serveur actuel, c'est presque toujours GPT (GUID Partition Table), qui a remplacé l'ancienne table MBR : elle accepte des disques de plus de 2 Tio, plus de quatre partitions sans artifice, et donne à chaque partition un identifiant unique (PARTUUID) et un nom (PARTLABEL).

  Volume Block Storage Scaleway (réseau)
                │
                ▼
  /dev/sdb   périphérique bloc (vu par le noyau via virtio-scsi)
                │
                ├── table GPT
                │     └── /dev/sdb1   partition « donnees »
                │            │
                │            ▼
                │        ext4  (superbloc, inodes, données)  UUID=3f6c...
                │            │
                ▼            ▼
                      monté sur /srv/donnees

Des noms instables, des identifiants stables

Le noyau nomme les disques selon leur pilote et leur ordre de détection :

NomPiloteOù on le rencontre
/dev/sda, /dev/sdbSCSI, SATA, USB, virtio-scsiInstances Scaleway (volumes Block Storage), disques SATA
/dev/vda, /dev/vdbvirtio-blkMachines KVM locales, beaucoup d'hébergeurs OpenStack
/dev/nvme0n1, partitions /dev/nvme0n1p1NVMeServeurs physiques, instances AWS Nitro, Elastic Metal
/dev/xvdaXenAnciennes instances AWS

La lettre (a, b, c) n'est pas une propriété du disque : c'est l'ordre dans lequel le noyau l'a découvert. Attachez deux volumes, détachez le premier, redémarrez : celui qui s'appelait sdc s'appelle maintenant sdb. Toute configuration qui écrit /dev/sdb en dur est donc une panne en sursis.

Pour désigner un disque durablement, on utilise des identifiants que udev (le gestionnaire de périphériques de l'espace utilisateur, détaillé à la leçon Le noyau : modules et paramètres) publie sous forme de liens symboliques dans /dev/disk/ :

  • by-uuid/ : l'UUID du système de fichiers, écrit dans son superbloc par mkfs. Il suit le système de fichiers partout, et change si l'on reformate.
  • by-label/ : l'étiquette du système de fichiers (mkfs.ext4 -L), lisible, mais rien n'empêche deux disques de porter la même.
  • by-partuuid/ et by-partlabel/ : les identifiants de la partition GPT, utiles quand la partition n'a pas encore de système de fichiers.
  • by-id/ : l'identité matérielle du disque, construite à partir du fabricant, du modèle et du numéro de série. Chez Scaleway, la documentation indique que les volumes Block Storage annoncent le fabricant SCW, le modèle sbs et le numéro de série volume-<uuid>, l'UUID étant celui du volume dans l'API. Le lien prend la forme /dev/disk/by-id/scsi-0SCW_sbs_volume-<uuid>.

Le lien by-id a une qualité précieuse dans le cloud : il relie ce que vous voyez dans la console ou la CLI Scaleway à ce que voit le système, avant même qu'il existe un système de fichiers. C'est lui qu'il faut utiliser pour être certain de formater le bon volume. L'UUID, lui, est le bon choix dans /etc/fstab, parce qu'il désigne précisément ce que l'on monte.

/etc/fstab et systemd

/etc/fstab (file systems table) est la liste des montages permanents. Chaque ligne a six champs séparés par des espaces ou des tabulations, décrits par fstab(5) :

# <source>                                  <point>        <type> <options>                             <dump> <pass>
UUID=3f6c1a2e-8b4d-4c1f-9e2a-5d7b0c9e4f11  /srv/donnees   ext4   defaults,noatime,nodev,nosuid,nofail  0      2
  1. La source : UUID=, LABEL=, PARTUUID=, PARTLABEL= ou un chemin dans /dev.
  2. Le point de montage, un répertoire qui doit exister (ou none pour le swap).
  3. Le type : ext4, xfs, vfat, swap, tmpfs... auto laisse le système deviner, ce qu'il vaut mieux éviter sur un serveur.
  4. Les options, séparées par des virgules, sans espace.
  5. dump : un reliquat de l'outil de sauvegarde dump(8). On met 0.
  6. pass : l'ordre de vérification par fsck au démarrage. 1 pour la racine, 2 pour les autres systèmes de fichiers locaux, 0 pour ne jamais vérifier (swap, tmpfs, systèmes réseau, et XFS, dont l'outil fsck.xfs ne fait rien par conception).

Historiquement, des scripts de démarrage lisaient ce fichier et appelaient mount -a. Sur une distribution à systemd, ce n'est plus le cas : au démarrage et à chaque systemctl daemon-reload, le générateur (generator, petit programme que systemd exécute très tôt pour produire des unités à partir d'une configuration externe) systemd-fstab-generator traduit chaque ligne en une unité systemd de type .mount, écrite dans /run/systemd/generator/. Le nom de l'unité dérive du chemin : /srv/donnees devient srv-donnees.mount. C'est systemd qui monte ensuite, en respectant les dépendances.

La conséquence pratique est majeure, et la page systemd.mount(5) la décrit précisément. Par défaut, un montage local reçoit une dépendance Before=local-fs.target, et local-fs.target le requiert. Si le périphérique n'apparaît pas, systemd l'attend (90 secondes par défaut, réglage DefaultDeviceTimeoutSec=), puis local-fs.target échoue et la machine bascule en mode d'urgence : plus de réseau, plus de SSH. C'est la panne décrite en détail à la leçon Dépanner un serveur qui ne démarre plus.

L'option nofail change cette relation : selon systemd.mount(5), le montage est alors seulement « voulu » (Wants=) et non « requis » par local-fs.target, et il n'est plus ordonné avant elle. Le démarrage continue sans attendre, que le montage réussisse ou non. Pour tout volume qui n'est pas indispensable au démarrage du système lui-même, et un volume réseau attachable et détachable entre dans cette catégorie, nofail est la règle.

Les options de montage qui comptent

OptionEffetQuand l'utiliser
defaultsrw,suid,dev,exec,auto,nouser,asyncPoint de départ, sert surtout à remplir le champ
roLecture seuleDonnées de référence, montage de secours pour inspecter un disque
noatimeNe met plus à jour la date d'accès à chaque lectureVolumes de données lus intensivement
nodevIgnore les fichiers spéciaux de périphériqueTout ce qui n'est pas / ni /dev
nosuidIgnore les bits setuid et setgidTout volume de données
noexecRefuse l'exécution directe des fichiersVolumes de données pures, /tmp selon les cas
nofailLe démarrage ne dépend pas de ce montageTout volume qui n'est pas indispensable au système
x-systemd.device-timeout=30sAttente maximale du périphérique au démarrageAvec nofail, pour ne pas ralentir le démarrage
discardTRIM immédiat à chaque suppressionRarement : on préfère fstrim.timer

Sur les dates d'accès : depuis le noyau 2.6.30, le comportement par défaut est relatime, qui ne met à jour la date d'accès que si elle est antérieure à la date de modification, ou vieille de plus de 24 heures. noatime supprime ce reste d'écritures. Rares sont les logiciels qui s'appuient sur la date d'accès ; les clients de messagerie locaux qui comparent accès et modification en sont l'exemple historique, et ils n'ont rien à faire sur sig-outils.

Sur noexec : l'option empêche ./script.sh, mais pas sh script.sh ni python3 script.py, puisque c'est alors l'interpréteur, situé ailleurs, qui est exécuté. C'est une barrière contre les maladresses et les attaques peu élaborées, pas une garantie.

En pratique

Les commandes de cette section s'appliquent à sig-outils (Debian 13, zone fr-par-1 dans nos exemples) et aux instances Ubuntu 24.04 quand c'est précisé. Les sorties sont des exemples construits d'après la documentation et le code source des outils, au format exact de ceux-ci ; les identifiants et les tailles seront différents chez vous.

Faire l'inventaire avant de toucher

Avant d'ajouter quoi que ce soit, regardez ce qui existe :

$ lsblk -f

-f (fs) ajoute aux périphériques les colonnes du système de fichiers. La sortie ressemble à ceci :

NAME    FSTYPE FSVER LABEL UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
sda
├─sda1  ext4   1.0         0b1f2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d    1.2G    93% /
├─sda14
└─sda15 vfat   FAT32 UEFI  A1B2-C3D4                             112.1M     9% /boot/efi

On lit : un seul disque sda, une partition racine ext4 presque pleine, une petite partition (sda14, souvent réservée au chargeur BIOS dans les images cloud) et la partition EFI. La disposition exacte dépend de l'image ; c'est le principe qui compte. Pour savoir ce qu'est chaque disque, la documentation Scaleway recommande lsblk --scsi, qui affiche les attributs SCSI :

$ lsblk --scsi -o NAME,HCTL,VENDOR,MODEL,SERIAL,SIZE

Sortie typique :

NAME HCTL       VENDOR   MODEL SERIAL                                       SIZE
sda  0:0:0:0    SCW      sbs   volume-8d2e41c0-5b7a-4f3e-9c61-2a0b7d94e3f5  18.6G

Le volume système de sig-outils est lui aussi un volume Block Storage : il n'y a pas de « disque local » sur les types d'instances récents. Le 20 Go de Scaleway s'affiche 18.6G parce que Scaleway compte en gigaoctets décimaux (10⁹ octets) et lsblk en gibioctets (2³⁰ octets).

Complétez par les montages actifs et le contenu de fstab :

$ findmnt --real
$ cat /etc/fstab

findmnt affiche l'arbre des montages avec leur source et leurs options ; --real masque les pseudo-systèmes de fichiers (proc, sysfs, cgroup2...), qui noient l'information utile.

Créer et attacher le volume

Côté Scaleway, on crée un volume de 50 Go dans la même zone que l'instance, et on l'attache. Le volume étant zonal, il ne pourra jamais être attaché à une instance d'une autre zone.

$ VOLUME_ID=$(scw block volume create name=sig-outils-donnees perf-iops=5000 \
    from-empty.size=50GB zone=fr-par-1 -w -o json | jq -r .id)
$ SERVEUR_ID=$(scw instance server list name=sig-outils zone=fr-par-1 -o json | jq -r '.[0].id')
$ scw instance server attach-volume server-id="$SERVEUR_ID" volume-id="$VOLUME_ID" \
    volume-type=sbs_volume zone=fr-par-1
$ echo "$VOLUME_ID"
  • perf-iops=5000 choisit la classe de performance sbs_5k ; 15000 donne sbs_15k. Des exports et des journaux n'ont pas besoin de plus.
  • from-empty.size=50GB crée un volume vide ; -w attend qu'il soit disponible ; -o json | jq -r .id extrait son identifiant.
  • volume-type=sbs_volume est le type d'attachement des volumes Block Storage.
  • Notez l'identifiant affiché : c'est lui qui vous permettra de reconnaître le volume côté système.

L'attachement est à chaud. Sur sig-outils, le noyau signale l'arrivée du disque dans son tampon (sudo dmesg -T | tail) et udev crée les liens :

$ ls -l /dev/disk/by-id/ | grep sbs

Sortie typique :

lrwxrwxrwx 1 root root  9 Oct  7 09:12 scsi-0SCW_sbs_volume-8d2e41c0-5b7a-4f3e-9c61-2a0b7d94e3f5 -> ../../sda
lrwxrwxrwx 1 root root 10 Oct  7 09:12 scsi-0SCW_sbs_volume-8d2e41c0-5b7a-4f3e-9c61-2a0b7d94e3f5-part1 -> ../../sda1
lrwxrwxrwx 1 root root  9 Oct  7 09:41 scsi-0SCW_sbs_volume-c47a9b12-0e3d-4b8f-a6f2-71d5e0c3b9a8 -> ../../sdb

Le nouveau volume est celui dont le numéro de série reprend $VOLUME_ID. À partir d'ici, plutôt que de taper /dev/sdb, on travaille avec une variable qui pointe vers le lien stable :

$ DISQUE=/dev/disk/by-id/scsi-0SCW_sbs_volume-c47a9b12-0e3d-4b8f-a6f2-71d5e0c3b9a8
$ readlink -f "$DISQUE"
/dev/sdb

Vérifier que le disque est vide

Un volume neuf est vide. Un volume récupéré, ou un disque que l'on croit neuf, ne l'est pas forcément. wipefs sans option liste les signatures connues (table de partitions, système de fichiers, RAID, LVM) sans rien effacer :

$ sudo wipefs "$DISQUE"
$ sudo blkid -p "$DISQUE"

Aucune sortie : aucune signature. Si quelque chose apparaît, arrêtez-vous et cherchez d'où vient ce volume avant d'aller plus loin. blkid -p (probe) sonde directement le périphérique au lieu de consulter le cache.

Partitionner, ou pas

Deux écoles coexistent pour un volume de données dans le cloud.

Sans partition, on crée le système de fichiers directement sur /dev/sdb. C'est ce que montre la documentation Scaleway, et l'agrandissement est plus simple : une étape de moins. L'inconvénient : un outil ou un collègue qui inspecte le disque avec un outil de partitionnement le voit « vide » et peut proposer de l'initialiser.

Avec une partition GPT unique couvrant tout le disque, la nature du disque est explicite pour tous les outils, la partition porte un nom, et la disposition est la même que celle des disques physiques. Le prix : il faudra agrandir la partition avant le système de fichiers. C'est le choix retenu ici, parce qu'il fait apparaître toutes les étapes.

En mode non interactif, avec parted :

$ sudo parted --script "$DISQUE" mklabel gpt mkpart donnees ext4 0% 100%
$ sudo parted --script "$DISQUE" align-check optimal 1
1 aligned
$ sudo parted --script "$DISQUE" unit MiB print
  • --script (-s) : aucune question ; indispensable dans un script, et dangereux pour la même raison.
  • mklabel gpt écrit une nouvelle table GPT (en effaçant l'ancienne).
  • mkpart donnees ext4 0% 100% : sur GPT, le premier argument est le nom de la partition (PARTLABEL). ext4 n'écrit aucun système de fichiers, il sert seulement à choisir le code de type de partition. 0% laisse parted placer le début sur une frontière alignée (1 Mio en pratique), ce qui évite des écritures à cheval sur deux blocs physiques.
  • align-check optimal 1 vérifie l'alignement de la partition 1.

L'équivalent avec sgdisk (paquet gdisk), souvent préféré dans les scripts pour sa syntaxe compacte :

$ sudo sgdisk --new=1:0:0 --typecode=1:8300 --change-name=1:donnees "$DISQUE"

--new=1:0:0 crée la partition 1 du premier au dernier secteur disponible (0 signifie « valeur par défaut »), --typecode=1:8300 lui donne le type « Linux filesystem », --change-name son nom. Utilisez l'un ou l'autre outil, pas les deux.

Le noyau relit la table de partitions ; attendez que udev ait créé les liens :

$ sudo udevadm settle
$ ls -l "${DISQUE}-part1"

Créer le système de fichiers

$ sudo mkfs.ext4 -L donnees -m 1 "${DISQUE}-part1"
  • -L donnees : l'étiquette, 16 octets au maximum selon mke2fs(8).
  • -m 1 : réserve 1 % des blocs à root, au lieu de 5 % par défaut. La réserve sert deux buts : laisser de la marge aux démons qui tournent en root quand les utilisateurs ont tout rempli, et limiter la fragmentation d'un système de fichiers presque plein. Sur la racine, gardez la valeur par défaut. Sur un volume de données de 50 Go, 5 % représentent 2,5 Go immobilisés pour un usage qui n'existe pas ; 1 % suffit. On peut la changer plus tard avec tune2fs -m.
  • Rien d'autre : les valeurs par défaut de /etc/mke2fs.conf (blocs de 4 Kio, un inode pour 16 Kio de données, journal) conviennent à des fichiers de taille courante.

La sortie se termine ainsi :

Creating filesystem with 12206771 4k blocks and 3055616 inodes
Filesystem UUID: 3f6c1a2e-8b4d-4c1f-9e2a-5d7b0c9e4f11
Superblock backups stored on blocks:
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
	4096000, 7962624, 11239424

Allocating group tables: done
Writing inode tables: done
Creating journal (65536 blocks): done
Writing superblocks and filesystem accounting information: done

Deux lignes méritent l'attention. Le nombre d'inodes est fixé maintenant, pour toute la vie du système de fichiers ext4 : mke2fs(8) précise que le ratio octets par inode ne peut plus changer après la création. Si sig-outils devait stocker des dizaines de millions de petits fichiers, ce serait le moment de choisir -i 4096 ou -T small. Les copies de secours du superbloc permettent à fsck de réparer un système de fichiers dont le superbloc principal est endommagé (e2fsck -b 32768).

Note

mke2fs n'initialise pas toutes les tables d'inodes immédiatement : l'option lazy_itable_init, active par défaut, délègue ce travail à un fil du noyau (ext4lazyinit) après le premier montage. Pendant quelques minutes, le volume montre une activité d'écriture alors que personne n'écrit : c'est normal.

Monter, une première fois à la main

$ sudo mkdir -p /srv/donnees
$ sudo mount -o noatime,nodev,nosuid,noexec LABEL=donnees /srv/donnees
$ findmnt /srv/donnees

Sortie typique :

TARGET       SOURCE    FSTYPE OPTIONS
/srv/donnees /dev/sdb1 ext4   rw,nosuid,nodev,noexec,noatime

/srv est, selon la norme FHS, l'emplacement des données servies par la machine : c'est la bonne place pour les exports et les journaux reçus. La racine du nouveau système de fichiers appartient à root et contient un répertoire lost+found, où e2fsck range les fichiers retrouvés sans nom ; ne le supprimez pas. Créez l'arborescence et donnez-la aux comptes qui en ont besoin :

$ sudo install -d -o signalements -g signalements -m 0750 /srv/donnees/exports
$ sudo install -d -o root -g adm -m 0750 /srv/donnees/journaux

Rendre le montage permanent

Récupérez l'UUID du système de fichiers :

$ sudo blkid -s UUID -o value "${DISQUE}-part1"
3f6c1a2e-8b4d-4c1f-9e2a-5d7b0c9e4f11

Puis éditez /etc/fstab avec sudoedit /etc/fstab (vu dans Lire et éditer du texte) plutôt qu'avec un echo >> : une redirection mal écrite (> au lieu de >>) écrase le fichier entier, et la machine ne démarre plus. Ajoutez, avec un commentaire qui servira à la personne suivante :

# Volume Block Storage sig-outils-donnees (c47a9b12-0e3d-4b8f-a6f2-71d5e0c3b9a8), exports et journaux
UUID=3f6c1a2e-8b4d-4c1f-9e2a-5d7b0c9e4f11  /srv/donnees  ext4  noatime,nodev,nosuid,noexec,nofail,x-systemd.device-timeout=30s  0  2

defaults n'est pas nécessaire dès que d'autres options remplissent le champ. x-systemd.device-timeout=30s réduit l'attente du périphérique, et n'est compris que dans /etc/fstab, comme le précise systemd.mount(5).

Vérifier avant de redémarrer, toujours

Trois commandes, dans cet ordre :

$ sudo findmnt --verify --verbose
$ sudo systemctl daemon-reload
$ sudo umount /srv/donnees && sudo mount -a && findmnt /srv/donnees

findmnt --verify analyse /etc/fstab : syntaxe, existence des points de montage, sources joignables, type de système de fichiers reconnu sur le disque. Sans --verbose, il n'affiche que les problèmes. La sortie ressemble à ceci :

/
   [ ] target exists
   [ ] UUID=0b1f2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d translated to /dev/sda1
   [ ] source /dev/sda1 exists
   [ ] FS type is ext4
/srv/donnees
   [ ] target exists
   [ ] UUID=3f6c1a2e-8b4d-4c1f-9e2a-5d7b0c9e4f11 translated to /dev/sdb1
   [ ] source /dev/sdb1 exists
   [ ] FS type is ext4
Success, no errors or warnings detected

Les lignes marquées [W] sont des avertissements, [E] des erreurs ; le code de retour est non nul s'il y a des erreurs.

daemon-reload relance les générateurs : sans lui, systemd travaille avec l'ancienne version de fstab. mount le rappelle d'ailleurs lui-même quand il le détecte, par ce message tiré du code de util-linux :

mount: (hint) your fstab has been modified, but systemd still uses
       the old version; use 'systemctl daemon-reload' to reload.

Enfin, démonter puis mount -a rejoue tout fstab : si la ligne est fausse, vous l'apprenez maintenant, avec un shell ouvert, et pas au prochain redémarrage, sans SSH. Vérifiez aussi l'unité générée :

$ systemctl status srv-donnees.mount
$ systemctl cat srv-donnees.mount

systemctl cat affiche le fichier produit par le générateur, sous /run/systemd/generator/. On y retrouve SourcePath=/etc/fstab, What=/dev/disk/by-uuid/3f6c..., Where=/srv/donnees et les options.

Tip

Avant toute modification de fstab sur une machine distante, prenez un instantané du volume système (scw block snapshot create) et assurez-vous que vous savez ouvrir la console série de l'instance. Les deux prennent une minute et transforment une panne de démarrage en simple contretemps.

Agrandir à chaud

Six mois plus tard, /srv/donnees atteint 85 %. On passe le volume à 100 Go. Scaleway n'autorise que l'agrandissement, jamais la réduction :

$ scw block volume update "$VOLUME_ID" size=100GB zone=fr-par-1
$ scw block volume wait "$VOLUME_ID" terminal-status=in_use zone=fr-par-1

wait attend la fin de l'état resizing ; un volume attaché revient à l'état in_use. Sur l'instance, le noyau doit voir la nouvelle taille. En général, il reçoit la notification et l'écrit dans son tampon, sous la forme sdb: detected capacity change from 97656250 to 195312500 (en secteurs de 512 octets). Sinon, demandez au pilote SCSI de relire la capacité :

$ echo 1 | sudo tee /sys/class/block/sdb/device/rescan
$ lsblk "$DISQUE"

Le disque fait maintenant environ 93,1 G, la partition toujours 46,6 G. Trois couches, trois étapes : volume (fait), partition, système de fichiers.

$ sudo growpart /dev/sdb 1
CHANGED: partition=1 start=2048 old: size=97654169 end=97656216 new: size=195310419 end=195312466
$ sudo resize2fs /dev/sdb1
$ df -h /srv/donnees
  • growpart (paquet cloud-guest-utils) prend le disque et le numéro de partition, séparés par une espace. Il étend la partition jusqu'à la fin du disque sans déplacer son début, ce qui préserve les données. S'il n'y a rien à faire, il répond NOCHANGE: partition 1 is size ... it cannot be grown et rend un code non nul.
  • resize2fs sans taille étend le système de fichiers à toute la partition. resize2fs(8) indique qu'un système ext4 monté peut être agrandi en ligne si le noyau le permet, ce qui est le cas de tous les noyaux actuels.

La documentation Scaleway recommande de démonter la partition avant growpart, par prudence. Ce n'est pas une contrainte technique : growpart met à jour la table puis demande au noyau de prendre en compte la nouvelle taille (via partx), et c'est exactement ainsi que cloud-init agrandit la partition racine, montée, au premier démarrage d'une instance. Prenez en revanche l'instantané que la même documentation recommande : c'est lui qui vous protège d'une erreur de numéro de partition.

Pour XFS, le système de fichiers par défaut de Red Hat, la dernière étape s'écrit sudo xfs_growfs /srv/donnees : elle prend le point de montage, et XFS ne peut que grandir, jamais rétrécir. Pour ext4, la réduction existe, mais uniquement démonté ; dans le cloud, on préfère copier vers un volume plus petit.

Note

Le volume racine suit le même principe, avec une facilité : sur les images Ubuntu et Debian pour le cloud, cloud-init (module growpart) ou l'option x-systemd.growfs agrandissent partition et système de fichiers au démarrage. Après avoir agrandi le volume système dans Scaleway, un redémarrage suffit souvent ; à chaud, les trois mêmes commandes fonctionnent sur /dev/sda.

Surveiller l'espace

La leçon Manipuler fichiers et répertoires a présenté df et du, et le cas des fichiers supprimés encore ouverts (lsof +L1). On y ajoute trois réflexes.

Lire df correctement. Sur ext4, Size n'est pas égal à Used + Avail :

$ df -h /srv/donnees
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdb1        92G   78G   13G  86% /srv/donnees

La différence est la réserve de root : Avail est ce que peut encore écrire un utilisateur ordinaire. Le compte signalements reçoit No space left on device alors que root peut encore écrire. Pour connaître la réserve :

$ sudo tune2fs -l /dev/sdb1 | grep -E 'Block count|Reserved block count|Block size'

Penser aux inodes. df -i affiche les inodes disponibles. Un système de fichiers ext4 peut être plein à 40 % en octets et à 100 % en inodes, si une application crée des millions de petits fichiers (sessions, fichiers de verrouillage, files d'attente mal purgées). Le message est le même : No space left on device. XFS alloue ses inodes dynamiquement et y est moins sujet.

Trouver ce qui occupe. Sur un système de fichiers donné, sans déborder sur les autres :

$ sudo du -xh --max-depth=1 /srv/donnees | sort -h | tail
$ sudo ncdu -x /srv/donnees

-x (--one-file-system) reste sur le système de fichiers de départ : sans lui, du / descend dans /proc, /sys et tous les volumes montés. sort -h trie les tailles lisibles (4.0K, 12M, 3.1G) dans le bon ordre. ncdu (paquet du même nom, à installer) offre une vue interactive où l'on navigue avec les flèches et supprime avec d ; sur un serveur de production, utilisez-le en lecture et faites les suppressions en connaissance de cause. Pour compter les inodes par répertoire : sudo du -x --inodes --max-depth=1 /srv/donnees | sort -n | tail.

Ajouter un fichier d'échange

Les images cloud d'Ubuntu et de Debian ne créent pas de swap (espace d'échange, zone de disque où le noyau déplace des pages de mémoire peu utilisées pour libérer de la mémoire vive). Vérifiez :

$ swapon --show
$ free -h

Aucune ligne pour swapon --show : pas de swap. Faut-il en ajouter ? Sur sig-outils, une petite instance qui exécute des tâches de fond irrégulières, un swap modeste (1 à 2 Go) donne au noyau un endroit où mettre les pages anonymes oubliées depuis des heures (un interpréteur Python resté en mémoire, des bibliothèques jamais réutilisées), et amortit un pic. Il ne remplace pas la mémoire : une machine qui échange en permanence devient lente au point d'être indisponible, et les limites de mémoire des services (leçon Borner les ressources) restent la vraie protection. Sur sig-app-1 et sig-app-2, qui servent des requêtes interactives, beaucoup d'équipes préfèrent ne pas en mettre : mieux vaut un processus tué et relancé qu'une API qui répond en dix secondes. Le réglage vm.swappiness, qui oriente le noyau entre récupérer du cache et échanger, est expliqué à la leçon Le noyau : modules et paramètres.

Sur Ubuntu 24.04 (util-linux 2.39) :

$ sudo fallocate -l 2G /swapfile
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile

Sur Debian 13, util-linux 2.41 permet de tout faire en une commande, mkswap créant le fichier avec les bonnes permissions :

$ sudo mkswap --file --size 2G /swapfile
$ sudo swapon /swapfile
  • fallocate réserve les blocs sans les écrire, ce qui est instantané. Un fichier d'échange ne doit pas avoir de « trous » : swapon refuse un fichier creux (créé par truncate) avec le message skipping - it appears to have holes. fallocate convient sur ext4 et XFS ; sur Btrfs, il faut une procédure particulière.
  • chmod 600 : le swap contient des morceaux de mémoire de tous les processus, mots de passe et clés compris. swapon avertit sinon : /swapfile: insecure permissions 0644, 0600 suggested.
  • mkswap écrit l'en-tête de l'espace d'échange.

Pour le rendre permanent, dans /etc/fstab :

/swapfile  none  swap  sw  0  0

Le point de montage est none, le type swap, et pass vaut 0. Le générateur en fait une unité swapfile.swap. Le swap se place sur le volume système plutôt que sur le volume de données monté en nofail : si celui-ci manquait, le swap manquerait aussi, silencieusement.

Note

zram est une alternative : un périphérique bloc compressé en mémoire, utilisé comme swap. Il échange du temps processeur contre de la mémoire, sans écrire sur disque. Fedora l'active par défaut ; sur Ubuntu et Debian, il s'installe avec systemd-zram-generator ou zram-tools. Il a du sens sur les petites instances, moins quand la mémoire est déjà le facteur limitant.

TRIM et fstrim.timer

Quand un fichier est supprimé, le système de fichiers marque ses blocs comme libres, mais le support n'en sait rien. TRIM (discard dans le vocabulaire Linux) est la commande qui informe le disque que des blocs ne servent plus. Un SSD s'en sert pour son ramasse-miettes interne ; un volume à allocation dynamique (thin provisioning) pour libérer de la place sur le stockage sous-jacent.

Deux façons de l'appliquer : l'option de montage discard, qui envoie un TRIM à chaque suppression (coûteux sur certains supports), ou un passage périodique de fstrim sur tous les systèmes de fichiers qui le permettent. La seconde est recommandée, et util-linux fournit fstrim.timer, hebdomadaire. Il est activé par défaut sur Ubuntu, mais pas sur Debian : le fichier README.Debian de util-linux précise qu'il est disponible « but is not enabled by default ». Pour savoir si un disque accepte TRIM, et l'activer sur Debian :

$ lsblk --discard /dev/sdb
$ systemctl status fstrim.timer
$ sudo systemctl enable --now fstrim.timer

lsblk --discard affiche DISC-GRAN et DISC-MAX : des valeurs nulles signifient que le périphérique n'accepte pas TRIM, et fstrim l'ignorera. Sur un volume Block Storage Scaleway, facturé sur la taille provisionnée, l'enjeu n'est pas financier ; c'est une question d'hygiène et d'homogénéité entre les machines.

Démonter proprement

Pour détacher le volume (le passer à une autre instance, le remplacer), il faut d'abord le démonter :

$ sudo umount /srv/donnees
umount: /srv/donnees: target is busy.

Un processus utilise le système de fichiers : un fichier ouvert, un répertoire courant, une bibliothèque projetée en mémoire. Trouvez-le :

$ sudo fuser -vm /srv/donnees

Sortie typique :

                     USER        PID ACCESS COMMAND
/srv/donnees:        root     kernel mount /srv/donnees
                     signalements 2417 F.... python3
                     admin      3012 ..c.. bash
  • -m : tous les processus qui utilisent le système de fichiers contenant ce chemin, pas seulement ce fichier.
  • -v : affichage détaillé, avec la colonne ACCESS : c répertoire courant, e exécutable en cours, f fichier ouvert, F fichier ouvert en écriture, r répertoire racine, m fichier projeté en mémoire.

Ici, l'export Python écrit dans un fichier, et votre propre shell (bash, PID 3012) a son répertoire courant dans /srv/donnees : un cd / suffit pour celui-là. sudo lsof /srv/donnees donne la même information avec le nom des fichiers. Arrêtez proprement les services concernés (systemctl stop), puis démontez.

umount -l (lazy) détache immédiatement le point de montage de l'arborescence et ne libère réellement le système de fichiers qu'à la fermeture du dernier fichier. C'est parfois utile pour débloquer un montage réseau mort ; sur un volume que l'on s'apprête à détacher, c'est une erreur : les processus continuent d'écrire, et le détacher côté Scaleway à ce moment revient à arracher un disque en pleine écriture. Après le démontage, retirez ou commentez la ligne de fstab, daemon-reload, puis :

$ scw instance server detach-volume server-id="$SERVEUR_ID" volume-id="$VOLUME_ID" zone=fr-par-1

/tmp : sur disque ou en mémoire

Debian 13 a changé un comportement ancien. Ses notes de publication l'annoncent : à partir de trixie, /tmp est par défaut un tmpfs, stocké en mémoire, monté par l'unité tmp.mount de systemd, limité à 50 % de la mémoire (un maximum : la mémoire n'est consommée que par les fichiers réellement créés). Les systèmes mis à niveau depuis Debian 12 ne basculent qu'au redémarrage suivant, et un /tmp déjà déclaré dans fstab n'est pas touché. Ubuntu 24.04, lui, garde /tmp sur le disque racine.

$ findmnt /tmp

Sur sig-outils, la sortie typique est :

TARGET SOURCE FSTYPE OPTIONS
/tmp   tmpfs  tmpfs  rw,nosuid,nodev,size=1004564k,nr_inodes=1048576,inode64

Sur sig-app-1, la commande ne renvoie rien : /tmp n'est pas un montage, c'est un répertoire du système de fichiers racine.

Conséquences pratiques pour Signalements :

  • Un traitement qui écrit un gros fichier temporaire dans /tmp consomme désormais de la mémoire sur sig-outils. L'export CSV, s'il construit son fichier dans /tmp, doit plutôt l'écrire dans /srv/donnees/exports ou dans /var/tmp.
  • Le contenu de /tmp disparaît à chaque redémarrage, ce qui était déjà le cas en pratique.
  • Les mêmes notes indiquent que, sur les nouvelles installations, systemd-tmpfiles supprime les fichiers de /tmp inutilisés depuis 10 jours et ceux de /var/tmp inutilisés depuis 30 jours. Les systèmes mis à niveau reçoivent un fichier /etc/tmpfiles.d/tmp.conf qui conserve l'ancien comportement.

Pour borner la taille, on surcharge l'unité plutôt que d'ajouter une ligne dans fstab :

$ sudo systemctl edit tmp.mount
[Mount]
Options=mode=1777,strictatime,nosuid,nodev,size=512M,nr_inodes=1m

Pour revenir à un /tmp sur disque : sudo systemctl mask tmp.mount, puis redémarrer. Le choix de noexec sur /tmp, recommandé par les guides de durcissement, est discuté à la leçon Durcir un serveur.

Sous le capot

Ce que fait mount

mount est un programme de l'espace utilisateur (util-linux, bibliothèque libmount) qui prépare un appel système. Il résout la source (LABEL=donnees vers /dev/sdb1, en consultant /dev/disk/by-label/ ou blkid), détecte le type si on ne l'a pas donné, sépare les options en trois familles, puis appelle le noyau. findmnt --verify --verbose montre d'ailleurs cette classification :

  • les options du VFS (la couche générique des systèmes de fichiers du noyau), communes à tous : ro, nosuid, nodev, noexec, noatime. Elles deviennent des drapeaux de l'appel système et s'appliquent au montage, pas au système de fichiers : un même système de fichiers peut être monté deux fois, une fois en noexec, une fois sans ;
  • les options propres au système de fichiers, transmises telles quelles au pilote : errors=remount-ro, commit=30, data=ordered pour ext4 ;
  • les options de l'espace utilisateur, que le noyau ne voit jamais : nofail, noauto, user, et toutes les x-systemd.*. mount et systemd les interprètent, puis les retirent.

Le noyau publie l'état réel des montages dans /proc/self/mountinfo, une ligne par montage, avec un identifiant, le parent, le numéro de périphérique (majeur:mineur), la racine, le point de montage et les deux familles d'options du noyau. C'est cette table que lisent findmnt et systemd ; /etc/mtab n'est plus qu'un lien symbolique vers /proc/self/mounts.

Le chemin d'une ligne de fstab au démarrage

    flowchart TD
    A["/etc/fstab"] -->|systemd-fstab-generator| B["/run/systemd/generator/srv-donnees.mount"]
    B --> C{"Option nofail ?"}
    C -->|non| D["local-fs.target Requires= et After= srv-donnees.mount"]
    C -->|oui| E["local-fs.target Wants= srv-donnees.mount, sans ordre"]
    B --> F["dépendance sur l'unité .device du disque"]
    F -->|udev signale le disque| G["systemd-fsck@... puis mount(2)"]
    F -->|délai x-systemd.device-timeout dépassé| H["échec du montage"]
    H --> D2["sans nofail : local-fs.target échoue, mode d'urgence"]
    H --> E2["avec nofail : avertissement dans le journal, le démarrage continue"]
  

Le générateur ajoute aussi une dépendance vers l'unité .device du disque (dev-disk-by\x2duuid-....device, le tiret du chemin étant échappé en \x2d), et, si pass est non nul, vers systemd-fsck@.service, qui lance fsck avant le montage. systemd-escape -p --suffix=mount /srv/donnees calcule le nom d'unité correspondant à n'importe quel chemin.

Monter par-dessus un répertoire non vide

Le noyau autorise le montage sur un répertoire qui contient déjà des fichiers. Ceux-ci deviennent invisibles, sans être effacés, et occupent toujours de la place sur le système de fichiers parent. Combiné avec nofail, cela crée un piège : si le volume manque au démarrage, /srv/donnees est un simple répertoire du disque racine, l'export de la nuit y écrit, remplit la racine, et ces fichiers disparaissent de la vue dès que le volume revient. On les retrouve en montant la racine ailleurs par un montage lié, qui ne reprend pas les sous-montages :

$ sudo mount --bind / /mnt
$ sudo du -sh /mnt/srv/donnees
$ sudo umount /mnt

La parade est dans la section En production.

Pourquoi growpart ne perd pas les données

Une partition n'est qu'une entrée de table : un secteur de début et un secteur de fin. growpart réécrit la fin en gardant exactement le même début, après avoir sauvegardé l'ancienne table ; les données ne bougent pas. Le danger vient d'un début modifié, ce qui arrive quand on recrée une partition à la main avec un outil interactif. Le système de fichiers, lui, ignore que sa partition a grandi tant que resize2fs n'a pas ajouté de groupes de blocs et mis à jour le superbloc.

Pièges courants

mount: /srv/donnees: wrong fs type, bad option, bad superblock on /dev/sdb, missing codepage or helper program, or other error. Le message générique de libmount quand le noyau répond EINVAL. Causes fréquentes : monter le disque (/dev/sdb) alors que le système de fichiers est sur la partition (/dev/sdb1) ; une faute dans une option (noatim) ; un type absent (mkfs pas encore fait). La ligne suivante du message est la bonne piste : dmesg(1) may have more information after failed mount system call. Le noyau y écrit la vraie raison, par exemple EXT4-fs (sdb1): Unrecognized mount option "noatim" or missing value.

mount: /srv/donnees: mount point does not exist. Le répertoire n'a pas été créé, ou il a été créé sur une autre machine par le script de provisionnement. mkdir -p d'abord.

mount: /srv/donnees: special device UUID=... does not exist. L'UUID de fstab ne correspond à aucun système de fichiers présent. Volume détaché, volume reformaté (nouvel UUID), ou UUID copié depuis une autre machine. Notez un détail du code de libmount : avec nofail, ce cas-là est traité comme un succès silencieux par mount -a, ce qui est voulu au démarrage mais peut masquer l'erreur lors d'un test. findmnt --verify le signale, lui : pour toute ligne sans noauto, il affiche [E] unreachable on boot required source: UUID=... (et seulement [W] unreachable: UUID=... pour une ligne en noauto). Vérifiez avec lsblk -f que l'UUID existe.

umount: /srv/donnees: target is busy. Un processus utilise le système de fichiers ; fuser -vm ou lsof le désignent. Le plus souvent, c'est votre propre shell, ou une session tmux oubliée.

Formater le mauvais disque. mkfs.ext4 /dev/sda1 au lieu de /dev/sdb1 détruit la racine d'une machine en production. mkfs.ext4 avertit parfois (/dev/sda1 contains a ext4 file system ... Proceed anyway? (y,N)), mais pas si l'on a ajouté -F. Travaillez par le lien by-id qui contient l'identifiant du volume, vérifiez avec wipefs et lsblk juste avant, et lisez la commande deux fois.

Écrire /dev/sdb1 dans fstab. Cela fonctionne jusqu'au jour où un second volume est attaché et que les lettres changent. Au mieux le montage échoue, au pire un autre système de fichiers est monté à la place, et les exports partent sur le volume des journaux.

resize2fs ne gagne rien. The filesystem is already 12206771 (4k) blocks long. Nothing to do! : la partition n'a pas été agrandie, ou le noyau ne voit pas encore la nouvelle taille du disque. Vérifiez chaque couche avec lsblk : disque, puis partition, puis df.

Disque plein alors que df -h montre de la place. Trois suspects : les inodes (df -i), la réserve de root (vous êtes un utilisateur ordinaire et Avail est à zéro), ou un fichier supprimé encore ouvert (lsof +L1), qui fait l'inverse : df compte plus que du.

Oublier daemon-reload après avoir modifié fstab. mount -a lit le fichier directement et semble confirmer que tout va bien ; au démarrage suivant, c'est pourtant le générateur qui compte, et systemctl status srv-donnees.mount décrit encore l'ancienne ligne tant que le rechargement n'a pas eu lieu.

Un fichier d'échange sur le volume nofail, ou un service qui écrit dans /srv/donnees sans dépendre du montage : voir ci-dessous.

Sécurité

Les options de montage sont une défense en profondeur. nodev empêche qu'un fichier spécial de périphérique déposé sur un volume de données (par exemple une copie de /dev/sda créée avec mknod par un attaquant qui aurait obtenu les droits root ailleurs, ou présente sur un volume restauré) donne accès au disque brut. nosuid neutralise un binaire setuid root déposé dans les exports. noexec complique l'exécution d'un outil téléchargé. Le guide de l'ANSSI BP-028 v2.0 recommande une partition dédiée pour les zones où des utilisateurs ou des services écrivent, montée avec les options les plus restrictives que l'usage permet (recommandation « partitionnement type »). Sur sig-outils, /srv/donnees n'a aucune raison de contenir un exécutable ou un périphérique : les trois options s'imposent.

Un volume se déplace. Un volume Block Storage peut être détaché et attaché à une autre instance du même projet, par toute personne qui en a le droit dans l'IAM Scaleway. Les permissions Unix du système de fichiers ne protègent rien contre quelqu'un qui le monte ailleurs en root. Les droits IAM sur les volumes et les instantanés font donc partie de la sécurité des données ; le chiffrement du volume côté système (LUKS), qui rend un volume ou un instantané illisible sans la clé, sera traité dans le cours Stockage sous Linux.

Le swap et /tmp contiennent des secrets. Des pages de mémoire de Gunicorn, avec des jetons ou des données de signalement, peuvent se retrouver dans le fichier d'échange, d'où le chmod 600 impératif. Un /tmp en tmpfs ne laisse rien sur disque au redémarrage, mais ses pages peuvent elles aussi être échangées vers le swap.

Effacer ne suffit pas toujours. Les exports CSV contiennent des données personnelles (adresses des signalements, parfois coordonnées des personnes) : le RGPD impose de les supprimer au terme de leur durée de conservation. Sur un volume à allocation dynamique ou un SSD, réécrire un fichier avec shred ne garantit pas que les anciens blocs soient effacés : shred(1) prévient lui-même que son efficacité suppose que le système de fichiers réécrive les données en place, ce que ne font ni certains modes de journalisation ni les supports qui réallouent les blocs. La suppression régulière (minuteur de purge, leçon 10), la suppression du volume en fin de vie et la maîtrise des instantanés qui en conservent des copies sont les vrais leviers. Pensez aux instantanés oubliés : ils contiennent l'état du volume au moment où ils ont été pris, données personnelles comprises.

Les droits sur le point de montage. Le répertoire racine d'un ext4 neuf appartient à root avec les droits 755 : tout le monde peut le lister. Réglez les droits après le montage, sur la racine du volume ; ceux du répertoire sous-jacent, masqué, ne s'appliquent plus.

En production

Rendre les services dépendants de leurs montages. Avec nofail, la machine démarre sans le volume, mais le service d'export doit, lui, refuser de démarrer. La directive RequiresMountsFor= de systemd le fait en une ligne, dans un drop-in de l'unité :

[Unit]
RequiresMountsFor=/srv/donnees

systemd ajoute alors Requires= et After= vers srv-donnees.mount : sans volume, le service ne démarre pas, et l'échec est visible dans systemctl --failed au lieu de remplir la racine en silence. Une protection complémentaire consiste à rendre le répertoire sous-jacent non inscriptible (volume démonté, sudo chattr +i /srv/donnees), pour qu'aucune écriture n'y aboutisse par accident.

Alerter avant le plein, et sur la tendance. Une alerte à 85 % d'espace utilisé et à 85 % d'inodes, par système de fichiers, est un minimum. Mieux : alerter sur la vitesse de remplissage (« plein dans moins de 48 heures au rythme actuel »), qui distingue la croissance normale d'une application qui s'emballe. Le cours Performance et diagnostic et les outils de supervision prennent le relais ; sans eux, un minuteur qui exécute df --output=pcent,ipcent,target et envoie une notification vaut mieux que rien.

Écrire l'infrastructure plutôt que la taper. Chaque étape de cette leçon est une commande. Sur un parc, elles vont dans un outil de gestion de configuration (cours Ansible), dans cloud-init au démarrage de l'instance (avec les modules disk_setup, fs_setup et mounts), et le volume lui-même dans Terraform ou OpenTofu. Un volume dont l'existence n'est consignée nulle part sera oublié lors de la reconstruction de la machine. À défaut, consignez-le dans la fiche de serveur de sig-outils (leçon Prendre en charge un serveur) : identifiant du volume, taille, point de montage, usage.

Le volume n'est pas une sauvegarde. Un volume Block Storage est répliqué par Scaleway contre les pannes matérielles, mais un rm -rf ou un rançongiciel sont fidèlement répliqués aussi. Les instantanés protègent contre l'erreur, dans le même compte et la même zone ; la vraie sauvegarde, hors du volume et hors de portée de la machine, est l'objet de la leçon Sauvegarder et restaurer un serveur.

Exercices

1. Lire une machine (niveau 100). Sur une machine Ubuntu ou Debian, sans rien modifier, répondez : combien de disques et de partitions ? Quel système de fichiers est monté sur /, avec quelles options ? Y a-t-il du swap ? /tmp est-il un montage ? fstrim.timer est-il actif ?

Solution

lsblk -f pour les disques, partitions et systèmes de fichiers. findmnt / pour la source, le type et les options de la racine (souvent rw,relatime,discard,errors=remount-ro sur les images cloud, errors=remount-ro faisant repasser la racine en lecture seule en cas d'erreur d'écriture). swapon --show ou free -h pour le swap ; aucune ligne signifie aucun swap. findmnt /tmp : une ligne tmpfs sur Debian 13, rien sur Ubuntu 24.04. systemctl is-enabled fstrim.timer et systemctl list-timers fstrim.timer : activé sur Ubuntu, désactivé par défaut sur Debian.

2. Une ligne de fstab à relire (niveau 200). Camille a laissé cette ligne dans le fstab de sig-outils. Relevez tous les problèmes et proposez une version corrigée.

/dev/sdb  /srv/donnees  auto  defaults  0  0
Solution
  • /dev/sdb : nom instable, et c'est le disque entier. S'il porte une partition, le montage échoue (wrong fs type...) ; si les lettres changent, un autre volume sera monté. Il faut UUID= du système de fichiers (blkid).
  • auto : laisse deviner le type ; mieux vaut l'écrire (ext4), ce qui évite aussi de monter par erreur un volume d'un autre type.
  • defaults seul : pas de nofail, donc un volume absent bloque le démarrage en mode d'urgence ; pas de nodev, nosuid, noexec, noatime pour un volume de données.
  • pass à 0 : le système de fichiers n'est jamais vérifié au démarrage ; 2 pour un ext4 de données.

Version corrigée :

UUID=3f6c1a2e-8b4d-4c1f-9e2a-5d7b0c9e4f11  /srv/donnees  ext4  noatime,nodev,nosuid,noexec,nofail,x-systemd.device-timeout=30s  0  2

Puis sudo findmnt --verify, sudo systemctl daemon-reload, sudo umount /srv/donnees && sudo mount -a.

3. Le disque plein qui ne l'est pas (niveau 200). L'export échoue avec No space left on device. df -h /srv/donnees affiche Use% 61%. Donnez la démarche de diagnostic et les deux causes les plus probables, avec leur correction.

Solution
  1. df -i /srv/donnees : si IUse% est à 100 %, ce sont les inodes. Trouver le répertoire coupable avec sudo du -x --inodes --max-depth=2 /srv/donnees | sort -n | tail, puis purger les petits fichiers inutiles (fichiers temporaires jamais nettoyés, par exemple). À long terme : purge automatique ; si l'usage est légitime, un nouveau système de fichiers créé avec plus d'inodes (mkfs.ext4 -i 4096), car le nombre d'inodes d'un ext4 ne change pas après sa création (il augmente seulement en proportion si on l'agrandit).
  2. Si les inodes vont bien, autre cause classique : l'export n'écrit pas là où l'on croit. Sur Debian 13, s'il construit son fichier dans /tmp, c'est le tmpfs qui est plein (df -h /tmp) ; correction : faire écrire le fichier temporaire dans /srv/donnees/exports ou /var/tmp, ou agrandir tmp.mount par un drop-in.

4. Agrandir sans couper (niveau 200). Le volume de sig-outils passe de 50 à 100 Go. Écrivez la suite complète des commandes, côté Scaleway et côté système, avec la vérification de chaque couche, en supposant une partition 1 sur /dev/sdb et un ext4.

Solution
$ scw block snapshot create volume-id="$VOLUME_ID" name=sig-outils-donnees-avant-agrandissement zone=fr-par-1
$ scw block volume update "$VOLUME_ID" size=100GB zone=fr-par-1
$ scw block volume wait "$VOLUME_ID" terminal-status=in_use zone=fr-par-1
$ lsblk /dev/sdb                                     # le disque a-t-il grandi ?
$ echo 1 | sudo tee /sys/class/block/sdb/device/rescan   # seulement s'il n'a pas grandi
$ sudo growpart /dev/sdb 1
$ lsblk /dev/sdb                                     # la partition a-t-elle grandi ?
$ sudo resize2fs /dev/sdb1
$ df -h /srv/donnees                                 # le système de fichiers a-t-il grandi ?

L'instantané d'abord : il protège d'une erreur de numéro de partition ou de disque. Aucune de ces commandes n'impose d'arrêter l'export ou de démonter le volume. Pour XFS, la dernière commande serait sudo xfs_growfs /srv/donnees.

5. Le volume fantôme (niveau 300). Après une maintenance Scaleway, sig-outils a redémarré sans son volume de données (attaché de nouveau une heure plus tard). Depuis, la racine est pleine à 98 %, alors que du -xsh /srv/donnees ne montre que le contenu attendu du volume. Expliquez ce qui s'est passé, comment récupérer les fichiers égarés, et quelles deux mesures empêchent la récidive.

Solution

Grâce à nofail, la machine a démarré sans le volume : /srv/donnees était alors un simple répertoire du disque racine. L'export (et la réception des journaux) y ont écrit pendant une heure, remplissant la racine. Quand le volume a été remonté, ces fichiers ont été masqués par le montage, mais occupent toujours la racine.

Récupération, sans démonter le volume : sudo mount --bind / /mnt, puis sudo du -sh /mnt/srv/donnees/* pour voir les fichiers masqués ; les déplacer vers le volume (sudo rsync -a /mnt/srv/donnees/ /srv/donnees/ après avoir vérifié qu'ils ne remplacent rien de plus récent, ou fusionner à la main), les supprimer de /mnt/srv/donnees/, puis sudo umount /mnt.

Prévention : RequiresMountsFor=/srv/donnees dans les unités des services qui écrivent sur le volume (ils refusent de démarrer sans lui, et apparaissent en échec), et rendre le répertoire sous-jacent immuable (volume démonté, chattr +i /srv/donnees). Ajoutez une alerte sur l'état de srv-donnees.mount et sur le remplissage de la racine.

Récapitulatif

  • Un périphérique bloc porte éventuellement une table de partitions GPT, qui porte un système de fichiers, que l'on monte sur un répertoire.
  • Les noms /dev/sdX changent ; on désigne un volume par /dev/disk/by-id/ (identité du volume Scaleway) pour le préparer, et par UUID= dans fstab.
  • wipefs et lsblk -f avant tout mkfs ; mkfs.ext4 -L ... -m 1 pour un volume de données ; le nombre d'inodes d'un ext4 est fixé à la création.
  • fstab : six champs ; sur un volume de données, noatime,nodev,nosuid,noexec,nofail, et pass à 2. nofail évite le mode d'urgence quand le volume manque.
  • systemd traduit fstab en unités .mount ; après modification : findmnt --verify, systemctl daemon-reload, mount -a, avant tout redémarrage.
  • Agrandir : volume (scw block volume update), partition (growpart), système de fichiers (resize2fs ou xfs_growfs), à chaud.
  • Disque plein : espace, inodes (df -i), réserve de root, fichiers supprimés ouverts ; du -x et ncdu -x pour trouver.
  • Swap : un fichier chmod 600, sur le volume système, utile sur les petites machines à tâches de fond.
  • fstrim.timer actif sur Ubuntu, à activer sur Debian. umount « target is busy » : fuser -vm, lsof.
  • Debian 13 monte /tmp en tmpfs, limité à la moitié de la mémoire ; Ubuntu 24.04 non.
  • Un service qui écrit sur un volume déclare RequiresMountsFor=.

Pour aller plus loin

  • Les pages fstab(5), systemd.mount(5) et systemd-fstab-generator(8) : la seconde liste toutes les options x-systemd.*, dont x-systemd.automount pour monter à la première utilisation.
  • mke2fs(8) et /etc/mke2fs.conf, pour comprendre les valeurs par défaut d'ext4 et les profils -T.
  • La documentation Scaleway sur l'identification des périphériques, qui montre aussi comment écrire une règle udev pour obtenir des liens plus courts du type /dev/disk/scw/volume-<uuid>.
  • Le cours Stockage sous Linux, pour LVM, le RAID logiciel, le chiffrement LUKS et le choix entre ext4, XFS et Btrfs.
  • La leçon suivante, Configurer le réseau d'un serveur.
+20 XP Carte du ciel →Mon cosmonaute →

Sources