- Published on
AWS Lambda MicroVMs — 用 VM 隔离运行智能体写的代码,以及快照带来的新问题
- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 引言 — 该在哪里运行智能体写的代码
- Lambda MicroVMs 到底是什么
- 快速启动的真相 — 不启动、而是从快照中恢复
- 快照的代价 — 本该唯一的东西并不唯一
- VMGenID 修复了什么,又没修复什么
- VM 边界挡不住的东西
- 关于数字的诚实说明
- 替代方案 — gVisor 那边是怎么做的
- 什么时候不该用
- 结语
- 参考资料
引言 — 该在哪里运行智能体写的代码
让 LLM 写代码,现在已经算是简单的部分了。难的是运行这些代码的那一环。模型刚生成的代码按定义是没有经过评审的,只要中一次提示注入,它就会变成用户从未打算执行的代码。到底该在哪里运行这些代码,不是口味问题,而是隔离边界该画在哪里的问题。
容器不太适合放在这个位置,原因只有一个 — 它们共享内核。namespace、cgroup、seccomp 收得再紧,租户 A 的代码和租户 B 的代码敲的还是同一个内核的系统调用接口。这个接口上只要炸出一个洞,边界就会整体垮掉。所以真正认真对待这个问题的团队,最终都往更底层走了 — 走向硬件虚拟化,或者用户态内核。
AWS 在 2026 年 6 月 22 日推出Lambda MicroVMs,正是在这个背景下。这不是一项新的隔离技术 — Firecracker 从 2018 年就存在了,Lambda 本身也一直跑在它上面。新的是卖法。AWS 把 Firecracker 的隔离、快照、生命周期作为原语直接开放给你操作,而 hypervisor 仍然由 AWS 运营。
本文不是产品介绍,而是关于边界的讨论。我们要看这道边界到底挡住了什么、没挡住什么,以及快照这个实现选择,又带来了什么新问题。
Lambda MicroVMs 到底是什么
AWS Compute 博客(2026 年 7 月 10 日,Kulkarni、Agarwal、Madan)描述的模型是这样的。
- MicroVM 镜像 — 把 Dockerfile 和代码打包成 zip 上传到 S3 后,Lambda 会执行这个 Dockerfile,启动应用,然后对完全初始化好的状态做一次 Firecracker 快照。这是一个带版本号的产物。
- MicroVM — 从该镜像按需启动的单个实例。按会话、按用户、按作业各分配一个。
API 很精简:create-microvm-image、run-microvm、suspend-microvm、resume-microvm、terminate-microvm、delete-microvm-image。
aws lambda-microvms run-microvm \
--image-identifier arn:aws:lambda:us-east-1:123456789012:microvm-image:analytics-notebook \
--idle-policy '{"maxIdleDurationSeconds":300,"suspendedDurationSeconds":28800,"autoResumeEnabled":true}' \
--maximum-duration-in-seconds 28800 \
--region us-east-1
只挑出可核实的规格,是这样的。来源是开发者指南的规格表。
基线 → 峰值(自动垂直扩展4倍) 最大磁盘
0.5 GB / 0.25 vCPU → 2 GB / 1 vCPU 8 GB
1 GB / 0.5 vCPU → 4 GB / 2 vCPU 8 GB
2 GB / 1 vCPU (默认) → 8 GB / 4 vCPU 8 GB
4 GB / 2 vCPU → 16 GB / 8 vCPU 16 GB
8 GB / 4 vCPU → 32 GB / 16 vCPU 32 GB
这里要澄清一个常见的误解。到处被引用的「32GB / 16vCPU」并不是基线,而是最大基线的峰值。只要设置内存,vCPU 就会按每 2GB 配 1 个的比例自动跟上,峰值则会自动升到基线的 4 倍。AWS 新闻博客的表述是"up to 16 vCPUs, 32 GB of memory, and 32 GB of disk per MicroVM",指的就是这个意思。
其余的边界条件:
- 仅支持 ARM64。 没有 x86。
- 5 个区域 — 弗吉尼亚北部、俄亥俄、俄勒冈、爱尔兰、东京。
- 最长 8 小时(28,800 秒)。这既是会话寿命,也是空闲挂起的保留上限。
- 每个 MicroVM 都会拿到一个专属的 HTTPS 端点,支持 HTTP/1.1、HTTP/2、WebSocket、gRPC、SSE。鉴权用
create-microvm-auth-token签发的 JWE token,放进X-aws-proxy-auth请求头里发送。token 里嵌入了允许的端口和过期时间。
正因为是 VM 边界,才有一件事变得可能,这是真正的优点。把 additionalOsCapabilities 设为 ["ALL"],就能打开文件系统挂载、创建网络命名空间、运行 eBPF 之类的能力。文档里的这句话说得很准确 — "Capabilities are applied within the VM isolation boundary and do not affect the host or other MicroVMs."。在沙箱里给出近乎 root 的权限,宿主机却依然安全,是因为它下面还有一层 hypervisor。容器做不了这笔交易。
快速启动的真相 — 不启动、而是从快照中恢复
"near-instant startup" 的实质,是不启动。用的是 Lambda SnapStart 那套技术 — 从Firecracker 快照中恢复。
在镜像构建阶段,Lambda 依次做的事情是:从基础镜像启动一个新的 MicroVM,执行 Dockerfile,通过 ENTRYPOINT/CMD 启动应用,用生命周期钩子确认初始化已完成,然后对磁盘和内存状态做快照。钩子有两个。
/ready → /aws/lambda-microvms/runtime/v1/ready
应用是否处于可以打快照的状态。503 表示重试,200 表示打快照。
/validate → /aws/lambda-microvms/runtime/v1/validate
构建完成后,用该镜像启动的新 MicroVM 确认恢复能正常工作。
/validate 钩子有一个文档里写明的隐藏用途 — 在这里跑一遍模拟负载,Lambda 就能追踪出快照的哪些区域实际被访问到,从而在启动时优化这些区域的读取。快照恢复归根到底是在惰性拉取内存页,提前知道哪些页是"热"的,就能让恢复更快。
文档明确写出了快照里包含什么 — 所有运行中进程的内存状态(包括后台守护进程、cron、子进程),磁盘状态,以及已初始化的网络连接和文件描述符。
请再读一遍最后这一项。从这里开始,才是本文真正的主题。
快照的代价 — 本该唯一的东西并不唯一
Lambda MicroVMs 的模型是"一个镜像 → N 个 MicroVM"。也就是说,数百个 VM 会反复从同一份快照恢复。这既是它快的原因,也是它有问题的原因。
Firecracker 自己的文档是怎么称呼这种模式的,原文照搬:
When snapshots are used in a such a manner that a given guest's state is resumed from more than once, guest information assumed to be unique may in fact not be; this information can include identifiers, random numbers and random number seeds, the guest OS entropy pool, as well as cryptographic tokens. Without a strong mechanism that enables users to guarantee that unique things stay unique across snapshot restores, we consider resuming execution from the same state more than once insecure.
它明确把"从同一状态恢复两次以上"称为"insecure"。而 Firecracker 文档举的那个"potentially insecure use"的例子 — 从同一份快照 S 分别恢复出 microVM B 和 C — 正是 Lambda MicroVMs 的正常运作方式本身。
AWS 也没有回避这一点。快照文档里的原话:
If your code generates unique content during image version build phase (unique IDs, secrets, or entropy for pseudorandomness), that content is shared across all MicroVMs run from the same image version.
来看看具体会在哪里出问题。
环境变量。 根据文档,环境变量是在镜像构建阶段设置的(最多 50 个),并在快照构建过程中被注入到容器里。也就是说,你放进环境变量里的任何机密,都会被从这个镜像启动的所有租户的 MicroVM 共享。要是按容器的习惯把 API key 塞进 env,整个多租户沙箱看到的就是同一把 key。要在运行时注入,得用 run-microvm 的动态负载。
随机数与加密 token。 构建阶段生成的会话 ID、种子、token,全都会被复制。AWS 给的处方是"不要在构建时生成,要在 MicroVM 启动后生成",并为重设提供了 /run 生命周期钩子。
OpenSSL。 这是最具体的一个陷阱。文档要求使用 AWS 提供的基础容器镜像 public.ecr.aws/lambda/microvms:al2023-minimal。原因是里面装的是"AWS-patched version of OpenSSL that is compatible with snapshotting"。如果你用自己的基础镜像,就得自己把 Amazon Linux 2023 的 openssl-snapsafe-libs 包装进去。
为什么单单 OpenSSL 要被特殊对待?下一节会回答。
VMGenID 修复了什么,又没修复什么
内核这一侧是有解法的。VMGenID 是一个虚拟设备,让客户机能够察觉"我刚刚从快照中被恢复了"。它向客户机暴露一个 16 字节的随机标识符,每次快照恢复时 hypervisor 都会改变这个值。Firecracker 始终启用这个设备,恢复时先写入新的 16 字节值,再在恢复 vCPU 之前给客户机注入一个中断。Linux 从 5.18 起(基于 ACPI;DeviceTree 则从 6.10 起)能检测到这个值的变化,并重新为内核内部的 CSPRNG 播种。
所以 AWS 指引的那些各语言 CSPRNG — Java 11+ 的 SecureRandom、Node.js 的 crypto.randomBytes、Python 3.12+ 的 Secrets.SystemRandom、.NET 8+ 的 Cryptography.RandomNumberGenerator — 都是安全的。它们的共同点是,全都通过 /dev/random 或 /dev/urandom 从内核获取熵。内核被重新播种了,它们也就跟着变了。
问题出在不经过内核的那些东西上。Firecracker 文档的原话照搬:
State other than the guest kernel entropy pool, such as unique identifiers, cached random numbers, cryptographic tokens, etc will still be replicated across multiple microVMs resumed from the same snapshot. Users need to implement mechanisms for ensuring de-duplication of such state, where needed.
will 加粗是原文自带的。VMGenID 只修复内核熵池。如果用户态自己另外维护了一份熵池 — OpenSSL 恰恰就是这样 — 那份熵池就会保持被复制的状态。这就是为什么会有 openssl-snapsafe-libs 这个单独的包,也是为什么 AWS 建议使用它的基础镜像。
Firecracker 关于熵的文档,对这个局限说得更坦白 — 关于用户态各库各自维护熵池的问题,它写道,"目前的编程模型下没有通用解法,我们能做的只是建议不要在快照之前的逻辑里使用它们"。
把这件事通知到用户态的标准化工作正在推进。用户态可以通过 mmap() 监视 VMClock 设备的 vm_generation_counter,或者通过 poll() 接收通知,这项支持通过 Amazon 一位工程师(itazur@amazon.com)在 2026 年 1 月 30 日发的补丁,合并进了 Linux 内核 v7.0。Amazon Linux 的 microvm 内核 5.10 和 6.1 系列上也有回合(backport)。不过这只有在"库已经被改到会监视这个设备"时才有价值。而现在你用的库大概率还没做这个改动。
归纳一下,快照恢复时唯一性的责任分工是这样的。
内核熵池 → VMGenID 自动重新播种 (Linux 5.18+) [已解决]
使用 /dev/urandom 的 CSPRNG → 走内核,自动安全 [已解决]
OpenSSL 等自带熵池 → 需要打过补丁的构建 (openssl-snapsafe-libs) [部分解决]
应用生成的 ID、token、种子 → 没人替你修。在 /run 钩子里自己重新生成 [你的责任]
构建阶段的环境变量 → 原样烙进快照里。用运行时注入来规避 [你的责任]
最后两行是本文最重要的部分。VM 隔离边界对这个问题什么都做不了。挡住租户间的内核逃逸,和租户们看到同一个种子,是完全不同层面的问题。
VM 边界挡不住的东西
就算快照的问题全都解决了,VM 边界挡不住的东西还是在那儿,而且实务中,出事更多的往往是这一类。
默认是开放的互联网。 网络文档原话是这么写的 — "By default, Lambda MicroVMs have public internet access on the egress path."。设想一下,一个被提示注入攻陷的智能体,在沙箱里读到凭证或用户数据,然后用 curl 把它们发到外面去。VM 边界对这一切一点也挡不住。站在 hypervisor 的角度看,那不过是客户机在正常做网络 I/O。要控制出站流量,得用 Lambda Network Connector 把流量绕回自己的 VPC,走安全组和 NACL。也就是说,真正的防线不是 hypervisor,而是你自己写的网络策略。
这不是 AWS 独有的问题。Anthropic 的自托管沙箱安全文档把同一道边界写得更直白 — "Without egress restrictions, a compromised tool execution can reach arbitrary external hosts."。而在"Anthropic 无法替你做的事"清单里,有这么一条:"Isolate tools inside your sandbox. Anthropic's security boundary stops at the sandbox."。顺带一提,AWS Compute 博客明确介绍了把 Lambda MicroVMs 当作 Claude Managed Agents 自托管沙箱供应方的用法 — 智能体循环留在 Anthropic 那一侧,工具执行放在你的 MicroVM 里。
IAM 依然是你的事。 Compute 博客提到一个不错的细节:构建时的 IAM 角色和运行时的 IAM 角色可以分开。要给每个租户精细授权,就得用上这一点。要是执行角色权限过大,VM 隔离再强也没用。
提示注入不是隔离问题。 模型被骗去做"被允许的事",hypervisor 没有任何办法察觉。VM 边界是缩小爆炸半径的工具,不是阻止智能体判断出错的工具。
关于数字的诚实说明
启动延迟的数字,AWS 没有给。 翻遍 Compute 博客、新闻博客、开发者指南,能看到的都是"near-instant startup"、"resume within seconds"、"starts within seconds"这类说法。毫秒级的数字哪儿都没有。所以我不会在这里凭空编一个数字出来 — 这是你得拿自己的镜像大小和工作集去实测的值。既然快照恢复的速度和页面读取量成比例,几个 GB 的工作集和一个 200MB 的镜像,恢复时间不可能一样。
Firecracker 的规模数字是厂商自己的说法。 "15 trillion+ monthly invocations"(开发者指南)、"tens of trillions of requests each month for over 1.5 million customers"(Compute 博客),都是 AWS 在谈自家服务时给出的数字,测量条件没有公开。作为"Firecracker 已在大规模场景下得到验证"的定性证据,这些数字是够用的,但也就仅此而已。
成本是可以算出来的。 Lambda 定价页给出的 us-east-1 ARM 公开费率是这样的。
vCPU $0.0000276944 / vCPU-second
内存 $0.0000036667 / GB-second
快照写入 $0.0038 / GB (挂起)
快照读取 $0.00155 / GB (启动/恢复)
快照存储 $0.08 / GB-month
让默认基线(2GB / 1vCPU)一直开着,每秒是 0.0000350278 美元。每小时约 $0.126,一天约 $3.03,30 天约 $91。这只是基线本身的底价,超出基线的用量以及快照、数据传输费用都是另算的。顺带一提,InfoQ 的报道里引用的从业者估算,也是一天 $3.03,和从公开费率独立算出来的数字一致 — 两边独立推导出的结果吻合,这个数字是可信的。同一篇文章还引用了一个说法:这个价格超过 Fargate Spot 的 9 倍。
由此可以得出一个设计上的含义。在这套计费模型下,把闲置的 MicroVM 一直开着,纯粹就是在烧钱。这就是为什么挂起不是可选项而是必须项,也是为什么 idle-policy 是这个 API 里的一等公民。挂起之后,计算费用就停了,只剩存储费率。反过来,如果你的负载是像强化学习环境那样,批量跑大量短命的 VM,那就得把"每次启动都要付一次快照读取费"这件事算进模型里。
运营负担也带着数字来。 基础镜像有一个废弃周期 — DEPRECATED(60 天) → EXPIRING(30 天,不能再创建新镜像) → EXPIRED(既不能构建也不能运行)。也就是说,镜像做好了就丢在一边不管,总有一天会启动不了。重新构建是一项例行工作。
替代方案 — gVisor 那边是怎么做的
公平起见,也该看看用另一种边界解决同一问题的做法。Google 在 2026 年 5 月 21 日发布了 GKE Agent Sandbox。它没有走硬件虚拟化,而是用 gVisor — 一个在用户态拦截系统调用的内核 — 再配上默认拒绝的 Kubernetes 网络策略。它还留了接口,可以接入 Kata Containers 之类的其他沙箱,是 Kubernetes SIG 旗下的开源项目。
Google 给出的数字是"每个集群每秒分配 300 个沙箱,亚秒级延迟,90% 的分配在 200 毫秒内完成"。这是厂商自测的数字,集群配置之类的条件在博客里没有说明。"在 Axion 上比其他超大规模云厂商最多好 30% 的性价比",同样也是 Google 自己的比较。
边界性质上的差异,值得讲清楚。gVisor 在用户态重新实现系统调用,从而缩小接触宿主内核的面 — 又薄又快,但归根结底是软件在模仿内核接口,所以这个软件本身就成了攻击面。Firecracker 是跑在 KVM 之上的真实 VM,所以客户机拥有自己的内核 — 相应地更重,而且带来了本文占了半篇幅去讲的快照问题。哪一边"更安全",脱离条件是说不出口的。唯一确定的是,默认拒绝的出站策略,两个阵营都得各自另行处理。
什么时候不该用
不要用,如果
- 你要运行的代码是你自己的代码。没有信任边界的情况下,没有理由去为按租户计费的 VM 付钱。一天
$3的底价和 8 小时的上限,都没有理由去接受。 - 负载是无状态且短命的。快照生命周期、唯一性处理、挂起策略,全都是为了保存状态而存在的复杂度 — 如果你根本不需要保存状态,那就老老实实用一个普通的 Lambda 函数。
- 你需要 x86。它只支持 ARM64。
- 你需要这 5 个区域以外的地方。
- 会话需要超过 8 小时。这是硬上限,没有绕过的办法。
- 你没法锁住出站流量。在默认开放互联网的基础上跑不可信代码,等于买了 VM 隔离,却把真正要紧的那扇门开着。这与其说是"别用",不如说是"如果你不打算做这件事,那就没有理由为 VM 隔离付钱"。
值回成本的情况恰好相反,非常清楚 — 需要把用户或智能体生成的代码按租户隔离运行,会话长、有状态、有空闲区间,需要在沙箱里给出较高的操作系统权限(比如像扫描器那样),同时又不想自己运营 Firecracker 基础设施。这个组合正是 AWS 瞄准的位置,实际用在这个位置上也确实合适。
结语
Lambda MicroVMs 是个不错的东西。只是不能把"卖的是什么"和"买的是什么"搞混。卖的是把 hypervisor 运营外包出去 — 不自己去跑 Firecracker 的隔离和快照,而是通过 API 来用它。买的是强的租户间内核边界,这道边界是真实存在的,容器卖不了你这个。
买不到的东西也同样清楚。让从快照恢复出来的那些 VM,不看到同样的机密和同样的种子,依然是你自己的活。VMGenID 只修复到内核熵池这一层,再往上一层,Firecracker 自己的文档已经明说会"被复制"。出站流量也是你的事 — 因为默认就是开放的互联网。IAM 是,提示注入也是。
所以这款产品真正的教训,并不在隔离技术本身,而在它下面一层。为了求快而做出的实现选择,会造出新的信任假设。 用快照跳过启动的那一刻,"每个进程都从唯一状态开始"这条已有 40 年历史的假设,就被悄悄打破了。hypervisor 不知道这件事。知道这件事的,只有把文档读到最后的你。
参考资料
- AWS Lambda MicroVMs 发布公告 (2026-06-22)
- Run isolated sandboxes with full lifecycle control: AWS Lambda introduces MicroVMs — AWS 新闻博客
- Announcing Lambda MicroVMs — AWS Compute 博客 (2026-07-10)
- Lambda MicroVMs 开发者指南 — 概览
- MicroVM 镜像 — 规格表、构建钩子、基础镜像生命周期
- Working with snapshots — 唯一性、CSPRNG、OpenSSL 注意事项
- Networking — 默认出站与 JWE 鉴权
- AWS Lambda 定价
- Firecracker — Snapshot support (快照安全性与唯一性、VMGenID、VMClock)
- Firecracker — Entropy for Clones
- AWS Launches Lambda MicroVMs for Isolated Agent and User Code Execution — InfoQ
- Bringing you Agent Sandbox on GKE and Agent Substrate — Google Cloud 博客 (2026-05-21)
- Claude Managed Agents — 自托管沙箱安全模型