So spiegeln Sie einen gesamten ZFS-Pool in einen anderen ZFS-Pool


15

Ich habe einen ZFS-Pool mit mehreren ZVOLs und Datensätzen, von denen einige auch verschachtelt sind. Alle Datensätze und zvols werden regelmäßig von zfs-auto-snapshot erfasst. Alle Datensätze und Zvols verfügen auch über einige manuell erstellte Snapshots.

Ich habe einen Remote-Pool eingerichtet, in dem aus Zeitgründen das anfängliche Kopieren über das lokale Hochgeschwindigkeitsnetzwerk per zfs send -R nicht abgeschlossen wurde (einige Datensätze fehlen, einige Datensätze sind veraltet oder es fehlen Momentaufnahmen).

Jetzt ist der Pool physisch über eine langsame Verbindung entfernt, und ich muss den Remotepool regelmäßig mit dem lokalen Pool synchronisieren. Dies bedeutet, dass Daten, die im lokalen Pool vorhanden sind, in den Remotepool kopiert werden müssen. Daten, die aus dem lokalen Pool entfernt wurden, müssen aus dem Remotepool gelöscht werden Daten, die im Remotepool, aber nicht im lokalen Pool vorhanden sind, müssen aus dem Remotepool gelöscht werden, indem Daten wie "zvols", "datasets" oder "snapshots" verwendet werden.

Wenn ich dies zwischen zwei regulären Dateisystemen mit rsync machen würde, wäre es "-axPHAX --delete" (das ist, was ich tatsächlich mache, um einige Systeme zu sichern).

Wie richte ich eine Synchronisierungsaufgabe ein, damit die ZVOLs und Datasets des Remote-Pools (einschließlich ihrer Snapshots) mit den lokalen ZVOLs, Datasets und Snapshots synchronisiert werden können?

Ich möchte die Übertragung über ssh vermeiden, da die Durchsatzleistung von ssh gering ist. Ich bevorzuge stattdessen mbuffer oder iscsi.


Wie hast du deine Initiale gemacht zfs send -R ...? Wenn Sie die Ausgabe über weitergeleitet haben ssh, haben Sie die Escape-Zeichen mit deaktiviert zfs send -R ... | ssh -e none ...?
Andrew Henle

Außerdem müssen Sie sicherstellen, dass Ihre langsame Verbindung über genügend Bandbreite verfügt, um die Remote-Kopie auf dem neuesten Stand zu halten. Wenn Sie mehr Änderungen am lokalen System erhalten, als Sie an das ferne System senden können, können Sie die ferne Kopie niemals auf dem neuesten Stand halten. Nehmen Sie einen inkrementellen zfs-Replikationsdatenstrom und speichern Sie ihn in einer Datei. Wenn die Datei größer ist als die Datenmenge, die Sie in der Zeitspanne zwischen den Snapshots an die Remote-Site senden können, werden Sie nie Schritt halten. zfs send -R -i pool@snap1 pool@snap2 | gzip --fast > /output/file.gz
Andrew Henle

Sie können auch versuchen, dieses Skript automatisch zu verwenden: github.com/psy0rz/zfs_autobackup/blob/master/README.md
edwin eefting

Antworten:


10

Haftungsausschluss: Da ich nie zvols verwendet habe, kann ich nicht sagen, ob sie sich in der Replikation von normalen Dateisystemen oder Snapshots unterscheiden. Ich nehme an, dass dies der Fall ist, aber nehme mein Wort nicht dafür.


Ihre Frage ist eigentlich mehrere Fragen, ich versuche, sie getrennt zu beantworten:

Replizieren / Spiegeln des gesamten Pools an einen Remotestandort

Sie müssen die Aufgabe in zwei Teile aufteilen: Erstens muss die erste Replikation abgeschlossen sein, danach ist eine inkrementelle Replikation möglich, solange Sie nicht mit Ihren Replikations-Snapshots herumspielen . Um die inkrementelle Replikation zu aktivieren, müssen Sie die letzten Replikations-Snapshots aufbewahren, alles, was zuvor gelöscht werden kann. Wenn Sie den vorherigen Snapshot löschen, zfs recvwird die Replikation beanstandet und abgebrochen. In diesem Fall müssen Sie noch einmal von vorne beginnen. Versuchen Sie also, dies nicht zu tun.

Wenn Sie nur die richtigen Optionen benötigen, sind dies:

  • zfs send:
    • -R: Sende alles unter dem angegebenen Pool oder Datensatz (rekursive Replikation, wird die ganze Zeit benötigt, enthält -p). Außerdem werden beim Empfang alle gelöschten Quellschnappschüsse auf dem Ziel gelöscht.
    • -I: Alle Zwischen-Snapshots zwischen dem letzten Replikations-Snapshot und dem aktuellen Replikations-Snapshot einschließen (nur bei inkrementellen Sends erforderlich)
  • zfs recv:
    • -F: Erweitern Sie den Zielpool, einschließlich des Löschens vorhandener Datensätze, die in der Quelle gelöscht wurden
    • -d: Verwerfen Sie den Namen des Quellpools und ersetzen Sie ihn durch den Namen des Zielpools (der Rest der Dateisystempfade wird beibehalten und bei Bedarf auch erstellt).
    • -u: Hänge das Dateisystem nicht am Ziel an

Wenn Sie ein vollständiges Beispiel bevorzugen, finden Sie hier ein kleines Skript:

#!/bin/sh

# Setup/variables:

# Each snapshot name must be unique, timestamp is a good choice.
# You can also use Solaris date, but I don't know the correct syntax.
snapshot_string=DO_NOT_DELETE_remote_replication_
timestamp=$(/usr/gnu/bin/date '+%Y%m%d%H%M%S')
source_pool=tank
destination_pool=tank
new_snap="$source_pool"@"$snapshot_string""$timestamp"
destination_host=remotehostname

# Initial send:

# Create first recursive snapshot of the whole pool.
zfs snapshot -r "$new_snap"
# Initial replication via SSH.
zfs send -R "$new_snap" | ssh "$destination_host" zfs recv -Fdu "$destination_pool"

# Incremental sends:

# Get old snapshot name.
old_snap=$(zfs list -H -o name -t snapshot -r "$source_pool" | grep "$source_pool"@"$snapshot_string" | tail --lines=1)
# Create new recursive snapshot of the whole pool.
zfs snapshot -r "$new_snap"
# Incremental replication via SSH.
zfs send -R -I "$old_snap" "$new_snap" | ssh "$destination_host" zfs recv -Fdu "$destination_pool"
# Delete older snaps on the local source (grep -v inverts the selection)
delete_from=$(zfs list -H -o name -t snapshot -r "$source_pool" | grep "$snapshot_string" | grep -v "$timestamp")
for snap in $delete_from; do
    zfs destroy "$snap"
done

Verwenden Sie etwas schneller als SSH

Wenn Sie eine ausreichend gesicherte Verbindung haben, z. B. IPSec- oder OpenVPN-Tunnel, und ein separates VLAN, das nur zwischen Sender und Empfänger besteht, können Sie von SSH zu unverschlüsselten Alternativen wie mbuffer wechseln, wie hier beschrieben , oder SSH mit schwacher / keiner Verschlüsselung verwenden und deaktivierte Komprimierung, die hier detailliert beschrieben wird . Es gab auch eine Website über das Rekomilieren von SSH, um viel schneller zu sein, aber ich erinnere mich leider nicht an die URL - ich bearbeite sie später, wenn ich sie finde.

Bei sehr großen Datenmengen und langsamen Verbindungen kann es auch nützlich sein, die erste Übertragung über die Festplatte durchzuführen (verwenden Sie eine verschlüsselte Festplatte, um zpool zu speichern und in einem versiegelten Paket per Kurier, Post oder persönlich zu senden). Da die Übertragungsmethode für send / recv keine Rolle spielt, können Sie alle Daten auf die Festplatte leiten, den Pool exportieren, die Festplatte an das Ziel senden, den Pool importieren und anschließend alle inkrementellen Sends über SSH senden.

Das Problem mit kaputten Schnappschüssen

Wie bereits erwähnt, erhalten Sie beim Löschen / Ändern Ihrer Replikations-Snapshots die Fehlermeldung

cannot send 'pool/fs@name': not an earlier snapshot from the same fs

Dies bedeutet, dass entweder Ihr Befehl falsch war oder Sie sich in einem inkonsistenten Zustand befinden, in dem Sie die Schnappschüsse entfernen und von vorne beginnen müssen.

Dies hat mehrere negative Auswirkungen:

  1. Sie können einen Replikations-Snapshot erst löschen, wenn der neue Replikations-Snapshot erfolgreich übertragen wurde. Da diese Replikations-Snapshots den Status aller anderen (älteren) Snapshots enthalten, wird der leere Speicherplatz gelöschter Dateien und Snapshots nur dann wiederhergestellt, wenn die Replikation abgeschlossen ist. Dies kann zu vorübergehenden oder dauerhaften Speicherplatzproblemen in Ihrem Pool führen, die Sie nur durch einen Neustart oder Abschluss des vollständigen Replikationsvorgangs beheben können.
  2. Sie werden viele zusätzliche Snapshots haben, die den Befehl list verlangsamen (mit Ausnahme von Oracle Solaris 11, wo dies behoben wurde).
  3. Möglicherweise müssen Sie die Snapshots vor (versehentlichem) Entfernen schützen, außer durch das Skript selbst.

Es gibt eine mögliche Lösung für diese Probleme, aber ich habe es nicht selbst ausprobiert. Sie könnten zfs bookmarkeine neue Funktion in OpenSolaris / illumos verwenden, die speziell für diese Aufgabe erstellt wurde. Dies würde Sie von der Snapshot-Verwaltung befreien. Der einzige Nachteil ist, dass es derzeit nur für einzelne Datensätze funktioniert, nicht rekursiv. Sie müssten eine Liste aller Ihrer alten und neuen Datensätze speichern und diese dann durchlaufen, mit Lesezeichen versehen, senden und empfangen und dann die Liste (oder eine kleine Datenbank, wenn Sie dies vorziehen) aktualisieren.

Wenn Sie die Lesezeichenroute ausprobieren, würde mich interessieren, wie es für Sie geklappt hat!


Vielen Dank für diese ausführliche Antwort. Ich sende nur ... empfange a zpool.
Jitter

1
schönes Skript. Ich würde -d 1beide zfs listBefehle ergänzen , um die Suchtiefe zu begrenzen (es ist nicht erforderlich, unter dem Poolnamen zu suchen). Dies vermeidet lange Verzögerungen bei Pools mit vielen Snapshots (z. B. mein "Backup" -Pool enthält 320000 Snapshots und zfs list -r -t snapshot backupdie Ausführung dauert 13 Minuten. Mit dauert es nur 0,06 Sekunden -d 1). Der zfs destroyBefehl in der for-Schleife benötigt dann die -rOption, alle Snapshots mit demselben Snap-Namen rekursiv zu löschen.
cas

5

Persönlich würde ich mir eine Liste von Zvols, Datasets usw. auf dem Remote-Server erstellen, die keine aktuellen Snapshots enthalten, und diese Snapshots dann auf den neuesten Stand bringen zfs send, auch wenn dies zeitaufwändig ist und viel Zeit in Anspruch nimmt der Bandbreite.

Dann könnte ich einfach zfs sendvon da an weiterverwenden und müsste das Rad nicht neu erfinden, indem ich meinen eigenen Synchronisationscode schreibe. rsyncist nett für ältere Dateisysteme, aber zfs sendviel besser für zfs - es weiß genau, welche Blöcke sich im Snapshot geändert haben und sendet nur diese, während rsync einzelne Dateien und / oder Zeitstempel zwischen lokalen und entfernten Servern vergleichen muss. Gleiches gilt btrfs sendfür BTRFS-Pools.

Wenn Sie nur eine kleine Anzahl von Schnappschüssen haben, die aktualisiert werden müssen, kann dies manuell erfolgen. Andernfalls benötigen Sie eine Liste der neuesten lokalen Snapshots und Remote-Snapshots sowie ein Skript zum Vergleichen von Versionen und zfs sendlokalen Snapshots, die auf dem Remote-Server nicht mehr aktuell sind.

Dies reicht aus, wenn Sie sich nur um den neuesten Schnappschuss für jeden Datensatz kümmern. Wenn Sie sich für alle vorherigen Schnappschüsse interessieren, muss Ihr Skript natürlich auch damit umgehen ... und das wird VIEL komplizierter. In einigen Fällen müssen Sie möglicherweise ein Rollback auf dem Remoteserver durchführen, damit Sie die zwischenzeitlichen / fehlenden Snapshots erneut senden können.

Wenn Sie eine sichere Verbindung zum Remote - Server wollen, haben Sie wirklich keine andere Wahl , bekam aber zu verwenden ssh- oder vielleicht einen Tunnel mit einrichten openvpnoder etwas und Verwendung netcat.


Was ist mit Zrep? bolthole.com/solaris/zrep
Xdg

Keine Ahnung, habe es nie benutzt. sieht so aus, als wäre es eine gute Antwort, wenn jemand ein wenig recherchieren und testen und es aufschreiben würde (das ist ein Hinweis).
cas

Ich habe es unter Ubuntu (ZFS unter Linux) getestet und es funktionierte nicht auf tieferen Datensätzen (tank / something / someother). Ich habe diesen Port für die Shell- Verbindung verwendet . Die rekursive Flagge export ZREP_R=-Rfunktionierte überhaupt nicht. :(
Xdg

1

Schauen Sie sich 'zrepl' auf FreeBSD an, was Ihr Leben und das von anderen viel einfacher machen könnte. Es wurde vor einigen Tagen während der BSDCan2018 in Ottawa vorgestellt. Es sieht vielversprechend aus und kann eine Lösung für Ihre Probleme sein



Die Frage in der Frage lautet: "Wie richte ich eine Synchronisierungsaufgabe ein, damit die ZVOLs und Datasets des Remote-Pools (einschließlich ihrer Snapshots) mit den lokalen ZVOLs, Datasets und Snapshots synchronisiert werden können?"
Jeff Schaller

0

zrep ist eine nette All-in-One-Lösung und hat Dokumentation + Haken, wie man schnellere Übertragungen als nur einfache SSH-Übertragungen erhält

https://github.com/bolthole/zrep

es ist auch plattformübergreifend: unterstützt unter linux, freebsd und solaris / illumos



1
Die Frage in der Frage lautet: "Wie richte ich eine Synchronisierungsaufgabe ein, damit die ZVOLs und Datasets des Remote-Pools (einschließlich ihrer Snapshots) mit den lokalen ZVOLs, Datasets und Snapshots synchronisiert werden können?"
Jeff Schaller

Jeff, schlagen Sie vor, dass die beste "Antwort" darin besteht, Bits aus der zrep-Dokumentation auszuschneiden und einzufügen, anstatt nur einen Verweis auf zrep zu geben?
Philip Brown

1
Ich weiß nicht, was die beste Antwort wäre, aber eine Verknüpfung mit Software ist keine Lösung. Es wurde bereits erwähnt. Die Frage lautet: „Wie richte ich eine Synchronisierungsaufgabe ein, damit die ZVOLs und Datasets des Remote-Pools (einschließlich ihrer Snapshots) mit den lokalen ZVOLs, Datasets und Snapshots synchronisiert werden können?“
Jeff Schaller

ja das ist die frage. Um die Aufgabe GUT zu erfüllen, ist jedoch viel mehr als nur eine kurze Beschreibung auf einer Webseite erforderlich. Deshalb ist zrep ein Shellscript mit 2000 Zeilen. Selbst wenn man alle Teile entfernen würde, die das ursprüngliche Problem nie benötigt hätte, wären immer noch ein paar hundert Zeilen Skript erforderlich, um es GUT zu tun.
Philip Brown
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.