运行 AI 生成代码,如何选择隔离方案
文章比较 Firecracker、gVisor、容器和完整虚拟机的隔离机制与部署代价。选型重点包括代码可信度、KVM 可用性、系统调用兼容性、资源密度及硬件访问需求。
AI 深度解读
AI Agent 执行自己生成的代码时,风险不只在于程序会不会报错,还在于它能碰到宿主机的哪些能力。原文给出的选择很明确:不可信代码优先用 Firecracker microVM,没有 KVM 时考虑 gVisor,可信任务、GPU 和极致密度需求则可以选容器。
这篇值得读的地方,是把隔离边界、启动速度、内存成本和环境恢复放到了一起。但要分清:Firecracker 的规格、OpenDsec 的实测,以及作者的选型判断,并不是同一类证据。
隔离强不强,先看代码能碰到谁的内核
容器通过 namespaces 隔离进程、网络和挂载视图,通过 cgroups 限制资源,用 overlayfs 提供文件系统。它启动快、占用低,因为启动容器接近启动普通进程,不需要额外运行一个操作系统内核。
代价也来自这里:容器里的进程直接调用宿主机内核。即使删掉不必要的 capabilities,再用 seccomp 拦截挂载、bpf、userfaultfd、加载内核模块、创建 user namespaces 等危险操作,剩余的数百个系统调用仍然通向宿主机。一个可利用的内核漏洞,就可能成为逃逸入口。
gVisor 在中间加了一层用 Go 编写的应用内核 Sentry。沙箱发出的系统调用先被平台层截获,默认平台 systrap 基于 seccomp,再交给 Sentry 处理;文件访问则经过另一个宿主机进程 Gofer。
它以 OCI runtime runsc 的形式接入 Docker 和 Kubernetes,不需要硬件虚拟化,普通云主机也能运行。原文还提到,Modal 的沙箱默认使用 gVisor。
但兼容性需要逐项验证。gVisor 尚未实现全部系统调用,以及全部 /proc、/sys 文件;系统调用密集的任务也可能表现较差。对 Agent 来说,只测一个简单脚本远远不够,编译器、包管理器和数据库都可能走到不同的接口。
选型首先是在选择攻击边界,然后才是在比较启动时间。
Firecracker 的价值,既是独立内核,也是可恢复的运行状态
Firecracker 是 AWS 为 Lambda 和 Fargate 开发的虚拟机监控器(VMM),采用 Apache-2.0 开源协议。它基于 KVM 运行真正的虚拟机,每个沙箱拥有自己的 guest kernel,但只保留网络、块设备、vsock、entropy、pmem 等少量虚拟设备。
因此,沙箱里的 root 首先只是客户机内核的 root。攻击者要继续逃逸,需要突破虚拟设备实现或 KVM。生产环境还会通过 Firecracker 自带的 jailer,叠加 chroot、cgroups、namespaces、权限降低和每线程 seccomp 过滤。
原文引用的 Firecracker 规格包括:
- 从启动请求到客户机内核运行,耗时 ≤125 ms。
- 对于 1 vCPU、128 MiB 的虚拟机,VMM 线程内存开销 ≤5 MiB。
- 计算性能超过裸机的 95%。
这里最容易误读的是第二项。≤5 MiB 指 VMM 线程开销,不能当成整个沙箱的内存占用,客户机内核和应用仍然要占内存。
microVM 的另一项能力是内存快照:保存整个虚拟机的内存状态,恢复后让正在运行的进程继续执行。依赖装好、服务启动完之后再保存,后续沙箱就能从这个状态出发。原文提到 E2B 也基于 Firecracker。
限制同样明确:宿主机需要 Linux 和 /dev/kvm,通常是裸机,或者开启嵌套虚拟化的云主机;Firecracker 不支持 GPU passthrough。
如果任务需要运行镜像自身的 init、其他操作系统,或通过 PCI 直通 GPU,原文建议用 QEMU full VM。它的设备模型更完整,启动、内存和攻击面成本也更高。Kubernetes 场景可以考虑 Kata Containers 的集成路径,而 OpenDsec 选择直接在节点上管理 Firecracker。
91 MB 和 55 ms,分别证明了什么
OpenDsec 提供容器、Firecracker microVM、QEMU full VM 三种后端,调用方在创建沙箱时选择。它没有 gVisor 后端,因此文中的实测不是四种技术的完整横向比较。
测试机器配置为 2 × AMD EPYC 9Y24、384 threads、1.5 TB RAM。原文报告,5,120 个 microVM 合计申请了 2.6 TB 内存,宿主机实际使用约 468 GB,平均每个约 91 MB。
这并不等于每台虚拟机申请的内存都被实际占满。作者解释了两个节省机制:free page reporting 让客户机通知宿主机哪些页面空闲,宿主机随后回收;virtio-pmem 配合 DAX,把只读镜像映射给多个虚拟机,使同一镜像的 page cache 可以共享。
这些机制说明,独立内核带来的内存成本有优化空间。但如果任务持续写入大量内存,或者各沙箱运行不同的大型服务,不能直接套用 91 MB。
启动数据也要分开读。OpenDsec 测得冷启动 microVM 约 0.1 s,从内存快照启动约 55 ms;Firecracker 的 ≤125 ms,则是从启动请求到客户机内核运行的规格。它们描述的阶段不同,不能拼成一个统一指标。
OpenDsec 默认选择 microVM,除了隔离,还看重从快照启动和携带内存状态的 fork:同一个运行状态可以复制成多个分支,用于树搜索和批量 rollout。DeepSeek 的 DSec 论文则以容器为主要后端,在需要更强隔离时使用 microVM。两者取舍不同。
此外,OpenDsec 对各后端统一叠加宿主机防护:通过 nftables 和 DNS proxy 默认拒绝出站网络,限制每条命令的输出,并支持让 Agent 与 grader 使用不同用户。CPU core scheduling 则避免两个沙箱同时占用同一物理核心的两个超线程,以防范经由超线程产生的侧信道。
我的判断
我赞同作者把不可信代码的隔离放在首位。对允许 Agent 自由执行命令的平台,独立内核是清晰的边界,内存快照也确实能服务于环境复用和状态分叉。
但原文没有提供足够证据,证明 Firecracker 在所有团队里都优于 gVisor。两者分别把主要边界放在硬件虚拟化和用户态内核,实际安全性仍取决于实现、配置与维护。关于它们的说明来自作者于 2026-10-25 核查的官方文档,OpenDsec 的性能数字则来自项目测试记录,证据范围需要分开看。
同样,约 55 ms 和约 91 MB 很有参考价值,却不足以推出普遍成本结论。原文没有充分交代这组测试的任务构成、持续时间、性能分布,以及相同任务下完整的容器对照。关于启动处于同一数量级、密度足够使用的判断,应视为该项目条件下的经验。
容器仍有合理位置。自己的可信构建、评分程序或 GPU 任务,可以接受不同的成本与风险组合;没有 KVM 又需要增强隔离时,gVisor 也值得测试。关键是把任务可信度和基础设施条件写进选型标准。
能拿来做什么
- 做前端或 Node Agent 执行平台时,先确认生产机器是否提供
/dev/kvm,再决定是否采用 Firecracker;缺少 KVM 时,把 gVisor 纳入验证范围。 - 评估 gVisor 时,用真实项目覆盖依赖安装、构建、测试和服务启动,记录兼容性与耗时,尤其关注系统调用密集的环节。
- 评估 microVM 时,分别测冷启动、快照恢复和任务运行期间的宿主机实际内存,避免把 VMM 开销当成完整沙箱成本。
- 如果任务需要从同一运行状态展开多条执行路径,重点验证内存快照与 fork;同时落实出站网络限制、输出上限和资源约束。