1 Punkte von GN⁺ 2024-07-03 | Noch keine Kommentare. | Auf WhatsApp teilen
  • Ein Experiment, bei dem Arch Linux mit Google Drive als Root-Dateisystem statt von einer lokalen Festplatte oder NFS gebootet wird
  • In der initramfs-Phase wird ein FUSE-Dateisystem gemountet, und mit Dracut wird ein angepasstes EFI-Image mit Netzwerkunterstützung und den nötigen Binärdateien erstellt
  • Nachdem das Konzept zunächst mit S3 und s3fs validiert wurde, wurden Fehler bei switch_root und pivot_root umgangen, indem chroot als PID 1 ausgeführt wurde
  • Bei der Umsetzung mit Google Drive kam google-drive-ocamlfuse zum Einsatz, doch wegen Einschränkungen bei symbolischen Links, Hardlinks, Berechtigungen, Attributen und Geschwindigkeit waren manuelle Korrekturen und angepasste Timeouts nötig
  • Am Ende bootete sogar ein Laptop ohne Speichergerät mit einer integrierten EFI-Datei auf USB und einem Treiber für kabelgebundenes Netzwerk; praktisch ist das kaum, zeigt aber mögliche Varianten wie SSHFS oder ein Git-basiertes Root-Dateisystem

Google Drive als Root-Dateisystem verwenden

  • Nach einem Bericht über das Booten von Linux über NFS wurde ein anspruchsvolleres Ziel versucht: Root-Boot von Google Drive
  • Da eine in sich geschlossene Struktur ohne separate Helfer-Maschine gewünscht war, fiel die Wahl auf FUSE, das im Userspace wie ein Dateisystemtreiber arbeitet
  • Die Kernanforderung ist, das FUSE-Programm und die Netzwerkkonfiguration in die initramfs zu packen, das entfernte Root-Dateisystem zu mounten und anschließend normal weiterzubooten

Ansatzpunkt im Linux-Bootprozess

  • Der Linux-Bootablauf lässt sich grob in folgende Schritte unterteilen
    • Die BIOS-/UEFI-Firmware startet den Bootloader
    • Der Bootloader lädt den Kernel
    • Der Kernel entpackt im RAM ein temporäres Dateisystem, die initramfs, und nutzt Werkzeuge zum Mounten des eigentlichen Dateisystems
    • Der Kernel wechselt auf das eigentliche Dateisystem und startet das init-System des neuen Dateisystems
  • Wenn im dritten Schritt ein FUSE-Dateisystem gemountet wird, kann der Bootvorgang fortgesetzt werden, während der entfernte Speicher wie Root verwendet wird

S3-Proof-of-Concept mit Dracut

  • Zum Erzeugen der angepassten initramfs wurde Dracut verwendet
  • Als Basisdistribution wurde das vergleichsweise schlanke und vertraute Arch Linux gewählt
  • Das Dracut-Modul enthält FUSE-bezogene Binärdateien wie fusermount, fuseiso und mkisofs
  • Mit dracut.sh wurde ein EFI-Image erstellt und in QEMU ausgeführt; nach einer Warnung über ein fehlendes root=-Argument landete es in der Debug-Shell
  • In der Debug-Shell wurden die fürs Booten nötigen Schritte manuell ausgeführt
    • Treiber wurden mit modprobe fuse und modprobe e1000 geladen
    • Das Netzwerk wurde mit dhclient eth0 und Routing-Einstellungen konfiguriert
    • Mit s3fs wurde ein lokaler S3-Bucket unter /sysroot gemountet

Scheitern von switch_root und Umweg über chroot

  • Obwohl unter /sysroot das Arch-Linux-Root sichtbar war, schlug switch_root /sysroot /sbin/init mit Input/output error fehl
  • Auch pivot_root war auf dem rootfs der initramfs nicht nutzbar und führte zu Invalid argument
  • Laut einer herangezogenen Stack-Exchange-Antwort sind pivot_root und Unmounts auf dem initramfs-rootfs nicht möglich; stattdessen muss das neue Root darüber gemountet und nach chroot init gestartet werden
  • Führt man in der Shell einfach chroot /sysroot /sbin/init aus, startet systemd nicht korrekt, weil es nicht PID 1 ist
  • In Dracuts init.sh wurden Netzwerkkonfiguration, s3fs-Mount sowie Bind-Mounts für /sys, /dev und /proc eingebaut, und am Ende wurde auf exec chroot /sysroot /sbin/init umgestellt; damit gelang der S3-Root-Boot

DNS-Problem im S3-Root

  • Nach dem Booten zeigte die Ausgabe von mount, dass / als Typ s3fs gemountet war
  • Beim Ausführen von pacman -Sy fastfetch schlug die Auflösung von Paket-Mirror-Hosts wie geo.mirror.pkgbuild.com fehl
  • Da das Root-Dateisystem auf S3 lag, ließ sich dieses Root auf einer anderen Maschine mounten und per chroot betreten, um Werkzeuge zu installieren
  • systemd-resolved lief wegen eines Rechteproblems bei der stdout-Verbindung zum Journal-Socket nicht, daher wurde DNS umgangen, indem nameserver 1.1.1.1 in /etc/resolv.conf eingetragen wurde

Umzug auf Google Drive

  • Als FUSE-Implementierung für Google Drive wurde google-drive-ocamlfuse verwendet
  • Im Google-Konto wurden OAuth2-Secrets erstellt und die API aktiviert, anschließend wurde das AUR-Paket in einer Arch-Linux-VM installiert
  • Nach dem Mounten von Google Drive wurden die Arch-Linux-Dateien in einem langen rsync-Lauf nach Drive kopiert
  • Beim Google-Drive-basierten Root sorgten Unterschiede im Dateisystemverhalten immer wieder für Probleme
    • Symbolische Links, die auf symbolische Links zeigen, funktionierten nicht und verursachten Probleme bei Einträgen rund um /usr/lib
    • Hardlinks funktionierten nicht
    • Relative symbolische Links funktionierten nicht
    • Defekte symbolische Links waren nicht erlaubt
    • Symbolische Links, die aus Google Drive herauszeigen, funktionierten nicht
    • Berechtigungen und Attribute funktionierten nicht
    • Die Geschwindigkeit war sehr niedrig
  • Um die Vorgabe beizubehalten, weder den FUSE-Treiber noch den Kernel zu ändern, wurden auf Basis der fehlgeschlagenen rsync-Logs manuell symbolische Links erstellt

initramfs-Anpassungen für Google Drive

  • In die initramfs wurden die auf dem Laptop erzeugte Token-Datei, die Google-Drive-FUSE-Binärdatei und SSL-Zertifikate aufgenommen
  • Dateien zu /.gdfuse/default/config, /.gdfuse/default/state, /etc/ssl und /etc/ca-certificates wurden ins Dracut-Image eingefügt
  • Beim Booten mit Google-Drive-Root trat chroot: /sbin/init: File not found auf
  • Selbst wenn die eigentliche Datei existiert, kann Linux File not found zurückgeben, wenn Abhängigkeitsbibliotheken oder der Pfad zum dynamischen Linker fehlen
  • Wegen des Problems mit relativen symbolischen Links suchte der Kernel innerhalb von /sysroot erneut nach /sysroot/sysroot; das wurde gelöst, indem /sysroot/sysroot erstellt und /sysroot dorthin bind-gemountet wurde
  • Auch danach war der Bootvorgang sehr langsam
    • Die Neuerzeugung des dynamischen Linker-Caches dauerte etwa 5 Minuten
    • Jede systemd-Unit brauchte etwa 1 Minute
    • Der Bootvorgang blieb wegen eines Warte-Timeouts auf /dev/ttyS0 hängen
  • In /etc/systemd/system/dev-ttyS0.device wurde JobTimeoutSec=infinity gesetzt, und in /etc/login.defs wurde LOGIN_TIMEOUT auf 0 geändert, um Login-Timeouts zu vermeiden
  • Nachdem sich Caches aufgebaut hatten, wurden Dateilesevorgänge weniger langsam als anfangs

Ausführung auf einem Laptop ohne Speichergerät

  • Auf einem übrigen Laptop ohne Speichergerät wurde ein Boot auf echter Hardware versucht
  • Ausgehend von der QEMU-Konfiguration wurden einige Punkte an die Hardware angepasst
    • Statt des standardmäßigen e1000 wurde der r8169-Treiber für den Ethernet-Port des Laptops verwendet
    • Es wurde kein serielles Display verwendet
    • Die Netzwerkkonfiguration wurde an die heimische Netzwerktopologie angepasst
  • Statt eines langen Ethernet-Kabels wurde Powerline verwendet
  • Eine integrierte EFI-Datei wurde gebaut, in den EFI-Bootpfad eines USB-Laufwerks gelegt und auf dem Laptop gebootet
  • Für die eingebaute Tastatur wurde keine passende modprobe-Anweisung gefunden; daher wurde hid_usb geladen und das Netzwerk mit einer externen Tastatur konfiguriert
  • Das Endergebnis war ein „Cloud Native Computer“, der ohne Speichergerät mit einem Google-Drive-basierten Root läuft

Mögliche Varianten und Grenzen

  • Das Projekt selbst hat stark spielerischen Charakter, aber auf dieselbe Weise lässt sich Linux über SSHFS booten
  • Mit gitfs wäre auch ein Ansatz möglich, bei dem Linux aus einem Git-Repository bootet und Änderungen per Git verfolgt werden
  • Die Möglichkeiten sind groß, die Praxistauglichkeit aber begrenzt
  • Als nächstes Experiment wurde eine Nix-Installation ins Auge gefasst

Noch keine Kommentare.

Noch keine Kommentare.