年をまたいでzfs send/receiveでファイルサーバをバックアップしてみた

結構ややこしい。慣れたり考え方を理解すれば楽勝だけど。ハマりポイントとしては以下のような感じか。

  • zfs sendできるのはスナップショットだけ。ライブのファイルシステムをコピーすることはできない。考えてみれば当然か。(コピー中にファイルシステムが変更されるとストリームとライブの整合性が失われる)
  • 2回目以降増分をzfs receiveするためには、受信側のライブファイルシステムが前回受信したスナップショットから変更されていてはいけない。これも考えてみればあたりまえ。ZFSは枝分かれスナップショットをサポートしていない(スナップショットからcloneしてpromoteすることで別ファイルシステムとすることはできるけど)。ロールバックでスナップショットに戻ることは可能。もちろんロールバックすると変更分は消える。

でも理屈が通っててわかると本当に気分がいい。ZFSがますます好きになった!順番に手順を書く。もっぱら将来の自分用に。

1. <送信側>スナップショットを取る

1
2
3
4
# zfs snapshot ore_no_tank@backup
# zfs list -t snapshot
NAME                                           USED  AVAIL  REFER  MOUNTPOINT
ore_no_tank@backup                                0      -  3.18T  -

詳細はOracleのZFS管理ガイドを見ればわかるが、REFERはそのファイルシステムが参照しているプール内のブロック(?)で、USEDは変更等の理由によりそのスナップショットから変更され、プール内のブロックを消費している量を指す。たぶん。

2. <送信側/受信側>zfs sendでスナップショットを送信する

スナップショットを送信する。ここではrootアカウントでやってるが、pfexecでやった方がいいのかもしれない。rootでのsshログインを許容するためにはユーザーロールを変更する(rolemod -K type=normal root)ことと、/etc/ssh/sshd_configでPermitRootLoginをyesにして、svcadm restart svc:/network/ssh:defaultする。(セキュリティが弱くなるのでちょう注意。作業が終わったら戻す方がいいよ)

1
# zfs send ore_no_tank@backup | ssh 192.168.xxx.xxx zfs receive -F ore_no_tank

-Fオプションで受信側のファイルシステムを強制的に置き換える。これ以降は受信側のファイルシステムには手で変更をくわえないようにする。といってもスナップショットにロールバックすれば元に戻るので。

送信後に受信側を見てみると、スナップショットも含めてコピーされていることがわかる。(zfs list -t snapshotしたときにUSEDに149Kのカウントされているのはスナップショット以降の変更分も一緒に受信しちゃってるのかもしれない。後ろの手順でやっている通り、一回zfs rollbackしておいたほうがいいかも)

1
2
3
4
5
6
# zfs list
NAME                       USED  AVAIL  REFER  MOUNTPOINT
ore_no_tank               3.41T  1.93T  3.18T  /ore_no_tank
# zfs list -t snapshot
NAME                             USED  AVAIL  REFER  MOUNTPOINT
ore_no_tank@backup               149K      -  3.18T  -

3. <送信側>再度スナップショット(増分スナップショット)を取る

容量が大きいファイルシステムや、複数で共有しているファイルシステムの場合、zfs send/receiveでコピーしている間にもいろいろファイルが作られたり消されたりする。その度にファイルシステム全体をコピーし直すのではいつまでたってもバックアップ先がバックアップ元と同期せずバックアップの意味がない。再度スナップショットを取って、差分だけバックアップ先に送るようにすればより頻繁にデータをバックアップできるチャンスが増え、より最新のデータに復元できたり、より精度高くデータを復元できる可能性が高まる。(例えば”先週のデータ”ではなくて、”昨日の15:30時点のデータ”とか)

送信側で再度スナップショットを取る。

1
2
3
4
5
# zfs snapshot ore_no_tank@backup2
# zfs list -t snapshot
NAME                                           USED  AVAIL  REFER  MOUNTPOINT
ore_no_tank@backup                            8.68G      -  3.18T  -
ore_no_tank@backup2                               0      -  3.18T  -

前回スナップショットを取ってから、8.68GB分の変更が発生していることがわかる。

4. <送信側/受信側>zfs sendで増分のみを送信する

再度スナップショットを送信する。送信側で"-i"オプションで増分計算元を指定していることと、受信側で"-F"オプションを外していることに注意。

1
# zfs send -i ore_no_tank@backup ore_no_tank@backup2 | ssh 192.168.xxx.xxx zfs recv ore_no_tank

増分を送信後に受信側の状態は以下のようになっている。増分のスナップショットが正しく展開されている。

1
2
3
4
5
6
7
# zfs list
NAME                       USED  AVAIL  REFER  MOUNTPOINT
ore_no_tank               3.42T  1.92T  3.18T  /ore_no_tank
# zfs list -t snapshot
NAME                             USED  AVAIL  REFER  MOUNTPOINT
ore_no_tank@backup                  8.67G      -  3.18T  -
ore_no_tank@backup2                     0      -  3.18T  -

zfs send/receiveした時に以下のようなエラーが出たら、受信側のファイルシステムが変更されている。zfs rollbackでスナップショットに戻ることで解決できる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<送信側>
# zfs send -i ore_no_tank@backup ore_no_tank@backup2 | ssh 192.168.xxx.xxx zfs receive ore_no_tank
cannot receive incremental stream: destination storage has been modified
since most recent snapshot
<受信側>
# zfs list -t snapshot
NAME                             USED  AVAIL  REFER  MOUNTPOINT
ore_no_tank@backup               149K      -  3.18T  -
# zfs rollback ore_no_tank@backup
# zfs list -t snapshot
NAME                             USED  AVAIL  REFER  MOUNTPOINT
ore_no_tank@backup              1.50K      -  3.18T  -
<送信側>
# zfs send -i ore_no_tank@backup ore_no_tank@backup2 | ssh 192.168.xxx.xxx zfs receive ore_no_tank
# (←成功したので何も出ない)

Happy ZFS !

comments powered by Disqus