2 Punkte von GN⁺ 2024-03-13 | 1 Kommentare | Auf WhatsApp teilen
  • Statt einen neuen Laptop von Grund auf neu einzurichten, wurde die gesamte Festplatte des bisherigen Laptops per NVMe over TCP bereitgestellt und unverändert über das Netzwerk geklont
  • Die bestehende Umgebung nutzte Full-Disk Encryption und eine 512-GB-Festplatte; der neue Laptop hat eine 1-TB-NVMe, daher mussten nach dem Klonen Partition, LUKS und BTRFS erweitert werden
  • Für den Festplatten-Export wurden statt systemd-storagetm.service beide Laptops mit einer GRML Rescue CD gebootet und mit nvmet-tcp sowie /sys/kernel/config/nvmet konfiguriert
  • Die eigentliche Kopie erfolgte mit dd; da der neue Laptop keinen Ethernet-Port hatte und nur WiFi genutzt wurde, dauerte das Klonen von 512 GB rund 7 Stunden 30 Minuten, bei etwa 18–20 MB/s
  • Nach dem Klonen wurde mit parted, growpart, cryptsetup resize und BTRFS resize angepasst, sodass die gesamten 1 TB nutzbar waren und die bisherige Laptop-Umgebung nahezu unverändert übernommen werden konnte

Bestehende Festplatte per NVMe over TCP exportieren

  • Um die Einrichtung des neuen Laptops nicht wiederholen zu müssen, wurde auf Vorschlag eines Kollegen entschieden, die gesamte Festplatte des bisherigen Laptops zu kopieren

  • Vor dem Start gab es zwei Hindernisse

    • Es gab kein Werkzeug, um den bisherigen Laptop zu öffnen und die neue Festplatte per USB anzuschließen
    • Der bisherige Laptop nutzte Full-Disk Encryption und eine 512-GB-Festplatte, während der neue Laptop eine 1-TB-NVMe hat, sodass eine Größenanpassung von LUKS nötig war
  • Der Ablauf bestand aus drei Schritten: Festplatte bereitstellen, kopieren und Kapazität erweitern

    • Die Festplatte des bisherigen Laptops per nvmet-tcp exportieren
    • Diese Festplatte auf dem neuen Laptop kopieren
    • Die Partition auf die gesamten 1 TB erweitern
    • Die Größe von LUKS anpassen
    • Abschließend die Größe der BTRFS-Root-Festplatte anpassen
  • GRML statt systemd-storagetm.service verwenden

    • Der einfachste Weg wäre die Nutzung von systemd-storagetm.service gewesen
    • Durch Angabe von rd.systemd.unit=storage-target-mode.target kann in storage-target-mode.target gebootet und der Dienst aufgerufen werden
    • Allerdings müsste dieser Ansatz Netzwerkdienste in das dracut-initrd-Image aufnehmen, und in diesem Modus ist die WiFi-Konfiguration umständlich, daher wurde er verworfen
    • Stattdessen wurden beide Laptops mit einer GRML Rescue CD gebootet; anschließend wurde die NVMe-Festplatte auf dem bisherigen Laptop mit dem Linux-Modul nvmet-tcp exportiert
    modprobe nvmet-tcp
    cd /sys/kernel/config/nvmet
    mkdir ports/0
    cd ports/0
    echo "ipv4" > addr_adrfam
    echo 0.0.0.0 > addr_traaddr
    echo 4420 > addr_trsvcid
    echo tcp > addr_trtype
    cd /sys/kernel/config/nvmet/subsystems
    mkdir testnqn
    echo 1 >testnqn/allow_any_host
    mkdir testnqn/namespaces/1
    cd testnqn
    
    
    # replace the device name with the disk you want to export
    echo "/dev/nvme0n1" > namespaces/1/device_path
    echo 1 > namespaces/1/enable
    ln -s "../../subsystems/testnqn" /sys/kernel/config/nvmet/ports/0/subsystems/testnqn
    
    • Mit dieser Konfiguration wird das Zielgerät per NVMe over TCP bereitgestellt
    • Auf dem neuen Laptop wird das exportierte Gerät gesucht und verbunden
    nvme discover -t tcp -a <ip> -s 4420
    nvme connectl-all -t tcp -a <> -s 4420
    
    • Danach lässt sich das auf dem neuen Laptop verbundene Gerät mit nvme list prüfen und die Festplattenkopie starten

Festplatte kopieren und Größe anpassen

  • 512 GB mit dd kopieren

    • Die Root-Festplatte wurde mit dem Befehl dd kopiert
    • Da der neue Laptop keinen Ethernet-Port hatte und nur WiFi genutzt wurde, dauerte das vollständige Kopieren von 512 GB etwa 7 Stunden 30 Minuten
    • Die Übertragungsrate lag bei etwa 18–20 MB/s
    • Als Alternativen wären möglich gewesen, zunächst Partitionen und Dateisysteme anzulegen und dann die Root-Festplatte mit rsync zu kopieren, oder die Dateisystem-Übertragung von BTRFS selbst zu nutzen
    dd if=/dev/nvme2n1 of=/dev/nvme0n1 status=progress bs=40M
    
  • Partition, LUKS und BTRFS erweitern

    • parted erkannte, dass die Partitionstabelle nicht zur Festplattengröße passte, fragte nach einer Korrektur und reparierte sie anschließend automatisch
    • Zum Erweitern der zweiten Partition wurde cloud-guest-utils installiert und growpart verwendet
    growpart /dev/nvem0n1 p2
    
    • Im nächsten Schritt wurde der LUKS-Container mit cryptsetup vergrößert
    cryptsetup luksOpen /dev/nvme0n1p2 ENC
    cryptsetup resize ENC
    
    • Nach dem Neustart von der Festplatte wurde die korrekte Funktion geprüft; nach dem Login wurde die Größe des BTRFS-Dateisystems angepasst
    • Für die Größenanpassung muss BTRFS gemountet sein, daher war dies im Live-Boot-Zustand nicht möglich
    btfs fielsystem resize max /
    
    • Im Ergebnis entstand auf dem neuen Laptop eine Umgebung, die sich anfühlt, als würde man den bisherigen Laptop weiterverwenden
    • Normalerweise dauert es etwa ein bis zwei Wochen, sich vollständig an einen neuen Laptop zu gewöhnen; mit diesem Ansatz wurde diese Zeit verkürzt
    • Zusätzlich blieb die Erfahrung, wie man eine Festplatte per NVMe over TCP exportiert

1 Kommentare

 
GN⁺ 2024-03-13
Meinungen auf Hacker News
  • Im Szenario des Autors wird am Ende mit dd(1) nur eine serielle Blockkopie durchgeführt, daher bringt NVMe/TCP kaum Vorteile. Der komplexe Befehl lässt sich durch ein einfaches netcat ersetzen
    Ziel-Laptop: $ nc -l -p 1234 | dd of=/dev/nvme0nX bs=1M
    Quell-Laptop: $ nc x.x.x.x 1234
    Das dd auf der Zielseite dient dazu, Schreibvorgänge zu puffern und sie schneller und effizienter zu machen. Fügt man auf Quelle/Ziel gzip/gunzip hinzu, wird es deutlich schneller, wenn die Platte nicht voll ist und es viele Nullblöcke gibt. Persönlich ist das meine bevorzugte Methode, um PC-Images übers Netzwerk zu erstellen, und ich habe sie schon mehrfach genutzt
    Bei GigE ist oft die Kompression der Flaschenhals, daher sollte man gzip --fast mitgeben; noch besser ist es, statt gzip/gunzip lz4/unlz4 zu verwenden, das ist schneller. Als ich früher einen neuen Windows-Laptop mit 1 TB NVMe über GigE als Image gesichert habe, dauerte es etwa 20 Minuten; der leere Speicherplatz wurde praktisch auf null komprimiert, und das resultierende Image war 20 GB groß. Normalerweise bewahre ich dieses lz4-Image als Backup auf und stelle es ein paar Jahre später, wenn ich den Laptop spende, mit unlz4 | dd wieder her — sehr bequem
    Allerdings kannte ich das Linux-Kernelmodul nvme-tcp nicht; man lernt jeden Tag etwas Neues. Das scheint eher nützlich zu sein, um ein Dateisystem auf einer entfernten NVMe zu mounten, als für Rohzugriff mit dd
    Außerdem beträgt die maximale Pipe-Puffergröße unter Linux 64 kB, daher muss das Argument dd bs=X technisch gesehen nicht größer sein. Trotzdem schadet bs=1M nicht: Es sammelt 64-kB-Lesevorgänge, bis 1 MB erreicht ist, und ist auch für künftig größere Pipe-Größen vorbereitet. Einige netcat-Versionen haben Optionen für die Ein-/Ausgabe-Blockgröße, sodass dd bs=X nicht nötig ist; das netcat auf einer Rettungsdisk hat aber meist keine solche Option

    • Der Pipe-Puffer von Linux lässt sich vergrößern, und der Standard-Maximalwert liegt meines Wissens meist bei etwa 1 MB. Über die Kommandozeile ist das etwas knifflig, aber ein mögliches Implementierungsbeispiel gibt es unter https://unix.stackexchange.com/a/328364
    • Es ist zwar etwas unsauber, aber wenn man auf beiden Seiten statt dd pv verwendet, muss man sich keine Gedanken über eine passende Blockgröße machen und bekommt außerdem eine hübsche Fortschrittsanzeige
    • Vor etwa 9 Jahren war ich als Berater bei einem Unternehmen, das intern gehackt worden war: Ein verärgerter Mitgründer hatte eine Art Dead-Man-Switch eingerichtet, der die ersten 20 MB aller Disks in irgendeinen Bucket kopierte und sie danach mit Nullen überschrieb. Um die Daten wiederherzustellen, mussten wir mit testdisk die Partitionstabellen rekonstruieren; vorher wollten wir die beschädigten Disks aber nicht anfassen, also kopierten wir mit Rettungs-Flash-Disk, netcat und Laufwerken rund 40 TB
      Bei einigen Servern waren alle physischen RAID-Slots belegt, sodass wir nicht einmal einen freien Disk-Slot nutzen konnten, und wir verwendeten ungefähr dd if=/dev/sdc bs=xxx | gzip | nc -l -p 8888 sowie den entsprechenden umgekehrten Befehl auf der Gegenseite. Es funktionierte überraschend gut. Eine Sache, auf die man achten sollte, ist die dd bs-Kombination an die Sektorgröße anzupassen; die passende Größe hatte großen Einfluss auf den Durchsatz von dd
    • Diese Verwendung von dd kann Beschädigungen verursachen. Damit Blöcke nicht abgeschnitten werden, braucht man iflag=fullblock; und auch wenn es eine blinde Angewohnheit sein kann, schadet conv=sync nicht. Persönlich bevorzuge ich einfach nc -l -p 1234 > /dev/nvme0nX
    • Bei den meisten dürfte das lokale Netzwerk nicht schneller sein als die SSD-Übertragungsrate. Trotzdem frage ich mich, ob es für Leute mit einer solchen Umgebung ein Tool zum gleichzeitigen Klonen von Blockgeräten mit paralleler Ein-/Ausgabe gibt
      Wenn man pv in die Pipeline setzt, kann man die geschätzte Abschlusszeit sehen, allerdings kann das die Performance leicht beeinflussen
  • Danke an AWS/Annapurna/Nitro/Lightbits dafür, NVMe-over-TCP in Linux gebracht zu haben
    https://www.techtarget.com/searchstorage/news/252459311/Ligh...
    „Das NVM-Express-Konsortium ratifizierte NVMe/TCP im November 2018 als gebundene Transportschicht. Der Standard entwickelte sich ursprünglich aus einer Codebasis, die das Engineering-Team von Lightbits bei NVM Express eingereicht hatte.“
    https://www.lightbitslabs.com/blog/linux-distributions-nvme-...
    https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...

  • Wirkt deutlich umständlicher als Folgendes: nbdkit file /dev/nvme0n1, nbdcopy nbd://otherlaptop localfile

    • Diese Methode ist tatsächlich deutlich besser: nbdcopy kann Sparse Files verarbeiten, die Anzahl der Verbindungen und Threads an die Zahl der Kerne anpassen, vor dem Beenden einen erzwungenen Flush durchführen und eine Fortschrittsleiste aktivieren. Bei einem unverschlüsselten Laufwerk unterstützt es auch TLS
  • Kürzlich musste ich auf einem neuen Laptop xubuntu installieren. Früher habe ich geklont, aber diesmal wollte ich einige Einstellungen neu aufräumen.
    Die Übertragung mit 10 Gb/s über ein USB-C-Kabel war wirklich nützlich. Die einzige Alternative wäre nämlich WiFi gewesen.
    Wenn man die Computer direkt miteinander verbindet, entsteht ein temporäres Netzwerk, und man kann die Daten einfach mit rsync übertragen. Dem Anschein nach war der Link ausgelastet, daher schien ein anderes Protokoll kaum einen Unterschied zu machen. Natürlich ist es gut, etwas Neues zu lernen, aber vielleicht nicht gerade in dem Moment, in dem man einen Laptop klont.

    • Mich würde interessieren, ob das einfach direkt funktioniert hat. Ich frage ernsthaft, weil ich das letzte Mal in den 90ern eine direkte Verbindung versucht habe, die nicht Ethernet war.
    • Ich habe das auch gemacht, musste aber ein Thunderbolt-4-Kabel für über 30 Dollar kaufen, damit Networking funktioniert. Ein normales USB3-C-Kabel reichte nicht aus.
      Die Übertragung selbst war extrem schnell; 1 TB war in wenigen Minuten drüben. Diesmal habe ich keine Verschlüsselung verwendet, was es deutlich einfacher gemacht hat.
    • Mich würde interessieren, ob du von einer Live-Disk gebootet und dann das gesamte Dateisystem übertragen hast, oder ob du erst ein Basissystem installiert und danach nur die Dateien kopiert hast.
  • Ich verstehe nicht, warum nicht einfach btrfs über das Netzwerk gepipet wurde. Erst einen btrfs-Snapshot erstellen und dann btrfs send => nc => network => nc => btrfs receive; so werden nur die tatsächlich verwendeten Blöcke übertragen.

    • Als ich gesehen habe, dass btrfs verwendet wurde, war das auch mein erster Gedanke. Ich nutze btrfs send/receive ständig über SSH, und es funktioniert sehr gut. In einer GRML-Live-Session hätte man auch leicht einen SSH-Server starten können.
      Es gibt allerdings einen Haken. Bei btrfs kann man Snapshots nicht rekursiv senden; wenn es also viele rekursive Snapshots gibt, ist es vergleichsweise schwierig, dieselbe Struktur auf einer neuen Disk zu spiegeln. Bei Docker/LXD/Incus kann das vorkommen. Ich mag btrfs, aber rekursives send/receive ist ein Bereich, in dem ZFS besser ist.
  • Kürzlich musste ich etwa 200 GB an Dateien über WiFi kopieren. Damit ich bei einem Verbindungsabbruch nicht wieder von vorn anfangen muss und nichts verloren geht, habe ich rsync verwendet, aber es dauerte mindestens 6 Stunden. Ich frage mich, ob es eine bessere Methode gegeben hätte.
    Außerdem frage ich mich, welche Garantien die dd-Methode bietet. Muss man den md5-Hash des resultierenden Block-Devices vergleichen?

    • 6 Stunden für 200 GB über WiFi sind für eine lokale Übertragung kein beeindruckender Durchsatz. Da hätte man vermutlich ein Ethernet-Kabel verwenden sollen.
      Bei WiFi gibt es deutlich mehr mögliche Performance-Flaschenhälse. Schon wenn nur eines der Geräte per Kabel am Router hängt und das andere drahtlos bleibt, hilft das ziemlich.
    • Wenn es sehr viele sehr kleine Dateien waren, war wahrscheinlich der Umstand der Flaschenhals, dass rsync jeweils nur eine Datei auf einmal überträgt. Man kann die Dateiliste mit xargs/parallel aufteilen und mehrere rsync-Instanzen laufen lassen, oder etwas wie rclone verwenden, das parallele Übertragungen von sich aus unterstützt.
    • 6 Stunden entsprechen grob 10 MB/s, also hätte es sehr wahrscheinlich deutlich schneller gehen können. Mich würde interessieren, ob mit -z komprimiert wurde. Wenn Ethernet möglich gewesen wäre, wären die meisten Geräte nahe an 100 MB/s gekommen, also etwa 35 Minuten.
    • Wenn rsync über SSH übertragen hat, ist das häufig der Flaschenhals. OpenSSH hatte historisch seltsame Performance-Limits, und zeitweise brauchte man wenig bekannte Patches, um sie zu umgehen. Wenn nicht die CPU der Flaschenhals ist, kann es auch helfen, Kompression zu aktivieren.
    • WiFi teilt sich das Medium Luft mit allen anderen Funkgeräten. Wenn eine Kollision erkannt wird, hält es an und wartet eine zufällige Zeitspanne.
      „In der Computernetzwerktechnik ist Carrier Sense Multiple Access with Collision Avoidance (CSMA/CA) ein Netzwerk-Mehrfachzugriffsverfahren, das Carrier Sensing nutzt, aber Kollisionen zu vermeiden versucht, indem eine Übertragung erst gestartet wird, nachdem der Kanal als ‚frei‘ erkannt wurde. Beim Senden überträgt ein Knoten seine Paketdaten vollständig.
      Das ist besonders wichtig für drahtlose Netzwerke, in denen CSMA/CD mit Kollisionserkennung nicht verwendet werden kann, weil ein drahtloser Sender während der Paketübertragung seinen Empfänger desensibilisiert und damit praktisch abschaltet.
      CSMA/CA ist wegen des Hidden-Node-Problems weniger zuverlässig.
      CSMA/CA ist ein Protokoll, das auf der Sicherungsschicht arbeitet.“
      https://en.wikipedia.org/wiki/Carrier-sense_multiple_access_...
  • Dieser Ansatz hat sicher seine Vorteile, aber als ich früher einen Laptop migriert habe, habe ich auf beiden Seiten den Installer gestartet und dann dd mit nc kombiniert. Soweit ich mich erinnere, habe ich auch gzip ergänzt, um große Nullbereiche schneller zu übertragen.
    Wenn der neue Laptop keinen Ethernet-Port hatte, war meine hackige Methode dank Kompression vielleicht sogar etwas schneller. Schließlich wäre der Netzwerkdurchsatz bei einem schnellen Link wohl nicht nahe an die Grenze gekommen, die die zusätzliche Kompression setzt.

    • Bei vollständiger Festplattenverschlüsselung erhält man mit der vom Autor beschriebenen Methode im Grunde nur Zufallsdaten, sofern man LUKS nicht angewiesen hat, TRIM durchzureichen.
  • Warum nicht einfach Clonezilla verwenden? Es kopiert nur tatsächlich belegte Datenblöcke und kann Partitionen automatisch in der Größe anpassen. Ich mache das immer so.
    Normalerweise nehme ich allerdings die NVMe-Disk aus dem Laptop und stecke sie in ein schnelles Dock.

    • Clonezilla ist großartig. Es hat genau eine Aufgabe und schafft sie meistens beim ersten Versuch. Mein einziger Kritikpunkt ist die anfängliche Lernkurve, wegen der man erst einiges ausprobieren muss.
      Ganz auf „starten und unbeaufsichtigt laufen lassen“ vertraue ich ihm noch nicht. Ein Backup ist nicht dasselbe wie Backup plus Restore, daher sind Tests empfehlenswert. Auch Clonezilla kann Probleme bekommen, wenn es Partitionen auf einer Disk neu erstellt, die sich stark vom Original unterscheidet.
  • Es ist Jahrzehnte her, dass ich auf einem Desktop oder Laptop ein Betriebssystem tatsächlich „installiert“ habe; ich habe immer Dateien kopiert und danach nur das Nötige angepasst. Meistens nutze ich die Gelegenheit, um ein neues Dateisystem anzulegen und Parameter wie Dateisystemtyp oder Blockgröße sowie Verschlüsselung zu aktualisieren, und verschiebe die Dateien dann mit rsync.
    Wer aber gern im Voraus plant, ist mit einem deklarativeren Ansatz wie NixOS vermutlich besser bedient: nur die Konfiguration kopieren und den Rest automatisch neu installieren lassen.

  • Wenn man die Geräte per WiFi direkt verbindet, ohne AP dazwischen, ließe sich die Übertragungsgeschwindigkeit wahrscheinlich verdoppeln. In dieser Situation wäre das wohl einen Versuch wert gewesen.