ZFS プール全体を別の ZFS プールに一方向ミラーリングする方法

ZFS プール全体を別の ZFS プールに一方向ミラーリングする方法

複数の zvol とデータセットを含む 1 つの zfs プールがあり、その一部はネストされています。すべてのデータセットと zvol は、zfs-auto-snapshot によって定期的にスナップショットされます。すべてのデータセットと zvol には、手動で作成されたスナップショットもあります。

リモート プールをセットアップしましたが、時間が足りなかったため、zfs send -R によるローカル高速ネットワーク経由の初期コピーが完了しませんでした (一部のデータセットが欠落しており、一部のデータセットのスナップショットが古かったり欠落していたり​​します)。

現在、プールは低速接続を介して物理的にリモートにあり、リモート プールをローカル プールと定期的に同期する必要があります。つまり、ローカル プールにあるデータはリモート プールにコピーし、ローカル プールからなくなったデータはリモート プールから削除し、リモート プールにはあるがローカル プールにはないデータはリモート プールから削除する必要があります。ここでいうデータとは、「zvols」、「データセット」、または「スナップショット」のことです。

rsync を使用して 2 つの通常のファイルシステム間でこれを実行する場合は、「-axPHAX --delete」になります (これは、一部のシステムをバックアップするために実際に実行していることです)。

リモート プールの zvol とデータセット (そのスナップショットを含む) をローカルの zvol、データセット、スナップショットと同期できるように同期タスクを設定するにはどうすればよいですか?

ssh のスループット パフォーマンスが低いため、ssh 経由の転送は避けたいと思います。代わりに mbuffer または iscsi を使用します。

答え1

免責事項: 私は zvol を使用したことがないので、レプリケーションに関して通常のファイルシステムやスナップショットと何か違いがあるかどうかはわかりません。違うと思いますが、鵜呑みにしないでください。


あなたの質問は実際には複数の質問なので、個別に回答してみます。

プール全体をリモートの場所に複製/ミラーリングする方法

タスクを2つの部分に分割する必要があります。まず、初期レプリケーションを完了する必要があり、その後増分レプリケーションが可能になります。レプリケーションスナップショットをいじらない限り増分レプリケーションを有効にするには、最後のレプリケーション スナップショットを保存する必要があります。それ以前のものはすべて削除できます。以前のスナップショットを削除すると、 がzfs recvエラーを出してレプリケーションを中止します。この場合、最初からやり直す必要があるため、これを行わないようにしてください。

正しいオプションだけが必要な場合は、次のオプションを使用します。

  • zfs send:
    • -R: 指定されたプールまたはデータセットの下にあるすべてのものを送信します (再帰レプリケーション、常に必要、を含む-p)。また、受信時に、削除されたソース スナップショットはすべて宛先でも削除されます。
    • -I: 最後のレプリケーション スナップショットと現在のレプリケーション スナップショットの間のすべての中間スナップショットを含めます (増分送信の場合にのみ必要)
  • zfs recv:
    • -F: ソース上で削除された既存のデータセットの削除を含むターゲットプールの拡張
    • -d: ソース プールの名前を破棄し、宛先プールの名前に置き換えます (残りのファイル システム パスは保持され、必要に応じて作成されます)
    • -u: 宛先にファイルシステムをマウントしない

完全な例がお好みの場合は、次の小さなスクリプトをご覧ください。

#!/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

SSHよりも高速なものを使用する

IPSecやOpenVPNトンネルなど、十分に安全な接続と、送信者と受信者の間にのみ存在する別のVLANがある場合は、SSHからmbufferなどの暗号化されていない代替手段に切り替えることができます。ここで説明されているようにまたは、弱い/暗号化なし、圧縮無効のSSHを使用することもできます。詳細はここをご覧くださいSSH を再コンパイルしてさらに高速化するという Web サイトもありましたが、残念ながら URL を覚えていません。後で見つけたら編集します。

データセットが非常に大きく、接続が遅い場合は、最初の送信をハードディスク経由で行うことも有効です (暗号化されたディスクを使用して zpool を保存し、密封されたパッケージで宅配便、メール、または直接送信します)。送信方法は send/recv では重要ではないため、すべてをディスクにパイプし、プールをエクスポートし、ディスクを宛先に送信し、プールをインポートしてから、すべての増分送信を SSH 経由で送信できます。

スナップショットが乱れた場合の問題

前述のように、レプリケーションスナップショットを削除/変更すると、エラーメッセージが表示されます。

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

これは、コマンドが間違っているか、一貫性のない状態にあるため、スナップショットを削除して最初からやり直す必要があることを意味します。

これにはいくつかの否定的な意味合いがあります。

  1. 新しいレプリケーション スナップショットが正常に転送されるまで、レプリケーション スナップショットを削除することはできません。これらのレプリケーション スナップショットには、他のすべての (古い) スナップショットの状態が含まれているため、削除されたファイルとスナップショットの空き領域は、レプリケーションが終了した場合にのみ再利用されます。これにより、プールで一時的または永続的な領域の問題が発生する可能性があります。この問題は、完全なレプリケーション手順を再起動または完了することによってのみ解決できます。
  2. 追加のスナップショットが多数存在するため、list コマンドの速度が低下します (この問題は修正された Oracle Solaris 11 を除く)。
  3. スクリプト自体以外による(偶発的な)削除からスナップショットを保護する必要がある場合があります。

これらの問題には解決策がありますが、私は自分で試していません。zfs bookmarkこのタスク専用に作成された OpenSolaris/illumos の新機能である を使用できます。これにより、スナップショット管理から解放されます。唯一の欠点は、現時点では単一のデータセットに対してのみ機能し、再帰的には機能しないことです。古いデータセットと新しいデータセットのリストを保存し、それらをループしてブックマークし、送受信し、リスト (または必要に応じて小さなデータベース) を更新する必要があります。

ブックマークルートを試した場合、それがどのように機能したかをお聞かせください。

答え2

個人的には、リモートサーバー上のzvol、データセットなどのリストを自分で作成します。しない最新のスナップショットを用意し、zfs send時間がかかり、多くの帯域幅を消費するとしても、それらのスナップショットを で最新の状態にします。

そうすれば、その後も使い続けることができzfs send、独自の同期コードを書いて車輪の再発明をする必要がなくなります。rsync古いファイルシステムには適していますが、zfs sendzfsにははるかに優れています。その通りスナップショットで変更されたブロックを送信しますのみ一方、rsync はローカル サーバーとリモート サーバー間で個々のファイルやタイムスタンプを比較する必要があります。同じことがbtrfs sendbtrfs プールにも当てはまります。

最新の状態にする必要があるスナップショットが少数であれば、手動で行うことができます。それ以外の場合は、自動的に行うには、最新のローカル スナップショットとリモート スナップショットのリストと、バージョンを比較し、zfs sendリモート サーバー上の古いローカル スナップショットを比較するスクリプトが必要です。

各データセットの最新のスナップショットだけを気にするのであれば、これで十分です。以前のスナップショットをすべて気にするのであれば、当然スクリプトでそれらも処理する必要があります。そしてそれは非常に複雑になります。場合によっては、中間スナップショットや欠落スナップショットを再送信できるように、リモート サーバーでロールバックする必要があるかもしれません。

リモート サーバーへの安全な接続が必要な場合は、 を使用するか、 または何かを使用しsshてトンネルを設定して を使用する以外に選択肢はほとんどありません。openvpnnetcat

答え3

FreeBSD の「zrepl」を見てください。これは、あなたの生活、そして実際は誰の生活もずっと楽にしてくれるかもしれません。これは数日前にオタワで行われた BSDCan2018 で発表されました。これは有望に思え、あなたの問題の解決策になるかもしれません。

答え4

zrep は優れたオールインワンソリューションであり、単なる SSH 転送よりも高速な転送を実現する方法に関するドキュメントとフックを備えています。

https://github.com/bolthole/zrep

また、クロスプラットフォームです。Linux、FreeBSD、Solaris/Illumosでサポートされています。

関連情報