Running aarch64 QEMU/KVM virtual machines on aarch64 Raspberry Pi host.
討論如何在ARM架構的Raspberry Pi執行另外一個系統的虛擬機。
如果你是想要在x86架構電腦用QEMU模擬ARM架構的樹莓派請看 這篇。
Raspberry Pi執行的是Linux系統,自然能夠跑Docker、Podman、LXC這類容器技術,那麼有沒有可能跑虛擬機呢?可以。x86架構平台常用的 Virt Manager+QEMU/KVM也能在ARM架構使用,並且能夠使用KVM核心模組加速虛擬機執行。
類似專案還有非官方移植的 jiangcuo/Proxmox-Port套件,可將樹莓派變成Proxmox系統。
本文Ivon採取的是比較簡陋的作法,直接裝Libvirt與QMEU套件。
1. 環境#
- 開發板:Raspberry Pi 5
- 系統版本:Raspberry Pi OS 12,核心版本6.6.42-v8-16k+
- 虛擬機系統:Alpine Linux ARM
考慮到虛擬機的硬碟存取速度,Raspberry Pi的系統最好安裝在SSD,或者至少虛擬機的qcow2虛擬磁碟得放在SSD分區讀取速度才會快。
另外Raspberry Pi 5的CPU老實說也不是很快,所以執行虛擬機的效率可能不如容器要好。
2. 安裝Libvirt套件#
- 安裝以下套件
sudo apt install qemu-system libguestfs-tools libvirt-clients libvirt-daemon-system bridge-utils virt-manager ovmf swtpm
- 調整使用者權限
sudo usermod -a -G libvirt $USER
sudo usermod -a -G kvm $USER
sudo usermod -a -G input $USER
- 設定開機自動啟用虛擬機服務
sudo systemctl enable libvirtd
sudo systemctl start libvirtd
sudo virsh net-start default
sudo virsh net-autostart default
- 檢查KVM存在與否
ls /dev/kvm
- 編輯
/boot/firmware/cmdline.txt
,在開機核心參數末端加入以下內容
cgroup_enable=cpuset cgroup_enable=devices cgroup_enable=freezer cgroup_enable=memory cgroup_memory=1
- 重開機,執行
virt-host-validate
指令,確認QEMU部份全部都有PASS,環境符合Libvirt需求。
3. Virt Manager新增Linux虛擬機#
請用 Cockpit或者 Virt Manager SSH遠端控制樹莓派上的虛擬機。
關於作業系統系統架構部分,QEMU/KVM只能跑同為ARM64架構的虛擬機,模擬x86架構會非常慢。
鑒於Windows 11 ARM安裝起來比較麻煩,而且吃效能,所以使用小巧的Alpine Linux ARM測試吧!
- 到 Alpine Linux ARM官網複製ISO下載連結,下載。
sudo wget https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/aarch64/alpine-standard-3.20.2-aarch64.iso
不知為何,Cockpit嘗試啟動虛擬機沒多久後,Raspberry Pi系統就會整個當掉無回應,可能是bug?所以我用Virt Manager新增虛擬機。
虛擬機架構選aarch64,UEFI韌體選
/usr/share/AAVMF/AAVMF_CODE.fd
開機後登入root帳號,執行
setup-alpine
指令稿,完成Alpine Linux系統安裝。
4. QEMU純指令開機#
本節是方便除錯用的開機方法。
- 建立虛擬硬碟
qemu-img create -f qcow2 alpine.qcow2 32G
- 建立儲存EFI VARS的二個檔案
truncate -s 64m varstore.img
truncate -s 64m efi.img
dd if=/usr/share/qemu-efi-aarch64/QEMU_EFI.fd of=efi.img conv=notrunc
- 啟動虛擬機,以下指令會進入純文字安裝界面
qemu-system-aarch64
-M virt \
-enable-kvm \
-cpu host \
-smp sockets=1,cores=4,threads=1 \
-m 2048 \
-drive if=pflash,format=raw,file="efi.img",readonly \
-drive if=pflash,format=raw,file="varstore.img" \
-device virtio-net-pci,netdev=net0,romfile="" \
-netdev type=user,id=net0 \
-object rng-random,filename=/dev/urandom,id=rng0 \
-device virtio-rng-pci,rng=rng0 \
-device virtio-blk-pci,drive=drv0 \
-drive format=qcow2,file="alpine.qcow2",if=none,id=drv0 \
-nographic \
-device virtio-scsi \
-device scsi-cd,drive=cd \
-drive if=none,id=cd,file="alpine-standard-3.20.2-aarch64.iso"