FreeNAS の ZFS Snapshot からファイルを復元する方法

FreeNAS ではファイルシステムとして ZFS を採用しているため、ZFS の一機能である snapshot が利用できます。オペミスやプログラムのバグによる意図しない操作が起因のデータ損失に備えることができそうです。

FreeNAS の Web UI を利用すれば、定期的なスナップショットタスクを設定すること自体はそれほど難しい操作は必要ではありません。しかし、古いスナップショットに含まれるファイルをどのように取り出すかがわからなかったので調べてみました。

スナップショットの時点までデータセットをロールバックする方法

あるスナップショットの時点までデータセットの内容を丸ごと元に戻す方法です。zfs コマンド と Web UI のどちらからでもロールバックすることが可能です。

# スナップショットの一覧を確認
[user@freenas] /% zfs list -t snapshot
NAME                                            USED  AVAIL  REFER  MOUNTPOINT
freenas-boot/ROOT/default@2016-11-01-06:40:09  2.96M      -   620M  -
volume0/data@auto-20161106.1423-2w             2.00K      -  18.7M  -
volume0/data@auto-20161106.1440-2w             2.00K      -  18.7M  -
volume0/data@auto-20161106.1445-2w                 0      -  18.7M  -
volume0/data@auto-20161106.1450-2w                 0      -  18.7M  -
volume0/data@auto-20161106.1455-2w                 0      -  18.7M  -
volume0/data@auto-20161106.1500-2w                 0      -  18.7M  -
volume0/data@auto-20161106.1505-2w                 0      -  18.7M  -
volume0/data@auto-20161106.1510-2w                 0      -  18.7M  -

# 最新の snapshot にロールバック可能
[user@freenas] /% sudo zfs rollback volume0/data@auto-20161106.1510-2w

ただし、ロールバックすることができるのは、最後に作成されたスナップショットとなり、それより古い世代のスナップショットにはロールバックできないようです。Web UI の場合は古いスナップショットにはロールバックボタンが表示されず、コマンドの場合はエラーとなります。

# 最新の snapshot より古い世代にロールバックしようとするとエラーとなる
[user@freenas] /% sudo zfs rollback volume0/data@auto-20161106.1445-2w
cannot rollback to 'volume0/data@auto-20161106.1445-2w': more recent snapshots or bookmarks exist
use '-r' to force deletion of the following snapshots and bookmarks:
volume0/data@auto-20161106.1505-2w
volume0/data@auto-20161106.1510-2w
volume0/data@auto-20161106.1500-2w
volume0/data@auto-20161106.1450-2w
volume0/data@auto-20161106.1455-2w

コマンドによるロールバックの場合は -r オプションを使うことで、途中のスナップショットを削除して指定したスナップショットの時点に強制的にロールバックすることが可能です。

# -r オプションで途中のスナップショットを削除して強制的にロールバックすることが可能
[user@freenas] /% sudo zfs rollback -r volume0/data@auto-20161106.1445-2w

.zfs/snapshot を参照しファイルを取り出す方法

ZFS Snapshot は、データストアのマウントポイント以下の .zfs/snapshot に展開されています。後から特定のファイルだけ復旧という使い方が可能です。SSH で FreeNAS サーバにログインすることで、通常のディレクトリと同様に cdcp コマンドが使えます。

しかし、デフォルトではマウントポイント配下で ls -a などをしても .zfs ディレクトリとして見えないようになっているようで、シェルのディレクトリ名補完も使えないので少々使いづらいです。

# .zfs が見当たらない
[root@freenas] ~# cd /mnt/volume0/data
[root@freenas] /mnt/volume0/data# ls -la
total 26
drwxr-xr-x  3 user  user   3 Nov  4 23:46 ./
drwxr-xr-x  5 root  wheel  5 Nov  1 23:33 ../
drwxr-xr-x  4 root  user   8 Nov  4 23:46 dir/

# ls では見えないが存在する模様
[root@freenas] /mnt/volume0/data/.zfs% ls
./        ../       shares/   snapshot/

また、ネットワーク経由でファイル共有を行っている場合、クライアント側でマウントしたデータストアでは .zfs/snapshot を正常に参照できないという問題もあるようです。

# OS X で AFP mount して snapshot ディレクトリへ移動しようとするとエラー
% cd /Volumes/data/.zfs/snapshot/auto-20161103.1538-2w
cd: is a directory: /Volumes/data/.zfs/snapshot/auto-20161103.1538-2w

Unable to browse snapshot directory via AFP

I can navigate to the .zfs folder and display the content: ls -al total 0 dr-xr-xr-x 1 peter staff 264 6 Sep 12:48 . drwx------ 1 peter staff 264 6 Sep 14:50 .. dr-xr-xr-x 1 peter...

デフォルトの設定では .zfs ディレクトリは不可視の状態になっているようです。 フォーラムの内容を参考に zfs set コマンドでスナップショットディレクトリが見えるよう設定変更を行います。これで通常の隠しディレクトリと同様に ls -la でディレクトリが見えるようになりました。ネットワーク共有した場合でも、クライアント側からスナップショットディレクトリを参照することができます。

[root@freenas] ~# zfs set snapdir=visible volume0/data
[root@freenas] ~# cd /mnt/volume0/data
[root@freenas] /mnt/volume0/data# ls -la
total 26
drwxr-xr-x  4 user  user   3 Nov  4 23:46 ./
drwxr-xr-x  5 root  wheel  5 Nov  1 23:33 ../
dr-xr-xr-x  4 root  wheel  4 Nov  1 23:33 .zfs/
drwxr-xr-x  4 root  user   8 Nov  4 23:46 dir/

まとめ

ドキュメントでは .zfs/snapshot にスナップショットが置かれていると書かれていたのですが、デフォルトの状態では見当たらないのでハマりました。

個人的には「ミスって必要なファイルを削除してしまい復元したい」という状況をカバーしたいので、スナップショットディレクトリを可視状態にして、必要なファイルのみ cp する使い方をしてみようかと思います。


comments powered by Disqus