操作ミスや事故等、何らかの理由で過去の任意の時点のファイルをリストアしたくなることは、たまに起こる。自分自身でやらかす場合もあるし、一般ユーザー (=家族) が救済を求めて来ることもある。僕は過去に何度か痛い目に遭った教訓からかなり入念なバックアップ体制を敷いているので、今は大概のトラブルには耐えられると思うが、たかが数個のファイル、数 KB のテキストデータ 1個をリストアするのに GB 単位のアーカイブを展開しなければならない (ディスク容量節約のため、バックアップデータは DAR + gzip で圧縮してある) と言うのは、けっこうダルい。
そこでファイル単位で過去の任意の時点に戻るリストアが気楽にできるように、DAR による通常のバックアップと並行して、LVM のスナップショットを利用した簡易的なバックアップを導入してみることにした。「過去の任意の時点に戻る」 のは Subversion や Git (読みは 「ギット」。「ジット」 に非ず) のようなバージョン管理ツールが得意とするところだが、保護したいデータはテキストデータだけではないし、データがテキストだけでもユーザーに新たなツールの使用方法習得を強いるのは極力避けたいので、今回はアウト。
具体的には、まず保護したい論理ボリューム (以下 LV) 単位で定期的にスナップショットを取得して、任意のディレクトリに読み取り専用でマウントする。このディレクトリ名は LV 名やスナップショット取得時刻を元に、「どの時点の状態か」 が一目でわかる名前を機械的に生成する。
作成するスナップショットのサイズは、オリジナル LV と同サイズが理想だが、それでは LV のスナップショットを定期的に作成して一定期間保管すると言う本システムの性質上、ボリューム・グループ (以下 VG) の空き容量がすぐに尽きてしまう。従って、LV ごとにデータが更新される頻度、更新されるファイルのサイズの傾向をつかみ、スナップショットの作成頻度、保管期間を考えながら、必要最低限のサイズを算出する。例えば、ある LV はプログラムのソース等テキストデータが中心で、バックアップは 1時間ごとに作成して 8世代保管するので、スナップショットのサイズは LV の 1/20 で十分。一方別の LV は数十~数百 MB の 3D モデルや画像データを編集することが多く、バックアップは 1時間ごとに作成して 6世代保管するので、スナップショットのサイズは LV サイズの 1/5 程度必要、と言った具合だ。
尚 LVM は、オリジナル LV 内のデータに更新が発生した際、変更前のデータを各スナップショットにコピーする。VG に空き容量があるからと言って調子に乗ってスナップショットを作り過ぎると、この元データ退避のオーバーヘッドが問題になりそうなので (どの程度で影響があるかは未検証)、スナップショットの作成頻度や保管世代数は、冷静に計画した方がいいと思う。
上記作業の事前準備として、スナップショットをマウントするディレクトリの上の階層のディレクトリを Samba 共有フォルダーとして Windows から任意のネットワーク・ドライブとしてマウントするか、既存の Samba 共有フォルダー内からシンボリック・リンクを作成しておくと、自動生成&マウントされるスナップショットに対して、ファイル単位のアクセスが可能になる。アクセス権をユーザーやグループ単位で細かくコントロールする場合は、ディレクトリのマウント方法やシンボリック・リンクの張り方で、もうひと工夫必要になる。
あとは一定期間または一定個数以上の古いスナップショットを削除するところまでスクリプトで自動化できれば、cron に登録して完了。
自動取得した LV "works" のスナップショット群を Windows XP から見た例
これをもっと洗練させて、スカしたインターフェイスでラッピングすると、Mac OS X の Time Machine のパクリ的な機能が実現できそうな気がする。時間も気力もスキルもないので、多分挑戦しないと思うが・・・。
「複数世代のデータをバックアップ」 と言っても、LVM のスナップショットはオリジナルの LV が正常であることが前提で、この方法はあくまでも 「ファイル単位でのリストアを容易にする」 ための簡易バックアップに過ぎない。LV や VG の破損、ディスク障害に備えた通常のバックアップは従来通り必要なので、同様の手法を試してみる場合は、それで安心してしまわないようにご注意を。