Ich hatte testweise 2 Proxmox-Hosts als Cluster im Betrieb, und wollte nun alle meine VMs und LXCs, die sich im Laufe der Zeit auf den 2 Hosts gebildet haben, auf einen Host migrieren. Leider funktioniert die Proxmox-GUI-Migration nur, wenn beide Hosts einen gleichen Speicher haben, zB local-lvm. Da aber ein Host bei mir ZFS Mirror als Base-System hat, und der andere LVM, funktioniert diese Methode nicht. Bei kleinen VMs und Containern, bei denen eine Downtime von 10 Minuten keine Tragik darstellt, lässt sich das ganze mit der Backup & Restore – Methodik bewerkstelligen. Dabei wird einfach die Instanz online genommen, mittels GUI eine Archiv der VM oder des Containers erstellt, diese wird dann im Terminal vom Pfad /var/lib/vz/dump/vzdump... auf den anderen Host mittels SCP kopiert und dort unter dem local-Datenspeicher ausgewählt und wieder eingespielt.

Was aber tun, wenn die VM oder der Container zB mehrere Tibibyte groß ist, wie es bei einer Nextcloud-Instanz schnell der Fall sein kann? In diesem Fall würde die Backup & Restore – Methode aus 2 Gründen nicht gut funktionieren:

  • Der lokale Speicher, wo das Betriebssystem installiert ist, hat meistens nicht mehrere Terabyte für ein Backup frei
  • Vor allem bei LXCs muss für ein Backup der Container zeitweise offline genommen werden, diese Downtime ist in den allermeisten Fällen nicht vertretbar

Nun gibt es mehrere Möglichkeiten, wie dieses Problem gelöst werden kann:

  1. Man fügt beiden Hosts einen Shared-Storage hinzu:
    • Dazu benötigt man jedoch einen dritten Host mit viel freiem Speicher, oder freie Anschlüssen an einem Proxmox-Host
    • Meistens hat man nicht mehrere Tibibyte an Festplatten zuhause liegen, die frei zur Verfügung sind
  2. Man macht es manuell über die Command-Line

Da ich keine Festplatten rumliegen habe, dich ich einfach so einbauen kann, kam für mich nur die 2. Möglichkeit in Frage, ich hatte nämlich in beiden Host Festplatten, die groß genug sind, die allerdings nicht leer sind. Da ich nicht mit Shared-Storage herumpfuschen wollte, den ich dann bei nur einem Host gar nicht brauchen kann und nur hinderlich ist, habe ich den Weg der direkten Migration über die Command-Line gewählt.

Mein Vorteil ist, dass beide Festplattenspeicher in meinen Hosts ZFS-Pools sind. Die genaue Konstellation ist dabei gar nicht wichtig, ob das jetzt ein ZFS-Mirror ist oder ein RAIDZ1, spielt keine Rolle. Wichtig ist nur, das genug Platz auf den Pools ist. In meinem Fall war die Nextcloud-Instanz schon auf dem ZFS-Pool installiert, sollte das nicht der Fall sein, kann aber die VM oder der Container über die GUI verschoben werden, sofern sich der Speicher im gleichen Host befindet.

Wenn nun auf einem Host die Instanz als Block-Storage auf ZFS vorhanden ist, können wir nun mit der manuellen Migration beginnen, die sich wie folgt darstellt:

  1. Einen ZFS-Snapshot der Instanz erstellen
  2. Diesen ZFS-Snapshot auf den 2. Host übertragen
  3. Gegebenfalls einen weiteren Zwischensnapshot machen und übertragen, falls die Nextcloud-Instanz regen Datenverkehr gesehen hat.
  4. Die Instanz herunterfahren
  5. Einen neuen ZFS-Snapshot auf dem 1. Host anfertigen
  6. Die Änderungen der Snapshots übertragen
  7. Die Config verschieben
  8. Die Config bearbeiten
  9. Die Instanz am anderen Host wieder booten

Im Falle von ZFS sieht das nun wie folgt aus:

  1. Der Snapshot kann über die GUI gemacht werden oder über die Command Line, das liegt jedem frei, mein Snapshot heißt „migration_state“

  2. Die Übertragung des ersten Snapshots erfolgt nun mittels ZFS send/receive vom ersten Host:
    zfs send --replicate --large-block --compressed --verbose zfspool1/subvol-161-disk-0@migration_state | ssh root@10.10.0.150 zfs recv -v zfspool2/subvol-161-disk-0
    Dies kann nun einige Zeit dauern, das lässt man am besten in Ruhe in einem tmux-Fenster werken und detached sich derweilen.

  3. Habe ich ausgelassen, weil ich meine Instanz ruhig für eine viertel Stunde offline nehmen kann, ohne das es jemanden stört. Falls es sich um eine viel-besuchte Instanz handelt, hier die Schritte Punkt 5 und 6 benutzen.

  4. Jetzt die Instanz herunterfahren, damit wir einen konsistenten Stand übertragen können.

  5. Nun fertigen wir erneut einen Snapshot wie in Punkt 1 an, meiner heißt final_state

  6. Nun übertragen wir die Änderungen des „migration_state“ und des neuen final_state Snapshots mittels diesem Befehl:
    zfs send --large-block --compressed --verbose -i migration_state zfspool1/subvol-161-disk-0@final_state | ssh root@10.10.0.150 zfs recv -v -F zfspool2/subvol-161-disk-0
    WICHTIG: Der bei -i angeführte Snapshot ist der letzte, der auf dem Host 2 vorhanden ist, der nach dem @ bei send ist der aktuellste, den wir übertragen wollen. Der Parameter -F bei recv ist dafür zuständig, das wir eventuelle Änderungen am Host 2 überschreiben. Das macht uns nichts aus, weil die Instanz ja noch nicht von dort läuft.

  7. Nun können wir die Config-File verschieben. Dies wird automatisch über das Proxmox-Cluster mit dem 2. Host synchronisiert. (In meinem Fall handelt es sich um einen LXC, bei VMs liegt die Config im Ordner qemu-server)
    mv /etc/pve/nodes/host1/lxc/161.conf /etc/pve/nodes/host2/lxc/

  8. Nun muss die Datei 161.conf bearbeitet werden, um jede Referenz auf das Dataset zu ändern:
    nano /etc/pve/nodes/host2/lxc/161.conf
    In unserem Fall wird
    zfspool1/subvol-161-disk-0
    zu
    zfspool2/subvol-161-disk-0
    ausgebessert. Je mehr Snapshots von dieser VM vorhanden sind, umso mehr Zeilen müssen ausgebessert werden.

  9. Nun können wir die Instanz am neuen Host wieder booten. Alle Daten und Einstellungen sind übernommen, und die Instanz funktioniert wie sie soll.

Wenn das Prinzip einmal verstanden ist, kann das auch mit anderen Konstellationen funktionieren. Wichtig ist dabei immer, nicht zu voreilig zu handeln, und die Befehle bei Unsicherheit in einer Test-VM zu probieren, um keine bösen Überraschungen fürchten zu müssen.