Ubuntu 26.04 の KVM 環境で、テンプレート qcow2 から個別 VM を作成する手順を整理します。前の記事で作成したテンプレートディスクを複製し、VM 名、CPU / メモリ、NVRAM、ディスク、仮想 NIC、libvirt XML を個別 VM として定義します。
この記事では、virt-install で毎回インストールするのではなく、テンプレートから VM を増やす運用を前提にします。実際の環境では構成管理で定義していますが、ここでは手動で何を作っているのかを追える形に分解します。
書籍
作って理解する仮想化技術 ── ハイパーバイザを実装しながら仕組みを学ぶ
ハイパーバイザ、CPU 仮想化支援、メモリ仮想化、割り込み、仮想デバイスなど、VM の性能設計を低レイヤから理解したい場合の参考書籍です。価格や在庫はリンク先で確認してください。
Amazon で見るこのリンクは Amazon アソシエイトリンクです。
VM 作成で決めること
テンプレートから VM を作る場合でも、VM ごとに決める値があります。ここを曖昧にすると、同じテンプレートから作った VM 同士で名前、MAC、OVN port、NVRAM、ディスクが衝突します。
- VM 名
- 複製元テンプレート qcow2 と作成先ディスクパス
- CPU / メモリのリソース profile
- UEFI NVRAM の個別ファイル
- 接続する bridge または logical switch
- MAC アドレスと OVN interface ID
テンプレートディスクを確認する
まず、複製元となるテンプレートディスクが存在することを確認します。テンプレートは直接起動せず、個別 VM のディスクへ複製して使います。
sudo qemu-img info /var/lib/libvirt/images/ubuntu-template-40g.qcow2
sudo test -f /var/lib/libvirt/images/ubuntu-template-40g.qcow2
virsh --connect qemu:///system list --allVM 用ディスクを作成する
VM 用ディスクはテンプレート qcow2 から作成します。単純な cp でも作れますが、ここでは形式を明示するために qemu-img convert を使います。
VM_NAME="ubuntu-test-g01-n001-v.mgmt.s01.example.com"
BASE_IMAGE="/var/lib/libvirt/images/ubuntu-template-40g.qcow2"
VM_IMAGE="/var/lib/libvirt/images/${VM_NAME}.qcow2"
sudo qemu-img convert \
-f qcow2 \
-O qcow2 \
-o preallocation=off \
"$BASE_IMAGE" \
"$VM_IMAGE"
sudo qemu-img info "$VM_IMAGE"テンプレート方式では、この時点で OS の中身は複製されています。hostname、machine-id、cloud-init 状態などをどの段階で個別化するかは、テンプレート設計と初回起動時の処理に依存します。
UEFI NVRAM を VM ごとに用意する
UEFI 起動の VM では、NVRAM も VM ごとに分けます。複数 VM で同じ NVRAM ファイルを共有してはいけません。
VM_NAME="ubuntu-test-g01-n001-v.mgmt.s01.example.com"
NVRAM_DIR="/var/lib/libvirt/qemu/nvram"
NVRAM_TEMPLATE="/usr/share/OVMF/OVMF_VARS_4M.fd"
NVRAM_PATH="${NVRAM_DIR}/${VM_NAME}_VARS.fd"
sudo mkdir -p "$NVRAM_DIR"
sudo cp -n "$NVRAM_TEMPLATE" "$NVRAM_PATH"
sudo chown root:root "$NVRAM_PATH"
sudo chmod 0644 "$NVRAM_PATH"OVN logical switch port を用意する
OVN を使う構成では、VM の仮想 NIC に対応する logical switch port を作成します。interface ID は UUID 形式で一意にし、libvirt XML の virtualport と対応させます。
LOGICAL_SWITCH="ls3032"
INTERFACE_ID="$(uuidgen | tr 'A-Z' 'a-z')"
sudo ovn-nbctl --may-exist lsp-add "$LOGICAL_SWITCH" "$INTERFACE_ID"
sudo ovn-nbctl lsp-set-addresses "$INTERFACE_ID" unknown
sudo ovn-nbctl clear Logical_Switch_Port "$INTERFACE_ID" port_security
echo "$INTERFACE_ID"
sudo ovn-nbctl show通常の Linux bridge だけで VM を接続する場合、この OVN port 作成は不要です。この手順は、VM の NIC を OVN logical switch と対応させるためのものです。
libvirt XML を作成する
VM は libvirt XML として定義します。ここでは、host-passthrough、HugePages、UEFI、qcow2、io_uring、virtio NIC、Open vSwitch virtualport を含む例を示します。
VM_NAME="ubuntu-test-g01-n001-v.mgmt.s01.example.com"
VM_IMAGE="/var/lib/libvirt/images/${VM_NAME}.qcow2"
NVRAM_PATH="/var/lib/libvirt/qemu/nvram/${VM_NAME}_VARS.fd"
INTERFACE_ID="replace-with-interface-uuid"
mkdir -p "$HOME/work/libvirt/qemu"
cat > "$HOME/work/libvirt/qemu/${VM_NAME}.xml" <<EOF
<domain type='kvm'>
<name>${VM_NAME}</name>
<memory unit='MiB'>4096</memory>
<currentMemory unit='MiB'>4096</currentMemory>
<vcpu placement='static' current='2'>2</vcpu>
<cpu mode='host-passthrough' check='none' migratable='on'>
<topology sockets='1' cores='2' threads='1'/>
</cpu>
<memoryBacking>
<hugepages/>
</memoryBacking>
<os>
<type arch='x86_64' machine='q35'>hvm</type>
<loader readonly='yes' type='pflash'>/usr/share/OVMF/OVMF_CODE_4M.fd</loader>
<nvram template='/usr/share/OVMF/OVMF_VARS_4M.fd'>${NVRAM_PATH}</nvram>
<boot dev='hd'/>
</os>
<features>
<acpi/>
</features>
<devices>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' io='io_uring' cache='none' discard='unmap' detect_zeroes='unmap'/>
<source file='${VM_IMAGE}'/>
<target dev='vda' bus='virtio'/>
</disk>
<interface type='bridge'>
<source bridge='br-int'/>
<model type='virtio'/>
<virtualport type='openvswitch'>
<parameters interfaceid='${INTERFACE_ID}'/>
</virtualport>
</interface>
<console type='pty'>
<target type='serial' port='0'/>
</console>
<serial type='pty'>
<target port='0'/>
</serial>
</devices>
</domain>
EOFこの XML は、この環境寄りの構成です。一般的な KVM では HugePages、io_uring、Open vSwitch virtualport まで最初から入れない場合もあります。まず単純な VM を作る場合は、Linux bridge と通常の disk driver から始めても構いません。
VM を define して起動する
XML を作成したら、virsh define で libvirt に登録し、状態を確認してから起動します。
VM_NAME="ubuntu-test-g01-n001-v.mgmt.s01.example.com"
XML_PATH="$HOME/work/libvirt/qemu/${VM_NAME}.xml"
sudo virsh --connect qemu:///system define "$XML_PATH"
sudo virsh --connect qemu:///system dominfo "$VM_NAME"
sudo virsh --connect qemu:///system start "$VM_NAME"
sudo virsh --connect qemu:///system list --all起動後に確認する
VM が起動したら、libvirt、OVS / OVN、console の順に確認します。疎通できない場合でも、まず VM が起動しているのか、NIC が bridge に接続されているのか、OVN port と対応しているのかを分けて見ます。
VM_NAME="ubuntu-test-g01-n001-v.mgmt.s01.example.com"
sudo virsh --connect qemu:///system domstate "$VM_NAME"
sudo virsh --connect qemu:///system domiflist "$VM_NAME"
sudo virsh --connect qemu:///system console "$VM_NAME"
sudo ovs-vsctl show
sudo ovn-nbctl showリソース profile を分ける
VM の CPU / メモリは、都度ばらばらに決めるより、small / medium のような profile に分けておくと管理しやすくなります。
small: vCPU 2、memory 4096 MiBmedium: vCPU 4、memory 8192 MiB- CPU topology は sockets / cores / threads を明示する
- ホストの NUMA や用途に応じて profile を増やす
確認ポイント
- テンプレート qcow2 から VM 用ディスクを作っている
- UEFI NVRAM を VM ごとに分けている
- OVN を使う場合、interface ID が UUID 形式で一意になっている
- libvirt XML の disk / interface / cpu / memory が意図通りになっている
- VM 起動後に
virsh、ovs-vsctl、ovn-nbctlで状態を確認している
まとめ
Ubuntu 26.04 の KVM VM 作成では、テンプレート qcow2 を複製して終わりではありません。VM ごとの NVRAM、libvirt XML、仮想 NIC、OVN logical switch port、リソース profile をそろえて初めて、個別 VM として管理できる状態になります。
次は、VM の操作権限や interface 単位の制御を整理するために、KVM VM の ACL へ進みます。
関連記事
- Ubuntu 26.04 KVM VM テンプレートの作成 – autoinstall と qcow2 複製の基本
- Ubuntu 26.04 KVM の基本構築 – libvirt / OVS / OVN の土台を作る
- Ubuntu 26.04 KVM Bridge ネットワークの基本設定 – Linux bridge / OVS / OVN の使い分け
- Ubuntu 26.04 KVM VM の ACL
- Ubuntu 26.04 KVM HugePages の基本
- Ubuntu 26.04 仮想マシンの性能確認
- VM パフォーマンス Day4 – ストレージ I/O 最適化と virtio / raw / qcow2 / io_uring の考え方
- KVM の io_uring はどれだけ効くのか – QEMU ストレージ I/O の検証




