容器不是 AI agents 的 sandbox
Source: Dev.to
请提供您希望翻译的具体文本内容,我将按照要求保留源链接、格式和技术术语,仅翻译正文部分。谢谢!
当容器不再简单
容器被宣传为一种已解决的抽象。你打包文件系统,声明一个进程,世界就变得可复现。这个说法大体上是对的——直到你让容器去做一些会泄漏到内核边界的事的那一刻。
那一刻通常是意外的。
你开始“只是添加一个依赖”。也许是用于工具的浏览器。也许是一个模拟器。也许是需要更强隔离的沙箱。Dockerfile 增加了几行。所有东西仍然可以构建。测试仍然通过。然后,悄悄地,你触及了容器实际能承诺的边界。
我在构建一个容器化的 IDE 环境时碰到了这个边界——这个环境不仅仅是编译代码,而是要在可通过浏览器访问的容器中运行完整的图形化工具链和模拟器。纸面上,它仍然是“仅仅 Docker”。实际操作中,它迫使我们面对一个不太舒服的真相:
Containers don’t virtualize the kernel; they borrow it.
一旦你内化了这一点,很多容器的传说就会崩塌。
用户空间容易,内核不易
第一类问题看起来非常直接。你想在环境内部加强行为控制——阻止某些协议处理程序,限制用户点击链接时的行为,减少意外的逃逸通道。这完全属于用户空间。
- 你安装软件包。
- 你编写配置文件。
- 你控制默认设置。
这让人感觉在进步,因为它确实是进步。它是以文件形式表达的策略,而容器在这方面表现出色。
随后出现第二类问题,表面相似却本质不同。
- 你想要加速。
- 你想要虚拟化。
- 你想要比命名空间更强的隔离。
于是你安装 QEMU,添加引用 KVM 的配置文件,并写下每篇博客都推荐的咒语。镜像构建顺利。
但实际上并没有任何改变。
因为此时你不再是配置容器,而是试图从一个不拥有它的进程内部去配置宿主内核。再多的 Dockerfile 巧思也跨不过这道边界。
嵌套虚拟化、设备访问、硬件加速 并不是镜像的属性;它们是执行环境的属性。它们依赖 CPU 标志、内核模块、hypervisor 配置以及运行时权限。只有当宿主明确允许时,容器才能受益。
这正是许多容器设计悄然失效的时刻——不是因为理念错误,而是抽象被过度扩展。
同样的边界也出现在代理系统中
这远不止 IDE 或模拟器。现代 AI 系统日益依赖 agents——不仅思考,还会行动的进程。它们运行工具、克隆仓库、安装依赖,并执行任意代码,常常并发且代表用户操作。
乍一看,容器似乎是完美的选择:
- 每个代理一个容器。
- 干净的文件系统。
- 通过 cgroups 限制资源。
- 完成后即销毁。
这在以下情况之前都能正常工作:
- 运行不可信代码。
- 防止横向移动。
- 控制出站网络行为。
- 强制严格的文件系统策略。
- 支持 Docker‑in‑Docker 类工作流。
- 安全地提供硬件加速。
一旦涉及这些需求,你会再次发现同样的边界:容器 不是安全沙箱;它们是共享内核的进程隔离。
如果一个代理需要跨越到宿主级能力——启动兄弟容器、访问 /dev/kvm、挂载文件系统、操作网络命名空间——你就回到了特权、设备和内核信任的世界。
IDE 问题和代理问题本质上是同一个问题,只是换了不同的外衣。
强隔离不是容器的问题
在基础设施设计中常见的错误是:试图用容器来解决策略问题,却忽视了容器本身的局限性。
(未完待续)
Source: …
与打包工具相关的问题。
容器是 打包加轻量级隔离。它们在可复现性和部署方面表现出色,但 并不是完整的安全边界。
一旦接受了这一点,架构决策就会更加清晰。
- 如果你的代理运行 受信任 的代码,容器可能已经足够。
- 如果你的代理运行 不受信任 的代码,容器可能不足以满足需求。
这时就会出现其他工具:
- MicroVM(Firecracker、Kata)。
- 沙箱运行时(gVisor)。
- 短暂执行环境。
- 严格的系统调用过滤 和出站策略。
这些系统启动更慢、运维更困难,但它们把边界划在了正确的位置:在内核接口处,而不是在内部。看似额外的复杂性往往只是对实际隔离来源的诚实描述。
真正的产品是策略
从所有这些中得到的最重要的细微教训是:
难点不在于运行代码,而在于决定这些代码被允许做什么。
- 打开链接。
- 访问网络。
- 从磁盘读取。
- 写入制品。
- 使用硬件加速。
每个有意义的系统最终都会以显式或隐式的方式编码策略。容器让我们可以轻松地将策略作为配置进行交付,但它们并不能消除对策略进行推理的需求。
能够规模化的代理编排系统不会由巧妙的提示或调度来定义,而是由以下因素决定:
- 明确的信任边界。
- 明确的执行合约。
- 可复现但受限的环境。
- 能将行为映射回意图的可观测性。
这不是 AI 问题,而是我们已经解决了数十年的基础设施问题——只是换了不同的名称。
容器仍然是正确的起点
这些并不是对容器的反对论点。
容器仍然是我们拥有的 最佳默认抽象。它们让我们能够低成本实验、本地推理并快速迭代。它们是正确的起点——但不是终点。
每个严肃的系统最终都会到达必须直接处理内核边界的阶段,而你在此选择的工具将决定是否能够在安全性、性能和运维简易性之间获得恰当的组合。
当 “只要放进 Docker” 不再是答案时
“只要放进 Docker” 不再是答案而变成问题的临界点在于你需要:
- 内核特性
- 硬件保证
- 恶意代码隔离
此时必须更改架构。
预期
- 可预测的边界 – 如果你知道该关注什么,就能预见它的出现。
- 没有快速解决方案 – 你无法用 Dockerfile 来掩盖它。
*Found this useful? I write about AI infrastructure, security, and the engineering challenges of building production AI systems. Connect with me on [LinkedIn](https://www.linkedin.com/in/siddhantkhare24) or [Twitter/X](https://x.com/siddhant_K_code).*
*Built by [Siddhant Khare](https://siddhantkhare.com/).*