第四章 · Firecracker——微虚拟化的「Linux 内核」
这章为谁设计
你想理解「所有基于 KVM 的沙箱项目的底层是什么」。Firecracker 是 CubeSandbox 和 E2B 的发动机——先理解发动机,后面理解整车才不会迷路。
一句话定位
AWS 开源的 microVM 引擎,AWS Lambda 和 Fargate 的隐形心脏。它回答的问题是:「怎么用最少的资源、最小的攻击面,给代码造一个硬件级隔离的牢笼?」
日常类比
传统虚拟机(QEMU)像一套五星级酒店房间——有大床、浴缸、冰箱、电视、保险柜、迷你吧。Firecracker 像一间太空舱旅馆——只有一张床和一盏灯。但门锁一样结实(KVM 硬件隔离),入住速度快十倍(因为不用等服务员介绍设施)。
类比边界:太空舱旅馆的「只有床和灯」不是偷工减料——是刻意设计。每少一个设施,就少一个坏掉的可能、少一个被黑客利用的入口。
核心设计哲学:极端精简
传统 VM(QEMU)模拟一台完整的电脑——有 BIOS、USB 控制器、PCI 桥、声卡、显卡、键盘控制器……Firecracker 把这些全砍了,只留 4 个设备:
- 网卡(virtio-net):让 VM 能上网
- 磁盘(virtio-blk):让 VM 能读写文件
- 串口(console):让 VM 能输出日志
- 定时器(timer):让 VM 知道时间
就这四个。没有声卡(VM 不需要放音乐)、没有 USB(VM 不需要插 U 盘)、没有显卡(VM 不需要显示画面)。
这个设计在安全上极其聪明:每砍掉一个虚拟设备,攻击面就缩小一块。Firecracker 的攻击面只有几万行 Rust 代码,而 QEMU 是几十万行 C 代码。代码越少,bug 越少,被黑客利用的可能越小。
这个设计在性能上也极其聪明:不模拟的设备不占启动时间。所以 Firecracker 能做到 <5MB 内存和 ~125ms 启动——不是因为用了什么黑魔法,而是因为它什么 Extra 都没带。
Firecracker 的技术架构
VMM 进程启动流程
Firecracker 是一个单体 Rust 二进制。启动时做这些事:
main() 启动
→ 设置崩溃处理器(panic handler)
→ 注册信号处理器(优雅关机)
→ 解析命令行参数(API socket 路径、实例 ID)
→ 二选一:
① 有 REST API → 创建 API Server 线程 + VMM 线程
② 无 API → 直接启动 VM
→ 进入事件循环(epoll 驱动)
epoll:Linux 内核提供的高效事件通知机制。类比:与其每秒去 100 个信箱检查有没有新信(轮询),不如让邮局在有新信时主动通知你(事件驱动)。
MicroVM 创建过程
当 API 收到「创建 VM」的请求时,按以下步骤执行:
- KVM 初始化:跟 Linux 内核申请一个 KVM 虚拟机实例
- vCPU 创建:给 VM 分配虚拟 CPU(每个 vCPU 是一个独立线程)
- 内存分配:给 VM 分配一块独立的物理内存区域
- 设备挂载:按固定顺序挂载 4 个 VirtIO 设备
- 加载内核:把 Linux 内核镜像加载到 VM 的内存中
- 启动:让 vCPU 开始执行内核代码
KVM(Kernel-based Virtual Machine):Linux 内核自带的虚拟化模块。它让 CPU 硬件直接执行 VM 里的指令,不需要软件翻译——所以性能接近原生。类比:不是让翻译官口译(软件模拟),而是让两个人直接面对面说话(硬件直通)。
vCPU(virtual CPU):虚拟 CPU。物理机有 8 个 CPU 核,可以分给 10 个 VM 各一个 vCPU——操作系统通过时间片切换让每个 vCPU 都能跑。
VirtIO:一种标准化的虚拟设备接口。类比:USB 是物理设备的标准接口(不管是鼠标还是键盘都用 USB),VirtIO 是虚拟设备的标准接口(不管是虚拟网卡还是虚拟磁盘都用 VirtIO)。
vCPU 事件循环
每个 vCPU 线程的核心逻辑是一个循环:
vCPU 线程启动
→ 加载安全过滤器(seccomp)
→ 进入「暂停」状态,等待信号
→ 收到「运行」信号后进入循环:
调用 KVM_RUN(让 CPU 执行 VM 内的指令)
→ CPU 一直执行,直到遇到「退出事件」:
① VM 要读写设备(MMIO) → 路由到对应的虚拟设备处理
② VM 要关机/重启 → 发信号给 VMM
③ 外部中断(暂停/恢复) → 暂停 VM
→ 处理完退出事件后,再次 KVM_RUN
循环直到 VM 停止
MMIO(Memory-Mapped I/O):设备操作通过特定内存地址进行。类比:你往某个信箱里塞一张纸条(写特定内存地址),信箱后面的人(虚拟设备)就知道你要它做什么了。
Jailer 安全机制:7 层防护
Firecracker 不只是一个 VM 引擎——它的 Jailer(牢笼看守)给 VMM 进程本身加了 7 层保护:
| 层 | 机制 | 作用 |
|---|---|---|
| 1 | 关闭所有多余文件描述符 | 防止 VMM 继承的文件被恶意利用 |
| 2 | 清除所有环境变量 | 防止密钥通过 env var 泄漏 |
| 3 | 路径验证 | 防止路径遍历攻击 |
| 4 | Chroot Jail | 把 VMM 锁在一个小目录里,看不到系统其他文件 |
| 5 | Cgroup 资源限制 | 限制 CPU / 内存 / IO 使用量 |
| 6 | 网络命名空间隔离 | VMM 只能看到自己的网络 |
| 7 | 权限降级 | VMM 以非特权用户运行 |
这意味着:即使 VM 里的恶意代码攻破了 KVM 隔离(极低概率),攻击者面对的 VMM 进程本身也是被锁在笼子里的——再攻破一层才能碰到 host 系统。
vsock 通信模型
VM 内部的程序怎么和外部通信?Firecracker 用 vsock:
VM 内部程序(AF_VSOCK)
↕ 通过虚拟 socket
Firecracker VMM(VsockMuxer)
↕ 通过 Unix socket
主机上的程序(AF_UNIX)
vsock:一种让 VM 内部和主机通信的 socket 类型。类比:宾馆房间里的电话只能打前台(VM 只能通过 vsock 联系 VMM),不能直接打外面的号码。前台(VMM)决定是否帮你转接外部电话。
快照 / 恢复
Firecracker 支持两种快照:
| 类型 | 内容 | 大小 | 速度 | 用途 |
|---|---|---|---|---|
| Full Snapshot | 完整内存 + 所有状态 | 大 | 慢 | 冷启动加速(预热好环境,直接恢复) |
| Diff Snapshot | 仅修改过的内存页 | 小 | 快 | 增量备份、检查点 |
Dirty Bitmap:一个标记「哪些内存页被修改过」的位图。类比:考试时用荧光笔标记改过的答案,交卷时只提交标记的部分就行。
Firecracker 在生态中的角色
关键定位:它是「引擎供应商」,不是「产品」。
- 它不提供 SDK(你不能
from firecracker import Sandbox) - 它不提供文件系统视图(你不能直接读写 VM 内的文件)
- 它不提供代码执行接口(你不能直接告诉它「跑这段 Python」)
这些全留给上层项目去实现。E2B 在 Firecracker 之上加了 SDK + 云服务。CubeSandbox 在 Firecracker 同源技术之上加了快照 + 网络控制 + E2B 兼容 SDK。
一个容易被忽视的细节
Firecracker 的 OpenAPI 规范在 src/firecracker/swagger/firecracker.yaml 里。这意味着你可以用任何语言自动生成 API 客户端(Python、Go、TypeScript),然后通过 REST API 控制 VM 的创建、启动、停止、快照。API 设计极其干净,值得学习。
读完这章你应该能回答
- Firecracker 和 QEMU 的核心区别是什么?(精简设备模型 → 小攻击面 + 快启动)
- 为什么 Firecracker 的攻击面小?(Rust 语言 + 只有 4 个设备 + 几万行代码)
- Firecracker 不做什么?(不做 SDK、不做文件系统接口、不做代码执行 API)
- Jailer 的 7 层防护保护的是谁?(保护 host 不被 VM 逃逸后的攻击者伤害)
导读目录:README.md 上一章:第三章 · 隔离的五个层级:从「不设防」到「硬件防弹」 下一章:第五章 · CubeSandbox——为 AI Agent 而生的「最后一公里」