鲲鹏轻量级虚拟化实验(华为云ECS版)
鲲鹏轻量级虚拟化实验(华为云ECS版)
实验简介
实验介绍
本实验介绍在华为鲲鹏平台上安装鲲鹏轻量级虚拟化软件 StratoVirt,并在此之上配置虚拟机、管理虚拟机生命周期、管理虚拟机资源,以及了解如何对接 iSula 安全容器。
与最初基于物理服务器的版本相比,本版面向华为公有云 ECS 编写。公有云 ECS 默认不开放嵌套虚拟化(Guest 内部没有 /dev/kvm),而 StratoVirt 只支持 KVM 加速,因此 StratoVirt 无法直接在 ECS 内启动虚拟机。本实验的处理方式是:
- 保留 StratoVirt 的安装、KVM 能力检查、镜像准备等全部内容;
- 使用 QEMU + TCG(纯软件模拟) 承载 openEuler 官方 StratoVirt 演示镜像,启动同一台 openEuler 虚拟机;
- 使用 QMP(QEMU Machine Protocol) 完成生命周期、热插拔、Balloon、内存快照等全部管理练习。QMP 是 StratoVirt 与 QEMU 共同支持的管理接口,命令语义基本一致,差异点在文中逐条标注。
这样既不动摇"轻量级虚拟化 + QMP 管理"的核心技能,也能让学生在一个真实的公有云环境中完整走通实验,并理解"嵌套虚拟化"这一云上常见限制。
与物理服务器版本的差异(先读)
| 项目 | 物理服务器版本 | 华为云 ECS 版本(本手册) |
|---|---|---|
| 虚拟化加速 | KVM(/dev/kvm 可用) | 无 KVM,改用 QEMU/TCG 纯软件模拟 |
| 启动程序 | stratovirt | qemu-system-aarch64 |
| 管理接口 | StratoVirt QMP | QEMU QMP(需先执行 qmp_capabilities 握手) |
| 设备模型 | virtio-mmio(microvm) | virtio-pci(标准机 virt) |
| 镜像 | 手工编译内核 + Alpine rootfs | 官方 std-vmlinux.bin + openEuler 镜像 |
| 性能 | 接近原生 | 明显变慢,仅用于功能验证 |
说明:本手册任务一~任务六的主干命令与回显,均在华为云 ECS(openEuler 22.03 LTS,aarch64,8 vCPU)上实际验证通过。任务七的 iSulad 安装与配置可参照执行,安全容器运行部分受 KVM 限制,未在公有云 ECS 上验证。
建议课时
本实验建议安排 2.5~3 学时:任务一~任务三约 60 分钟(含镜像下载),任务四~任务六约 60 分钟,任务七(选做)约 30 分钟。
预备知识
学习本实验需要掌握基本的 Linux 操作系统操作命令,了解 SSH 登录、软件包安装、磁盘与进程的基本操作。
实验目的
- 理解 StratoVirt 的架构、原理,以及它对 KVM 的依赖。
- 掌握 StratoVirt 的安装与虚拟化能力检查。
- 掌握在公有云 ECS 上准备镜像并启动轻量级虚拟机。
- 掌握通过 QMP 管理虚拟机的生命周期、磁盘/网卡热插拔、内存 Balloon 与内存快照。
- 了解 StratoVirt 对接 iSula 安全容器(Kata Containers)的原理与配置。
实验环境
云主机(华为云 ECS)要求:
| 项目 | 要求 |
|---|---|
| 架构 | AArch64(鲲鹏,不能选 x86 规格) |
| 规格 | 建议 8 vCPU / 16 GiB 及以上(最低 4 vCPU / 8 GiB) |
| 系统盘 | 80 GiB 及以上 |
| 操作系统 | openEuler 22.03 LTS(aarch64) |
| 网络 | 绑定弹性公网 IP,安全组放通 TCP 22 |
| 登录方式 | SSH,root 用户 |
嵌套虚拟机配置:
| 类型 | 要求 |
|---|---|
| 数量 | 1 |
| 操作系统 | openEuler 22.03 LTS(aarch64) |
| vCPU | 4 核(最大可扩展 8 核) |
| 内存 | 4 GiB |
| 磁盘 | 官方镜像约 1.2 GiB(实验另加 512 MiB 数据盘) |
实验软件:
| 软件 | 用途 | 获取方式 |
|---|---|---|
| stratovirt | 轻量级虚拟化软件 | yum install stratovirt |
| qemu-system-aarch64 | 本实验的虚拟机运行载体(TCG) | yum install qemu-system-aarch64 |
| nmap(含 ncat) | 连接 QMP 管理通道 | yum install nmap |
| socat | 连接虚拟机串口控制台 | yum install socat |
| openEuler 官方镜像 | 内核与根盘 | openEuler 镜像站 |
| MobaXterm / 终端 | SSH 登录 ECS | 官网下载 |
实验架构
┌──────────────────────────── 华为云 ECS(aarch64,openEuler 22.03)────────────────────────────┐
│ │
│ ┌─────────────┐ QMP(unix socket) ┌──────────────────────────────────────────────┐ │
│ │ ncat 终端 │◄────────────────────►│ qemu-system-aarch64(TCG 模拟,替代 StratoVirt)│ │
│ └─────────────┘ │ ├─ 内存:4 GiB(virtio-balloon 可调) │ │
│ │ ├─ 磁盘:openEuler 官方镜像(virtio-blk) │ │
│ ┌─────────────┐ 串口 console.sock │ ├─ 网卡:virtio-net(可热插拔) │ │
│ │ socat 终端 │◄────────────────────►│ └─ QMP:/tmp/qmp1.socket │ │
│ └─────────────┘ └───────────────────┬──────────────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ openEuler 22.03 │ │
│ │ 嵌套虚拟机 │ │
│ └─────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────────────────┘
任务零:开通并初始化华为云 ECS
步骤1 购买 ECS
在华为云控制台购买一台 ECS,关键选项如下:
| 配置项 | 选择 |
|---|---|
| 计费模式 | 按需计费(实验结束及时释放) |
| 区域 | 就近选择 |
| 规格 | 鲲鹏通用计算型 kc1(如 8 vCPU / 16 GiB) |
| 镜像 | 公共镜像 → openEuler → openEuler 22.03 LTS(aarch64) |
| 系统盘 | 80 GiB 高 IO |
| 网络 | 默认 VPC,自动分配 |
| 弹性公网 IP | 现在购买,按带宽计费(5 Mbit/s 足够) |
| 安全组 | 放通 TCP 22(SSH) |
| 登录凭证 | 密码(本实验使用 root 登录) |
提示:实验只需一台 ECS。若预算有限,4 vCPU / 8 GiB 也可以完成,但 TCG 模式下启动和操作会明显变慢。
步骤2 登录 ECS
在本地终端(Windows 可用 MobaXterm 或 PowerShell 自带的 ssh)执行:
ssh root@<ECS 弹性公网 IP>
首次登录输入 yes,再输入购买时设置的密码。
步骤3 检查环境
uname -m # 应输出 aarch64
cat /etc/os-release # 应为 openEuler 22.03 LTS
nproc # CPU 核数
free -h # 内存
df -h / # 系统盘剩余空间
预期结果:
aarch64
NAME="openEuler"
VERSION="22.03 LTS"
...
步骤4 检查软件源
华为云 openEuler 镜像默认已配置华为云 repo:
cat /etc/yum.repos.d/openEuler.repo | grep baseurl
若后续安装软件时出现 GPG 校验失败(公有云镜像常见),在命令后追加 --nogpgcheck 临时跳过校验即可,例如:
yum install -y stratovirt --nogpgcheck
注意:
--nogpgcheck仅用于实验环境绕过镜像源签名问题,生产环境不建议长期使用。
任务一:安装 StratoVirt 并验证虚拟化能力
本任务完成 StratoVirt 的安装,并学会判断一台云主机是否具备运行 StratoVirt 的条件。这是本实验在云上最重要的一个认知环节。
步骤1 安装 StratoVirt
yum install -y stratovirt --nogpgcheck
查看版本:
stratovirt -version
预期输出:
StratoVirt 2.1.0
步骤2 检查 KVM 设备
StratoVirt 是基于 KVM 的轻量级虚拟化软件,运行前必须存在 /dev/kvm 设备:
ls -l /dev/kvm
在华为云 ECS 上,预期输出为:
ls: cannot access '/dev/kvm': No such file or directory
步骤3 查看内核虚拟化初始化信息
dmesg | grep -i 'HYP mode'
预期输出:
[ 1.217066] kvm [1]: HYP mode not available
HYP mode not available 表示当前 ECS 自身运行在 KVM 虚拟机中,宿主机没有向它暴露 ARM 的 EL2(Hypervisor)异常级别,因此 ECS 内部不能再创建 KVM 虚拟机。这就是公有云上"不支持嵌套虚拟化"的直接表现。
步骤4 结论与实验方案
- StratoVirt 只支持
-accel kvm,没有 TCG 软件模拟后端,因此在没有/dev/kvm的 ECS 上无法启动。 - 本实验后续改用 QEMU 的 TCG 模式运行同一套 openEuler 官方 StratoVirt 镜像,并使用 QMP 完成全部管理练习。
- 如果后续拿到支持嵌套虚拟化的环境(裸金属服务器、支持嵌套虚拟化的规格),可以无缝切回 StratoVirt,命令见附录 D。
本步骤的验证实验在任务二下载完镜像后进行(需要内核和根盘才能看到 StratoVirt 的真实报错)。
任务二:准备虚拟机镜像
步骤1 安装运行环境
yum install -y qemu-system-aarch64 nmap socat --nogpgcheck
qemu-system-aarch64:本实验的虚拟机运行载体。nmap:提供ncat,用于连接 QMP 管理通道。socat:用于连接虚拟机串口控制台。
检查:
qemu-system-aarch64 --version | head -1
which ncat socat
预期输出类似:
QEMU emulator version 6.2.0 (qemu-6.2.0-88.oe2203)
/usr/bin/ncat
/usr/bin/socat
步骤2 下载 openEuler 官方镜像
StratoVirt 官方在 openEuler 22.03 LTS 镜像目录中提供了配套的内核与根盘。本实验使用 标准机(virt) 版本,因此内核必须使用 std-vmlinux.bin。
mkdir -p /opt/vm
cd /opt/vm
BASE=https://dl-cdn.openeuler.openatom.cn/openEuler-22.03-LTS/stratovirt_img/aarch64
wget $BASE/std-vmlinux.bin
wget $BASE/openEuler-22.03-LTS-stratovirt-aarch64.img.xz
wget $BASE/std-vmlinux.bin.sha256sum
wget $BASE/openEuler-22.03-LTS-stratovirt-aarch64.img.xz.sha256sum
如果
dl-cdn地址访问慢,可换成https://repo.openeuler.org/openEuler-22.03-LTS/stratovirt_img/aarch64/,内容相同。
步骤3 校验并解压
cd /opt/vm
sha256sum -c std-vmlinux.bin.sha256sum
sha256sum -c openEuler-22.03-LTS-stratovirt-aarch64.img.xz.sha256sum
xz -dk openEuler-22.03-LTS-stratovirt-aarch64.img.xz
ls -lh
预期结果:
std-vmlinux.bin: OK
openEuler-22.03-LTS-stratovirt-aarch64.img.xz: OK
...
-rw-r--r-- 1 root root 1.2G ... openEuler-22.03-LTS-stratovirt-aarch64.img
-rw-r--r-- 1 root root 24M ... std-vmlinux.bin
步骤4 认识两个内核(关键)
镜像目录下有两个内核文件,选错内核是本实验最常见的启动失败原因:
| 文件 | 大小 | 适用机器类型 | 设备模型 | 能否配标准镜像启动 |
|---|---|---|---|---|
vmlinux.bin | 约 10.3 MiB | microvm | virtio-mmio | 不能:没有 virtio-blk-pci,会出现 VFS: Cannot open root device "vda" 内核 panic |
std-vmlinux.bin | 约 23.7 MiB | 标准机 virt | virtio-pci | 可以 |
本实验使用标准机 virt + std-vmlinux.bin + 官方根盘。若使用 microvm,需要配套的 microvm 内核和 virtio-blk-device 设备模型,不能直接套用本文的 root=/dev/vda 配置。
步骤5 验证 StratoVirt 在本机无法启动(理解 KVM 依赖)
下载完镜像后,可以亲眼看到 StratoVirt 在无 KVM 环境下的真实报错:
stratovirt -machine virt -accel kvm \
-kernel /opt/vm/std-vmlinux.bin \
-append "root=/dev/vda console=ttyAMA0 rw" \
-drive file=/opt/vm/openEuler-22.03-LTS-stratovirt-aarch64.img,id=rootfs \
-m 2G -smp 2 \
-qmp unix:/tmp/sv.qmp,server,nowait -D /tmp/sv.log -nographic
cat /tmp/sv.log
预期输出(关键行):
ERROR: Failed to open /dev/kvm: No such file or directory (os error 2)
这说明 StratoVirt 已经安装成功,但缺少 KVM 设备无法运行。后续任务改用 QEMU/TCG 完成。
步骤6(拓展,选做)手工编译内核与制作 rootfs
本节仅用于理解原理,不要求完成。公有云 ECS 上编译内核耗时长,且手工镜像容易出现驱动缺失、串口配置错误等问题,实验统一使用官方镜像。
编译内核(了解):
yum install -y git flex bison elfutils-libelf-devel dwarves bc openssl-devel \
ncurses-devel rpm-build --nogpgcheck
yum groupinstall -y "Development Tools" --nogpgcheck
cd /root
git clone https://gitee.com/openeuler/kernel
cd kernel
git checkout openEuler-22.03-LTS
# 使用 StratoVirt 提供的 microvm 内核配置
cp ~/stratovirt-master/docs/kernel_config/kernel_config_5.10_aarch64 /root/kernel/kernel510.config
make olddefconfig
make -j"$(nproc)" vmlinux
objcopy -O binary vmlinux vmlinux.bin
注意事项:
- 编译产物是 microvm 内核,只能配合 microvm 机器类型和 virtio-mmio 设备使用。
- 编译时间较长(ECS 上可能 30 分钟以上),可跳过。
- 若使用本手册的标准机配置,请直接使用官方
std-vmlinux.bin。
制作 rootfs(了解):
cd /home
dd if=/dev/zero of=./rootfs.ext4 bs=1G count=10
mkfs.ext4 ./rootfs.ext4
mkdir -p /mnt/rootfs
mount ./rootfs.ext4 /mnt/rootfs && cd /mnt/rootfs
wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.16.0-aarch64.tar.gz
tar -zxvf alpine-minirootfs-3.16.0-aarch64.tar.gz
rm alpine-minirootfs-3.16.0-aarch64.tar.gz
若 ECS 无法访问 alpine 官网,可由教师提供
alpine-minirootfs-3.16.0-aarch64.tar.gz,用scp上传到/mnt/rootfs后再解压。
为镜像制作一个简单的 /sbin/init。注意:此时当前目录是挂载点,但 /sbin/init 是宿主机的绝对路径,必须写成 $ROOT/sbin/init,否则会破坏 ECS 自身的 init!
ROOT=/mnt/rootfs
rm -f "$ROOT/sbin/init"
cat > "$ROOT/sbin/init" <<'EOF'
#!/bin/sh
mount -t devtmpfs dev /dev
mount -t proc proc /proc
mount -t sysfs sysfs /sys
ip link set up dev lo
exec /sbin/getty -n -l /bin/sh 115200 /dev/ttyAMA0
EOF
chmod +x "$ROOT/sbin/init"
cd /
umount /mnt/rootfs
注意:
- 标准机
virt的串口是ttyAMA0,不是ttyS0;写错会看不到登录提示符。 - 不要在 init 末尾直接写
poweroff -f,否则串口会话结束会立刻关机。 - 手工 rootfs 的驱动、串口配置与官方内核不一定匹配,容易启动失败;实验仍以官方镜像为准。
步骤7(了解)标准启动所需固件
StratoVirt 在 aarch64 上支持 UEFI 标准启动,需要 EDK II 固件:
yum install -y edk2-aarch64 --nogpgcheck
ls /usr/share/edk2/aarch64/
本实验使用 -kernel 直接引导内核,不经过 UEFI 固件,因此该步骤只作了解。
任务三:启动第一台虚拟机
步骤1 创建启动脚本
cat > /opt/vm/start-vm.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
VM_DIR=/opt/vm
# 防止重复启动(两个实例同时写一块磁盘会损坏镜像)
if [ -f "$VM_DIR/qemu.pid" ] && kill -0 "$(cat "$VM_DIR/qemu.pid")" 2>/dev/null; then
echo "VM already running (pid $(cat "$VM_DIR/qemu.pid"))"
exit 1
fi
rm -f /tmp/qmp1.socket "$VM_DIR/console.sock"
qemu-system-aarch64 \
-machine virt,gic-version=3 \
-accel tcg,thread=multi -cpu cortex-a72 \
-smp 4,maxcpus=8 -m 4G \
-kernel "$VM_DIR/std-vmlinux.bin" \
-append "root=/dev/vda console=ttyAMA0 rw reboot=k panic=1" \
-drive file="$VM_DIR/openEuler-22.03-LTS-stratovirt-aarch64.img",if=virtio,format=raw \
-device virtio-balloon-pci,id=balloon0 \
-device pcie-root-port,id=rp1,chassis=1,slot=1 \
-device pcie-root-port,id=rp2,chassis=2,slot=2 \
-display none \
-qmp unix:/tmp/qmp1.socket,server=on,wait=off \
-chardev socket,id=con0,path="$VM_DIR/console.sock",server=on,wait=off,logfile="$VM_DIR/console.log",logappend=on \
-serial chardev:con0 \
-pidfile "$VM_DIR/qemu.pid" -daemonize
echo "VM started, pid $(cat "$VM_DIR/qemu.pid")"
EOF
chmod +x /opt/vm/start-vm.sh
步骤2 启动虚拟机
/opt/vm/start-vm.sh
查看进程和串口日志:
ps -p "$(cat /opt/vm/qemu.pid)" -o pid,etime,pcpu,pmem,comm
tail -f /opt/vm/console.log
TCG 为纯软件模拟,启动到登录提示约需 15~30 秒。看到如下内容即启动成功:
openEuler 22.03 LTS
Kernel 5.10.0 on an aarch64
StratoVirt login:
按
Ctrl+C退出tail。
步骤3 登录虚拟机
新开一个 SSH 终端(保持虚拟机运行),执行:
socat -,raw,echo=0 unix-connect:/opt/vm/console.sock
出现登录提示后输入:
用户名:root
密码:openEuler12#$
登录成功后会看到:
[root@StratoVirt ~]#

断开控制台:按
Ctrl+C(只断开 socat,不会关闭虚拟机)。再次执行socat命令可重新接入。
步骤4 启动参数说明
| 参数 | 作用 | 说明 |
|---|---|---|
-machine virt,gic-version=3 | 标准机机型 | aarch64 的标准机;对应 StratoVirt 的 -machine virt |
-accel tcg,thread=multi | 软件模拟加速器 | 无 KVM 时的替代方案 |
-cpu cortex-a72 | 模拟 CPU 型号 | 鲲鹏平台通用 |
-smp 4,maxcpus=8 | 4 个在线 vCPU,最多可扩展到 8 个 | 便于观察 offline vCPU |
-m 4G | 内存 4 GiB | Balloon 实验使用 |
-kernel std-vmlinux.bin | 标准机内核 | 必须用 std 内核 |
-append ... | 内核命令行 | 串口 ttyAMA0、根盘 /dev/vda |
-drive ...,if=virtio | 根盘 | virtio-blk-pci 设备 |
-device virtio-balloon-pci | 内存气球设备 | 任务五使用 |
-device pcie-root-port ×2 | PCIe 根端口 | 热插拔磁盘/网卡必须挂到根端口上 |
-qmp unix:/tmp/qmp1.socket | QMP 管理通道 | 任务四使用 |
-chardev socket... + -serial | 串口控制台 | 通过 socat 接入 |
-daemonize | 后台运行 | 断开 SSH 不影响虚拟机 |
步骤5 常见启动问题
| 现象 | 原因 | 处理 |
|---|---|---|
Kernel panic ... VFS: Cannot open root device "vda" | 使用了 microvm 内核 vmlinux.bin | 改用 std-vmlinux.bin |
| 启动后没有任何输出 | 串口参数写成 ttyS0,或没有接入 console.sock | 内核命令行用 ttyAMA0,用 socat 接入 |
qemu-system-aarch64: -drive ... Could not open | 镜像路径错误或未解压 | 检查 /opt/vm 下文件 |
| 启动非常慢 | TCG 软件模拟 | 正常现象;可减小 -smp/-m,但功能验证建议保持 4 核 4G |
任务四:管理虚拟机生命周期
StratoVirt 与 QEMU 都通过 QMP 管理虚拟机。QEMU 的 QMP 在建立连接后需要先执行一次 qmp_capabilities 握手,这是与 StratoVirt 的最大差异。
步骤1 连接 QMP
新开一个 SSH 终端(虚拟机已在后台运行),执行:
ncat -U /tmp/qmp1.socket
会收到 QEMU 的问候消息:
{"QMP": {"version": {"qemu": {"micro": 0, "minor": 2, "major": 6}, "package": "qemu-6.2.0-88.oe2203"}, "capabilities": ["oob"]}}
步骤2 执行 QMP 握手
{"execute":"qmp_capabilities"}
返回:
{"return": {}}
没有这一步,后续命令会返回
CommandNotFound或QMP capability negotiation failed。StratoVirt 的旧示例中没有这一步,直接敲命令即可,二者不同。
步骤3 查询虚拟机信息
查询状态:
{"execute":"query-status"}
返回:
{"return": {"status": "running", "singlestep": false, "running": true}}
查询 vCPU:
{"execute":"query-cpus-fast"}
返回 4 个 vCPU 的信息(thread-id、qom-path、cpu-index 等)。
QEMU 6.2 已移除
query-cpus命令,请使用query-cpus-fast。
查询 vCPU 上线情况:
{"execute":"query-hotpluggable-cpus"}
返回 8 个可能的 vCPU,其中 core-id 0~3 带有 qom-path(在线),4~7 没有(离线)。这与原 StratoVirt 实验中"online 的 vCPU 有 qom-path"的结论一致。
步骤4 暂停虚拟机
{"execute":"stop"}
查询状态确认:
{"execute":"query-status"}
返回 "status": "paused"。
步骤5 恢复虚拟机
{"execute":"cont"}
再次查询状态,返回 "status": "running"。
步骤6 退出虚拟机
{"execute":"quit"}
QMP 连接会断开,虚拟机进程退出。按 Ctrl+C 退出 ncat,再按回车回到主机命令行。
提示:直接按
Ctrl+C断开ncat不会关闭虚拟机;只有发送quit才会退出虚拟机进程。
重新启动虚拟机:
/opt/vm/start-vm.sh
步骤7 与 StratoVirt QMP 的差异对照
| 操作 | StratoVirt | QEMU(本实验) |
|---|---|---|
| 握手 | 无 | 必须先 {"execute":"qmp_capabilities"} |
| 查询 CPU | query-cpus | query-cpus-fast |
| 查询拓扑 | query-hotpluggable-cpus | 同名,可用 |
| 暂停/恢复/退出 | stop / cont / quit | 同名,可用 |
| 管理通道 | /tmp/qmp1.socket | /tmp/qmp1.socket |
任务五:管理虚拟机资源
本任务中的热插拔操作需要虚拟机启动时预留 PCIe 根端口(启动脚本中的
rp1、rp2),否则会报错Bus 'pcie.0' does not support hotplugging。
步骤1 热插拔磁盘
准备数据盘
公有云 ECS 没有多余的空闲块设备,本实验用文件模拟一块 512 MiB 的磁盘:
dd if=/dev/zero of=/opt/vm/data1.img bs=1M count=512 status=none
mkfs.ext4 -q /opt/vm/data1.img
热插磁盘
在 QMP 终端中依次执行:
{"execute":"blockdev-add","arguments":{"node-name":"drive-0","driver":"file","filename":"/opt/vm/data1.img"}}
{"execute":"device_add","arguments":{"driver":"virtio-blk-pci","drive":"drive-0","id":"drive-0","bus":"rp1"}}
两条命令均返回 {"return": {}}。
在虚拟机内验证
通过串口控制台登录虚拟机,执行:
lsblk
可以看到新增的 vdb:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
vda 254:0 0 1.2G 0 disk /
vdb 254:16 0 512M 0 disk
挂载并写入数据:
mkdir -p /mnt/data
mount /dev/vdb /mnt/data
df -h /mnt/data
echo "hello stratovirt" > /mnt/data/test.txt
cat /mnt/data/test.txt
热拔磁盘
先在虚拟机内卸载文件系统(否则设备可能处于 busy 状态):
umount /mnt/data
在 QMP 终端中执行:
{"execute":"device_del","arguments":{"id":"drive-0"}}
等待数秒(等 guest 完成设备移除),再执行:
{"execute":"blockdev-del","arguments":{"node-name":"drive-0"}}
在虚拟机内再次执行 lsblk,vdb 已消失。
注意:
device_del后立即执行blockdev-del可能报Node drive-0 is in use,等待几秒后重试即可;只要 guest 中vdb已消失,稍后一定能删除成功。
步骤2 热插拔网卡
在宿主机创建 tap 设备
ip tuntap add tap0 mode tap
ip link set tap0 up
ip addr add 10.0.0.1/24 dev tap0
热插网卡
在 QMP 终端中执行:
{"execute":"netdev_add","arguments":{"type":"tap","id":"net-0","ifname":"tap0","script":"no","downscript":"no"}}
{"execute":"device_add","arguments":{"driver":"virtio-net-pci","netdev":"net-0","id":"net-0","bus":"rp2"}}
在虚拟机内验证
ls /sys/class/net
ip link set ens2 up
ip addr add 10.0.0.2/24 dev ens2
ip -brief addr show ens2
新网卡名称可能是
ens2或eth1,以ls /sys/class/net的实际结果为准。
在宿主机验证连通性
ping -c 2 10.0.0.2
预期可以 ping 通(0% packet loss)。
热拔网卡
{"execute":"device_del","arguments":{"id":"net-0"}}
{"execute":"netdev_del","arguments":{"id":"net-0"}}
虚拟机内 ls /sys/class/net 中对应的网卡消失。
说明:本实验只为验证热插拔,tap 网卡与 ECS 主网卡 eth0 无关,不会影响 SSH 连接。
步骤3 Balloon 设备使用
Balloon 用于从虚拟机回收空闲内存。启动脚本中已经加入 -device virtio-balloon-pci,id=balloon0。
在虚拟机内查看内存
free -m
初始 total 约为 3.9 GiB(启动时配置 4 GiB)。
通过 QMP 回收内存
将虚拟机内存调整为 1 GiB(单位:字节):
{"execute":"balloon","arguments":{"value":1073741824}}
执行后会收到 BALLOON_CHANGE 事件。查询当前实际内存:
{"execute":"query-balloon"}
返回类似:
{"return": {"actual": 4160749568}}
再次在虚拟机内执行 free -m,可以看到 total 明显下降(逐步回收,约 1 GiB)。
恢复内存
{"execute":"balloon","arguments":{"value":4294967296}}
说明:Balloon 回收的是 guest 中空闲的内存,不是硬性限制;guest 内存紧张时会自动归还。
任务六:虚拟机内存快照
StratoVirt 支持对暂停状态的虚拟机制作快照,并支持以快照恢复。QEMU 同样支持,但快照文件格式不同:StratoVirt 生成 memory + state 两个目录,QEMU 生成单个迁移流文件。
步骤1 暂停虚拟机
在 QMP 终端中执行:
{"execute":"stop"}
{"execute":"query-status"}
状态应为 paused。
步骤2 制作快照
QEMU 6.2 不支持 file: 迁移协议,使用 exec: 协议把迁移流写入文件:
{"execute":"migrate","arguments":{"uri":"exec:cat > /opt/vm/snapshot.bin"}}
查询迁移状态:
{"execute":"query-migrate"}
当返回中包含 "status": "completed" 时,快照制作完成:
{"return": {"status": "completed", ...}}
在宿主机查看快照文件:
ls -lh /opt/vm/snapshot.bin
文件大小约为虚拟机实际使用的内存量(约 190 MB)。
步骤3 退出虚拟机
{"execute":"quit"}
步骤4 从快照恢复虚拟机
使用与启动时完全相同的设备配置,并增加 -incoming 参数(QMP 使用新的 socket 路径):
qemu-system-aarch64 \
-machine virt,gic-version=3 \
-accel tcg,thread=multi -cpu cortex-a72 \
-smp 4,maxcpus=8 -m 4G \
-kernel /opt/vm/std-vmlinux.bin \
-append "root=/dev/vda console=ttyAMA0 rw reboot=k panic=1" \
-drive file=/opt/vm/openEuler-22.03-LTS-stratovirt-aarch64.img,if=virtio,format=raw \
-device virtio-balloon-pci,id=balloon0 \
-device pcie-root-port,id=rp1,chassis=1,slot=1 \
-device pcie-root-port,id=rp2,chassis=2,slot=2 \
-display none \
-qmp unix:/tmp/qmp2.socket,server=on,wait=off \
-chardev socket,id=con0,path=/opt/vm/console.sock,server=on,wait=off,logfile=/opt/vm/console.log,logappend=on \
-serial chardev:con0 \
-incoming "exec:cat /opt/vm/snapshot.bin" \
-pidfile /opt/vm/qemu.pid -daemonize
步骤5 确认恢复结果
连接新的 QMP:
ncat -U /tmp/qmp2.socket
执行握手和查询:
{"execute":"qmp_capabilities"}
{"execute":"query-migrate"}
{"execute":"query-status"}
query-migrate返回"status": "completed"表示快照加载完成;- 此时
query-status可能返回paused,执行{"execute":"cont"}恢复运行; - 再次查询状态为
running。
通过串口控制台重新登录,确认虚拟机正常运行:
socat -,raw,echo=0 unix-connect:/opt/vm/console.sock
注意:恢复时
-incoming的路径、内存大小、设备数量必须与快照时一致,否则会恢复失败。
任务七(选做):对接 iSula 安全容器
重要说明:Kata Containers 使用 StratoVirt 作为 hypervisor,启动安全容器同样需要
/dev/kvm,并且需要可访问的容器镜像仓库。华为云 ECS 默认不支持嵌套虚拟化,因此本任务无法在普通公有云 ECS 上完整运行。本任务在 ECS 上可完成的部分:iSulad 安装、devicemapper 存储配置、
isula info验证、Kata 配置文件修改(作为演示)。安全容器的实际启动需要支持 KVM 的环境(裸金属服务器或支持嵌套虚拟化的规格)。
步骤1 安装 iSulad
openEuler 22.03 官方仓库已提供 iSulad,无需修改 yum 源(原手册切换到 21.09 源的做法在公有云上容易破坏软件源,不建议使用):
提示:修改配置前先备份
/etc/isulad/daemon.json(cp /etc/isulad/daemon.json /etc/isulad/daemon.json.bak);不同 iSulad 版本的字段可能略有差异,最终以isula info的输出为准。
yum install -y iSulad lvm2 --nogpgcheck
systemctl enable --now isulad
isula version
步骤2 配置 devicemapper 存储
使用文件模拟一块 10 GiB 块设备:
dd if=/dev/zero of=/opt/isula_images bs=1G count=10
losetup /dev/loop0 /opt/isula_images
pvcreate /dev/loop0
vgcreate isulaVG0 /dev/loop0
lvcreate --wipesignatures y -n thinpool isulaVG0 -l 95%VG
lvcreate --wipesignatures y -n thinpoolmeta isulaVG0 -l 1%VG
lvconvert -y --zero n -c 512K --thinpool isulaVG0/thinpool --poolmetadata isulaVG0/thinpoolmeta
创建自动扩容配置 /etc/lvm/profile/isulaVG0-thinpool.profile:
activation {
thin_pool_autoextend_threshold=80
thin_pool_autoextend_percent=20
}
应用配置:
lvchange --metadataprofile isulaVG0-thinpool isulaVG0/thinpool
步骤3 修改 iSulad 配置
编辑 /etc/isulad/daemon.json,将存储驱动改为 devicemapper:
"storage-driver": "devicemapper",
"storage-opts": [
"dm.thinpooldev=/dev/mapper/isulaVG0-thinpool",
"dm.fs=ext4",
"dm.min_free_space=10%"
]
若只是验证 iSulad 基础功能(不使用 Kata),将默认运行时保持为 runc:
"default-runtime": "runc"
重启并验证:
systemctl daemon-reload
systemctl restart isulad
isula info
isula info 中应能看到 Storage Driver: devicemapper。
daemon.json是一个完整的 JSON 文件,修改时保留原有字段并注意逗号。改完建议先校验语法,再重启服务:python3 -m json.tool /etc/isulad/daemon.json > /dev/null && echo "JSON OK"
步骤4 配置 Kata Containers 使用 StratoVirt(需 KVM)
安装 Kata:
yum install -y kata-containers --nogpgcheck
编辑 /usr/share/defaults/kata-containers/configuration.toml,将 hypervisor 配置为 StratoVirt:
[hypervisor.stratovirt]
path = "/usr/bin/stratovirt"
kernel = "/var/lib/kata/vmlinux.bin"
initrd = "/var/lib/kata/kata-containers-initrd.img"
block_device_driver = "virtio-mmio"
use_vsock = true
internetworking_model = "tcfilter"
sandbox_cgroup_with_emulator = false
disable_new_netns = false
disable_block_device_use = false
disable_vhost_net = true
并将 iSulad 的默认运行时改为 Kata:
"default-runtime": "io.containerd.kata.v2"
重启 iSulad:
systemctl restart isulad
步骤5 运行安全容器(在支持 KVM 的环境执行)
isula run -tid --runtime "io.containerd.kata.v2" --net=none --name test busybox:latest sh
isula ps -a
isula exec -it test sh
在无 KVM 的 ECS 上,该命令通常会失败(容器退出码 125),
isula logs test或 journalctl 中一般能看到 StratoVirt/KVM 启动失败的信息,这是环境限制而非配置错误。
步骤6 在 ECS 上验证 iSulad 基础功能(替代练习)
如果只是练习 iSulad 命令与存储配置,可以在 ECS 上使用 runc 运行时:
isula run -tid --runtime runc --net=none --name test busybox:latest sh
isula ps -a
isula exec -it test sh
需要能够访问容器镜像仓库(如华为云 SWR 或实验提供的私有仓库)。若无法拉取镜像,可用
isula load -i <镜像tar包>离线导入。
任务八:清理环境
实验完成后,按顺序清理,避免占用磁盘和端口。
步骤1 停止虚拟机
/opt/vm/stop-vm.sh
或手动:
kill "$(cat /opt/vm/qemu.pid)"
步骤2 删除临时文件
rm -f /tmp/qmp1.socket /tmp/qmp2.socket /tmp/sv.qmp /tmp/sv.log
rm -f /opt/vm/console.sock /opt/vm/snapshot.bin /opt/vm/data1.img
rm -f /opt/vm/console.log /opt/vm/console.log.old /opt/vm/console.log.prev /opt/vm/console.log.bak
ip link del tap0 2>/dev/null || true
步骤3 可选:删除镜像与软件
如需释放磁盘空间(镜像约 1.3 GiB):
rm -f /opt/vm/openEuler-22.03-LTS-stratovirt-aarch64.img
rm -f /opt/vm/openEuler-22.03-LTS-stratovirt-aarch64.img.xz
rm -f /opt/vm/std-vmlinux.bin
如需卸载可选组件:
systemctl stop isulad 2>/dev/null || true
yum remove -y iSulad kata-containers 2>/dev/null || true
步骤4 释放云资源
实验结束后,在华为云控制台删除 ECS 和弹性公网 IP,避免继续计费。
实验总结
通过本次实验:
- 理解了 StratoVirt 的架构与"只支持 KVM"的加速器限制;
- 掌握了 StratoVirt 的安装,以及用
/dev/kvm、dmesg判断主机是否支持嵌套虚拟化; - 掌握了在公有云 ECS 上使用 QEMU/TCG 运行 openEuler 官方 StratoVirt 镜像;
- 掌握了通过 QMP 查询状态、暂停/恢复/退出虚拟机;
- 掌握了磁盘、网卡热插拔与 Balloon 内存回收;
- 掌握了虚拟机内存快照的制作与恢复;
- 了解了 StratoVirt 对接 iSula/Kata 安全容器的配置方法与 KVM 依赖。
思考题
- 为什么 StratoVirt 在华为云 ECS 上无法启动?如何判断一台主机是否具备运行条件?
vmlinux.bin和std-vmlinux.bin有什么区别?选错会出现什么现象?- QMP 中
query-hotpluggable-cpus返回的qom-path代表什么? - 热插拔磁盘时,为什么
device_add要指定bus=rp1?不指定会报什么错? - QEMU 的内存快照与 StratoVirt 的快照文件结构有什么不同?恢复时为什么需要执行
cont? - 如果实验环境换成裸金属服务器,如何改回使用 StratoVirt?需要修改哪些参数?
参考要点:
- 没有
/dev/kvm,dmesg显示HYP mode not available;StratoVirt 只支持 KVM,无 TCG 后端。 - microvm 内核只带 virtio-mmio 设备支持,没有 virtio-blk-pci;配标准镜像会
VFS: Cannot open root device "vda"。 qom-path表示该 vCPU 已经上线;offline 的 vCPU 没有该字段。pcie.0根总线不支持直接热插拔,必须挂到pcie-root-port上,否则报Bus 'pcie.0' does not support hotplugging。- StratoVirt 生成
memory/state目录,QEMU 生成单个迁移流文件;-incoming加载完成后 QEMU 处于paused,需要cont恢复运行。 - 使用
stratovirt -machine virt -accel kvm,把-drive/-device换成 StratoVirt 的virtio-blk、virtio-net参数(见附录 D)。
附录 A:华为云 ECS 采购与初始化清单
| 检查项 | 要求 | 检查命令 |
|---|---|---|
| 架构 | aarch64 | uname -m |
| 操作系统 | openEuler 22.03 LTS | cat /etc/os-release |
| CPU/内存 | ≥ 4 vCPU / 8 GiB(建议 8/16) | nproc; free -h |
| 系统盘 | ≥ 80 GiB | df -h / |
| 公网 IP | 已绑定 | ip addr |
| SSH | 安全组放通 22 | 本地 ssh root@EIP |
| 软件源 | 华为云 openEuler repo | cat /etc/yum.repos.d/openEuler.repo |
| KVM | 无(预期) | ls /dev/kvm |
附录 B:常见问题(FAQ)
Q1:安装软件时提示 GPG 校验失败怎么办?
在命令后加 --nogpgcheck,例如:
yum install -y stratovirt --nogpgcheck
Q2:编译内核时提示缺少 flex、bison、dwarves 等工具?
yum install -y flex bison elfutils-libelf-devel dwarves bc openssl-devel \
ncurses-devel rpm-build --nogpgcheck
yum groupinstall -y "Development Tools" --nogpgcheck
Q3:make -j vmlinux 执行很久,可以跳过吗?
可以。本实验直接使用官方 std-vmlinux.bin,编译内核仅为拓展了解。
Q4:虚拟机启动后内核 panic,提示找不到 vda?
使用了 microvm 内核 vmlinux.bin。改用 std-vmlinux.bin 即可。
Q5:虚拟机启动后串口没有任何输出?
- 内核命令行必须是
console=ttyAMA0(不是ttyS0); - 必须用
socat接入/opt/vm/console.sock; - 确认虚拟机进程存在:
ps -p $(cat /opt/vm/qemu.pid)。
Q6:QMP 命令没有反应或报 CommandNotFound?
先执行一次握手:
{"execute":"qmp_capabilities"}
另外 QEMU 6.2 没有 query-cpus,请用 query-cpus-fast。
Q7:热插拔磁盘报 Bus 'pcie.0' does not support hotplugging?
启动时没有预留 PCIe 根端口。使用本手册的启动脚本(含 -device pcie-root-port),并在 device_add 中指定 bus=rp1。
Q8:migrate 使用 file:/path 报 expects a valid migration protocol?
QEMU 6.2 不支持 file: 迁移协议,改用:
{"execute":"migrate","arguments":{"uri":"exec:cat > /opt/vm/snapshot.bin"}}
Q9:快照恢复后虚拟机是 paused 状态?
正常现象,执行 {"execute":"cont"} 恢复运行。
Q10:ncat 或 socat 命令不存在?
yum install -y nmap socat --nogpgcheck
Q11:虚拟机运行很卡?
TCG 是纯软件模拟,性能有限。功能验证建议保持 -smp 4 -m 4G;若宿主机核数较少可降到 -smp 2 -m 2G。
Q12:磁盘空间不足?
官方镜像解压后约 1.2 GiB,压缩包约 131 MiB,快照约 190 MiB。实验完成后按任务八清理。
Q13:能否在 ECS 上直接使用 StratoVirt?
不能。StratoVirt 只支持 KVM,而 ECS 默认不暴露 /dev/kvm。需使用裸金属服务器或支持嵌套虚拟化的规格。
Q14:/dev/vhost-vsock 不存在怎么办?
modprobe vhost_vsock
ls -l /dev/vhost-vsock
该设备用于 Kata 安全容器,本实验的 QEMU 虚拟机不依赖它。
Q15:ECS 重启后虚拟机会自动启动吗?
不会。本实验的虚拟机是手工启动的进程,ECS 重启后需要重新执行 /opt/vm/start-vm.sh。
附录 C:命令速查表
| 功能 | 命令 |
|---|---|
| 安装 StratoVirt | yum install -y stratovirt --nogpgcheck |
| 查看 StratoVirt 版本 | stratovirt -version |
| 检查 KVM | ls -l /dev/kvm、dmesg | grep -i 'HYP mode' |
| 安装运行环境 | yum install -y qemu-system-aarch64 nmap socat --nogpgcheck |
| 启动虚拟机 | /opt/vm/start-vm.sh |
| 连接串口 | socat -,raw,echo=0 unix-connect:/opt/vm/console.sock |
| 连接 QMP | ncat -U /tmp/qmp1.socket |
| 查看状态 | {"execute":"query-status"} |
| 暂停/恢复/退出 | {"execute":"stop"} / {"execute":"cont"} / {"execute":"quit"} |
| 查询 CPU | {"execute":"query-cpus-fast"} |
| 查询 CPU 拓扑 | {"execute":"query-hotpluggable-cpus"} |
| 热插磁盘 | blockdev-add + device_add ... bus=rp1 |
| 热插网卡 | netdev_add + device_add ... bus=rp2 |
| Balloon 回收内存 | {"execute":"balloon","arguments":{"value":1073741824}} |
| 制作快照 | {"execute":"migrate","arguments":{"uri":"exec:cat > /opt/vm/snapshot.bin"}} |
| 停止虚拟机 | /opt/vm/stop-vm.sh |
附录 D:在支持 KVM 的环境使用 StratoVirt
如果实验环境是裸金属服务器或支持嵌套虚拟化的 ECS,可以直接使用 StratoVirt 完成同一套实验。
标准机(对应本手册的官方镜像):
stratovirt -machine virt -accel kvm \
-kernel /opt/vm/std-vmlinux.bin \
-append "root=/dev/vda console=ttyAMA0 rw" \
-drive file=/opt/vm/openEuler-22.03-LTS-stratovirt-aarch64.img,id=rootfs \
-m 4G -smp 4 -nographic
microvm(对应官方 microvm 内核 + virtio-mmio):
先下载 microvm 专用内核(本手册任务二默认只下载了标准机内核):
cd /opt/vm
wget https://dl-cdn.openeuler.openatom.cn/openEuler-22.03-LTS/stratovirt_img/aarch64/vmlinux.bin
再执行:
stratovirt -machine microvm -accel kvm \
-kernel /opt/vm/vmlinux.bin \
-append "root=/dev/vda console=ttyAMA0 rw reboot=k panic=1" \
-drive file=/opt/vm/openEuler-22.03-LTS-stratovirt-aarch64.img,id=rootfs \
-device virtio-blk-device,drive=rootfs,id=rootfs \
-qmp unix:/tmp/qmp1.socket,server,nowait \
-m 4G -smp 4 -serial stdio
注意:StratoVirt 的 QMP 不需要
qmp_capabilities握手,query-cpus等命令也与 QEMU 略有差异,具体以 StratoVirt 版本文档为准。
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐



所有评论(0)