URL: https://linuxfr.org/users/ar7/journaux/btrfs-et-opensuse-episode-1-sous-volumes-snapshots-et-rollbacks Title: [Btrfs et openSUSE] Épisode 1 : sous‐volumes, snapshots et rollbacks Authors: AR7 Date: 2017年08月17日T16:11:10+02:00 License: CC By-SA Tags: opensuse et btrfs Score: 45 ![Btrfs is hard](https://openclipart.org/image/300px/svg_to_png/170369/Hard-Disk.png) **« Btrfs et openSUSE »** est une série de journaux sur le système de fichiers Btrfs, basée sur ma propre expérience d’utilisateur d’openSUSE. Au menu : * des généralités sur Btrfs [☑](https://linuxfr.org/users/ar7/journaux/btrfs-et-opensuse-episode-0-l-ex-fs-du-futur) ; * des noms qui pètent : sous‐volumes, _snapshots_, _rollbacks_ ; * du snapper ; * du grub ; * de la mise à jour incrémentale ; * des quotas ; * de la maintenance ; * des trucs spécifiques à openSUSE ; * des tentatives désespérées pour rester applicable à d’autres distributions ; * des erreurs (pas taper) ; * des bogues ; * des cris ; * des larmes ; * et bien plus ! Ou bien moins. **Aujourd’hui, l’épisode 1 : sous‐volumes, _snapshots_ et _rollbacks_.** # Quelques définitions ![Dictionnaire](https://geektionnerd.net/wp-content/uploads/2013/04/13-04-22-Dictionnaire.png) ## Sous‐volume Un **sous‐volume**, c’est un concept qui se situe entre celui du répertoire et celui de la partition. D’après la [FAQ du wiki Btrfs](https://btrfs.wiki.kernel.org/index.php/FAQ#What_is_a_subvolume.3F), voilà ce qu’on peut faire avec : * un sous‐volume peut être monté indépendamment du reste du système de fichiers ; * il est possible de faire un _snapshot_ d’un sous‐volume en une seule opération atomique ; * on peut assigner des limites de capacité à un sous‐volume via des quotas ou autrement partager l’espace de stockage entre tous les sous‐volumes. Ainsi les sous‐volumes peuvent partager des données entre eux (à travers la déduplication et les _snapshots_). On peut aussi copier des sous‐volumes d’une partition Btrfs à une autre (ce sujet aura un épisode dédié !). ## Snapshot Un **snapshot** — un instantané, un cliché — est un clone d’un et un seul sous‐volume à un instant t. Du coup, c’est aussi un sous‐volume. Avec un parent : le sous‐volume original. Rappelez‐vous [l’épisode précédent](https://linuxfr.org/users/ar7/journaux/btrfs-et-opensuse-episode-0-l-ex-fs-du-futur#cow--copy-on-write) : on avait dit que Btrfs se basait sur la technique du _Copy‐on‐Write_. Eh bien, Btrfs n’est pas seulement capable de faire des copies paresseuses de fichiers ; il est capable d’en faire pour un sous‐volume entier, comprenant maints répertoires et fichiers, et ce de façon quasi‐immédiate. ## Rollback Pour un système, un **rollback** est la restauration d’un état précédent de ce système. Dans notre contexte Btrfs, cela consiste à utiliser un instantané d’un sous‐volume — un cliché pris à un instant _t_ — à la place de ce sous‐volume. Donc revenir à un état précédent de ce sous‐volume. # Une installation d’openSUSE classique ![Caméléon](https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Chamaeleonidae_anatomy.jpg/630px-Chamaeleonidae_anatomy.jpg) Voici les sous‐volumes présents sur une openSUSE fraîchement installée. Le seul écart par rapport au partitionnement par défaut est de ne pas avoir de partition `/home` séparée en XFS mais simplement un sous‐volume Btrfs, pour des raisons de test. ```sh ~# btrfs subvolume list / ID 257 gen 184 top level 5 path @ ID 258 gen 971 top level 257 path @/.snapshots ID 259 gen 985 top level 258 path @/.snapshots/1/snapshot ID 260 gen 184 top level 257 path @/boot/grub2/i386-pc ID 261 gen 184 top level 257 path @/boot/grub2/x86_64-efi ID 262 gen 972 top level 257 path @/home ID 263 gen 184 top level 257 path @/opt ID 264 gen 925 top level 257 path @/srv ID 265 gen 984 top level 257 path @/tmp ID 266 gen 925 top level 257 path @/usr/local ID 267 gen 927 top level 257 path @/var/cache ID 268 gen 184 top level 257 path @/var/crash ID 269 gen 184 top level 257 path @/var/lib/libvirt/images ID 270 gen 184 top level 257 path @/var/lib/machines ID 271 gen 184 top level 257 path @/var/lib/mailman ID 272 gen 184 top level 257 path @/var/lib/mariadb ID 273 gen 184 top level 257 path @/var/lib/mysql ID 274 gen 184 top level 257 path @/var/lib/named ID 275 gen 184 top level 257 path @/var/lib/pgsql ID 276 gen 986 top level 257 path @/var/log ID 277 gen 184 top level 257 path @/var/opt ID 278 gen 986 top level 257 path @/var/spool ID 279 gen 984 top level 257 path @/var/tmp ~# cat /etc/fstab UUID=a2ec9936-18fe-4910-a50b-c120726264f8 swap swap defaults 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 / btrfs relatime 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /boot/grub2/i386-pc btrfs relatime,subvol=@/boot/grub2/i386-pc 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /boot/grub2/x86_64-efi btrfs relatime,subvol=@/boot/grub2/x86_64-efi 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /home btrfs relatime,subvol=@/home 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /opt btrfs relatime,subvol=@/opt 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /srv btrfs relatime,subvol=@/srv 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /tmp btrfs relatime,subvol=@/tmp 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /usr/local btrfs relatime,subvol=@/usr/local 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /var/cache btrfs relatime,subvol=@/var/cache 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /var/crash btrfs relatime,subvol=@/var/crash 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /var/lib/libvirt/images btrfs relatime,subvol=@/var/lib/libvirt/images 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /var/lib/machines btrfs relatime,subvol=@/var/lib/machines 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /var/lib/mailman btrfs relatime,subvol=@/var/lib/mailman 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /var/lib/mariadb btrfs relatime,subvol=@/var/lib/mariadb 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /var/lib/mysql btrfs relatime,subvol=@/var/lib/mysql 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /var/lib/named btrfs relatime,subvol=@/var/lib/named 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /var/lib/pgsql btrfs relatime,subvol=@/var/lib/pgsql 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /var/log btrfs relatime,subvol=@/var/log 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /var/opt btrfs relatime,subvol=@/var/opt 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /var/spool btrfs relatime,subvol=@/var/spool 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /var/tmp btrfs relatime,subvol=@/var/tmp 0 0 UUID=926a75ec-a27c-488a-aa90-ce131f6cd378 /.snapshots btrfs relatime,subvol=@/.snapshots 0 0 ~# ``` Que remarque‐t‐on au premier abord ? Trois choses : 1. il y a beaucoup de sous‐volumes (!) ; 2. il y a un sous‐volume `@` (?) ; 3. il y a un sous‐volume `@/.snapshots` et un autre `@/.snapshots/1/snapshot` (??). Essayons déjà de trouver des explications à ces trois points. ## Pourquoi tant de sous‐volumes ? ![Minions](http://vignette4.wikia.nocookie.net/despicableme/images/e/ef/The_minions_in_Minions.jpeg/revision/latest?cb=20160310145142) Essayons de répondre à la question suivante : quels sous‐volumes créer à l'installation d'une distribution GNU/Linux pour permettre de faire ensuite des snapshots pertinents du système (`/`) ? ### Un seul sous‐volume pour `/` ? Moui, le problème c’est que, sur un système complet il y a des données assez « volatiles » ou qui sont beaucoup réécrites : fichiers temporaires, caches, VM, bases de données, journaux... Il n’est pas franchement pertinent de conserver ces données à un instant t. En outre : * ces données sont peu propices à l’utilisation du CoW ; * ces données pourraient être exclues tout simplement pour les conserver tout au long de la vie du système ; typiquement les journaux système : c’est bien de garder la trace d’une restauration. Au final, faire régulièrement des instantanés d’un tel sous‐volume géant entraînerait une fragmentation et une consommation de l’espace disque importante en plus de ne pas être suffisamment flexible pour exclure certaines données des restaurations du système. ### Un sous‐volume par répertoire de haut niveau (`/usr`, `/etc`, ...) ? Moui, mais dans ce cas impossible pour un _snapshot_ de représenter un système fonctionnel. Souvenez‐vous, un _snapshot_ correspond à un seul sous‐volume. Cela rend compliqué la restauration du système (il faut restaurer plusieurs sous‐volumes au lieu d’un seul). ### La solution actuelle sur openSUSE Il s’agit simplement de multiplier les sous‐volumes afin de les exclure des instantanés de `/`, donc : * exit `/tmp`, `/var/tmp` : fichiers temporaires ; * exit `/var/cache` : caches ; * exit `/var/lib/libvirt/images`, `/var/lib/machines` : machines virtuelles ; * exit `/var/lib/mariadb`, `/var/lib/mysql`, `/var/lib/pgsql` : bases de données ; * exit `/var/log` : on veut conserver les traces d’une restauration du système ; * etc. D’où le grand nombre de sous‐volumes à l’installation. Je vous l’accorde, ce n’est pas la panacée. Personnellement, je trouve que c’est un peu bête de créer certains de ces sous‐volumes, car on ne va pas forcément les utiliser. Tous les utilisateurs ne vont pas forcément créer une base de données ni utiliser une machine virtuelle. Je me dis qu’on pourrait essayer de créer ces sous‐volumes à l’installation de certains paquets mais ça peut devenir vite compliqué. J’ai à ce sujet le vague souvenir qu’[une mise à jour de systemd m’avait créé le sous‐volume `/var/lib/machines`](https://cgit.freedesktop.org/systemd/systemd/commit/?id=113b3fc1a8061f4a24dd0db74e9a3cd0083b2251). Par ailleurs, puisque j’ai parlé de CoW : celui‐ci est carrément désactivé pour certains sous‐volumes. ```sh ~# lsattr -d /var/lib/{mariadb,mysql,pgsql,libvirt/images} ----------------C-- /var/lib/mariadb ----------------C-- /var/lib/mysql ----------------C-- /var/lib/pgsql ----------------C-- /var/lib/libvirt/images ~# ``` ## Le cas de `@` ![Arobase](https://upload.wikimedia.org/wikipedia/commons/a/a0/Animations-At.gif) Je ne connais pas l’origine de ce sous‐volume. Avant — disons en 2015, quand j’ai installé mon openSUSE Tumbleweed — on ne l’avait pas. On utilisait simplement `FS_TREE`, le « sous‐volume » avec l’ID 5. Je suppose que ce `FS_TREE` doit être suffisamment différent des autres sous‐volumes pour lui préférer `@` — qui déjà présente l’avantage d’avoir un vrai nom. Un caractère, c’est mieux que zéro. Si vous avez des explications plus complètes sur `@`, n’hésitez pas à le dire dans les commentaires. ;-) ## `@/.snapshots` et `@/.snapshots/1/snapshot` Sur openSUSE, la stratégie est de mettre tous les instantanés sous le sous‐volume `@/.snapshots`. C’est un choix. Plus étrange, on remarque la présence d’un premier instantané, alors que le système vient à peine d’être installé : ```sh ~# btrfs suvolume list -s / ID 259 gen 985 top level 258 path @/.snapshots/1/snapshot ~# ``` Mais qu’est‐ce don’ ? ```sh ~# btrfs property /.snapshots/1/snapshot ro=false label= ~# mount | grep "on / " /dev/vda2/ on / type btrfs (rw,relatime,space_cache,subvolid=259,subvol=/@/.snapshots/1/snapshot) ~# btrfs subvolume get-default / ID 259 (@/.snapshots/1/snapshot) ~# ``` En clair, ce premier _snapshot_ : * est le sous‐volume par défaut de `/` : ce n’est donc rien d’autre que notre `/` actuel ; * est en lecture‐écriture (et c’est heureux sinon on ne pourrait rien écrire sur `/`). Pourquoi ne pas utiliser directement `@` ? Eh bien, c’est pour éviter d’oublier [de nettoyer les données du sous‐volume initial](https://doc.opensuse.org/release-notes/x86_64/openSUSE/Leap/42.1/RELEASE-NOTES.fr.html#sec.upgrade.btrfsleak) après une première restauration. En effet, les _snapshots_... ça prend de la place. Le fait d’avoir tout sous `/.snapshots` facilite le ménage. Mais on reparlera de ça plus tard. # Manipuler des sous‐volumes et des snapshots ## Création et suppression de sous‐volumes ``` ~# btrfs subvolume create btrfs subvolume create: too few arguments usage: btrfs subvolume create [-i ] [/] Create a subvolume Create a subvolume in . If is not given subvolume will be created in the current directory. -i add the newly created subvolume to a qgroup. This option can be given multiple times. ~# btrfs subvolume delete btrfs subvolume delete: too few arguments usage: btrfs subvolume delete [options] [...] Delete subvolume(s) Delete subvolumes from the filesystem. The corresponding directory is removed instantly but the data blocks are removed later. The deletion does not involve full commit by default due to performance reasons (as a consequence, the subvolume may appear again after a crash). Use one of the --commit options to wait until the operation is safely stored on the media. -c|--commit-after wait for transaction commit at the end of the operation -C|--commit-each wait for transaction commit after deleting each subvolume -v|--verbose verbose output of operations ~# ``` Pas grand‐chose à dire là‐dessus. En pratique, je n’ai créé un sous‐volume qu’une seule fois, pour rajouter `/var/cache`. Ce n’était pas encore un sous‐volume créé à l’installation quand j’ai installé openSUSE Tumbleweed. ## Création et suppression de snapshots ``` ~# btrfs subvolume snapshot btrfs subvolume snapshot: too few arguments usage: btrfs subvolume snapshot [-r] [-i ] |[/] Create a snapshot of the subvolume Create a writable/readonly snapshot of the subvolume with the name in the directory. If only is given, the subvolume will be named the basename of . -r create a readonly snapshot -i add the newly created snapshot to a qgroup. This option can be given multiple times. ~# ``` Donc, pour créer un _snapshot_ en lecture seule de mon système actuel : ```sh ~# mkdir -p /.snapshots/42 ~# btrfs subvolume snapshot -r / /.snapshots/42/snapshot Create a readonly snapshot of '/' in '/.snapshots/42/snapshot' ~# ``` J’aurais pu remplacer `/` par `/.snapshots/1/snapshot`. Ça va très vite : ```sh ~# mkdir -p /.snapshots/43 ~# time btrfs subvolume snapshot -r /.snapshots/43/snapshot Create a readonly snapshot of '/' in '/.snapshots/43/snapshot' real 0m0,444s user 0m0,000s sys 0m0,019s ~# ``` Enfin, un _snapshot_ se supprime comme n’importe quel autre sous‐volume : ```sh ~# btrfs subvolume delete /.snapshots/{42,43}/snapshot Delete subvolume (no-commit): '/.snapshots/42/snapshot' Delete subvolume (no-commit): '/.snapshots/43/snapshot' ~# rmdir /.snapshots/{42,43} ~# ``` ## Restauration du système ![1814-1830](https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/G%C3%A9rard_-_Louis_XVIII_of_France_in_Coronation_Robes.jpg/416px-G%C3%A9rard_-_Louis_XVIII_of_France_in_Coronation_Robes.jpg) Faire un _rollback_, c’est simple : c’est remplacer un sous‐volume courant par une version précédente, c’est‐à‐dire par un instantané de ce sous‐volume. Comment pourrait-on faire ? Ça n’a pas l’air évident au premier abord. Il va falloir sans doute jouer avec le montage des sous-volumes et `mv`... Je simplifie le problème : ici, ce qui m’intéresse de changer, c’est le système, c’est le sous‐volume de `/`. Dans ce cas, et vu notre configuration, faire une restauration revient simplement à changer le sous‐volume par défaut de `/`. C’est tout. On a déjà vu quelle était la commande pour récupérer le sous‐volume par défaut : ```sh ~# btrfs subvolume get-default / ID 259 (@/.snapshots/1/snapshot) ~# ``` Le _setter_ n’est pas beaucoup plus compliqué : ```sh ~# btrfs subvolume set-default btrfs subvolume set-default: too few arguments usage: btrfs subvolume set-default Set the default subvolume of a filesystem ~# ``` Mais, allez, c’est parti, on y va ! Faisons une restauration complète ! On suppose que l’instantané à restaurer existe : `@/.snapshots/2/snapshot`. ```sh ~# mkdir -p /.snapshots/{3,4} ~# # Création d’un instantané en lecture‐seule du système actuel. ~# btrfs subvolume snapshot -r / /.snapshots/3/snapshot Create a readonly snapshot of '/' in '/.snapshots/3/snapshot' ~# ~# # Création d’un instantané en lecture‐écriture de l’instantané 2. ~# btrfs subvolume snapshot /.snapshots/2/snapshot /.snapshots/4 Create a snapshot of '/.snapshots/2/snapshot' in '/.snapshots/4/snapshot' ~# ~# # Définition du sous‐volume par défaut sur l’instantané 4. ~# btrfs subvolume set-default $id_snapshot_4 / ~# ``` Et voilà ! On peut redémarrer et booter sur notre système restauré ! ... Bien. Normalement, à ce moment précis, il va y avoir deux catégories de personnes : * celles qui vont dire : « C’est trop cooool ! » ; * celles qui vont dire : « Minute, papillon : il te reste encore à modifier ta configuration de GRUB pour que ça marche ! ». Et toutes ces personnes auront raison, en un sens. Parce que tel quel, ce qu’on a fait est suffisant sur openSUSE, mais pas forcément ailleurs. Et c’est bien embêtant. C’est si embêtant qu’on en parlera dans le prochain épisode ! _That’s all folks!_ # Liens Sur le wiki Btrfs : * le [guide de l’administrateur système](https://btrfs.wiki.kernel.org/index.php/SysadminGuide) ; * la FAQ, [la partie sur les sous‐volumes](https://btrfs.wiki.kernel.org/index.php/FAQ#Subvolumes). Sur le wiki openSUSE, [la liste des sous‐volumes créés par défaut](https://en.opensuse.org/SDB:BTRFS#Default_Subvolumes).

AltStyle によって変換されたページ (->オリジナル) /