qemu-img で スナップショットを取り扱う
Snapshot を使って仮想マシンを管理したいなと。
snapshot / qcow2
仮想マシンの状態保存する機能。
kvm + qemu / qcow2 で使える。qcow2 を使う場合に使える。
qcow2 のストレージでサポートされていて、qcow-img で管理する。
今回は、libvirt や qemu 自体のスナップショット関連機能は言及しない。
qcow2 / qcow-img に絞り仮想マシンのスナップショットを管理する方法を記載する。
qcow2 機能 cow とスナップショット
qcow の cow は copy on write の略称である。copy on write は、書き込み時にコピーし新領域に書き込む。つまり、古いデータを残せるってことよ。だからスナップショットを作れる。btrfs はFS自体に同じ機能を持ってるので、qcow2 をbtrfs 上につくる、qcow2 内部をbtrfs にすると無駄処理が増えてパフォーマンスは劣化する。(といっても現代はnvme ssd 数Gbps とかだし気にならない・・・はず)
qcow2 スナップショットの使い方
スナップショットは、qcow2 のファイル内部に保存される。
スナップショット一覧 -l
qemu-img snapshot -l name.qcow2
スナップショット作成 -c
名前を指定して作成
qemu-img snapshot -c 1.0.0 name.qcow2 qemu-img snapshot -c base name.qcow2
スナップショット選択 -a
apply / 名前を指定してそのバージョンのスナップショットを使う。
qemu-img snapshot -a testing name.qcow2
name.qcow2は スナップショット取得時に巻き戻される。
スナップショット削除 -d
名前を指定して削除
qemu-img snapshot -d 1.0.1 name.qcow
スナップショットからスナップショットを作成
スナップショットからスナップショットを起動するとは
- スナップショットの状態に戻す
- 戻した状態で起動する
- 別のスナップショットとして保存する。
ただし、スナップショットは単体でスナップショットであり、qcow2ファイルに親子関係は存在しない。単にスナップショットが増えるだけである。 スナップショットが複数ある状態になる。親子関係は名前を使い、自分で管理する。
スナップショットからスナップショットを作る(流れ)
わりやすさのため名前を番号にした。
スナップショットからスナップショットを作成する場合
qcow2 -> 1.0.0 -> 1.0.1 -> 1.0.2 └─ 2.0.0 -> 2.0.1
いったん、スナップショットを適用して作るといい
1.0.0 -> 1.0.1 -> 1.0.2 と順番に保存する時
qemu-img -c 1.0.0 name.qcow2 do something qemu-img -c 1.0.1 name.qcow2 do something qemu-img -c 1.0.2 name.qcow2
現在状態を捨てて 1.0.0 -> 2.0.1 と一旦戻して作る時
qemu-img -a 1.0.0 name.qcow2 do something qemu-img -c 2.0.0 name.qcow2
一旦スナップショットの状態に戻して起動、なんか作業をして、新しいスナップショットとして保存する。これが一連の流れになる。
スナップショットを単一ファイルにする
convert を使う
qemu-img -a 1.0.0 name.qcow2 qemu-img convert name.qcow2 -O qcow2 name-1.0.0.qcow2
スナップショットを単一のqcow2 ファイルとして取り出すことができる。コピーして取り出すことができる。
qcow2 スナップショットの制限
qcow2 のスナップショットは、 qemu-img で管理する。
qemu-img が qcow2 のストレージを直接扱うため、qcow2 に安全に書き込める必要がある。
つまり、qcow2 snapshotにはシャットダウンが必要である。
実験してみる
使い方がわかったので、ちょっと実験してみよう
仮想マシンの準備
virt-install とpreseedでサクッとインストールしておく
virt-install \ --connect=qemu:///system \ --graphics none \ --location http://ftp.kddilabs.jp/pub/Linux/distributions/Debian/debian/dists/buster/main/installer-amd64/ \ --extra-args="console=ttyS0" --ram 4096 \ --vcpus 8 \ --virt-type kvm \ --os-type linux \ --os-variant debian10 \ --name d01-manual \ --disk path=/var/lib/libvirt/images/d01.qcow2 \
インストールの自動化の細かいやり方は、別記事に書いた
vm の開始と接続
vm を開始し接続する
$ sudo virsh start d02 $ sudo virsh console d02 Debian GNU/Linux 10 d02 ttyS0 d02 login: takuya takuya@d02:~$ ls -lt total 0
そして、なにか作業(アップデートなど)をする
vm の強制終了
sudo virsh destroy d02
作業終了したら、シャットダウンする。
スナップショットを作る
必ず、停止してから行う。
$ sudo qemu-img snapshot -c 1.0.0 /var/lib/libvirt/images/d02.qcow2 $ sudo qemu-img snapshot -c 1.1.0 /var/lib/libvirt/images/d02.qcow2
スナップショットを作ったのを確認
$ sudo qemu-img snapshot -l /var/lib/libvirt/images/d02.qcow2 Snapshot list: ID TAG VM SIZE DATE VM CLOCK ICOUNT 1 1.0.0 0 B 2022-04-21 14:50:34 00:00:00.000 0 2 1.1.0 0 B 2022-04-21 14:51:00 00:00:00.000 0
スナップショットに入る。
スナップショットの状態で起動する
sudo qemu-img snapshot -a 1.1.0 /var/lib/libvirt/images/d02.qcow2 sudo virsh start d02
起動したら、スナップショット状態がわかるようにファイルを書いておく。
$ sudo virsh consle d02 Debian GNU/Linux 10 d02 ttyS0 d02 login: takuya Password: Linux d02 4.19.0-20-amd64 #1 SMP Debian 4.19.235-1 (2022-03-17) x86_64 takuya@d02:~$ ls -alt takuya@d02:~$ touch snapshot-1.1.0 takuya@d02:~$ sudo shutdown -h now
再起動してもデータが残ることを確認
$ sudo virsh start d02 $ sudo virsh consle d02 d02 login: takuya Password: Last login: Fri Apr 22 15:18:41 JST 2022 on ttyS0 takuya@d02:~$ ls -l total 0 -rw-r--r-- 1 takuya takuya 0 Apr 22 15:19 snapshot-1.1.0
スナップショットを切り替える
スナップショットを切り替えると、データが消えることを確認
sudo qemu-img snapshot -a 1.1.0 /var/lib/libvirt/images/d02.qcow2 sudo virsh start d02 d02 login: takuya Password: Last login: Fri Apr 22 15:18:41 JST 2022 on ttyS0 takuya@d02:~$ ls -l total 0 takuya@d02:~$ ls -l
snapshotは特定の状態に戻す機能
次のように、Aから Aダッシュまで、複数個のスナップショットを作っていたとして
A → A'→ A''→ A'''
A' を消したら A'' が辿れなくなるというわけでない
Aから派生したA'で、A' から派生したA''だとしても、スナップショットは仮想マシンのその時の状態を保存するものである。
したがってA''は単体スナップショットである。
A→A'の差分を保存しているわけではない。A'の状態を保存しているのである。なのでqcow2スナップショットに親子関係はなく、親子関係は利用者が覚えている限りである。
と考えるのが正しかろう
SnapShot で取り出し
スナップショットを適用する次のコマンド は 1.1.0
の状態に「復元」している
sudo qemu-img snapshot -a 1.1.0 /var/lib/libvirt/images/d02.qcow2
ファイルシステム状態は、その時の状態にきれいに戻る。
snapshots [ A, A'', C, B, A'] ↑ qcow2
スナップショット同士には、相互に順番がない。スナップショットは、順不同でグチャッとqcow2保存されていると考えたらイメージしやすいと思う。あの時のあの状態で保存、名前をつけた時の状態へ戻す。っていう感じです。
スナップショットを取り出したあと、起動したら、起動時の状態はスナップショットより進んだ状態になる。
A → A'→ A''→ A'''
のように順番にならんだ差分を取りたいときはSnapShotではなく、backing-file-chain
とうqcow-imgの別の機能を使うことになる。backing-file機能がDocker仮想マシンのレイヤにt近い。snapshotはbacking-fileとは全く違う。スナップショットはwindowsやMacの「復元」と同じ機能ですよね。
snapshot の名前の付け方
takuya@:~$ sudo sudo qemu-img snapshot -l /var/lib/libvirt/images/d02.qcow2 Snapshot list: ID TAG VM SIZE DATE VM CLOCK ICOUNT 1 1.0.0 0 B 2022-04-21 14:50:34 00:00:00.000 0 2 1.1.0 0 B 2022-04-21 14:51:00 00:00:00.000 0 3 1.1.0 0 B 2022-04-22 16:01:42 00:00:00.000 0
スナップショットに指定するのは、名前ではなくタグです。
一見すると名前のように見えるし、名前のように使えます。ですが実際はタグです。
同じ名前で複数個作ることできます。同名のものはIDで識別されます。
同じ名前(タグ)で複数個作ることができるので、ある意味便利ですがある意味で不便です。
スナップショットIDを指定した、取り出し
特定のスナップショット状態を、一つのqcow2 ファイルとして取り出すことができる。
sudo qemu-img convert -l snapshot.id=3 name.qcow2 -f qcow2 -O qcow2 id-3.qcow2
snapshot.id を指定すれば、特定のスナップショットを確実に取り出すことができる
raw でほしいときは、raw を指定する(またはフォーマット指定省略)
sudo qemu-img convert -l snapshot.id=3 name.qcow2 -O raw id-3.qcow2 sudo qemu-img convert -l snapshot.id=3 name.qcow2 id-3.qcow2 # 省略時はraw
convertでタグだけを指定したときは、一番若いIDが採用されるようです。
次の状態のスナップショットがある時
takuya@:~$ sudo sudo qemu-img snapshot -l name.qcow2 Snapshot list: ID TAG VM SIZE DATE VM CLOCK ICOUNT 1 1.0.0 0 B 2022-04-21 14:50:34 00:00:00.000 0 2 1.1.0 0 B 2022-04-21 14:51:00 00:00:00.000 0 3 1.1.0 0 B 2022-04-22 16:01:42 00:00:00.000 0
convert で取り出してみると、id=3 , id=2 が候補になるが
### ID=2 が採用される sudo qemu-img convert -l 1.1.0 name.qcow2 id-3.qcow2
取り出されたのは、 id=2 でした。
convert でスナップショットを指定するとき、次の形式のようです。
man の記載より抜粋。
SNAPSHOT_PARAM is param used for internal snapshot, format is 'snapshot.id=[ID],snapshot.name=[NAME]' or '[ID_OR_NAME]'.
manを見た感じだと、'[ID_OR_NAME]'
と記載されているので、最初にヒットしたものが取り出されるって感じですね。
まとめ
qemu-img コマンドでスナップショットを取り扱える。
スナップショットは qcow2 で扱える
qemu-img でqcow2を任意の状態に保存できるし、巻き戻しできる
保存した状態を、別のファイルにすることができる。
差分だけを保存するわけではない。
docker のように差分差分を作るのは backing file という別の機能
libvirt など仮想マシン管理ソフトは、kvm/qemu ゲストに対しqemu-img の機能を呼び出している
スナップショットはIDが自動採番されている。
スナップショットには名前をつける(被ってもいい)
被った名前は、IDで識別される(同名の旧バージョンみたいな感じ)
ただし、スナップショットを扱うときは、仮想マシンを停止する必要がある。