Rock64 Mini NAS Upgrade (2022)

Nachdem mein Mini NAS auf Basis eines Pine Rock64 Single Board Computers (SBC) 4 Jahre lang gute Dienste verrichtet hat, war es an der Zeit, dem Setup ein Upgrade zu verpassen. Das NAS wird mittlerweile nicht nur mehr nur für Backups genutzt, sondern auch ein kleiner DNLA-Medienserver im lokalen Netzwerk. Daher war es mir wichtig, das NAS so umzubauen, dass

  1. Die Datensicherheit gewährleistet ist, also keine Daten durch Fehler verfälscht werden oder verloren gehen
  2. Mehr Speicherplatz zur Verfügung steht

Ich habe mich entschieden, die eine SSD mit einem Terabyte Speicherplatz durch zwei SSDs mit jeweils 2 TB Speicherplatz zu ersetzen und diese in einem RAID-1 Verbund laufen zu lassen. Als Dateisystem sollte ZFS eingesetzt werden. Für beide SSDs sollte ein ansehliches Gehäuse gefunden werden, das ich neben mein transparentes und halboffenes Rock64 Acrylgehäuse stellen kann.

Das Rock64 auf dem neuen SSD-Gehäuse
Das Rock64 auf dem neuen SSD-Gehäuse

ZFS als Dateisystem

ZFS nutze ich auf den großen Servern schon einige Jahre und bin begeistert von dessen Featureset und der Zuverlässigkeit. Besonders schön: Mit wenigen Kommandos übernimmt ZFS nicht nur die Rolle eines klassischen Dateisystems (mit speziellen Funktionen, wie z.B. Snapshots), sondern auch die Funktion eines Volume-Managers (Z.b: LVM) und eines RAID-Managers (MD). Und weil das noch nicht genug ist, übernimmt es in meinem Fall auch die Verschlüsselungs-Funktion, die man üblicherweise LUKS anvertraut. Alles in einem zu haben, gibt mir ein gutes Gefühl. Ich bin kein Fan von mehreren Schichten und Komplexität, wo sie nicht sein muss.

SSDs und Gehäuse

Bei den SSDs habe ich mich für die von mir geschätzten und bekannten Crucial BX 500 (2 TB) entschieden. Ich habe sowohl mit den MX500 als auch mit den BX500 langjährige, gute Erfahrungen gemacht - auch im RAID-Verbund und mit ZFS. Die BX500 unterscheiden sich maßgeblich in ihrer Schreibfestigkeit und der Garantie - hier liegen die MX500 leicht vorn. Da ich auf dem NAS aber ohnehin nicht exzessiv viel schreiben werde, habe ich mir einige Euro gespart und zu den BX500 gegriffen. Bevor ich die `Totel Terabytes Written" erreicht haben werde, werde ich vermutlich schon ein neues NAS System zusammengebaut oder zumindest mehr Speicherbedarf haben.

Oh - und warum überhaupt SSDs und nicht viel günstigere HDDs? Darum:

  • SSDs sind schnell
  • SSDs sind robust
  • SSDs brauchen wenig Energie
  • SSDs sind leise
  • HDDs kommen mir antik vor. Ja, vielleicht nicht zu recht, aber da bin ich eitel.

Das Gehäuse - ein IcyBox “RAID Gehäuse für 2x HDD/SSD mit USB 3.1” hat mich gleich begeistert, weil es nicht nur gut aussieht und kompakt ist, sondern mit USB 3.1 auch eine schnelle Anbindung bietet. Da die beiden SSDs im RAID laufen, wird die USB Schnittstelle doppelt belastet. Mit USB 2 würde man hier sehr schnell an unangenehme Grenzen stoßen. USB 3.1 wird zwar von Rock64 noch nicht untersützt, aber zumindest kann ich auf USB 3.0 zurückgreifen und mich freuen, dass mein Gehäuse zukunftsfähig ist … falls das Rock64 Board einmal gegen ein stärkeres ausgetauscht wird.

Die eingebaute RAID-Funktionalität des Gehäuses interessiert mich übrigens nicht besonders. Ich nutze das Gehäuse nur im “Single” Betrieb. Die beiden SSDs erscheinen für das Betriebssystem also als zwei voneinander unabhängige Laufwerke. Für die RAID-Funktionalität vertraue ich auf ZFS sehr viel mehr, als auf ein günstiges Festplattengehäuse. Zudem dürfte sich eine Wiederherstellung schwierig gestalten, wenn der integrierte RAID Controller einmal Schaden nehmen sollte …

Das Rock64 mit neuem SSD-Gehäuse im 19" Rack
Das Rock64 mit neuem SSD-Gehäuse im 19" Rack

Ein Armbian-Update

Mein Mini NAS läuft seit jeher mit Armbian. Beim ersten Anstecken der SSDs gab es jedoch einen Schreckmoment: Während die SSDs an meinem Laptop tadellos als zwei Blockdevices erkannt wurden, passierte am Rock64 USB 3.0 Anschluss nichts. Am USB 2.0 Anschluss hingegen wurden die SSDs erkannt.

Da sowieso ein Armbian-Upgrade auf eine neuere Version anstand und für diese Version auch noch keine ZFS-Pakete bereitstanden, nutzte ich die Gelegenheit zu einem Armbian-Upgrade - und siehe da: Nun wurden auch die SSDs korrekt erkannt. Glück gehabt!

ZFS Installieren

Die Installation von ZFS auf einer neuen Armbian-Version gestaltet sich sehr einfach (wenn auch etwas zeitintensiv). Da ZFS - anders als die anderen üblichen Dateisysteme - aus Lizenzgründen nicht im Linux-Kernel enthalten ist, muss es “out of tree” als Kernelmodul gebaut werden. Das nimmt einem das zfs-dkms Paket ab, welches über die Armbian-Paketquellen bereitsteht. Damit der Kompiliervorgang erfolgreich durchgeführt werden kann, müssen zuerst die Linux-Headerdateien für Armbian installiert werden. Die Installation führt über armbian-config:

$ armbian-config
Dann "Software" > "Install Headers"

Schließlich können endlich die ZFS-Pakete installiert werden:

ZFS Pakete installieren:

apt install zfsutils-linux zfs-dkms

Im Zuge der Paketinstallation wird ein dynamisches Kernelmodul für ZFS gebaut - also nicht wundern, wenn der Schritt “Building initial module for 5.15.72-rockchip64” einige Minuten dauert. Dem Rock64 geht dabei ziemlich die Luft aus …

Nach der Installation kann mittels zfs list nachgesehen werden, ob der Dateisystemtreiber korrekt in den Kernel integriert ist. Erscheint keine Fehlermeldung, ist ZFS bereit. Andernfalls muss das Rock64 evtl. neu gestarter werden.

Verschlüsselten RAID-1 ZFS Pool erzeugen

Nun ist es Zeit, sich um die Verschlüsselung zu kümmern: Persönliche Daten auf dem NAS sollen auch nach der zukünftigen Entsorgung meiner SSDs privat bleiben. Hierzu will ich die SSDs per default Verschlüsseln (wobei sich aber für gewisse ZFS Volumes auch Ausnahmen definieren lassen).

Die Entschlüsselung geschieht ohne weiteres Zutun beim Booten über eine Key-Datei, die im Root-Filesystem des Rock64 (der SD-Karte) liegen. Die Schlüsseldatei wird wie folgt erzeugt und abgelegt:

mkdir /var/lib/zfs/
tr -dc A-Za-z0-9 </dev/urandom | head -c 16 > /var/lib/zfs/raid2tb.key
chmod 600 /var/lib/zfs/raid2tb.key 

Es empfiehlt sich, die Schlüsseldatei kurz mittels cat auszugeben, um sich den Schlüssel in einem Passwortmanager wegzusichern. Geht diese Datei bzw. ihr Inhalt verloren, können die auf den SSDs befindlichen Daten nicht wiederhergestellt werden.

Nun wird der ZFS-Pool generiert: Wie schon beschrieben - mit RAID-1 und aktiver Verschlüsselung (per default).

Pool erstellen:

zpool create \
	-o feature@encryption=enabled \
	-O encryption=on \
	-O atime=off \
	-O keylocation=file:///var/lib/zfs/raid2tb.key \
	-O keyformat=passphrase \
	raid2tb mirror \
        /dev/disk/by-id/ata-CT2000BX500SSD1_2237E6655828 \
        /dev/disk/by-id/ata-CT2000BX500SSD1_2237E665585F

(Achtung, erste -o Option is klein geschrieben!) - atime=off schaltet “access time” feature ab

Damit die automatische Entschlüsselung beim Boot funktioniert, wird eine neue systemd-Servicedatei angelegt unter /etc/systemd/system/zfs-load-key.service:

[Unit]
Description=Load encryption keys
DefaultDependencies=no
After=zfs-import.target
Before=zfs-mount.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/zfs load-key -a
StandardInput=tty-force

[Install]
WantedBy=zfs-mount.service

Dann wird der neue Service aktiviert:

systemctl daemon-reload
systemctl enable zfs-load-key

ZFS Volumes erstellen

In meinem Fall soll es zunächst zwei ZFS Volumes und daher zwei Mountpoints geben: Ein Volume für Backup-Daten und ein zweites als Medienspeicher für den DLNA-/Medienserver.

mkdir -p /mnt/raid2tb/backup
mkdir -p /mnt/raid2tb/media

ZFS Datasets anlegen:

zfs create \
	-o mountpoint=/mnt/raid2tb/backup \
	raid2tb/backup
	
zfs create \
	-o mountpoint=/mnt/raid2tb/media \
	raid2tb/media

Automatisch erstellten Mountpoint für Stamm-Dataset entfernen (wird nicht benötigt):

zfs set mountpoint=none raid2tb

Die ZFS Volumes werden automatisch nach dem Erzeugen an den Mountpoints gemountet und sind einsatzbereit.

Performance mit Verschlüsselung

SSDs im Mirror-Betrieb (RAID-1) und verbunden durch USB 3.0 versprechen hohe Geschwindigkeiten beim Lesen und Schreiben, oder?

“Rohes” Lesen von nur einer Festplatte - ohne Beachtung des Dateisystems:

hdparm -tT --direct /dev/sda

/dev/sda:
 Timing O_DIRECT cached reads:   628 MB in  2.00 seconds = 313.31 MB/sec
 Timing O_DIRECT disk reads: 976 MB in  3.01 seconds = 324.77 MB/sec

Das sieht schon mal ganz ordentlich aus! Definitiv mehr, als ich über die Gigabit-Ethernet Schnittstelle des Rock64 übertragen kann (brutto theoretisch max. 120 MB/s). Hier haben wir also kein Problem.

Deutlich trauriger sieht die Situation aber aus, wenn ich eine Datei vom verschlüsselten ZFS Dataset auslese:

Lesen:

fio --rw=read --name=test --size=1G --direct=1

Run status group 0 (all jobs):
READ: bw=9184KiB/s (9404kB/s), 9184KiB/s-9184KiB/s (9404kB/s-9404kB/s), io=1024MiB (1074MB), run=114175-114175msec 

Schreiben:

fio --rw=write --name=test --size=1G --direct=1

Run status group 0 (all jobs):
WRITE: bw=10.6MiB/s (11.2MB/s), 10.6MiB/s-10.6MiB/s (11.2MB/s-11.2MB/s), io=1024MiB (1074MB), run=96264-96264msec

Nur 9.4 MB/s beim Lesen und 11.2 MB/s beim Schreiben? Wie kann das sein? Die - zugegeben - sehr ernüchternde Performance wird durch die Verschlüsselung verursacht. Wie sich später herausstellte, beherrscht OpenZFS die ARM AES-Instuktionen für die hardwarebeschleunigte Verschlüsselung noch nicht und greift daher auf eine Software-basierte Verschlüsselung zurück. Diese ist Größenordnungen langsamer, als wir es von HW-beschleunigter Verschlüsselung kennen.

EIn Rückschlag, den ich nicht erwartet habe. Es gibt aber etwas Trost, denn die bereits aktivierte Verschlüsselung lässt sich bei Bedarf für einzelne ZFS Volumes auch ausschalten. Zum Beispiel für mein “media” Volume, bei dem ich sehr gut auf Verschlüsselung verzichten kann. Denn ob nun jemand in der Lage ist, Fernsehserien, Filme oder Musik aus meinen SSDs zu extrahieren, ist mir relativ egal.

Verschlüsselung wieder ausschalten

Für das “media” Dataset soll die Verschlüsselung also abgeschaltet werden. Allerdings muss dazu ein neues Dataset ohne Verschlüsselung erstellt werden, denn die Verschlüsselung kann nicht einfach abgeschaltet werden. Einmal beim Generierten eingeschaltet, bleibt sie für ein Dataset immer aktiv. Daher benennen wir das alte Dataset einfach um und erzeugen ein neues ohne Verschlüsselung:

zfs rename raid2tb/media raid2tb/media-old

Mountpoint des alten Datasets ändern:

zfs set mountpoint=/mnt/raid2tb/media-old raid2tb/media-old

Neues Dataset ohne Verschlüsselung erstellen:

zfs create -o encryption=off -o mountpoint=/mnt/raid2tb/media raid2tb/media

Daten verschieben (falls vorhanden):

mv /mnt/raid2tb/media-old/* /mnt/raid2tb/media/

Performance ohne Verschlüsselung

Nun nochmal ein Performancetest ohne Verschlüsselung:

Lesen:

fio --rw=read --name=test --size=1G --direct=1
[...]
Run status group 0 (all jobs):
READ: bw=123MiB/s (128MB/s), 123MiB/s-123MiB/s (128MB/s-128MB/s), io=1024MiB (1074MB), run=8357-8357msec

Schreiben:

fio --rw=write --name=test --size=1G --direct=1
[...]
Run status group 0 (all jobs):
WRITE: bw=61.5MiB/s (64.5MB/s), 61.5MiB/s-61.5MiB/s (64.5MB/s-64.5MB/s), io=1024MiB (1074MB), run=16657-16657msec

128 MB/s und 64.5 MB/s. Das ist zwar immer noch weit vom theoretischen Maximum der SSDs entfernt (irgendwo bei ca 500 MB/s), allerdings kann man hiermit schon gut arbeiten. Beim Lesen wäre ohnehin das Ethernet der Flaschenhals und auch mit der Schreibrate von nur 61 MB/s kann ich mich arrangieren, wenn ich bedenke, dass die meisten meiner Dateiübertragungen über das SSH Protokoll laufen und dadurch sowieso schon auf ca. 26 MB/s limitiert sind (ähnliches Problem: Auch bei SSD kommt das Rock64 mit der SSH-Verschlüsselung kaum hinterher).

Die geringe Schreib-/Leserate bei verschlüsselten Datasets bleibt ernüchternd. Hier muss ich wohl auf einen Entwickler warten, der die ZFS Cryptofunktionen fit für ARM Prozessoren macht. Ob daran ein dringendes Interesse besteht, darf aber bezweifelt werden. Solange muss ich mit der eher mäßigen Performance leben oder auf eine andere Lösung umschwenken. Da wäre zum Beispiel noch LUKS, welches auf ARM besser performt _(… und welches ich eigentlich vermeiden wollte, weil es Dinge wieder komplexer macht … *grummel*).

Fazit und Ausblick

Ich habe gemischte Gefühle. Auf der Positiv-Seite stehen die nun aktivierte Verschlüsselung, die Ausfall- und Datensicherheit durch ein RAID-1 und die Möglichkeit, mittels ZFS Snapshots von meinen Dateien anlegen zu können. Alles mittels ZFS realisieren zu können, gefällt mir. Außerdem verfüge ich nun über mehr Speicherplatz und habe die SSDs in einem schicken neuen Gehäuse untergebracht, das in meinem Rack positiv auffällt und die LED-Lightshow bereichert.

Ein negativer Beigeschmack bleibt wegen der miesen ZFS Performance auf verschlüsselten Datasets. Ich kann vorerst damit leben, weil in der Kette zwischen Laptop und Speicher auch noch andere limitierende Faktoren hängen; zum Beispiel das WLAN oder SSH-Verbindungen. Auf längere Sicht will ich die Performance aber verbessern. Sei es durch ein HW-Upgrade (es gibt da vielversprechende Rock64 Alternaiven und Nachfolger), oder durch eine SW-Änderung. Vielleicht habe ich ja Glück und HW AES-SUpport für ARM wird von ZFS schon bald unterstützt. Das dazugehörige GitHub Ticket ist jedenfalls auf der Watchlist.