đïž Sauvegarde au branchement avec Systemd et BTRFS
Introduction
Dans lâarticle sur la sauvegarde automatique dĂšs le branchement pour mes photos, jâindiquais comment jâavais rĂ©ussi Ă gĂ©rer des sauvegardes automatiques au branchement pour mes photos. Cela est trĂšs bien, mais pourquoi pas ne pas Ă©tendre la mĂ©canique pour la sauvegarde de fichiers ? La mĂ©canique de base sâavĂšre trĂšs proche, mais complĂ©tĂ© pas les fonctionnalitĂ©s du systĂšme de fichier btrfs, cela donne un systĂšme de sauvegarde trĂšs flexible.
Contrairement aux sauvegardes de photos qui allait de la carte SD au NAS, lâidĂ©e lĂ est inverse. On veut pouvoir connecter un disque et le systĂšme va Ă©crire de lui-mĂȘme sur ce disque la nouvelle sauvegarde.
Principe
Enregistrement automatique de sauvegarde dâun disque dur
Le principe est assez simple :
- Je branche un disque dur Ă mon NAS, le disque dur contient une partition avec le label âbackupâ
- Le disque dur est dĂ©tectĂ© et la partition âbackupâ est montĂ© par le systĂšme.
- Le systĂšme dĂ©marre la sauvegarde, ici avec lâaide de btrbk et de systemd.
- Le systÚme démonte la partition du disque automatiquement lorsque la sauvegarde est terminé.
Ajoutons un peu de BTRFS par-dessus
Le systĂšme de fichiers btrfs par ses fonctionnalitĂ©s : gestion de sous-volume et instantanĂ© (snapshot), nous permet de figer lâimage dâun sous-volume Ă un instant T directement sans copie. Cette image peut ĂȘtre en lecture seule. Câest un instantanĂ©.
LâintĂ©rĂȘt ? Il est possible de stocker nos donnĂ©es Ă sauvegarder dans un sous-volume btrfs, qui sera alors sauvegardĂ© sous la forme dâun instantanĂ© en lecture seule quâon pourra ainsi transmettre sur un autre disque sans risque de corruption de donnĂ©es liĂ© Ă des modifications durant la sauvegarde.
Les instantanĂ©s permettent aussi localement un mĂ©canisme de sauvegarde simple permettant de ârevenir dans le tempsâ. Lâautre avantage des instantanĂ©s btrfs est quâils permettent dâutiliser le mĂ©canisme send-receive qui permet de copier efficacement des sous-volumes (et donc des instantanĂ©s) dâun volume btrfs Ă un autre, potentiellement dâune façon incrĂ©mentale en utilisant les sous-volumes dĂ©jĂ transmis.
Donc le principe est le suivant :
- On met en route une sauvegarde.
- Le systÚme crée un instantané sur le volume source.
- Le systÚme copie cet instantané sur le disque de
sauvegarde grùce au mécanisme
send-receive
. il tire parti des instantanés déjà transmis pour ne pas tout retransmettre.
Les limitations de la mécanique sont les suivantes :
send-receive
ne gĂšre pas les coupures de rĂ©seau, donc pas trĂšs efficace par le rĂ©seau, car il devra renvoyer tout lâinstantanĂ© en cas dâinterruption.- il ne faut pas abuser des instantanĂ©s, lâimpact de beaucoup dâinstantanĂ©s sur lâespace disque et les performances peuvent ĂȘtre important, il faut donc faire le mĂ©nage.
La pratique
Prérequis : utiliser btrfs et les sous-volumes
Pour pouvoir utiliser la fonctionnalité, il faut que le disque à sauvegarder utilise btrfs, et il est conseillé de créer des sous-volumes pour définir les différents traitements.
ConsidĂ©rons que lâon veut sauvegarder la partition
/home
seulement, il faut donc un sous-volume sur
home :
Imaginons quâon a cette arborescence :
/
âââ srv : point de montage direct du volume btrfs (voir fstab)
â âââ @home : emplacement du sous-volume `@home` dans le sous-volume par dĂ©fault de btrfs.
ââ home : On va monter @home ici (voir fstab)
On aurait ainsi des paramĂštres de montage dans le fichier
/etc/fstab
similaire à ça :
UUID=6875f33c-4fed-4f43-bf34-4af0b2412ca4 /srv auto defaults 0 0
UUID=6875f33c-4fed-4f43-bf34-4af0b2412ca4 /home auto subvol=@home 0 0
Vous noterez que lâUUID est le mĂȘme, car on pointe littĂ©ralement sur la mĂȘme partition.
Quant au sous-volume @home, il a pu ĂȘtre crĂ©Ă© tout simplement avec cette commande (volume /srv montĂ©)
sudo btrfs subvolume create /srv/@home
Pour ce qui est des instantanés, nous les placerons dans
le dossier snapshots
à la raçine de
/srv
et les sauvegardes seront dans le dossier
snapshots
Ă la racine de
/mnt/backup
.
Je ne rentrerai pas plus dans le détail de la mécanique de btrfs, il existe une littérature importante à ce sujet.
Créer une rÚgle Udev
Comme prĂ©cĂ©demment, il nous faut passer par udev pour gĂ©rer lâaspect montage automatique.
99-automount_backup_drive.rules
# Automount usb backup drive on insertion
ACTION!="remove", SUBSYSTEM=="block", ENV{ID_PART_ENTRY_NAME}=="backup", ENV{SYSTEMD_WANTS}+="backup.service"
Ce qui signifie :
- Si une action provenant dâun pĂ©riphĂ©rique de systĂšme
block dâun pĂ©riphĂ©rique donc le label de partition est
backup
active un Ă©vĂšnement qui nâest pas âremoveâ, alors, on demande Ă activer lâunitĂ© systemdbackup.service
. On reviendra plus en détail ensuite sur pourquoibackup.service
et pasmnt-backupt.mount
đ Note : lâaction est sur les pĂ©riphĂ©riques de type
block, ce qui signifie que câest agnostique du moyen de
communication utilisé : USB, SATA, NVME, Réseau. Du
moment que le systÚme voit une partition labellisée
backup
, il tentera de la monter.
Point de montage
Comme
précédemment, il nous faut un fichier
.mount
.
/etc/systemd/system/mnt-backup.mount
[Unit]
Description=Mount Backup
BindsTo=btrbk_resume.service
[Mount]
What=/dev/disk/by-partlabel/backup
Where=/mnt/backup
ReadWriteOnly=true
Type=btrfs
Avec ce point de montage, systemd sait maintenant, quâen
cas dâactivation de mnt-backup.mount
:
- quâil doit monter la partition de label
backup
dans/mnt/backup
. - quâil doit la monter en lecture/Ă©criture (sinon on va avoir des soucis) !
- quâil doit dĂ©marrer
btrbk_resume.service
. Je reviens dessus aprĂšs. - quâil doit la monter en btrfs. Il sâagit lĂ dâune vĂ©rification supplĂ©mentaire, car on va utiliser des outils spĂ©cifiques Ă btrfs. si lâon branche un disque de sauvegarde en ext4, il faut mieux que le processus sâarrĂȘte au plus tĂŽt.
Btrbk
Pour gérer efficacement la sauvegarde aprÚs quelques
hĂ©sitations et un script perso, jâai finalement dĂ©cidĂ©
dâutiliser btrbk.
btrbk
est un outil en perl pour gérer les
sauvegarde via btrfs, notamment avec la mĂ©thode âcrĂ©ation
dâinstantanĂ©s puis envois sur disque via btrfs
send/receiveâ.
Il a beaucoup dâavantages :
- paquet debian.
- gĂšre correctement lâincrĂ©mental.
- gére toute la mécanique de rotation des sauvegardes.
En bref, il nous simplifie la vie pour utiliser les fonctionnalités de btrfs dans notre cas.
Il faut nĂ©anmoins un peu de temps pour lâapprivoiser les rĂšgles de conservations sont ainsi assez compliquĂ© Ă comprendre. Je vous laisse chercher dans la documentation.
Dans notre cas simple, on aura donc une configuration de ce style :
transaction_log /var/log/btrbk.log
# les snapshot du volume src et targets seront placé dans le dossier snapshot à la racine
snapshot_dir snapshots
# rĂšgle de conservation des snapshots
snapshot_preserve_min 2d
snapshot_preserve 14d
# rĂšgle de conservation des sauvegardes sur le disque de sauvegarde
target_preserve_min no
target_preserve 20d 10w *m
# on définis ici qu'on fait des snapshot pour le sous volume @home de /srv
# et qu'on les copie en mode send-receive vers /mnt/backup
volume /srv
target send-receive /mnt/backup
subvolume @home
On pourrait sâarrĂȘter lĂ et modifier le systĂšme pour que
backup.service
lance le
btrbk.service
du paquet debian et ça
fonctionnerait pour la sauvegarde Ă chaud. Mais mon souhait
et dâavoir un snapshot journalier dans tous les cas et
Ă©ventuellement une sauvegarde si le disque de sauvegarde est
branché.
Snapshot régulier et sauvegarde si possible
Pour rĂ©aliser cette mĂ©canique dâinstantanĂ©s rĂ©guliers en plus de la sauvegarde Ă chaud, il faut jouer un peu avec systemd.
Btrbk, permet de séparer la transmission de sauvegarde de
la réalisation de snapshot. Pour ce faire, au lieu de faire
btrbk run
on peut utiliser btrbk snapshot
-p
et btrbk resume
. Avec quelques override
systemd, on peut arriver au bon résultat :
- On surcharge
btrbk.service
pour ne faire que des instantanés et ne rien supprimer(-p
):
# /lib/systemd/system/btrbk.service
[Unit]
Description=btrbk backup
Documentation=man:btrbk(1)
[Service]
Type=oneshot
ExecStart=/usr/sbin/btrbk run
# /etc/systemd/system/btrbk.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/sbin/btrbk snapshot -p
- On ajoute
btrbk_resume.service
pour faire la transmission des sauvegardes:
# /etc/systemd/system/btrbk_resume.service
[Unit]
After=btrbk.service
# đ note: on demande implicitement `mnt-backup.mount`.
RequiresMountsFor=/mnt/backup
RefuseManualStart=true
[Service]
Type=oneshot
# đ note: On n'a pas mis de `-p` ici,
# la rotation des instanées et sauvegardes se fera à la fin de la transmission des sauvegardes.
ExecStart=/usr/sbin/btrbk resume
- On crée
backup.service
notre point dâentrĂ©e pour tous processus de sauvegarde qui fera :- la crĂ©ation des instantanĂ©s
- tentera dâexĂ©cuter la sauvegardes
# /etc/systemd/system/backup.service
[Unit]
After=btrbk.service btrbk_resume.service
Requires=btrbk.service btrbk_resume.service
[Service]
# đ Note: Ce service est un peu subtil, car on tire profit des spĂ©cificitĂ©s des services oneshot.
# Ce service lancera les 2 services btrbk et restera en activating, jusqu'Ă qu'ils s'arrĂȘtent et donc sera enfin `inactivate`.
# il n'est Ă ma connaissance pas possible de faire la mĂȘme chose avec des `.target` qui seront en `activate` Ă la fin du processus.
Type=oneshot
# Fausse commande car c'est obligatoire pour les service
ExecStart=/bin/true
- On surcharge aussi
btrbk.timer
des paquets pour dĂ©marrer notre point dâentrĂ©e :
# /lib/systemd/system/btrbk.timer
[Unit]
Description=btrbk daily backup
[Timer]
OnCalendar=daily
AccuracySec=10min
Persistent=true
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/btrbk.timer.d/override.conf
[Timer]
Unit=backup.service
đ Note : Il ne faut pas oublier dâactiver ce service sinon vous nâaurez pas les sauvegardes rĂ©guliĂšres
Récapitulatif Scénario
On à donc les 3 scénarios suivants :
1. Branchement Ă chaud
- On branche le disque de sauvegarde.
- udev demande à démarrer
backup.service
backup.service
dĂ©marre dâabordbtbrk.service
carbtrbk_resume.service
demande Ă ĂȘtre exĂ©cutĂ© aprĂšs.- les snapshots sont crĂ©Ă©s,
btrbk_resume.service
est démarré. btrbk_resume.service
montemnt-backup.service
. Il fait la sauvegarde.- Ă la fin de
btrbk_resume
,mnt-backup.service
est démonté
2. Sauvegarde réguliÚre
btrbk.timer
démarrebackup.service
backup.service
dĂ©marre dâabordbtbrk.service
carbtrbk_resume.service
demande Ă ĂȘtre exĂ©cutĂ© aprĂšs.- les snapshots sont crĂ©Ă©s,
btrbk_resume.service
est démarré. btrbk_resume.service
montemnt-backup.service
. Il fait la sauvegarde.- Ă la fin de
btrbk_resume
,mnt-backup.service
est démonté.
3. Sauvegarde réguliÚre sans disque branché
btrbk.timer
démarrebackup.service
backup.service
dĂ©marre dâabordbtbrk.service
carbtrbk_resume.service
demande Ă ĂȘtre exĂ©cutĂ© aprĂšs.- les snapshots sont crĂ©Ă©s,
btrbk_resume.service
est démarré. btrbk_resume.service
montemnt-backup.service
maismnt-backup.service
ne peut ĂȘtre dĂ©marrĂ©. arrĂȘt du service.backup.service
se stoppe, mais les instantanés ont bien été créés.
Conclusion
Btrfs nâest pas si facile Ă prendre en main, mais les concepts bien compris et Ă lâaide de systemd, on peut crĂ©er des mĂ©canismes de sauvegardes puissants.