QEMU/KVM Ubuntu高度設定 — ネットワーク・ストレージ・PCIパススルー

仮想化

この記事のポイント

  • Ubuntu 24.04 では qemu-system-x86 8.2.2 + libvirt 10.0 が利用できる(22.04 の QEMU 6.2 から大幅アップ)
  • ネットワークは NAT・ブリッジ・macvtap の3つが主要モード。用途に合わせて選ぶ
  • ストレージは raw(シンプル・高速)と qcow2(スナップショット・シンプロビジョニング)の違いを理解してから設定する
  • PCI パススルーは IOMMU 有効化 → vfio-pci バインドの順で設定する。GRUB の変更が必要

QEMU/KVM を apt install しただけの状態でも VM は動きますが、実際に本番で使うとなると「ネットワークをどのモードにするか」「ストレージは raw にするか qcow2 にするか」「GPU をゲストに直接渡すには何をすればいいか」という疑問が次々出てきます。

本記事では Ubuntu 24.04 LTS の QEMU 8.2.2 + libvirt 10.0 を対象に、高度な設定の3テーマを実際のコマンド出力とともに解説します。パッケージバージョンの確認は ubuntu:24.04 Docker公式イメージで実測しています。

QEMU/KVM パッケージバージョン比較(Ubuntu 22.04 vs 24.04)実測
QEMU/KVM パッケージバージョン比較(Ubuntu 22.04 vs 24.04)実測

前提環境と基本インストール

この記事の手順は次の環境で確認しています。

項目 バージョン
OS Ubuntu 24.04 LTS(Noble Numbat)
qemu-system-x86 1:8.2.2+ds-0ubuntu1.17(実測)
libvirt-daemon-system 10.0.0-2ubuntu8.14(実測)
qemu-img 8.2.2(実測)
ovmf(UEFI) 2024.02-2ubuntu0.8(実測)

まだインストールしていない場合は次のコマンドで揃います。




ubuntu@server: ~
$ sudo apt update
$ sudo apt install -y qemu-system-x86 qemu-kvm libvirt-daemon-system libvirt-clients virt-manager bridge-utils
パッケージリストを読み込んでいます… 完了
依存関係ツリーを作成しています… 完了

Setting up libvirt-daemon-system (10.0.0-2ubuntu8.14) …
Setting up qemu-system-x86 (1:8.2.2+ds-0ubuntu1.17) …
$ virsh –version
10.0.0
$ qemu-img –version
qemu-img version 8.2.2 (Debian 1:8.2.2+ds-0ubuntu1.17)

インストール後はカレントユーザーを kvmlibvirt グループに追加してから再ログインします。




ubuntu@server: ~
$ sudo usermod -aG kvm,libvirt $USER
$ sudo systemctl enable –now libvirtd
Synchronizing state of libvirtd.service…
$ systemctl status libvirtd | head -3
● libvirtd.service – Virtualization daemon
Loaded: loaded (/lib/systemd/system/libvirtd.service; enabled; vendor preset: enabled)
Active: active (running) since …

ネットワーク設定:NAT・ブリッジ・macvtap の選び方

QEMU/KVM のネットワークは、目的によって3つのモードを使い分けます。何も設定しなければ default(NAT)ネットワークに接続されますが、外部からゲストに直接アクセスしたい場合やパフォーマンスを追求したい場合はほかのモードが必要です。

QEMU/KVM ネットワークモード比較(NAT/ブリッジ/macvtap)
QEMU/KVM ネットワークモード比較(NAT/ブリッジ/macvtap)

正直なところ、最初は「NAT でいいか」と思って進めたのですが、外部から VM にアクセスしたくなった瞬間にブリッジに乗り換えることになります。最初から用途を決めてから設定したほうが手戻りが少ないです。

①NAT(デフォルト)— 開発・テスト用途向け

libvirt のデフォルトネットワーク(virbr0)を使う方式です。ゲストは 192.168.122.0/24 のアドレスを取得し、ホストの NAT 経由でインターネットに出ます。設定なしでそのまま動くのがメリット。ただし外部→ゲストへの直接アクセスにはポート転送が必要です。




ubuntu@server: ~ [NAT ネットワーク確認]
$ virsh net-list –all
Name State Autostart Persistent
——————————————–
default active yes yes
$ virsh net-dumpxml default | grep -A5 ‘forward\|bridge\|ip ‘
<forward mode=’nat’>
<nat><port start=’1024′ end=’65535’/></nat>
</forward>
<bridge name=’virbr0′ stp=’on’ delay=’0’/>
<ip address=’192.168.122.1′ netmask=’255.255.255.0′>

②ブリッジネットワーク — 本番・外部公開用途向け

ホストの物理NICにブリッジ(br0)を作り、ゲストを直接 LAN に参加させます。外部から VM のIPアドレスに直接アクセスできるため、Webサーバーやデータベースを運用するときに向いています。

設定手順は次のとおりです。Ubuntu 24.04 では Netplan を使います。




ubuntu@server: ~ [Netplan でブリッジ作成]
$ sudo nano /etc/netplan/01-netcfg.yaml

ファイルの内容は次のように書きます(enp3s0 は実際のNIC名に合わせてください)。

network:
  version: 2
  renderer: networkd
  ethernets:
    enp3s0:
      dhcp4: false
  bridges:
    br0:
      interfaces: [enp3s0]
      dhcp4: true
      parameters:
        stp: false
        forward-delay: 0



ubuntu@server: ~ [Netplan 適用]
$ sudo netplan apply
$ ip link show type bridge
3: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff

注意

Netplan の変更を適用すると 一時的にネットワークが切断されます。SSH で接続中の場合は sudo netplan try(120秒で自動ロールバック)を先に試してください。

ブリッジを作ったら、virsh にブリッジネットワークとして登録します。




ubuntu@server: ~ [libvirt ブリッジネットワーク登録]
$ cat << ‘EOF’ > /tmp/br0-network.xml
<network>
<name>br0</name>
<forward mode=’bridge’/>
<bridge name=’br0’/>
</network>
EOF
$ virsh net-define /tmp/br0-network.xml
Network br0 defined from /tmp/br0-network.xml
$ virsh net-start br0 && virsh net-autostart br0
Network br0 started
Network br0 marked as autostarted
$ virsh net-list
Name State Autostart Persistent
br0 active yes yes
default active yes yes

③macvtap — 高パフォーマンス要件向け

macvtap はホストのNICから直接 macvlan インタフェースを作り、ゲストに割り当てます。カーネルレベルで処理するためブリッジよりオーバーヘッドが小さく、高スループットが必要な場合に選択肢に入ります。ただし ホスト↔ゲスト間の通信ができない(macvlan の制限)という制約があります。

macvtap の制限

macvtap を使うとホストからゲストに ping が届かなくなります。デバッグ時は SSH の代替手段(シリアルコンソールなど)を用意しておく必要があります。ホスト↔ゲスト間の通信が必要なら素直にブリッジを選ぶほうが無難です。

ストレージ設定:raw vs qcow2 の違いと使い分け

QEMU/KVM のストレージで迷うのが raw と qcow2 の選択です。実際に qemu-img で 10GB のイメージを作って比較してみました。

raw vs qcow2 ディスクイメージ形式の実サイズ比較(実測)
raw vs qcow2 ディスクイメージ形式の実サイズ比較(実測)

実測して驚いたのが、raw も qcow2 も 作成直後の実サイズはほぼゼロという点です。raw は 4.0KB、qcow2 は 196KB(メタデータ分のみ)で、書き込みが進むにつれて実際のサイズが増えていきます。「raw のほうが事前にディスクを消費する」と思っていたのですが、sparse file として作成されるため事前確保は起きませんでした。

それぞれの特性をまとめると次のとおりです。

項目 raw qcow2
I/O パフォーマンス 高い(オーバーヘッドなし) やや低い(CoW処理あり)
スナップショット なし あり(qemu-img snapshot
シンプロビジョニング ○(スパースファイル) ○(メタデータ管理)
圧縮 なし あり(-c オプション)
転送の容易さ △(ファイルが大きくなりがち) ○(圧縮・変換で小さくできる)
推奨場面 本番・ベンチマーク重視 開発・スナップショット活用

手順1:raw イメージを作成する




ubuntu@server: ~ [raw イメージ作成]
$ qemu-img create -f raw /var/lib/libvirt/images/ubuntu-vm.raw 20G
Formatting ‘/var/lib/libvirt/images/ubuntu-vm.raw’, fmt=raw size=21474836480
$ du -sh /var/lib/libvirt/images/ubuntu-vm.raw
0 /var/lib/libvirt/images/ubuntu-vm.raw

手順2:qcow2 イメージを作成する




ubuntu@server: ~ [qcow2 イメージ作成]
$ qemu-img create -f qcow2 /var/lib/libvirt/images/ubuntu-vm.qcow2 20G
Formatting ‘/var/lib/libvirt/images/ubuntu-vm.qcow2’, fmt=qcow2
cluster_size=65536 extended_l2=off compression_type=zlib
size=21474836480 lazy_refcounts=off refcount_bits=16
$ qemu-img info /var/lib/libvirt/images/ubuntu-vm.qcow2 | grep -E ‘format|virtual|disk’
file format: qcow2
virtual size: 20 GiB (21474836480 bytes)
disk size: 196 KiB

手順3:raw から qcow2 へ変換する

すでに raw で運用しているVMを qcow2 に変換したい場合(スナップショット機能を後から使いたいなど)は qemu-img convert を使います。VMを停止してから実行してください。




ubuntu@server: ~ [raw → qcow2 変換]
$ virsh shutdown ubuntu-vm # VM を停止
$ qemu-img convert -p -f raw -O qcow2 ubuntu-vm.raw ubuntu-vm.qcow2
(100.00/100%)
$ qemu-img info ubuntu-vm.qcow2 | grep format
file format: qcow2

qcow2 スナップショットの操作

qcow2 のスナップショットは VM を止めた状態でも動作します。重要な変更を加える前に取っておくと、失敗したときにすぐ戻せます。

qcow2 スナップショット機能(実測)
qcow2 スナップショット機能(実測)



ubuntu@server: ~ [qcow2 スナップショット管理]
$ qemu-img snapshot -c snap_before_upgrade ubuntu-vm.qcow2
$ qemu-img snapshot -l ubuntu-vm.qcow2
Snapshot list:
ID TAG VM SIZE DATE VM CLOCK
1 snap_before_upgrade 0 B 2026-06-20 13:26:13 00:00:00.000
# スナップショットを復元する(VM停止中に実行)
$ qemu-img snapshot -a snap_before_upgrade ubuntu-vm.qcow2
# スナップショットを削除する
$ qemu-img snapshot -d snap_before_upgrade ubuntu-vm.qcow2

virsh から VM の実行中スナップショット(RAM状態を含む)を取る場合は virsh snapshot-create-as を使います。




ubuntu@server: ~ [virsh スナップショット]
$ virsh snapshot-create-as ubuntu-vm snap_before_upgrade “upgrade前の状態” –disk-only
Domain snapshot snap_before_upgrade created
$ virsh snapshot-list ubuntu-vm
Name Creation Time State
—————————————————–
snap_before_upgrade 2026-06-20 13:30:00 +0900 disk-snapshot

PCIパススルー:GPU/NICをゲストに直接割り当てる

PCI パススルーは物理の GPU や NIC をゲスト VM に直接割り当てる機能です。ホスト OS を介さないため、GPU をゲストでネイティブ速度で使えます。設定には IOMMU の有効化が必要で、CPU と BIOS の両方でサポートが必要です。

PCI パススルー設定手順(IOMMU有効化〜VFIO設定)
PCI パススルー設定手順(IOMMU有効化〜VFIO設定)

手順1:CPU と BIOS の確認




ubuntu@server: ~ [IOMMU対応確認]
$ grep -E ‘vmx|svm’ /proc/cpuinfo | head -1
flags : … vmx … ← Intel VT-x 対応
# VT-d(Intel)/ AMD-Vi(AMD)がBIOSで有効になっているかを確認
$ dmesg | grep -E ‘IOMMU|iommu’ | head -5
[ 0.000000] DMAR: IOMMU enabled
[ 0.515162] iommu: Default domain type: Translated

手順2:GRUB に IOMMU オプションを追加する




ubuntu@server: ~ [GRUB 設定変更]
$ sudo nano /etc/default/grub
# Intel の場合
GRUB_CMDLINE_LINUX_DEFAULT=”quiet splash intel_iommu=on iommu=pt”
# AMD の場合
GRUB_CMDLINE_LINUX_DEFAULT=”quiet splash amd_iommu=on iommu=pt”
$ sudo update-grub
Generating grub configuration file …
Found linux image: /boot/vmlinuz-6.8.0-83-generic
done
$ sudo reboot

iommu=pt(passthrough)オプションを付けると IOMMU は PCI パススルーに使うデバイスのみ管理し、ほかのデバイスへのオーバーヘッドを減らせます。

手順3:パススルーするデバイスの ID を確認する




ubuntu@server: ~ [PCIデバイスID確認]
$ lspci -nn | grep -i ‘VGA\|GPU\|NVIDIA\|AMD\|Radeon’
01:00.0 VGA compatible controller [0300]: NVIDIA GeForce RTX [10de:2204] (rev a1)
01:00.1 Audio device [0403]: NVIDIA GA102 HD Audio [10de:1aef] (rev a1)
# IOMMU グループを確認(同グループは一緒にパススルーする必要がある)
$ for d in /sys/kernel/iommu_groups/*/devices/*; do
n=${d#*/iommu_groups/}; n=${n%%/*}
echo “Group $n: $(lspci -nns ${d##*/})”
done | grep -i ‘nvidia\|10de’
Group 14: 01:00.0 VGA compatible controller [0300]: NVIDIA GeForce [10de:2204]
Group 14: 01:00.1 Audio device [0403]: NVIDIA GA102 HD Audio [10de:1aef]

手順4:vfio-pci ドライバをバインドする

パススルーするデバイスを vfio-pci ドライバに割り当てます。同じ IOMMU グループのデバイスはすべてまとめてバインドします。




ubuntu@server: ~ [vfio-pci バインド]
$ echo ‘options vfio-pci ids=10de:2204,10de:1aef’ | sudo tee /etc/modprobe.d/vfio.conf
options vfio-pci ids=10de:2204,10de:1aef
$ echo ‘vfio-pci’ | sudo tee /etc/modules-load.d/vfio-pci.conf
$ sudo update-initramfs -u
update-initramfs: Generating /boot/initrd.img-6.8.0-83-generic
$ sudo reboot
# 再起動後に確認
$ lspci -nnk -d 10de:2204
01:00.0 VGA compatible controller [0300]: NVIDIA GeForce [10de:2204] (rev a1)
Kernel driver in use: vfio-pci

手順5:virsh の XML にデバイスを追加する




ubuntu@server: ~ [VM に GPU をアタッチ]
$ virsh edit ubuntu-vm
# <devices> セクションに追加:
<hostdev mode=’subsystem’ type=’pci’ managed=’yes’>
<source>
<address domain=’0x0000′ bus=’0x01′ slot=’0x00′ function=’0x0’/>
</source>
</hostdev>

注意:UEFI(OVMF)が必要

GPU パススルーには BIOS の代わりに UEFI ファームウェア(OVMF)を使う必要があります。Ubuntu 24.04 では sudo apt install ovmf でインストールし、VM の XML に <loader>/usr/share/OVMF/OVMF_CODE.fd</loader> を追加してください。

ゲストVM への SSH 接続

VM が起動したら SSH で接続します。NAT ネットワーク(デフォルト)の場合は 192.168.122.x のアドレスが割り当てられます。

KVM ゲストVM への SSH 鍵認証設定(実測)
KVM ゲストVM への SSH 鍵認証設定(実測)



ubuntu@server: ~ [SSH 鍵生成 + ゲスト接続]
$ ssh -V
OpenSSH_9.6p1 Ubuntu-3ubuntu13.16, OpenSSL 3.0.13 30 Jan 2024
$ ssh-keygen -t ed25519 -f ~/.ssh/kvm_guest -N ” -C ‘kvm_vm_key’
Generating public/private ed25519 key pair.
Your public key has been saved in /root/.ssh/kvm_guest.pub
$ virsh domifaddr ubuntu-vm
Name MAC address Protocol Address
vnet0 52:54:00:xx:xx:xx ipv4 192.168.122.10/24
$ ssh-copy-id -i ~/.ssh/kvm_guest.pub ubuntu@192.168.122.10
Number of key(s) added: 1
$ ssh -i ~/.ssh/kvm_guest ubuntu@192.168.122.10
Welcome to Ubuntu 24.04.4 LTS (GNU/Linux 6.8.0-52-generic x86_64)

virsh コマンドチートシート

よく使う virsh コマンドをまとめます。

操作 コマンド
VM 一覧(実行中) virsh list
VM 一覧(すべて) virsh list --all
VM 起動 virsh start <name>
VM 正常終了 virsh shutdown <name>
VM 強制終了 virsh destroy <name>
VM の CPU/メモリ情報 virsh dominfo <name>
VM の IPアドレス確認 virsh domifaddr <name>
XML 設定を編集 virsh edit <name>
コンソール接続 virsh console <name>
自動起動を有効化 virsh autostart <name>
ネットワーク一覧 virsh net-list --all
スナップショット一覧 virsh snapshot-list <name>

よくあるトラブルと解決策

①「KVM acceleration can only be used when running on the host architecture」が出る

KVM の有効化を確認します。




ubuntu@server: ~ [KVM 確認]
$ ls -la /dev/kvm
crw-rw—- 1 root kvm 10, 232 Jun 20 10:00 /dev/kvm
$ kvm-ok
INFO: /dev/kvm exists
KVM acceleration can be used
# /dev/kvm がない場合: BIOS で Intel VT-x / AMD-V を有効化する
# グループ確認:
$ groups | grep kvm
kvm libvirt ← 表示されれば OK(表示されなければ再ログインが必要)

②「internal error: process exited while connecting to monitor: ioctl(KVM_CREATE_VM) failed: 16」

Hyper-V などのほかのハイパーバイザーが /dev/kvm を占有しています。VMware や Hyper-V を止めてから libvirtd を再起動します。WSL2 上で実行している場合は nested virtualization が必要で、ホスト Windows 側で wsl --update 後に wsl --set-version <distro> 2 を確認してください。

③ブリッジ設定後にホストのネットワークが切れた

Netplan の設定ミスが原因のことが多いです。sudo netplan try の代わりに sudo netplan apply を使った場合、ロールバックがありません。コンソールから sudo cp /etc/netplan/backup.yaml /etc/netplan/01-netcfg.yaml && sudo netplan apply でバックアップを復元します。

④PCI パススルー後に VM が起動しない(「VFIO: Failed to open /dev/vfio/14」)




ubuntu@server: ~ [VFIO 権限確認]
$ ls -la /dev/vfio/
crw-rw-rw- 1 root vfio 241, 0 Jun 20 10:00 /dev/vfio/vfio
crw——- 1 root root 241, 1 Jun 20 10:00 /dev/vfio/14
# libvirt ユーザーに VFIO デバイスへのアクセス権を付与
$ sudo chmod 666 /dev/vfio/14
# または /etc/udev/rules.d/99-vfio.rules に永続化:
SUBSYSTEM==”vfio”, MODE=”0666″

まとめ

QEMU/KVM の高度設定は「ネットワーク」「ストレージ」「PCIパススルー」の3つが鬼門です。本記事で確認したポイントをまとめます。

  • ネットワークは用途で選ぶ:開発・テストなら NAT のまま、本番公開はブリッジ(Netplan + virsh net-define)
  • ストレージの raw と qcow2 は作成直後の実サイズはほぼ同じ。スナップショットが必要なら qcow2 一択
  • qcow2 スナップショットは qemu-img snapshot -c <tag> で作成・-a <tag> で復元
  • PCIパススルーは IOMMU 有効化(GRUB)→ vfio-pci バインド → virsh XML 編集の順で進める
  • GPU パススルーには OVMF(UEFI)が必要
  • Ubuntu 24.04 では QEMU 8.2.2 + libvirt 10.0 が apt で入る(22.04 は QEMU 6.2)

VPS 上で QEMU/KVM を動かす場合、まずはネットワーク設定から試してみるのが現実的です。PCIパススルーはハードウェアに依存する部分が多いため、ベアメタルサーバーか自宅サーバーで試す場面が多いです。

コメント

タイトルとURLをコピーしました