2013年7月9日火曜日

rsnapshotによる差分バックアップ

はじめに

年々コンピューターの重要性が増し、今やデータのバックアップをとることは必須となって いますが、本当に大切なデータの場合、バックアップが1つだけでは不安ではあります。もし データが何らかの事情で壊れていて、それを古いバックアップの上に上書きしてしまったと なったらもう取り返しがつきません。そういう場合、変更したファイルのみ追記していく 差分バックアップを使用すれば少しは安心出来ます。
ということでちょうど一年前、共有のファイルサーバーのバックアップを差分で取ることに なりました。
差分バックアップを取るためのバックアップソフトが必要なりまりますが、 これもたくさん あり、どれを使うかという問題があります。初めて使うソフトなど本当にこれ取れてるのか と心配に思うこともあります。操作方法も簡単でないものも多いです。リストアの度に呼び 出されるなど、まっぴらごめんです。
フリーで使えるものには有名なものにrdiff-backupというものもあります。最新のファイル を取り出すにはいいのですが、古いファイルの場合コマンドを使用する必要があり、却下です。 (大きなファイルを扱う場合、後述のrsnapshotを使うより容量は小さくなるので、選択肢 としては悪くありません。)
理想として、Mac OS XのTime Machineは、使い勝手もよいですし、日付の入ったフォルダ に各バックアップが置かれるので古いバックアップを簡単に見ることができますが、Macで しか使えない問題があります。
ということで、今回はLinuxで使用出来るTime Machineに似たソフトrsnapshotについて 書いてみたいと思います。

rsnapshotについて

rsnapshotは名前の通り、サーバーからリモートコンピューターのファイルのスナップショット を取得します。もちろんリモートだけでなくローカルのファイルをバックアップすることも可能です。 サーバーといってもサービスを立ち上げるわけではなく、cron にでも登録し、 一定時間毎にバックアップコマンドを叩けばいいだけです。 スナップショットはディレクトリごとに置かれ、バックアップしたファイルがそのまま置かれるので、 通常のファイルとしてアクセスすることができます。
また、スナップショットを新しく作成する場合、古いスナップショットから変更のあった ファイルのみコピーし、変更のなかったファイルについては、古いスナップショットから ハードリンクを貼るということをします。ですので、変更の無いファイルについては、 バックアップ容量は必要ありませんし、スナップショット自体は通常のファイルシステム と同じようにアクセスできます。内部で使用しているコマンドもrsync, cp, mvなので、 何かあった際の調査もわりと簡単にすることができます。
rsnapshot を運用していくとバックアップ先のディレクトリには以下のように複数の種類 のスナップショットが作成されます。:
hourly.0  hourly.1 hourly.2 hourly.3 daily.0 daily.1 daily.2 daily.3 daily.4
weekly.0 weekly.1, weekly.2  weekly.3 weekly4 monthly.0 monthly.1 monthly.2
このhourlyというのは一時間ごと、 dailyというのは一日ごとにとったスナップショット です。同様にweeklyは一週間ごと、monthly.0は一ヶ月ごとです。各スナップショットの 後ろにある番号は0番が最新で、番号の大きいものほど古いスナップショットとなります。 ただしこの hourlyというのは自動的に作成してくれるわけではありません。 一時間ごとにrsnapshot hourlyというコマンドを打ち続けなければなりません。 dailyも同様で一日ごとにrsnapshot dailyを打たなければなりません。
なお、以下説明に入りますが、インストール方法はここでは書きません。 UNIX系のシステムであればインストール出来るはずです。 cygwin 版もあるので試しに使ってみるといいかもしれません。 あと、sshでリモートホストのファイルをバックアップできるはずですが、私の場合、 NFS でマウントした領域をバックアップ元・バックアップ先としているため、 試していないのでここでは書きません。
(バックアップと言う用語とスナップショットという用語が混ざっていますが、 全く考えなしに使っています。気にしないでください。)

バックアップ設定

まず、バックアップ元とバックアップ先を決めなければなりません。 そのためにはrsnapshotの設定ファイルに設定を書き込む必要があります。 /etc/rsnapshot.conf というファイルがあるはずです。 ない場合は、/usr/share/doc/rsnapshot* 以下にあるものを/etc以下にコピーする 必要があるかもしれません。
rsnapshot.conf に以下のようにバックアップ先のディレクトリを指定します。:
snapshot_root   /.snapshots/
次にバックアップ元を定義します。バックアップ元は以下のように定義します。 後ろの localhost/ はバックアップ先に作成するディレクトリです。 この下に元のファイルのあった場所のフルパスでファイルが置かれるのでlocalhost/の 部分はホストごとに共通で構いません。 バックアップ行は複数あればすべてバックアップ対象となります。:
backup  /etc            localhost/
通常スナップショットの作成に cp と rsync を使用します。 rsyncのバージョンが2.57以降であれば、link_dest を使用すると、 rsync のみでスナップショットの作成を行います。動作がわかりやすいので、 ここではlink_dest オプションをONにしておきます。 ( HowTo を見るとLinuxではこのオプションは特に推奨はしていないのかもしれません。 英語が読めません。):
link_dest   1
コピー動作
ここでrsnapshotを実行してみましょう。 オプション-vをつけると実行内容が詳しく表示されます。以下のように実行します。 (rsnapshotの前後の出力は省略しています。cygwinで実行):
$ rsnapshot -v hourly
/usr/bin/rsync -a --delete --numeric-ids --relative --delete-excluded /etc \
    /.snapshots/hourly.0/localhost/
$ ls /.snapshots/
hourly.0/
指定した/.snapshots 以下にhourly.0というスナップショットが作成され、 その中に/etcの内容がrsyncでコピーされました。(以降このコピー動作を同期(sync)と呼びます。) ではもう一度実行してみます。:
$ rsnapshot -v hourly
mv /.snapshots/hourly.0/ /.snapshots/hourly.1/
/usr/bin/rsync -a --delete --numeric-ids --relative --delete-excluded \
    --link-dest=/.snapshots/hourly.1/localhost/ /etc \
    /.snapshots/hourly.0/localhost/
$ ls /.snapshots/
hourly.0/ hourly.1/
    (前後の出力は省略しています)
今度は一番はじめにmvコマンドでhourly.0をhourly.1に退避してから、 hourly.0にファイルを同期しています。 スナップショットはhourly.0とhourly.1になりました。 hourly.0 が最新のスナップショットです。
ここでのrsyncコマンドは前回と違い–link-dest オプションが付与されています。 このオプションが付けられるとhourly.0からコピーするときにhourly.1のファイルと 同じであれば、そのファイルのハードリンクをhourly.0に置きます。 ハードリンクなので、どちらにアクセスしても同じファイルにアクセスできます。 気をつけるのはスナップショット内のファイルに書き込んではいけないということです。

スナップショット数の設定

上記でスナップショットを2回取得しましたが、上記の状態からrsnapshot hourlyを もう一度打つと、スナップショットはhourly.0 hourly.1 hourly.2となります。 このまま増えていくと際限なくスナップショットが増えてしまいます。 スナップショット数の制限については、rsnapshot.conf 内で以下のように指定します。 この場合hourlyは3つに制限されます。 次にrsnapshot hourlyを実行するとhourly.2はhoulry.3にならず消去されます。:
interval       hourly 3
interval       daily  4
interval       weekly 4
interval       monthly  2
コマンドの実行結果は以下です。:
$ ls /.snapshots/
hourly.0/  hourly.1/  hourly.2/
$ rsnapshot -v hourly
/usr/bin/rm -rf /.snapshots/hourly.2/
mv /.snapshots/hourly.1/ /.snapshots/hourly.2/
mv /.snapshots/hourly.0/ /.snapshots/hourly.1/
/usr/bin/rsync -a --delete --numeric-ids --relative --delete-excluded \
    --link-dest=/.snapshots/hourly.1/localhost/ /etc \
    /.snapshots/hourly.0/localhost/
 $ ls /.snapshots/
hourly.0/  hourly.1/  hourly.2/
   (出力は一部省略しています)
では、dailyバックアップをする場合はどうでしょうか。 hourly以外のdailyなどについては動作が少し異なります。 まず、dailyバックアップについてはdaily.0に同期するわけではなく、 hourlyの最後のスナップショットをdaily.0にリネームします。つまり上記の例で行くと rsnapshot dailyを実行すると、hourly.2がdaily.0にリネームされます。:
 $ rsnapshot -v daily
mv /.snapshots/hourly.2/ /.snapshots/daily.0/
$ ls /.snapshots/
daily.0/  hourly.0/  hourly.1/
    (出力は一部省略しています)
なお、ここでもう一度rsnapshot dailyを実行した場合、 先ほどのdaily.0の退避は行われますが、hourlyからdailyの移動はhourly.2が無いので エラーとなります。 hourlyが最大数まで達していないとdailyが作られないのは気をつける点です。:
 $ rsnapshot -v daily
mv /.snapshots/daily.0/ /.snapshots/daily.1/
/.snapshots/hourly.2 not present (yet), nothing to copy
    (出力は一部省略しています)
dailyが増えた場合の古いスナップショットの扱いについてはhourlyと同様です。 rsnapshot daily実行すると、daily.0をdaily.1にリネームし、hourly.2をdaily.0に リネームします。 weekly、monthly、yearlyも同様で、dailyの一番最後がweeklyに、 weeklyの一番最後がmonthly、monthlyの一番最後がyearlyにリネームされます。
1時間毎のバックアップが必要ない場合、interval hourlyの設定をコメントアウトすると dailyで同期が動くようになるので、hourlyは必要なくなります。
なお、私は以下の様な設定で使っています。:
interval        daily   7
interval        weekly  4
interval        monthly 12
interval        yearly  100

実行

rsnapshotの全体の動作は以上です。 後はcronに登録するだけです、 登録はcrontabに以下のように記述します。:
0 22 * * * root /usr/bin/rsnapshot daily
0 2 * * 0 root /usr/bin/rsnapshot weekly
0 3 1 * * root /usr/bin/rsnapshot monthly
0 4 1 1 * root /usr/bin/rsnapshot yearly

バックアップの失敗への対処

日々運用していくと同期の途中でコピーに失敗することは少なからずあるものです。 もし同期時点でバックアップに失敗すると不完全なままのスナップショットがhourly.0に 残ってしまいます。 やり直すためにrsnapshot hourlyコマンドを使用すると、 そのままではhourly.0はhourly.1にリネームされ、新しくhourly.0が作成されます。 もちろんこのhourly.1には失敗した不完全なスナップショットです。
これを正しくやり直すには、hourly.0を消して、古いスナップショットをすべて元の名前に 戻してやる必要があります。これではおちおち失敗もしてられません。 ということでこれを解決させるには、以下のオプションをつけてやります。:
sync_first      1
このオプションをつけた場合、まずrsnapshot syncコマンドで、「.sync」ディレクトリに 同期します。その次に通常どおりrsnapshot hourlyコマンドを使用すると「.sync」が 「hourly.0」にリネームされます。 この方法ならば、失敗してもrsynapshot syncコマンドを使用すれば、「.sync」ディレクトリに 対し再度rsyncがかかるので問題無くやり直すことができます。 重要なのはrsyncが正しく完了するまで、rsnapshot hourlyは使用しないことです。 通常モードとの運用の違いはhourlyコマンドの前に必ずsyncを実行してやることぐらいです。
ただしこれにはデメリットがあります。 使用するバックアップディスクの必要容量が.sync分多く必要になることです。
Note
なお、現在最新の1.3.1 より前のバージョンでこのオプションを前述のlink_dest と共に 使用しないでくださいバグがあります。
rsnapshotでははじめに古いスナップショットを消去します。バックアップが完全に完了 してないのに先に古いスナップショットが消されるのはやだという人は、 下のオプションをつけます。 ただし、これも1世代分バックアップディスクの容量が多く必要になります。 まあ、上のsync_firstをつければ、あまり必要ないオプションだと思います。:
use_lazy_deletes 1
同期中にファイルを移動させたりすると以下の警告が出ます。 リターンコードが0以外になるのでスクリプトから使用する際は気をつけましょう。:
WARNING: Some files and/or directories in /**** vanished during rsync operation

その他

スナップショットが溜まってきてディスク容量が圧迫してくると、 各スナップショットの容量が気になると思います。 以下のコマンドで簡単に容量が調べられます。:
# rsnapshot du
1.7M    /.snapshots/hourly.0/
48K     /.snapshots/hourly.1/
48K     /.snapshots/hourly.2/
48K     /.snapshots/daily.1/
1.9M    合計
これで各スナップショットの容量を表示させることができます。
デフォルトでは rsync はファイルの変更日付とサイズを見て転送するファイルを決めます。 心配な人は rsnapshot.conf に以下のオプションをつけると、 ファイルのチェックサムを比較して転送するので少し安心できるかもしれません。 ただし時間はとてもかかります。:
rsync_short_args    -ac
おわり。

0 件のコメント:

コメントを投稿