それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

Lvm Snapshotで稼働中OSや起動中VMのバックアップを取る。

Lvm Snapshot

スナップショットについて。

スナップショットを使うと、稼働中のVMのディスクイメージファイルをバックアップ取り出すことが出来ます。virsh snapshot だと qcow2 ディスクイメージファイルに書き込みが出来ず、virshだと仮想マシンのバックアップが作れず不便。lvm を使うとその点が解消される。

さらにルート・ファイルシステムのバックアップも可能。仮想マシンの親になっているOSのファイルをバックアップを取ることが出来る。これもとてもいい。

事前に必要なもの

lvm で構成したファイルシステムと、空き容量。空き容量が無いと使えないので注意。

lvm スナップショットのコマンド

スナップショットを作るには、LVMのコマンドを使います(要sudo)

スナップショットの作成

sudo lvcreate -s -L 5G -n my_snap /dev/vg0/lv0

スナップショットの一覧

sudo lvs  -S "lv_attr=~[^s.*]"

スナップショットの削除

スナップショットの削除をするときに確認が出てくる。-y をつければスキップできる

sudo lvremove  /dev/vg0/my_snap

スナップショットをオリジナルへ戻し

sudo lvconvert --merge  /dev/vg0/my_snap

スナップショットから戻すと、オリジナルはスナップショット時点に戻る。差分が多いと時間がかかる。マージ終了後はスナップショットはなくなります。稼働中(オンライン)マージは地獄を見そう

スナップショット作成直後

スナップショット作成直後は、スナップショットもオリジナルも同じ記憶域ブロックを参照しています。メインになるのはオリジナルです。スナップショットにソフトウェアから書き込まれることはありません。稼働中ソフトウェアが書き込むとオリジナルに変更が加わります。スナップショットは取得時点の参照を保持しています。

スナップショットの容量

スナップショットは、作成時点では同じブロックを指しています。容量は差分保持の上限容量です。

しばらく使っていると

しばらく使っていると、スナップショットがファイルを抱え込みます。

なぜなら、オリジナルが書き換わり、スナップショットだけが保持するからです。

オリジナルに変更が加わり、スナップショットにはバックアップが溜まります。このためておける上限が、スナップショットの容量になります。

takuya@:~$ sudo lvs
  LV              VG Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  lv              vg owi-aos--- 70.00g
  snap_2023_01_05 vg swi-aos--- 10.00g      lv     60.35

容量上限になると

容量上限に達したスナップショットは、もはや無意味です。オリジナルとの差分を保持できなくなっています。inactiveになっています、こうなるとマージによる復元は絶望的です。もしかしたら、スナップショットをマウントで取り出せるかもしれません。

容量上限になるようなスナップショットの利用は、時間と容量の無駄です。

スナップショットの活用例

lvm スナップショットを活用すると、バックアップがとても便利です。

libvirtd の仮想マシンに使う。

仮想マシン無停止でバックアップを取れます。

sudo lvcreate -s -L 5G -n snap01_05 /dev/vg/lv
sudo mount /dev/mapper/vg-snap01_05 /mnt
cd /mnt/var/lib/libvirt/images/
sudo rsync -avz ubuntu-01.qcow2 my-server:~/

スナップショット取得時点の仮想マシンのストレージが載っているブロックの参照がそのままコピーでき便利です。

仮想マシンが稼働中でも、更新はオリジナルに書かれます。スナップショットには取得時点の状態が保存されています。オリジナルへの更新差分がスナップショットに溜まって行きます。このおかげで無停止にバックアップが取れました。

ルートファイルシステムに使う。

そして、ルートファイルシステムも取り出すこともできそうです。

sudo lvcreate -s -L 5G -n snap20230105 /dev/vg/lv
sudo mount /dev/mapper/vg-snap_20230105 /mnt
tar cvzf - . | ssh server  'cat - > out.tar.gz '

ファイルを取り出すこと自体はできました。わたしは、復元をやったことがないのでここから復元ができるかわかりませんが。/usr,/etcなどの重要なファイルが取り出せて便利でした。スナップショット使わずに、rsync で持ち出しも不可能ではないですが、mountが複雑だと面倒なんですよね。スナップショットを使えばOSを停止せずにルート・ファイルシステムが取り出せます。スナップショットは無停止でルートが取り出せます。これ大事なので2回書きました。

データベースのバックアップ

他にも MySQLPostgreSQLなどのデータベースや、Gitlabなどのレポジトリを、無停止でバックアップを取り出す事ができます。

### スナップショット作成
sudo lvcreate -s -L 5G -n snap_2023_01_05 /dev/vg/lv  
## スナップショットをマウント
sudo mount /dev/mapper/vg-snap_2023_01_05 /mnt
## 無停止でバックアップ
rsync -av  /mnt/var/lib/mysql server:/nfs/mysql

これは、mysqldumpを使ったほうがいいと思うのですが。

スナップショットから取り出す注意点。

スナップショットを使えば、取得時点のブロックがあるので、ファイルとしてコピーできるので便利です。

ただし、スナップショット内部からスナップショット外部へコピーすると、ブロック割当の計算に時間がかかりますし、スナップショットとの差分が発生します。

### スナップショット作成
sudo lvcreate -s -L 5G -n snap_2023_01_05 /dev/vg/lv  
## スナップショットをマウント
sudo mount /dev/mapper/vg-snap_2023_01_05 /mnt
## 遅いバックアップ(スナップショットからオリジナルへ)
sudo rsync -avz /mnt/etc /tmp

上記のように、スナップショット内部から外部へコピーは、オリジナル側への書き込みであるため、オリジナルとスナップショットに差分が生じます、スナップショットの容量を蝕害します。スナップショットからデータ救出の際は、できる限り、別のブロックデバイスやネットワーク上へ転送したほうが無難です。

grub を使ってブート

ArchWikiによると、GRUBを使ってLVMのスナップショットを起動することも出来るらしい。LVM素晴らしい。

LVMは枯れた技術

LVMは登場から10年以上が経過し、十分に枯れた技術だと思います。ただSNS全盛期に枯れた技術になったのでWEBに情報が少なく、検索や活用例が思うように入手できずに困った。

私も、LVMを単なるディスクのストライプにしか使っていなかった。今後はもっと活用しておこうと思う。

スナップショット作成すら面倒

スナップショット作成し、マウントし、バックアップ取得、マウント解除、スナップショット削除という一連の手続きが、めんどくさいので、バックアップ手順だけにフォーカスしたい。とおもった。

バックアップ専用のライブラリを書いた。

GitHub - takuya/ruby-lvm-snapshot-wrapper: Wrapper for lvm, to use lvm snapshot.

スナップショットのことは考えずに、LVMの空き容量を確保しておく。あとはスクリプトを走らせるだけで、バックアップが取れるようにした。

require "takuya/lvm_snapshot"
LvmSnapShot = Takuya::LvmSnapShot
LvmSnapShot.new('vg0').enter_snapshot{
    ## ブロック内はスナップショットが有効
    FileUtils.cp_r('/mnt/var/lib/mysql', '/nfs/backup/mysql')
    ## 仮想マシンも無停止でバックアップが取れる!
    FileUtils.cp_r('/mnt/var/lib/libvirt/images', '/nfs/backup/vm-images')
}
## ブロック出るとスナップショットは削除されている。

参考資料