【从零造容器】microVM 实战:Firecracker API 启动与容器对比实测
上一篇 #10 讲了 microVM 为什么快、Firecracker 砍掉了什么。这篇动手做:下载 CI 内核与 rootfs、用 API 或 JSON 配置启动 microVM、在同一台机器上测启动时延,并与容器隔离模型对比。
测试环境说明 下文实测在 WSL2(Linux 6.6.87,KVM 可用)、Firecracker v1.8.0、guest 内核 vmlinux-6.1.172、Ubuntu 24.04 rootfs(Firecracker CI 构件)上完成。AWS .metal 上的绝对时延会更低(参见 #10 在 i3.metal 的数据);本文数值用于同机对比口径,不替代官方 SLA。
一、准备:二进制、内核、rootfs
1.1 检查 KVM
[ -r /dev/kvm ] && [ -w /dev/kvm ] && echo "KVM OK" || echo "KVM FAIL"
lsmod | grep kvm
Firecracker 依赖 /dev/kvm。WSL2 在较新版本上通常可用;裸金属或云 .metal 实例更稳定。
1.2 下载 Firecracker 与 CI 构件
与官方 Getting Started 一致,从 spec.ccfc.min 拉取最新日期前缀下的内核与 Ubuntu squashfs:
ARCH="$(uname -m)"
S3="https://s3.amazonaws.com/spec.ccfc.min"
CI_ARTIFACTS_PREFIX=$(curl -fsSL "$S3?list-type=2&prefix=firecracker-ci/&delimiter=/" \
| grep -oP "(?<=<Prefix>)firecracker-ci/[0-9]{8}-[^/]+/(?=</Prefix>)" \
| sort | tail -1)
latest_kernel_key=$(curl -fsSL "$S3?list-type=2&prefix=${CI_ARTIFACTS_PREFIX}${ARCH}/vmlinux-" \
| grep -oP "(?<=<Key>)(${CI_ARTIFACTS_PREFIX}${ARCH}/vmlinux-[0-9]+\.[0-9]+\.[0-9]{1,3})(?=</Key>)" \
| sort -V | tail -1)
wget "$S3/${latest_kernel_key}" -O vmlinux
latest_ubuntu_key=$(curl -fsSL "$S3?list-type=2&prefix=${CI_ARTIFACTS_PREFIX}${ARCH}/ubuntu-" \
| grep -oP "(?<=<Key>)(${CI_ARTIFACTS_PREFIX}${ARCH}/ubuntu-[0-9]+\.[0-9]+\.squashfs)(?=</Key>)" \
| sort -V | tail -1)
wget -O ubuntu.squashfs "$S3/$latest_ubuntu_key"
将 squashfs 转为 ext4(需 unsquashfs 与 mkfs.ext4):
unsquashfs -f -d squashfs-root ubuntu.squashfs
truncate -s 512M ubuntu.ext4
mkfs.ext4 -d squashfs-root -F ubuntu.ext4
本文实测使用的内核路径:vmlinux(6.1.172),rootfs:ubuntu.ext4(512 MB)。
二、方式 A:config-file 一键启动
最小 vmconfig.json(路径按本机修改):
{
"boot-source": {
"kernel_image_path": "/tmp/fc-bench/vmlinux",
"boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
},
"drives": [
{
"drive_id": "rootfs",
"path_on_host": "/tmp/fc-bench/ubuntu.ext4",
"is_root_device": true,
"is_read_only": false
}
]
}
启动:
sudo rm -f /tmp/firecracker.socket
sudo firecracker --api-sock /tmp/firecracker.socket \
--config-file /path/to/vmconfig.json
串口日志会打印 guest 内核启动过程。Guest 内执行 reboot 会优雅退出 Firecracker(未实现完整电源管理时的设计行为)。
三、方式 B:REST API 分步配置
适合集成到编排器:先起 VMM 进程,再通过 Unix socket 发 HTTP。
终端 1——启动 Firecracker(PCI virtio 可选,吞吐更好):
API_SOCKET="/tmp/firecracker.socket"
sudo rm -f "$API_SOCKET"
sudo firecracker --api-sock "$API_SOCKET" --enable-pci
终端 2——配置并启动(与官方文档一致,节选):
API_SOCKET="/tmp/firecracker.socket"
KERNEL="/path/to/vmlinux"
ROOTFS="/path/to/ubuntu.ext4"
sudo curl -sS -X PUT --unix-socket "$API_SOCKET" \
--data '{"kernel_image_path":"'"$KERNEL"'","boot_args":"console=ttyS0 reboot=k panic=1 pci=off"}' \
"http://localhost/boot-source"
sudo curl -sS -X PUT --unix-socket "$API_SOCKET" \
--data '{"drive_id":"rootfs","path_on_host":"'"$ROOTFS"'","is_root_device":true,"is_read_only":false}' \
"http://localhost/drives/rootfs"
sudo curl -sS -X PUT --unix-socket "$API_SOCKET" \
--data '{"action_type":"InstanceStart"}' \
"http://localhost/actions"
网络需额外配置 TAP(见官方 Getting Started 的 tap0 + 172.16.0.2 示例)。仅验证启动时可省略网卡。
API 形态定义见 Firecracker 源码中的 OpenAPI:src/firecracker/swagger/firecracker.yaml。
四、启动时延实测
4.1 测量口径
两种常见口径不要混用:
口径 含义 #10 AWS 参考 A:VMM → guest init 可用 到 init/systemd 就绪、可执行业务 ~125 ms(i3.metal,精简内核) B:VMM → 根文件系统挂载日志 串口出现 EXT4-fs ... mounted 更早截断,偏乐观
本文在 WSL2 上采用口径 B(串口出现 mounted filesystem),便于脚本自动化;与 #10 的 125 ms 不可直接对比。
4.2 实测结果(3 次,中位数)
Firecracker config-file 启动 → ext4 挂载日志:
run 1: 0.854 s
run 2: 0.850 s
run 3: 0.871 s
中位数: ~0.86 s
WSL2 上 guest 单 vCPU、完整 Ubuntu 24.04 rootfs、无网络 TAP——比 AWS 精简镜像慢是预期行为。瓶颈仍在 guest 内核启动 + 根文件系统挂载,与 #10 的分析一致。
4.3 与「容器级」隔离的对比
用 unshare + user namespace 模拟最轻量的进程隔离(非完整 runc 路径):
for i in 1 2 3 4 5; do
TIMEFORMAT=%R; time unshare -Ur --fork --map-root-user /bin/true
done
实测(WSL2,省略 --mount-proc 因权限限制):
unshare 冷启动(/bin/true):约 0.001–0.012 s(首次略高)
方案 本文 WSL2 实测 隔离边界 unshare / 轻量容器路径 ~1 ms 级 共享宿主内核 Firecracker microVM ~860 ms(至 ext4 mount 日志) 独立 guest 内核 + KVM #10 Firecracker ~125 ms(至 init,AWS metal) 同上
结论不变:microVM 用硬件虚拟化换隔离,启动与内存底线高于容器,但在 Serverless / 多租户沙箱场景可接受。
五、隔离方案选型
场景 推荐 原因
────────────────────────────────────────────────────────────
本地开发 / CI 容器 + seccomp 速度、工具链成熟
可信单租户生产 容器 + 加固 性价比最高
多租户执行不可信代码 Firecracker microVM 硬件级内核隔离
K8s 多租户需 VM 边界 Kata Containers OCI 接口 + 每 Pod 一 VM
syscall 拦截型沙箱 gVisor 无需完整 guest,但兼容性受限
追求极简 VMM Cloud Hypervisor Rust VMM,与 Firecracker 同类
Agent / 代码沙箱 SaaS Firecracker / E2B 与 Lambda 同技术栈
与 #10 和 容器安全 对照:
- gVisor:拦截 syscall,启动更快,但 Go 运行时与部分 syscall 行为需适配。
- Kata:kubelet 仍调 containerd,底层是 VM;冷启动与内存高于 runc。
- Firecracker:API 简单、设备模型极小;Lambda/Fargate/E2B 事实标准。
Agent 沙箱场景可延伸阅读本站 LLM Agent 框架 与 Serverless 挑战。
六、常见问题
Q:curl API 返回 connection refused? Firecracker 进程与 curl 须同一特权级(常需两边都 sudo);确认 ss -a | grep firecracker.socket。
Q:guest 起不来? 检查 vmlinux 是否为未压缩 ELF;boot_args 含 console=ttyS0;rootfs 为 ext4 且 e2fsck -fn rootfs.ext4 通过。
Q:和 QEMU/KVM 虚拟机有何不同? Firecracker 是 VMM,不是通用 PC 模拟器;设备仅 virtio-mmio(或 PCI virtio),见 #10 设备表。
参考资料
- Agache, A., et al. “Firecracker: Lightweight Virtualization for Serverless Applications.” *NSDI 2020*.
- Firecracker 文档:Getting Started、rootfs-and-kernel-setup —— https://github.com/firecracker-microvm/firecracker/tree/main/docs
- 本站 #10 microVM 原理、容器安全
示例代码:examples/containers/13-microvm-firecracker-practice/setup_fc.sh
上一篇: 容器 vs microVM:Firecracker 凭什么 125ms 启动 下一篇: 容器网络性能真相 相关: runc 源码考古 · Serverless 与 Firecracker
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。