Linux + KVM で仮想化ホストを構築してみた(Backing File編)
前回に続き、今回もDebianホスト上で仮想マシン環境を構築して、最終的にKubernetesのラボ構築を目指しています。本記事では、qemu-img resize を使ったディスク容量の拡張方法と、qcow2のBacking Fileを利用したLinked Cloneの仕組みを紹介します。
ディスク容量の拡張
bridge / cloud-init編では、クラウドイメージをインポートしてみました。
インストール要らずでとても楽でしたが、一つの問題点が残っています。ゲストOSにSSHで接続して、ディスク容量を見てみます。
| $ lsblk -o NAME,SIZE,TYPE,MOUNTPOINT
NAME SIZE TYPE MOUNTPOINT
sr0 368K rom
vda 3.5G disk
├─vda1 2.4G part /
├─vda13 1023M part /boot
├─vda14 4M part
└─vda15 106M part /boot/efi
|
ディスクはvdaのみで、その容量は3.5GB程度のようです。
これは、ダウンロードしたクラウドイメージのディスク容量が3.5GBだからです。以下のコマンドで確認できます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | $ qemu-img info questing-server-cloudimg-amd64.img
image: questing-server-cloudimg-amd64.img
file format: qcow2
virtual size: 3.5 GiB (3758096384 bytes)
disk size: 783 MiB
cluster_size: 65536
Format specific information:
compat: 1.1
compression type: zlib
lazy refcounts: false
refcount bits: 16
corrupt: false
extended l2: false
Child node '/file':
filename: questing-server-cloudimg-amd64.img
protocol type: file
file length: 783 MiB (821282816 bytes)
disk size: 783 MiB
|
virt-installの--diskパラメータでディスク容量を指定すれば良いでは?と思うかもしれませんが、容量指定ができるのは、仮想ディスクを新規作成時にのみで、クラウドディスクをインポートする場合は容量変更できません。指定しても無視されます。
そこで、qemu-img resizeを使用してサイズ変更します。
1
2
3
4
5
6
7
8
9
10
11
12 | $ cp questing-server-cloudimg-amd64.img new.qcow2
$ qemu-img resize new.qcow2 +20G
Image resized.
$ qemu-img info new.qcow2
image: new.qcow2
file format: qcow2
virtual size: 23.5 GiB (25232932864 bytes)
disk size: 783 MiB
cluster_size: 65536
...
|
リサイズ後は、イメージファイルとしてほとんどサイズが変わらないものの、「バーチャルサイズ」が20GB増えて、23.5GBになっています。
このイメージを使って仮想マシンを作成してみます。
1
2
3
4
5
6
7
8
9
10
11
12 | $ sudo cp new.qcow2 /var/lib/libvirt/images/
$ virt-install \
--name new \
--memory 8192 \
--vcpus 2 \
--import \
--disk path=/var/lib/libvirt/images/new.qcow2,format=qcow2,bus=virtio \
--disk path=/var/lib/libvirt/images/seed.iso,device=cdrom \
--network bridge=br0,model=virtio \
--os-variant ubuntu25.10 \
--graphics none \
--noautoconsole
|
起動後、SSHで接続し、再度容量を確認します。
| $ lsblk -o NAME,SIZE,TYPE,MOUNTPOINT
NAME SIZE TYPE MOUNTPOINT
sr0 368K rom
vda 23.5G disk
├─vda1 22.4G part /
├─vda13 1023M part /boot
├─vda14 4M part
└─vda15 106M part /boot/efi
|
パーティションの自動拡張
ここでは、cloud-initが起動時に自動的にgrowpartモジュールを実行してくれるので、パーティションサイズが自動的にディスク容量に合わせて拡張されます。
cloud-initの使われていないイメージの場合は、手動でパーティションサイズの変更が必要です。
Backing Fileの利用
Backing File、いわゆるLinked Cloneを可能にする仕組みです。こちらの動作を確認してみたいと思います。
まずは、クラウドイメージをコピーし、ディスクを20GBにリサイズして、これをベースとします。
| $ cp questing-server-cloudimg-amd64.img master.qcow2
$ qemu-img resize master.qcow2 20G
$ qemu-img info master.qcow2
image: master.qcow2
file format: qcow2
virtual size: 20 GiB (21474836480 bytes)
...
|
次に、master.qcow2をBacking Fileとして、差分ディスクを作成します。
| $ qemu-img create -f qcow2 -F qcow2 -b master.qcow2 vm1.qcow2
Formatting 'vm1.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=21474836480 backing_file=master.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
|
この差分ディスクの情報を見ると、ホスト側のディスク上でのサイズは、わずか196KBです。そして、backing file: master.qcow2と、Backing Fileの所在を記載しています。
| $ qemu-img info vm1.qcow2
image: vm1.qcow2
file format: qcow2
virtual size: 20 GiB (21474836480 bytes)
disk size: 196 KiB
cluster_size: 65536
backing file: master.qcow2
backing file format: qcow2
...
|
Backing Fileと差分ディスクを移動します。qemu-img createで差分ディスクを作成した際に、相対パスで記述したため、差分ディスクだけでなくBacking Fileも一緒に移動しないと、起動時にBacking Fileが見つからずエラーになります。
| $ sudo mv master.qcow2 vm1.qcow2 /var/lib/libvirt/images/
|
差分ディスクを使用して仮想マシンを作成します(seedは作成済みとします)。
| $ virt-install \
--name vm1 \
--memory 8192 \
--vcpus 2 \
--import \
--disk path=/var/lib/libvirt/images/vm1.qcow2,format=qcow2,bus=virtio \
--disk path=/var/lib/libvirt/images/seed.iso,device=cdrom \
--network bridge=br0,model=virtio \
--os-variant ubuntu25.10 \
--graphics none \
--noautoconsole
|
また、seed を変更すれば、この1つのBacking Fileから複数の差分ディスクを作成し、複数の仮想マシンを瞬時に起動することができます。
応用:自動化スクリプト
色々書きましたが、実際に複数の仮想マシンを作成する場合、やはり1個1個コマンドを打つのが大変なので、シンプルなシェルスクリプトにまとめました。
このスクリプトは、/var/lib/libvirt/images/master.qcow2というBacking Fileが存在することを前提としています。コマンドラインでVM名とIPアドレスを指定するだけで、VMをクラウドイメージから作成してくれて、設定してくれます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 | #!/usr/bin/env bash
set -euo pipefail
if [ "$EUID" -ne 0 ]; then
echo "This script must be run as root"
exit 1
fi
VM="${1:?usage: $0 <vm-name> <ip-address>}"
IP="${2:?usage: $0 <vm-name> <ip-address>}"
BASE="/var/lib/libvirt/images/master.qcow2"
DIR="/var/lib/libvirt/images/${VM}"
DISK="${DIR}/${VM}.qcow2"
SEED="${DIR}/${VM}-seed.iso"
RAM=8192
VCPUS=2
CIDR="/24"
GW="192.168.0.1"
DNS1="192.168.0.1"
BRIDGE="br0"
USER_NAME="nogawa"
SSH_KEY="$(cat /home/user/.ssh/id_ed25519.pub)"
mkdir -p "$DIR"
qemu-img create -f qcow2 -F qcow2 -b "$BASE" "$DISK" 20G
cat > "${DIR}/user-data" <<EOF
#cloud-config
users:
- name: ${USER_NAME}
sudo: ALL=(ALL) NOPASSWD:ALL
groups: users, admin
shell: /bin/bash
lock_passwd: true
ssh_authorized_keys:
- ${SSH_KEY}
packages:
- qemu-guest-agent
runcmd:
- systemctl enable --now qemu-guest-agent
EOF
cat > "${DIR}/meta-data" <<EOF
instance-id: ${VM}
local-hostname: ${VM}
EOF
cat > "${DIR}/network-config" <<EOF
network:
version: 2
ethernets:
server-main-nic:
match:
driver: virtio_net
addresses:
- ${IP}${CIDR}
routes:
- to: default
via: ${GW}
nameservers:
addresses: [${DNS1}]
EOF
cloud-localds "$SEED" "${DIR}/user-data" "${DIR}/meta-data" \
--network-config "${DIR}/network-config"
virt-install \
--name "$VM" \
--memory "$RAM" \
--vcpus "$VCPUS" \
--import \
--disk path="$DISK",format=qcow2,bus=virtio \
--disk path="$SEED",device=cdrom \
--network bridge="$BRIDGE",model=virtio \
--os-variant ubuntu25.10 \
--graphics none \
--noautoconsole
echo "VM created:"
echo " name: $VM"
echo " ip: $IP"
echo " ssh: ssh ${USER_NAME}@${IP}"
|
使い方はこんな感じです:
| $ sudo ./tool.sh vm3 192.168.0.123
Formatting '/var/lib/libvirt/images/vm3/vm3.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=21474836480 backing_file=/var/lib/libvirt/images/master.qcow2 backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16
Starting install...
Creating domain... | 00:00:00
Domain creation completed.
VM created:
name: vm3
ip: 192.168.0.123
ssh: ssh nogawa@192.168.0.123
|
これを使えば、1つのVMの作成に必要な時間は5秒未満でした。