snapperで作ったスナップショットに戻したい
なにもなかったことにしたいとき、あります。
というわけでsnapperで取得したsnapshotの差分をとって…… というのではなく、まるごとそのまま前の状態にもどしましょう。
rootfs切り替え時の注意
RHELだと/bootはLVMで管理しない生 パーティションのため、この手法でロールバックされません。「カーネルやinitramfsが/bootに入っているが/lib/modules以下にカー ネルモジュールが入っていない」という状態になる可能性があります。root fsのmountまではinitramfsでできているはずなのでなんとかkernelパッケージを再インストールしてしのぎます。
snapperのメタデータは対象のディレクトリ直下にある .snapshots ディレクトリに作成されます。この情報も古い状態にもどってしまいますので、必要に応じてバックアップ&リストアするのがよいです。
snapperはスナップショットのlv名が衝突すると適当に数を大きくして競合しないように命名してくれるので、既にあるスナップショットを snapperが管理してくれなくなる(=古いスナップショットが消えないので容量の無駄になる)以外には大きな実害はありません。
snapperによって作成されるLVの属性を確認する
まずはsnapperが作成するLVの状態を確認します。
[root@localhost ~]# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
pool00 rhel twi-aotz-- 12.00g 10.85 18.55
root rhel Vwi-aotz-- 12.00g pool00 10.02
root-snapshot10 rhel Vri---tz-k 12.00g pool00 root
root-snapshot11 rhel Vri---tz-k 12.00g pool00 root
root-snapshot12 rhel Vri---tz-k 12.00g pool00 root
root-snapshot13 rhel Vri---tz-k 12.00g pool00 root
Vri—-tz-k というのが属性で、元々のroot fsであるVwi-aotz— というのとはちょっと違いますね。
man lvs 内に各フラグの意味が書いてあります。関係するところだけひっぱってきます
1 Volume type: thin (V)olume
2 Permissions: (w)riteable, (r)ead-only
3 Allocation policy: (i)nherited
4 fixed (m)inor ← なし
5 State: (a)ctive
6 device (o)pen
7 Target type: (t)hin; whereas snapshots of thin volumes using the new thin provisioning driver appear as (t).
8 Newly-allocated data blocks are overwritten with blocks of (z)eroes before use.
9 Volume Health: ← なし
10 s(k)ip activation: this volume is flagged to be skipped during activation.
rootと、root-snapshot10 を比べてみると「read-onlyでactiveではなく、openされておらず、activationのときにskipされる」というのが違いです。
つまりこれを普通のボリュームにするには、「writableに変更し、activationのときにスキップしないように変更する」必要があります。起動時に自動的にLVをactivationする処理により、activeとopenは勝手に設定されます。
普段はsnapshotのデバイスがずらずらと並んでも同じUUIDを持っていたりしてxfsの誤動作の元になったりするくらいでいいことがないのでskipにしてあります。
dracutによるinitramfsで、root fsをmountする前に停止する
「じゃあ一旦umountしてからlvchangeでフラグを変更して、lvrenameすればいいんだな……」となるわけですが、 root fsが含まれているので「一旦umountして」という処理がちょっと面倒になります。
RHELの6から採用されているdracutでは、 カーネルのコマンドラインオプションに rd.break=pre-mount とつけることでroot fsをマウントする直前のところで停止してshellに落ちてくれる便利機能がついています。(RHEL6だとすこしオプション名がちがってrdbreak=…です)
man dracut.cmdline より
rd.break={cmdline|pre-udev|pre-trigger|initqueue|pre-mount|mount|pre-pivot|cleanup}
drop to a shell on defined breakpoint
再起動して、grubのメニューから rd.break=pre-mount というオプションを一時的に追加することで、initramfsだけがマウントされている状態のシェルが起動します。
この環境ではlvchangeなどのコマンドはlvmの対話シェル内から打ちこみます。
lvmでの作業
デフォルトではinitramfs内でLVMのメタデータを変更しない設定になっているので、lvmでの作業前に /etc/lvm/lvm.conf 内の locking_mode = 4 となっている行を1に変更します。
lvmの中で以下のような変更をおこないます。今回はsnapshot10の状態に戻してみます。
lvm> lvrename rhel/root root-original
lvm> lvrename rhel/root-snapshot10 root
lvm> lvchange -k n rhel/root ← s(k)ip をはずす
lvm> lvchange -p rw rhel/root ← readwriteができるようにする
lvm> lvchange -k y rhel/root-original ← s(k)ipするようにする
lvm> lvchange -p ro rhel/root-original ← read only にする
lvm> exit
しくじると再起動するときにroot fsのmountに失敗してしまうので、随時lvsなどで思った通り操作できているか確認しましょう。
このあと reboot コマンドで再起動します。
再起動後
[root@localhost ~]# snapper create
[root@localhost ~]# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
pool00 rhel twi-aotz-- 12.00g 11.15 24.41
root rhel Vwi-aotz-- 12.00g pool00 root-original 10.00
root-original rhel Vwi---tz-k 12.00g pool00
root-snapshot11 rhel Vri---tz-k 12.00g pool00 root-original
root-snapshot12 rhel Vri---tz-k 12.00g pool00 root-original
root-snapshot13 rhel Vri---tz-k 12.00g pool00 root-original
root-snapshot14 rhel Vri---tz-k 12.00g pool00 root-original
root-snapshot15 rhel Vri---tz-k 12.00g pool00 root-original
root-snapshot16 rhel Vri---tz-k 12.00g pool00 root-original
root-snapshot17 rhel Vri---tz-k 12.00g pool00 root-original
root-snapshot18 rhel Vri---tz-k 12.00g pool00 root-original
root-snapshot19 rhel Vri---tz-k 12.00g pool00 root
root-snapshot9 rhel Vri---tz-k 12.00g pool00 root-original
swap rhel -wi-ao---- 2.00g
[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 | | |
single | 19 | | Tue May 19 18:48:48 2015 | root | | |
snapperはきれいさっぱり10から18までのことは忘れています。記録がないから当然ですね。
元LVの削除
もろもろ試して、うまいこと古い状態に戻せて いることが確認できたら、元のLVをlvremoveで削除します。
[root@localhost ~]# lvremove rhel/root-original
Logical volume "root-original" successfully removed
[root@localhost ~]# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
pool00 rhel twi-aotz-- 12.00g 11.07 22.66
root rhel Vwi-aotz-- 12.00g pool00 10.00
root-snapshot11 rhel Vri---tz-k 12.00g pool00
root-snapshot12 rhel Vri---tz-k 12.00g pool00
root-snapshot13 rhel Vri---tz-k 12.00g pool00
root-snapshot14 rhel Vri---tz-k 12.00g pool00
root-snapshot15 rhel Vri---tz-k 12.00g pool00
root-snapshot16 rhel Vri---tz-k 12.00g pool00
root-snapshot17 rhel Vri---tz-k 12.00g pool00
root-snapshot18 rhel Vri---tz-k 12.00g pool00
root-snapshot19 rhel Vri---tz-k 12.00g pool00 root
root-snapshot9 rhel Vri---tz-k 12.00g pool00
swap rhel -wi-ao---- 2.00g
Originの表記が消えたりしていますがやはりあまり実害はないので気にしない方向で… 。