Snapshots avec BTRFS

Timemachine

Je n'écris pas beaucoup sur ce blog, par manque de temps essentiellement (les idées d'articles ne manquent pas). Cette fois j'ai décidé de prendre 5 minutes pour vous parler de mon utilisation des snapshots avec BTRFS.

BTRFS est un système de fichiers assez fun avec des fonctionnalités vraiment sympas. Il intègre notamment le COW (Copy-On-Write) qui va nous permettre de créer des snapshots à la vitesse de la lumière sans faire appel à des outils tiers et surtout en préservant l'espace disque, COW oblige.

Dans mon cas, j'ai deux partitions (en réalité beaucoup plus, mais on va simplifier) la racine / et /home.

Je n'utilise pas BTRFS pour partitionner mes disques car je préfère confier cette tâche à LVM qui est plus simple et plus approprié. En revanche, pour les snapshots, je préfère confier cette tâche au système de fichiers et BTRFS est un bon choix !

Le principe est le suivant : dans chaque partition BTRFS, on va créer un sous-volume (subvolume) qui va contenir nos snapshots :

$ btrfs subvolume create /home/snapshots  # un subvolume dans la partition /home
$ btrfs subvolume create /snapshots       # un subvolume dans la partition /

Maintenant, on est au début de la journée, et comme j'ai parfois peur de supprimer des fichiers par mégarde, je vais créer un snapshot :

$ btrfs subvolume snapshot -r /home /home/snapshots/mon_premier_snapshot
Create a readonly snapshot of '/home' in '/home/snapshots/mon_snapshot'

$ btrfs subvolume snapshot -r / /snapshots/snapshot_de_mon_system
Create a readonly snapshot of '/' in '/snapshots/snapshot_de_mon_system'  

La création du snapshot est très rapide, et pour cause, la commande ne fait pas "grand-chose". Elle dit simplement à BTRFS, qu'à partir de maintenant, tout fichier dans /home sera réécrit ailleurs de façon à garder les anciennes références depuis les snapshots. En gros, /home est en Copy-On-Write par rapport à mon snapshot.

Du coup, on peut faire cette manipulation autant de fois qu'on le veut. Pour l'instant, je n'ai pas constaté d'impacts sur les performances même si j'imagine qu'il doit y en avoir si on utilise beaucoup de snapshots.

Pour ma part, je fais un à deux snapshots par jour, en général, c'est suffisant. Ce qui est intéressant, en réalité, c'est la possibilité de faire un snapshot avant chaque manipulation un peu trop dangereuse.

Pour lister les snapshots, on utilise la commande suivante :

$ btrfs subvolume list /home/snapshots
ID 433 gen 5209 top level 5 path snapshots  
ID 458 gen 4945 top level 433 path 20150213-155018  
ID 459 gen 4996 top level 433 path 20150213-162327  
ID 466 gen 5188 top level 433 path 20150213-181931  
ID 467 gen 5210 top level 433 path mon_snapshot  

ou encore :

$ ls /home/snapshots
20150213-155018  20150213-162327  20150213-181931  latest  mon_snapshot  

Chaque dossier snapshot contient l'arborescence complète de la partition /home. Ce qui est vraiment pratique pour naviguer dans l'historique.

Pour restaurer, on peut utiliser rsync ou tout simplement cp

$ cp -aR --reflink /home/snapshots/mon_snapshot /home

Pour automatiser cette procédure, j'utilise btrfs-snapshot, un script python que j'ai repris de ce projet pour le modifier légèrement afin de correspondre à mon usage. Le script crée un lien symbolique latest qui pointe vers le dernier snapshot et gère la rotation des snapshots (je veux X snapshots au maximum).

$ ./btrfs-snapshot /home /home/snapshots
Create a readonly snapshot of '/home' in '/home/snapshots/20150213-190607'  
new snapshot at /home/snapshots/20150213-190607

$ readlink /home/snapshots/latest
/home/snapshots/20150213-190607

Il ne reste plus qu'à lancer le script régulièrement via cron ou systemd.timer.