Datenmigration eines verschlüsselten Systems

Da mir langsam aber sicher der Speicherplatz auf meinem System ausging war es an der Zeit, eine größere SSD anzuschaffen. Meine bisher verbaute Corsair Force 3 (120GB, Controller mit Kompression) sollte durch eine SSD ersetzt werden, welche zum einen ca. 250GB Speicherplatz bietet, zum anderen einen Controller verbaut hat, welcher die gespeicherten Daten nicht komprimiert.

Da ich eine Verschlüsselung basierend auf LUKS einsetze ist vor allem der zweite Punkt relevant. Die Mehrheit der Consumer-SSDs komprimiert intern Daten um überhaut die angegebenen Datenraten von 500MB/s und mehr zu erreichen. Da eine gute Verschlüsselung per Definition allerdings nicht komprimierbar ist, bricht die Datenrate bei diesen SSDs in der Regel auf Werte unter 250MB/s ein, kopiert man intern Daten (d.h. von einer Partition der SSD auf eine andere, beide Partitionen verschlüsselt und auf der gleichen SSD vorliegend) halbiert sich diese Datenrate nochmals.

Daher entschied ich mich nach diversen Testberichten für eine Samsung 850 Pro mit 256GB Kapazität. Die Schreib-/Lesegeschwindigkeiten liegen bei etwa 500MB/s, der Controller verzichtet auf eine Kompression.

Um die Daten von der alten SSD auf die neuere SSD zu kopieren habe ich dd mit entsprechenden Parametern verwendet. Für das interne Wear-Leveling der Festplatten zwar nicht optimal, allerdings lässt sich dieses Problem nachträglich mittels TRIM-Befehl lösen.

Das eigentliche Kopfzerbrechen hat mir die Vergrößerung der einzelnen Partitionen bereitet. Die Partitionierung sah nach dem geglückten Klonvorgang auf die Samsung 850 Pro in etwa so aus:

sda
 ├─ GPT-Header
 │   ├─ sda1, 200MB
 │   │   └─ fat32-Dateisystem, eingehängt als /boot
 │   └─ sda2, 119.8GB
 │       └─ LUKS-Container, 119.8GB
 │           └─ lvm (PV), 119.8GB
 │               └─ lvm (VG), 119.8GB
 │                   ├─ lvm-root (LV), 16GB
 │                   │   └─ ext4-Dateisystem, eingehängt als /root
 │                   ├─ lvm-home (LV), 78GB
 │                   │   └─ btrfs-Dateisystem, eingehängt als /home
 │                   ├─ lvm-storage (LV), 24GB
 │                   │   └─ ext4-Dateisystem, eingehängt als /media/storage
 │                   └─ 1.8GB unpartitionierter Bereich
 └─ 136GB freier Bereich

Wie man am Schema erkennen kann musste zuerst der 136GB umfassende, freie Bereich, in den GPT-Header aufgenommen werden. GParted erledigt dies auf Nachfrage automatisch, bei gdisk hingegen muss man über den Expertenmodus die Datenstruktur ändern (v → x → e → w). Der kniffligere Teil war die Vergrößerung des LUKS-Containers und dessen Inhalt, was im Folgenden beschrieben wird.

LUKS-Container vergrößern

Da ein LUKS-Container kein Dateisystem per se darstellt und auch eher schlecht unterstützt wird (im Gegensatz zu Dateisystemen wie ext4, welche beispielsweise Online-Vergrößerungen erlauben), musste ich auf den Terminal zurückgreifen.

Dazu startet man von einem Live-System aus als root gdisk und lässt sich mittels des Befehls „p“ die aktuelle Partitionstabelle anzeigen. Merken muss man sich hierbei den Startsektor seiner LUSK-Partition sowie den Partitionstyp (bei LUKS-Containern im Regelfall der Code „8300“). Anschließend löscht man mit dem Befehl „d“ die zu vergrößernde Partition und legt sie mittels des Befehls „n“ neu an. Hierbei kann dann die neue Größe eingetragen werden. Man sollte daruaf achten, dass der Startsektor mit der ursprünglichen Partition übereinstimmt, ebenso wie die Kennung der Partition. Dann tritt auch kein Datenverlust auf. Mit dem Befehl „w“ schreibt man die Änderungen auf die Festplatte, ein Überprüfen ist wiederum mittels „p“ möglich. Anschließend beendet man das Programm durch den Befehl „q“.

Nachdem dies geschehen ist kann der in sda2 enthaltene LUKS-Container vergrößert werden. Hierzu hängt man diesen ein und führt eine Größenänderung durch:

# cryptsetup luksOpen /dev/sda2 lvm
# cryptsetup --verbose resize /dev/mapper/lvm

LVM vergrößern

Das LVM-Setup, welches hier die Funktion der Partitionierung übernimmt (LUKS-Container können auf herkömmliche Weise nur eine Partition fassen), muss natürlich auch an die neue Größe des Containers angepasst werden.

Dazu ist es notwendig, erst das Physical Volume (PV), anschließend die Volume Group (VG) und letztlich die einzelnen Partitionen (LVs) sowie deren Dateisysteme zu vergrößern.

Physical Volume (PV) vergrößern

Die Größe des PV kann mittels des Befehls „pvs“ ermittelt werden. Eine Vergrößerung auf die maximale Größe der Partition erreicht man durch folgenden Befehl:

# pvresize /dev/mapper/lvm

Das Ergebnis kann wiederum durch ein „pvs“ oder auch „pvdisplay“ betrachtet werden.

Volume Group (VG) vergrößern

Die Größe der VG kann, ähnlich wie bei dem PV, durch den Befehl „vgs“ angezeigt werden. Eine Vergrößerung auf das Maximum des PV kann man wie folgt erreichen:

# vgextend lvm /dev/mapper/lvm

Das Ergebnis lässt sich wiederum durch ein „vgs“ oder „vgdisplay“ betrachten.

Logical Volumes (LV) vergrößern

Die LVs können wiederum mit dem Befehl „lvs“ aufgelistet werden. Es macht nur wenig Sinn alle LVs zu vergrößern, in meinem Falle habe ich daher lediglich die home- und storage-Partition um ein paar Gigabyte erweitert:

# lvextend -L +50GB /dev/lvm/home
# lvextend -L +40GB /dev/lvm/storage

Ob alles geklappt hat kann man sich wiederum mittels „lvs“ oder „lvdisplay“ anzeigen lassen.

Dateisysteme vergrößern

Bis auf die Dateisyteme ist nun alles auf die neue SSD angepasst. Je nach Dateisystem muss man hier allerdings unterschiedliche Wege gehen (und natürlich muss das ganze für jede Partition einzeln erledigt werden).

Ext2/3/4 und andere

Bevor man durch resize2fs die Parition vergrößern kann muss eine Dateisystemprüfung ausgeführt werden. Es empfiehlt sich zudem das Dateisystem auch nach der Vergrößerung nochmals zu überprüfen (hier wird dann auch gleich die neue Größe angezeigt).

# e2fsck /dev/lvm/storage
# resize2fs /dev/lvm/storage
# e2fsck /dev/lvm/storage

Btrfs

Bei btrfs hingegen benutzt man anstelle von resize2fs die Btrfs filesystem utilities:

# btrfs filesystem resize max /home
# btrfs filesystem show /home

Fazit

Ich persönlich bin ein Freund des Terminals, andrerseits wäre in diesem Falle ein grafisches Tool welches einem die einzelnen Partitionen einfach anpassen lässt wünschenswert gewesen. Gerade wenn man seinen Rechner nur einmalig aufsetzt entfallen einem gerne mal die nötigen Befehle, zum Glück gibt es aber Manpages.

Wie man ebenfalls sehen kann gibt es bei diesem Setup (welches ich als Standard für verschlüsselte Systeme ansehen würde) erheblich mehr Abstraktion als man anfangs erwartet. Vor allem das vergrößern des LUKS-Containers indem man die Partition löscht und neu anlegt kann einen kurz abschrecken. Letztlich hat die Migration allerdings problemlos geklappt und ich habe wieder ausreichend Speicherplatz auf meinem System frei – zumindest bis zum nächsten Urlaub und der sich daraus ergebenden Fotosammlung.