上一篇 #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 kvmFirecracker 依赖 /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 同技术栈
- 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
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【从零造容器】容器 vs microVM:Firecracker 凭什么 125ms 启动
容器用 namespace 隔离,microVM 用硬件虚拟化。AWS Lambda 背后的 Firecracker 去掉了 BIOS、ACPI、PCI,只用 virtio-mmio,125ms 启动一个 VM。两种隔离模型到底差在哪?安全性差多少?开销差多少?
从零造容器系列文章
用 C 和 Go 从零实现一个 OCI 兼容的迷你容器运行时,逐篇拆解 Linux 内核的隔离机制。不是讲 Docker 怎么用,而是理解容器到底是什么。
【从零造容器】Linux Namespaces:用 50 行 C 隔离一个进程
容器不是魔法。它就是几个系统调用。本文用 C 从 clone() 开始,逐个开启 PID/UTS/Mount/IPC namespace,看隔离到底是怎么回事。50 行代码,你就拥有了一个'容器'的雏形。
【从零造容器】Network Namespace:给你的进程接上虚拟网线
上一篇我们用 clone() 隔离了 PID、主机名和挂载点,但那个'容器'连 lo 都 ping 不通。本文从 CLONE_NEWNET 出发,用 veth pair + bridge + iptables MASQUERADE,一步步给容器接上网。