Worum geht es?

Mein Server hat eine einzelne NVMe-SSD, auf welcher das btrfs-Dateisystem „arthur-2020“ gespeichert ist und in mehreren Subvolumes das Betriebssystem selber sowie alle meine Daten hält. Von diesen erzeuge ich regelmäßig Snapshots, die ich dann inkrementell auf ein weiteres btrfs-Dateisystem „alex-pool“ sichere, welches alle Daten gespiegelt auf zwei konventionellen (aber dafür recht großen) Festplatten hält.

Da jeweils nur die seit der letzten Sicherung (seit dem letzten Snapshot) veränderten Daten gesichert werden müssen, erfolgt die Sicherung der einzelne Subvolumes auch bei großen Volumes sehr effizient und schnell.

Die Idee ist:

  • Auf der schnellen (aber relativ kleinen und teureren) NVMe arbeiten und wenige Snapshot-Genrationen halten
    (btrfs-Dateisystem „arthur-2020“)
  • Viele Generationen gespiegelt auf den langsamen (aber großen und günstigen) Festplatten archivieren
    (btrfs-Dateisystem „alex-pool“)

Die Spiegelung auf den Festplatten erfolgt hierbei im btrfs-Dateisystem „alex-pool“ direkt über das „raid1“-Profil für Daten und Metadaten wie hier auf der btrfs-Homepage beschrieben: Using Btrfs with Multiple Devices – also ohne ein (Software-)RAID.

Dieses Setup ist nicht neu, ich nutze es bereits seit vielen Jahren und es hat sich bewährt – aber vielleicht ist es ja für jemanden interessant, und ich habe mich nun endlich dazu aufraffen können, diesen schon vor vielen Monaten begonnenen Blog-Beitrag endlich zu Ende zu schreiben …

Also los!

Aufbau

Quell- („arthur-2020“) und Zeil-Dateisystem („alex-pool“) sind jeweils in einem Ordner mit ihrem Namen unterhalb von /media gemounted:

root@arthur:~ # tree -L 2 /media
/media
├── arthur-2020
│   ├── home
│   ├── home@20200629-1
│   ├── home@20200701-1
│   ├── root
│   ├── root@20200629-1
│   └── root@20200701-1
└── alex-pool
    ├── …
    ├── home@20200629-1
    ├── home@20200701-1
    ├── …
    ├── root@20200629-1
    └── root@20200701-1

Das Subvolume /media/arthur-2020/root ist hierbei das aktive root-Dateisystem / und /media/arthur-2020/home das aktuell aktive home-Dateisystem /home.

In der /etc/fstab sieht das exemplarisch so aus:

# /etc/fstab

UUID=xxx /media/arthur-2020 btrfs subvolid=0,compress=zstd 0 0
UUID=xxx / btrfs subvol=root,compress=zstd 0 1
UUID=xxx /home btrfs subvol=home,compress=zstd 0 0
UUID=xxx …

UUID=yyy /media/alex-pool btrfs subvolid=0,compress=zstd 0 0

…

Periodisch Subvolumes sichern

Die folgenden beiden Schritte müssen für jedes btrfs-Subvolume, welches in das andere btrfs-Dateisystem gesichert werden soll, periodisch einzeln ausgeführt werden:

  1. Erzeugen eines schreibgeschützten (read-only) Snapshots im Quell-Dateisystem (also hier „arthur-2020“)
  2. „Versenden” dieses Snapshots in das Ziel-Dateisystem (also hier „alex-pool“)

Dieser Prozess lässt sich natürlich hervorragend automatisieren 🙂

Read-Only-Snapshot erzeugen

Das Anlegen eines „Snapshots“ ist mit btrfs mit dem Befehl btrfs subvolume snapshot möglich. Hierbei wird ohne weitere Parameter ein beschreibbarer (read-write) Snapshot erzeugt.

Damit wir jedoch inkrementelle Sicherungen von eindeutig definierten Zuständen auf das gespiegelt btrfs-Dateisystem senden können, benötigen wir einen schreibgeschützten (read-only) Snapshot: ein solcher wird mit dem Parameter -r erzeugt. Weitere Parameter sind das existierende Subvolume, von welchem der Snapshot erzeugt werden soll (hier: /media/arthur-2020/home, also das aktive home-Dateisystem) sowie der Name des zu erstellenden Snapshots (hier: /media/arthur-2020/home@20210701-1).

Somit ergibt sich exemplarisch folgender Befehl:

root@arthur:~ # btrfs subvolume snapshot -r \
  /media/arthur-2020/home /media/arthur-2020/home@20210701-1
Create a readonly snapshot of '/media/arthur-2020/home' in '/media/arthur-2020/home@20210701-1'

btrfs-Dateisystem inkrementell „senden“ und „empfangen“

Nun müssen „nur“ die Verändungen zwischen dem gerade neu erstellen (letzten, im Beispiel „home@20210701-1“) Snapshot und dem vorletzten Snapshot (im Beispiel „home@20210629-1“) aus dem Quell-Dateisystem „arthur-2020“ in das Ziel-Dateisystem „alex-pool“ übertragen werden.

In der verwendeten Befehls-Pipeline kommen folgende Befehle zum Einsatz:

  • btrfs send: Daten eines read-only btrfs-Snapshots auslesen („senden“) – btrfs-send(8).
  • pv: Fortschritt eines Datenstroms anzeigen – pv(1).
  • btrfs receive: btrfs-Subvolume aus ausgelesenen Daten erzeugen („empfangen“) – btrfs-receive(8).

Das sieht dann beispielsweise so aus:

root@arthur:~ # ls -ld /media/alex-pool/home@20210629-1 /media/alex-pool/home@20210701-1
drwxr-xr-x 1 root root 270 Jun 29 09:56 '/media/alex-pool/home@20210629-1/'
ls: cannot access '/media/alex-pool/home@20210701-1': No such file or directory

root@arthur:~ # btrfs send -p \
  /media/arthur-2020/home@20210629-1 /media/arthur-2020/home@20210701-1 \
  | pv -tba \
  | btrfs receive /media/alex-pool
At subvol /media/arthur-2020/home@20210629-1
At snapshot home@20210701-1
2.34MiB 0:00:02 [ 902KiB/s]

root@arthur:~ # ls -ld /media/alex-pool/home@20210629-1 /media/alex-pool/home@20210701-1
drwxr-xr-x 1 root root 270 Jun 29 09:56 '/media/alex-pool/home@20210629-1/'
drwxr-xr-x 1 root root 270 Jul  1 19:17 '/media/alex-pool/home@20210701-1'

Mit btrfs send wird das Quell-Subvolume als Datenstrom „versendet“, in unserem Fall aber nur die Unterschiede zu einem „Eltern-Subvolume“ („parent“), welches im Ziel ebenfalls bereits identisch existieren muss und mit -p angegeben wird. Mit dem ls-Befehl hatte ich mich zu Beginn versichert, dass das „Eltern-Subvolume“ im Ziel-Dateisystem (hier: „alex-pool“) bereits existiert, der aktuelle Snapshot hingegen noch nicht.

Den pv-Befehl benötigt man funktionell nicht, er zeigt aber während das Dateisystem gesendet und empfangen wird eine Aktivitätsanzeige sowie am Ende die Dauer und den Durchsatz an. Ganz nett 🙂

Der mit btrfs send erzeugte btrfs-Datenstrom wird mit btrfs receive „empfangen“ und in das Ziel-Dateisystem geschrieben. Hier wird nur der Name des btrfs-Ziel-Dateisystems angegeben, der Name des Subvolumes wird aus dem Datenstrom entnommen.

Und schon ist die Sicherung des Volumes fertig!


Referenzen & Verweise

  • btfs Homepage
  • Manual pages:
    • btrfs(8) – a toolbox to manage btrfs filesystems
    • btrfs(5) – topics about the BTRFS filesystem (mount options, supported file attributes and other)

Alex

Alexander Barton, Freiburg, Deutschland. 🖥️🌳🚑⛵️🌈 Freiburger Bobbele (Freiburg, Breisgau, Hochschwarzwald). Wandern. Segeln (Schluchsee, …). Rettungsdienst, Sanitätsdienst und Katastrophenschutz (RD/SanD/KatS, JUH). Internet Relay Chat (IRC, ngIRCd). Computerei (macOS, iOS, Linux, Debian, systemd, Ansible, …).

2 Kommentare

tom · 10. Dezember 2023 um 12:18

Danke, sehr hilfreich!

    Alex · 10. Dezember 2023 um 16:48

    Freut mich, dass dir der Artikel geholfen hat!

Schreibe einen Kommentar

Avatar-Platzhalter

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert