我从来都不是一个重度 NetBSD 用户。很久以前(大概 30 年前)我有一台 68K 的 Mac,想在它上面跑一个类 Unix 系统时玩过它,当时 NetBSD 是唯一的选择。从那以后我也摆弄过一两次,但说实话,我从来没有遇到过 OpenBSD 或 Linux 不能更好满足的需求。
不过最近我看到 NetBSD 11 发布了,其中包含这样一段吹嘘:
面向 x86 的全新 MICROVM 内核:同时支持 i386 与 amd64,NetBSD 11.0 引入了一个专为极速虚拟机启动而设计的专用 MICROVM 内核,借助 PVH 启动、VirtIO MMIO 以及多项内核优化,在 2020 年时代的 x86 CPU 上大约 10 毫秒即可完成启动。
这听起来确实很酷!我家里的 Proxmox 跑在一颗 i5-8250U 上,比那个年代稍微早一点(它发布于 2017 年第三季度)。所以可能做不到刚好 10 毫秒,但应该还是相当快。
你为什么会关心这个?像我家里的实验室这种场景,你可能并不在意。是 10 毫秒还是 10 秒,差别并不大。但如果你跑在虚拟 fabric 上,需要快速的 ballooning(内存气球)、极快的故障切换,或者快速重启的能力,这种特性就会价值连城。
什么是 MICROVM?
MICROVM 是一种虚拟机理念:向客户机呈现尽可能精简的一组虚拟硬件。这意味着在启动时需要进行硬件发现和初始化的东西少得多。
一台普通的 Proxmox 虚拟机模拟出来的东西很像一台物理 PC:BIOS 或 UEFI、PCI/PCIe 总线、ACPI、显卡、SATA/SCSI/IDE 控制器、网卡、各种legacy 设备等。
MICROVM 则把大部分这些都剥离掉了。它通常只有 CPU、内存、一个串行控制台、VirtIO 磁盘和 VirtIO 网络。在 QEMU 的 microvm 机型下,通常没有 PCI 总线也没有 ACPI,设备通过 VirtIO-MMIO 而非 VirtIO-PCI 暴露。
主要好处是需要初始化和模拟的虚拟硬件更少。有一点很微妙:MICROVM 仍然是一台真正的硬件虚拟化虚拟机,它不是容器。NetBSD 仍然启动它自己的内核,拥有自己的内存、进程、文件系统和内核隔离边界。
我们来试试看!
我先是在 Proxmox 的图形界面里创建了一台 NetBSD 虚拟机,但那是条死路。我天真地以为只要换掉内核就万事大吉了。但 MICROVM 需要 QEMU 宿主端的配合。
Proxmox 宿主的 QEMU 支持 microvm,但 Proxmox 的虚拟机管理层仍然假设一种更传统的、PC 风格的机器布局。特别是,Proxmox 会自动注入诸如 PCI 桥之类的设备,并期望使用它常规的磁盘/网卡型号,而 QEMU 的 microvm 故意没有 PCI 总线。Proxmox 论坛上有一些关于缺乏支持的讨论,如果你够大胆,也有人做了补丁,但……我的 Proxmox 在某种意义上算是“生产环境”——各种对我很重要的东西都跑在上面,所以我不太想动它。
不过我们还是用 qemu 命令行试试看吧。NetBSD 官网上有说明,但你需要做几处调整。
首先,那个实时镜像的链接已经失效了。这里有一个更新后的链接。
然而,那个实时镜像用的不是 MBR 而是 GPT。所以如果你照着 NetBSD 的 MICROVM 页面上的配方 来做,会碰到这个问题。
到了那一步,我输入了一个 ?,它就列出了一堆可能的磁盘候选。我不知道为什么我还记得这个老把戏……一定是某个 30 年前本该过期却没过期的脑细胞。嗯,俗话说得好,缓存过期是计算机科学里最难的问题。
wedge:NBImgRoot 是你想要的。
所以我的命令是这样的(使用和 NetBSD 示例 中相同的变量来指向内核和实时镜像路径):
正如 NetBSD 站点所说,见证奇迹的时刻:
不赖!29 毫秒。我跑了几次,始终稳定在 28 毫秒到 31 毫秒之间,最常见的是 29 毫秒。
当然,真正把所有服务都启动起来等所花的时间会稍微长一些,如果是在真实生产环境里,还会更长——比如启动 Postgres 之类的。但内核本身确实不再是瓶颈了。
专业提示:如果哪里不工作,把 -z append= 那一行改成 -v。-z 表示“静默模式”,-v 表示“详细模式”。
