Red Hat Enterprise Linux 7でスナップショットとり放題生活をしてみよう

ゲストブログ
Red Hat Enterprise Linux 7ではスナップショットを低いコストで実現するLVM thin provisioningによる論理ボリュームがサポートされています。この記事ではLVM thin provisioning環境へのインストールと、基本的なスナップショットの作り方を説明したのち、定期的なスナップショットの取得やファイルの差分取得を簡単にできるsnapperを紹介します。

レッドハットの森若です。

今回はRed Hat Enterprise Linux 7で登場したLVM thin provisioningによるスナップショットのサポートと、このスナップショットを活用するsnapperをご紹介します。

インストール

RHEL7のインストーラではインストール対象としてLVM thin provisioningが選択できるようになっています。ここを選択して、容量を設定することでこの後説明するスナップショット機能が利用できるようになります。

状態を確認

操作する前にlsblkコマンドで現在の状態を確認しましょう。
[root@localhost log]# lsblk
NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                       8:0    0   20G  0 disk 
├─sda1                    8:1    0  500M  0 part /boot
└─sda2                    8:2    0 16.4G  0 part 
  ├─rhel-swap           253:0    0    2G  0 lvm  [SWAP]
  ├─rhel-pool00_tmeta   253:1    0   12M  0 lvm  
  │ └─rhel-pool00-tpool 253:3    0   12G  0 lvm  
  │   ├─rhel-root       253:4    0   12G  0 lvm  /
  │   └─rhel-pool00     253:5    0   12G  0 lvm  
  └─rhel-pool00_tdata   253:2    0   12G  0 lvm  
    └─rhel-pool00-tpool 253:3    0   12G  0 lvm  
      ├─rhel-root       253:4    0   12G  0 lvm  /
      └─rhel-pool00     253:5    0   12G  0 lvm  
sr0                      11:0    1  3.6G  0 rom  

[root@localhost log]# lvs
  LV     VG   Attr       LSize  Pool   Origin Data%  Meta%  Move Log Cpy%Sync Convert
  pool00 rhel twi-aotz-- 12.00g               9.38   5.18                            
  root   rhel Vwi-aotz-- 12.00g pool00        9.38                                   
  swap   rhel -wi-ao----  2.00g
lsblkに同じエントリ(rhel-rootとrhel-pool00)が2回でているので不安になるかもしれません。tmetaの方はメタデータ、tdataの方は実際のデータがはいっていてこの2つの組み合わせでrhel-rootとrhel-pool00が実現されています。
この例では12GBのpool00の下に12GBということになっているrootが含まれている状態です。
プールの詳細は、lvdisplayコマンドで確認します:
  [root@localhost log]# lvdisplay /dev/rhel/pool00 
  --- Logical volume ---
  LV Name                pool00
  VG Name                rhel
  LV UUID                vuooGK-VHow-JfAo-cPQb-Egf1-fCk4-qRpLqK
  LV Write Access        read/write
  LV Creation host, time localhost, 2015-05-15 19:15:03 +0900
  LV Pool metadata       pool00_tmeta
  LV Pool data           pool00_tdata
  LV Status              available
  # open                 2
  LV Size                12.00 GiB
  Allocated pool data    9.38%
  Allocated metadata     5.18%
  Current LE             3072
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           253:3
これで、lvmにより任意のタイミングでsnapshotをとり放題です。以下のようなコマンドでスナップショットを作成できます。
 # lvcreate --permission r --snapshot --name snapshot rhel/root 

snapperの初期設定

ここまででsnapshot作り放題なのは良いのですが、lvcreateで都度作成するのはスナップショットの名前を指定したり、定型的なオプションを指定する必要があるため煩雑です。そのためRHEL7には、SUSE出身のsnapperが含まれています。とても便利ですのでここからはsnapperをご紹介していきましょう。
まずは管理対象のディレクトリ(通常はマウントポイント)毎にsnapperの設定を作成します。デフォルトだと “root” という名前の設定で、それ以外だと-c “設定名” のようにオプションをつけて実行します。
[root@localhost ~]# snapper create-config -f 'lvm(xfs)' / 
このコマンドにより /etc/snapper/configs/rootに設定本体が作成され、
さらに設定一覧が /etc/sysconfig/snapper にあるのでここに設定名が追加されます。
snapperが持っている設定の一覧を確認します。”root”設定があるのがわかります。
[root@localhost log]# snapper list-configs 
Config | Subvolume
-------+---------- 
root | / 

snapshot作成

ここまで準備をするとスナップショットの作成は簡単。snapper createコマンドを実行するだけです。
 [root@localhost log]# snapper create 
様子を確認します。
[root@localhost log]# snapper list
Type   | # | Pre # | Date                     | User | Cleanup | Description | Userdata
-------+---+-------+--------------------------+------+---------+-------------+---------
single | 0 |       |                          | root |         | current     |         
single | 9 |       | Mon May 18 18:15:10 2015 | root |         |             |         

[root@localhost log]# lvs
  LV             VG   Attr       LSize  Pool   Origin Data%  Meta%  Move Log Cpy%Sync Convert
  pool00         rhel twi-aotz-- 12.00g               10.00  5.73                            
  root           rhel Vwi-aotz-- 12.00g pool00        10.00                                  
  root-snapshot9 rhel Vri---tz-k 12.00g pool00 root                                          
  swap           rhel -wi-ao----  2.00g
この例では、root-snapshot9 という名前のスナップショットが作成されています。snapperでは元の論理ボリュームのあとに”-snapshot<スナップショット番号>”をつけた名前を生成し、自動的に名付けてくれます。さらにスナップショット作成時刻や、オプションで指定することで任意のメモを付与することができます。

スナップショットのマウント

復旧作業を行うような場合には、スナップショットをマウントして、中のファイルやディレクトリを利用できます。
snapper mount サブコマンドにスナップショット番号をオプションとして指定することで、readonlyでmountすることができます。
管理対象ディレクトリ以下の、.snapshotディレクトリに例のようなディレクトリが作成され、mountされます。
以下の例ではスナップショット 10番をマウントし、dfコマンドでマウントされていることを確認しています。
[root@localhost ~]# snapper mount 10 

[root@localhost ~]# df

Filesystem                        1K-blocks    Used Available Use% Mounted on
/dev/mapper/rhel-root              12571648 1226516  11345132  10% /
devtmpfs                            1931348       0   1931348   0% /dev
tmpfs                               1941204       0   1941204   0% /dev/shm
tmpfs                               1941204    8580   1932624   1% /run
tmpfs                               1941204       0   1941204   0% /sys/fs/cgroup
/dev/sda1                            508588  168516    340072  34% /boot
/dev/mapper/rhel-root--snapshot10  12571648 1193528  11378120  10% /.snapshots/10/snapshot 

snapshot間の差分

snapperではsnapshotと現在のファイルシステムの分を取る仕組みがあります。
仕組みは簡単で、一時的なディレクトリにmountしておいてdiffを実行しています。
さらにスナップショットの属性としてpreとpostというタイプが導入されています。スナップショットの仕組み自体は同じなのですが、なんらかの作業前にpreスナップショットを取得、作業後にpostスナップショットを取得してペアにしています。postスナップショットを作成すると、snapperが自動的に対応づけられたpreスナップショットとの差分をバックグラウンドで取得し、作業によるファイル変更情報をまとめます。
preスナップショット作成
[root@localhost ~]# snapper create -t pre 
 [root@localhost ~]# snapper list Type   | #  | Pre # | Date                     | User | Cleanup | Description | Userdata -------+----+-------+--------------------------+------+---------+-------------+--------- single | 0  |       |                          | root |         | current     |          single | 9  |       | Mon May 18 18:15:10 2015 | root |         |             |          pre    | 10 |       | Mon May 18 18:18:32 2015 | root |         |             |
適当にファイルを変更
[root@localhost ~]# rm hoge 
rm: remove regular empty file ‘hoge’? y 
preスナップショット10番に対応するpostスナップショットを作成
[root@localhost ~]# snapper create -t post --pre-number=10

[root@localhost ~]# snapper list
Type   | #  | Pre # | Date                     | User | Cleanup | Description | Userdata
-------+----+-------+--------------------------+------+---------+-------------+---------
single | 0  |       |                          | root |         | current     |         
single | 9  |       | Mon May 18 18:15:10 2015 | root |         |             |         
pre    | 10 |       | Mon May 18 18:18:32 2015 | root |         |             |         
post   | 11 | 10    | Mon May 18 18:19:42 2015 | root |         |             |
差分の確認
[root@localhost ~]# snapper status 10..11
-..... /root/hoge
c..... /var/log/messages
c..... /var/log/snapper.log

差分対象の制限(フィルタ)

さきほどの例をみると、hogeファイルが消えているのと、/var/log以下のログが増えていることが表示されます。
ログの差分をとってもあまり嬉しくないような場合は、/etc/snapper/filters/ に、log.txtという名前で以下のようなファイルを作成します。このfilterディレクトリ内のファイルで指定されたパターンにマッチするファイルは差分チェックの対象になりません。
差分対象の制限
 /var/log/* 
差分の確認ふたたび
 [root@localhost ~]# snapper status 10..11
 -..... /root/hoge 

undochange

差分がとれるので、patchコマンドの要領でundoができます。
ただこのundoをした時に一貫性があるのか、もろもろ大丈夫なのかなどは特に保証されていませんので注意が必要です。この例では削除されたファイル “hoge” がスナップショットからコピーされて復旧します。
 [root@localhost ~]# snapper undochange 10..11
 create:1 modify:0 delete:0 

関連ドキュメント

snapperにはこの他にも定期的にsnapshotをとっておいて、過去数回分を残しておくなどの機能があります。ここでは説明できなかった点も多数ありますので、関連するドキュメントへのリンクを以下に記載します。