🎃

Raspberry Pi OS で KVM

2024/11/07に公開

環境について

64bit版のRaspberry Pi OS Lite(Debian12 Bookworm版)で、KVM のインストール、仮想マシンの作成をしてみます。
Raspberry Pi 4B 8GB版でテストしましたが、CPUの仮想化支援が効くので、低負荷で動作します。

$ cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

$ cat /etc/debian_version
12.7

$ uname -a
Linux testpi 6.6.51+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.6.51-1+rpt3 (2024-10-08) aarch64 GNU/Linux

NW設定

有線NICに仮想ブリッジを仕込み、KVMではブリッジを利用する想定。
以下のようなファイルをメディアに書き込んでOS起動する。

/etc/NetworkManager/system-connections/br0-<UUID>.nmconnection
[connection]
id=br0
uuid=<UUID>
type=bridge
interface-name=br0
timestamp=1720959930

[ethernet]

[bridge]
stp=false

[ipv4]
address1=<IPアドレス>/24,<デフォルトGW>
dns=<プライマリDNSサーバ>;<セカンダリDNSサーバ>;
method=manual
route1=<宛先NWアドレス>/24,<GWアドレス>

[ipv6]
addr-gen-mode=default
method=auto

[proxy]
/etc/NetworkManager/system-connections/bridge-slave-eth0.nmconnection
[connection]
id=bridge-slave-eth0
uuid=<UUID>
type=ethernet
interface-name=eth0
master=br0
slave-type=bridge

[ethernet]

[bridge-port]

作業用領域

ブートドライブの書き込み回数を減らしたいので、作業用領域は別のドライブに用意する。

$ dmesg | tail
$ sudo parted /dev/sda
> print
> rm 1
> mkpart primary 0% 100%
> print
> quit

$ sudo mkfs -t ext4 /dev/sda1
$ sudo mkdir /media/work

$ echo PARTUUID=$(ls -l /dev/disk/by-partuuid | grep sda1 | awk '{print $9}') /media/work ext4 defaults,noatime 0 1 | sudo tee -a /etc/fstab
PARTUUID=74e6849b-01 /media/work ext4 defaults,noatime 0 1

$ sudo mount /media/work
$ df

閑話休題
最初はUSBメモリを利用しようとしたのだが、I/Oの遅さのため断念。
10年以上前のSATAの2.5インチHDDを利用した。80GB。ケースに入れてUSB接続で利用できて便利。

関連パッケージのインストール

必要なパッケージをインストールします。

$ sudo apt install --no-install-recommends qemu-system-arm qemu-utils qemu-system-gui ipxe-qemu bridge-utils qemu-efi-aarch64 kpartx

仮想マシンの作成 Debian編

ここでは例として、Debian12 の仮想マシンを作成します。
https://www.debian.org/CD/netinst/ より、arm64 ネットインストール版CDイメージをダウンロードして利用します。(以下、debian-12.7.0-arm64-netinst.iso)

$ ls -l /media/work/iso/
-rw-r--r-- 1 pi pi 551858176 Nov  4 05:09 debian-12.7.0-arm64-netinst.iso

CDイメージからカーネルと初期化RAMディスクをコピー

インストールCDイメージから、カーネルと初期化RAMディスクをコピーします。

インストールメディアをマウント

$ sudo mkdir /media/iso
$ sudo mount /media/work/iso/debian-12.7.0-arm64-netinst.iso /media/iso

grub.cfg から、カーネルと初期化RAMディスクのパスを確認

$ egrep 'linux|initrd' /media/iso/boot/grub/grub.cfg | awk '{print $2}' | sort | uniq
/install.a64/gtk/initrd.gz
/install.a64/initrd.gz
/install.a64/vmlinuz

カーネルと初期化RAMディスクをコピー。コピーしたらアンマウント。

$ cd /media/work/iso/
$ cp -pi /media/iso/install.a64/vmlinuz debian-12.7.0-arm64-netinst.vmlinuz
$ cp -pi /media/iso/install.a64/initrd.gz debian-12.7.0-arm64-netinst.initrd.gz
$ ls -l /media/work/iso/
total 592188
-r--r--r-- 1 pi pi  21840895 Aug 31 19:41 debian-12.7.0-arm64-netinst.initrd.gz
-rw-r--r-- 1 pi pi 551858176 Nov  4 05:09 debian-12.7.0-arm64-netinst.iso
-r--r--r-- 1 pi pi  32692160 Aug 31 19:41 debian-12.7.0-arm64-netinst.vmlinuz
$ sudo umount /media/iso

仮想ディスクを作成

作業ディレクトリを作成

$ sudo mkdir /media/work/qemu
$ sudo chown pi: /media/work/qemu
$ cd /media/work/qemu/
$ qemu-img create -f qcow2 debian-12.7.0-arm64.qcow2.base 16G
Formatting 'debian-12.7.0-arm64.qcow2.base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=17179869184 lazy_refcounts=off refcount_bits=16

$ qemu-img info debian-12.7.0-arm64.qcow2.base
image: debian-12.7.0-arm64.qcow2.base
file format: qcow2
virtual size: 16 GiB (17179869184 bytes)
disk size: 196 KiB
cluster_size: 65536
Format specific information:
    compat: 1.1
    compression type: zlib
    lazy refcounts: false
    refcount bits: 16
    corrupt: false
    extended l2: false

$ ls -lhs debian-12.7.0-arm64.qcow2.base
196K -rw-r--r-- 1 pi pi 193K Nov  4 07:44 debian-12.7.0-arm64.qcow2.base

インストール

amd64のKVMでおなじみのパラメータの他に、カーネル、初期化RAMディスクを指定してインストーラを起動する。

$ sudo qemu-system-aarch64 \
-machine virt \
-cpu host \
-m 1024 \
-enable-kvm \
-kernel /media/work/iso/debian-12.7.0-arm64-netinst.vmlinuz \
-initrd /media/work/iso/debian-12.7.0-arm64-netinst.initrd.gz \
-cdrom /media/work/iso/debian-12.7.0-arm64-netinst.iso \
-drive file=debian-12.7.0-arm64.qcow2.base \
-net nic,macaddr=52:54:00:12:34:10 -net tap,ifname=tap1 -vnc 0.0.0.0:0

VNCビューアを実行して KVMホストの 5900ポートに接続する
QEMUコンソールが開いたら、Ctrl + Alt + 2 で画面をシリアルコンソールへ切り替える。
インストールは通常の手順で実行する。

インストール終了したら下記で仮想マシンを終了する。

  • QEMUを実行したコマンドプロンプトに戻って、Ctrl + c で終了する。
  • または、Ctrl + Alt + 1 で QEMUターミナルに戻り、q で終了する。

仮想ディスクからカーネルと初期化RAMディスクをコピー

仮想ディスクをマウント

$ sudo modprobe nbd
$ sudo qemu-nbd -c /dev/nbd0 debian-12.7.0-arm64.qcow2.base

$ sudo kpartx -av /dev/nbd0
add map nbd0p1 (254:0): 0 997376 linear 43:0 2048
add map nbd0p2 (254:1): 0 30597120 linear 43:0 999424
add map nbd0p3 (254:2): 0 1955840 linear 43:0 31596544

$ sudo mkdir /media/tmp
$ sudo mount /dev/mapper/nbd0p1 /media/tmp
$ df

カーネルと初期化RAMディスクをコピー

$ cp -pi /media/tmp/vmlinuz debian-12.7.0-arm64.vmlinuz
$ cp -pi /media/tmp/initrd.img debian-12.7.0-arm64.initrd.img
$ la -l

アンマウント

$ sudo umount /media/tmp
$ sudo kpartx -dv /dev/nbd0
$ sudo qemu-nbd -d /dev/nbd0
$ sudo rmmod nbd

オーバーレイストレージイメージ作成

インストール完了直後のイメージをバッキングファイルとして、オーバーレイストレージイメージ作成する。
(こうすることで、いつでもインストール直後のまっさらな状態に戻すことができる)

$ qemu-img create -f qcow2 -b debian-12.7.0-arm64.qcow2.base -F qcow2 debian-12.7.0-arm64.qcow2 16G
Formatting 'debian-12.7.0-arm64.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=17179869184 backing_file=debian-12.7.0-arm64.qcow2.base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16

$ qemu-img info debian-12.7.0-arm64.qcow2
image: debian-12.7.0-arm64.qcow2
file format: qcow2
virtual size: 16 GiB (17179869184 bytes)
disk size: 196 KiB
cluster_size: 65536
backing file: debian-12.7.0-arm64.qcow2.base
backing file format: qcow2
Format specific information:
    compat: 1.1
    compression type: zlib
    lazy refcounts: false
    refcount bits: 16
    corrupt: false
    extended l2: false

仮想マシン起動

コピーしたカーネル、初期化RAMディスクで仮想マシンを起動する。

$ sudo qemu-system-aarch64 \
 -machine virt \
 -cpu host \
 -m 1024 \
 -enable-kvm \
 -kernel debian-12.7.0-arm64.vmlinuz \
 -initrd debian-12.7.0-arm64.initrd.img \
 -append root=/dev/vda2 \
 -drive file=debian-12.7.0-arm64.qcow2 \
 -net nic,macaddr=52:54:00:12:34:0 -net tap,ifname=tap1 \
 -vnc 0.0.0.0:0 \
 -daemonize

VNCビューアを実行して KVMホストの 5900ポートに接続する
QEMUコンソールが開いたら、Ctrl + Alt + 2 で画面をシリアルコンソールへ切り替える。

$ ip a
ipアドレスが付与されていることを確認する。
$ su -
$ apt install --no-install-recommends openssh-server

他のホストからssh 接続をテストする。
接続できたら、VNCビューアは閉じてよい。

仮想マシンの作成 RockyLinux編

https://rockylinux.org/download より、arm64 minimal CDイメージをダウンロードして利用します。(以下、Rocky-9.4-aarch64-minimal.iso)

$ ls -l Rocky-9.4-aarch64-minimal.iso
-rw-r--r-- 1 pi pi 1694892032 Nov 16 05:58 Rocky-9.4-aarch64-minimal.iso

先のDebianのイメージもそうだが、ダウンロードには torrent の利用をお勧めしたい。
aria2 などを利用すれば torrent ファイルのリンクを与えるだけで簡単にDLできる。サーバの負荷を減らし回線を効率よく利用することができる。

CDイメージからカーネルと初期化RAMディスクをコピー

インストールCDイメージから、カーネルと初期化RAMディスクをコピーするため、インストールメディアをマウント。

$ sudo mount Rocky-9.4-aarch64-minimal.iso /media/iso
mount: /media/tmp: WARNING: source write-protected, mounted read-only.

grub.cfg から、カーネルと初期化RAMディスクのパスを確認。

$ awk '$1~/linux|initrd/ {print $2}' /media/iso/EFI/BOOT/grub.cfg | sort | uniq
/images/pxeboot/initrd.img
/images/pxeboot/vmlinuz

カーネルと初期化RAMディスクをコピー。コピーしたらアンマウント。

$ cd /media/work/iso

$ cp /media/iso/images/pxeboot/initrd.img Rocky-9.4-aarch64-minimal.initrd.img
$ cp /media/iso/images/pxeboot/vmlinuz Rocky-9.4-aarch64-minimal.vmlinuz

$ ls -l Rocky-9.4-aarch64-minimal.*
-rw-r--r-- 1 pi pi   92786688 Nov 16 06:12 Rocky-9.4-aarch64-minimal.initrd.img
-rw-r--r-- 1 pi pi 1694892032 Nov 16 05:58 Rocky-9.4-aarch64-minimal.iso
-rwxr-xr-x 1 pi pi   11946497 Nov 16 06:12 Rocky-9.4-aarch64-minimal.vmlinuz

$ sudo umount /media/iso

仮想ディスクを作成

$ cd /media/work/qemu/

$ qemu-img create -f qcow2 Rocky-9.4-aarch64.qcow2.base 16G
Formatting 'Rocky-9.4-aarch64.qcow2.base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=17179869184 lazy_refcounts=off refcount_bits=16

$ qemu-img info Rocky-9.4-aarch64.qcow2.base
image: Rocky-9.4-aarch64.qcow2.base
file format: qcow2
virtual size: 16 GiB (17179869184 bytes)
disk size: 196 KiB
cluster_size: 65536
Format specific information:
    compat: 1.1
    compression type: zlib
    lazy refcounts: false
    refcount bits: 16
    corrupt: false
    extended l2: false

インストール

-bios オプションが必要。

$ sudo qemu-system-aarch64 \
-machine virt \
-cpu host \
-m 1024 \
-enable-kvm \
-kernel /media/work/iso/Rocky-9.4-aarch64-minimal.vmlinuz \
-initrd /media/work/iso/Rocky-9.4-aarch64-minimal.initrd.img \
-append "inst.stage2=hd:LABEL=Rocky-9-4-aarch64-dvd ro" \
-cdrom /media/work/iso/Rocky-9.4-aarch64-minimal.iso \
-drive file=Rocky-9.4-aarch64.qcow2.base \
-net nic,macaddr=52:54:00:12:34:11 -net tap,ifname=tap1 -vnc 0.0.0.0:1 \
-bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd

起動したら、VNCビューアを実行して KVMホストの 5901ポートに接続する
QEMUコンソールが開いたら、Ctrl + Alt + 2 で画面をシリアルコンソールへ切り替える。
Xが起動しないメッセージが表示されるので、グラフィカルインストールのため、1 Start VNC を選択。VNC パスワードを指定する。
表示されたアドレスに VNC 接続すると、通常のインストーラの画面が表示される。
インストールは通常の手順で実行する。
(作成したqcow2イメージからカーネル等をコピーする手間を考慮し、LVMは使わない。KVMホストで対応しているファイルシステムを指定する)
インストール終了したら下記で仮想マシンを終了する。

仮想ディスクからカーネルと初期化RAMディスクをコピー

仮想ディスクをマウントして、カーネルと初期化RAMディスクをコピー。
コピーーしたらアンマウント。

$ sudo modprobe nbd
$ sudo kpartx -av /dev/nbd0
$ sudo mount /dev/mapper/nbd0p2 /media/tmp

$ sudo cp /media/tmp/initramfs-5.14.0-427.13.1.el9_4.aarch64.img Rocky-9.4-aarch64.initramfs
$ sudo cp /media/tmp/vmlinuz-5.14.0-427.13.1.el9_4.aarch64 Rocky-9.4-aarch64.vmlinuz

$ sudo umount /media/tmp
$ sudo kpartx -dv /dev/nbd0
$ sudo qemu-nbd -d /dev/nbd0
$ sudo rmmod nbd

オーバーレイストレージイメージ作成

インストール完了直後のイメージをバッキングファイルとして、オーバーレイストレージイメージ作成する。

$ qemu-img create -f qcow2 -b Rocky-9.4-aarch64.qcow2.base -F qcow2 Rocky-9.4-aarch64.qcow2 16G
Formatting 'Rocky-9.4-aarch64.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=17179869184 backing_file=Rocky-9.4-aarch64.qcow2.base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16

$ qemu-img info Rocky-9.4-aarch64.qcow2
image: Rocky-9.4-aarch64.qcow2
file format: qcow2
virtual size: 16 GiB (17179869184 bytes)
disk size: 196 KiB
cluster_size: 65536
backing file: Rocky-9.4-aarch64.qcow2.base
backing file format: qcow2
Format specific information:
    compat: 1.1
    compression type: zlib
    lazy refcounts: false
    refcount bits: 16
    corrupt: false
    extended l2: false

仮想マシン起動

sudo qemu-system-aarch64 \
-machine virt \
-cpu host \
-m 1024 \
-enable-kvm \
-kernel Rocky-9.4-aarch64.vmlinuz \
-initrd Rocky-9.4-aarch64.initramfs \
-append "root=/dev/vda3" \
-drive file=Rocky-9.4-aarch64.qcow2 \
-net nic,macaddr=52:54:00:12:34:11 -net tap,ifname=tap1 \
-vnc 0.0.0.0:1 -daemonize

仮想マシンの作成 FreeBSD編

https://www.freebsd.org/where/ より aarch64 の Boot Only の iso イメージをダウンロードする

$ ls -l FreeBSD-14.1-RELEASE-arm64-aarch64-bootonly.iso
-rw-r--r-- 1 pi pi 373553152 Nov 16 07:56 FreeBSD-14.1-RELEASE-arm64-aarch64-bootonly.iso

インストール実行

仮想ディスク作成

$ qemu-img create -f qcow2 FreeBSD-14.1-RELEASE-arm64-aarch64.qcow2.base 16G
Formatting 'FreeBSD-14.1-RELEASE-arm64-aarch64.qcow2.base', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=17179869184 lazy_refcounts=off refcount_bits=16

$ qemu-img info FreeBSD-14.1-RELEASE-arm64-aarch64.qcow2.base
image: FreeBSD-14.1-RELEASE-arm64-aarch64.qcow2.base
file format: qcow2
virtual size: 16 GiB (17179869184 bytes)
disk size: 196 KiB
cluster_size: 65536
Format specific information:
    compat: 1.1
    compression type: zlib
    lazy refcounts: false
    refcount bits: 16
    corrupt: false
    extended l2: false

インストーラを起動して、コマンドラインコンソールでインストールを実行する。
(カーネルや初期化RAMディスクの取り出しは不要で、ISOイメージから起動できる)

$ sudo qemu-system-aarch64 \
-machine virt \
-cpu host \
-enable-kvm \
-m 2048 \
-drive file=/media/work/iso/FreeBSD-14.1-RELEASE-arm64-aarch64-bootonly.iso,media=cdrom -boot c \
-device virtio-blk,drive=sda -drive id=sda,if=none,format=qcow2,file=FreeBSD-14.1-RELEASE-arm64-aarch64.qcow2.base \
-device virtio-net,netdev=net0,mac=52:54:00:12:34:12 -netdev tap,id=net0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown,ifname=tap2 \
-bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \
-vnc 0.0.0.0:2 -nographic

インストールができたらShellに落ちて shutdown -p now で終了

オーバーレイストレージイメージ作成

インストール完了直後のイメージをバッキングファイルとして、オーバーレイストレージイメージ作成する。

$ qemu-img create -f qcow2 -b FreeBSD-14.1-RELEASE-arm64-aarch64.qcow2.base -F qcow2 FreeBSD-14.1-RELEASE-arm64-aarch64.qcow2 16G
Formatting 'FreeBSD-14.1-RELEASE-arm64-aarch64.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=17179869184 backing_file=FreeBSD-14.1-RELEASE-arm64-aarch64.qcow2.base backing_fmt=qcow2 lazy_refcounts=off refcount_bits=16

$ qemu-img info FreeBSD-14.1-RELEASE-arm64-aarch64.qcow2
image: FreeBSD-14.1-RELEASE-arm64-aarch64.qcow2
file format: qcow2
virtual size: 16 GiB (17179869184 bytes)
disk size: 196 KiB
cluster_size: 65536
backing file: FreeBSD-14.1-RELEASE-arm64-aarch64.qcow2.base
backing file format: qcow2
Format specific information:
    compat: 1.1
    compression type: zlib
    lazy refcounts: false
    refcount bits: 16
    corrupt: false
    extended l2: false

仮想マシン起動

カーネルや初期化RAMディスクの取り出しは不要で、仮想マシン起動できる

sudo qemu-system-aarch64 \
-machine virt \
-cpu host \
-enable-kvm \
 -m 2048 \
-device virtio-blk,drive=sda -drive id=sda,if=none,format=qcow2,file=FreeBSD-14.1-RELEASE-arm64-aarch64.qcow2 \
-device virtio-net,netdev=net0,mac=52:54:00:12:34:12 -netdev tap,id=net0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown,ifname=tap2 \
-bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \
-vnc 0.0.0.0:2 -daemonize
GitHubで編集を提案

Discussion