资讯动态

DeepSeek DSec 沙箱架构解析:Agentic Training 的弹性计算与安全隔离实践

发布时间:2026/10/15 6:57:43 来源:尧图企业网站定制
1. 为什么一个做推理模型的团队要花力气造沙箱第一次看到 DeepSeek Elastic Compute后面统一简称 DSec这个标题的时候我的反应是有点意外的。DeepSeek 在大众认知里是做模型、做推理优化的团队MoE 架构、MLA 注意力、FP8 训练这些才是他们的标签。结果这篇论文讲的是一个沙箱基础设施而且是专门为 agentic training 服务的。这个组合本身就值得琢磨——为什么一个训练大模型的团队要专门去造一套沙箱答案藏在 agentic training 这个场景的特殊性里。传统的模型训练数据是静态的你准备好一批语料喂进去算 loss反向传播完事。但 agentic training 不一样模型要在训练过程中和环境交互执行代码、调用工具、读写文件、访问网络、跑测试用例。每一次交互都会产生新的状态而这些状态又会影响下一步的动作。这就意味着训练循环里嵌入了一个真实的执行环境而这个环境必须是可隔离的、可复现的、可大规模并行的。我见过不少团队在这个环节上翻车。最朴素的做法是直接用 Docker 容器每个 rollout 起一个容器跑完销毁。小规模测试的时候没问题一旦上到几百上千并发问题就全冒出来了容器启动慢、镜像拉取卡、资源回收不及时、状态污染导致训练信号不可信。更麻烦的是安全问题——模型生成的代码是不可信的它可能删文件、可能死循环、可能把内存吃光。你不可能让这种代码跑在训练集群的宿主机上。DSec 要解决的就是这一整套问题。从论文的定位来看它不是简单的给 agent 跑代码的容器管理而是一套完整的弹性计算基础设施核心目标有三个第一让沙箱的创建和销毁足够快快到能跟上训练循环的节奏第二让成千上万个沙箱能在一套集群上弹性调度资源利用率要高第三让沙箱之间的隔离足够硬模型生成的任意代码都跑不出自己的边界。这篇文章我打算按自己的理解把 DSec 这套东西拆开讲。不是逐段翻译论文而是把它当成一个工程问题来复盘如果我要给自己的 agentic training 搭一套沙箱DSec 的思路哪些能直接抄哪些需要根据自己的场景调整哪些坑是它已经帮你踩过的。适合正在做 agent 训练、代码执行环境、或者大规模沙箱调度的同学参考。哪怕你暂时不训模型只是想给自己的 agent 产品搭一个安全的代码执行后端里面的调度和隔离设计也有不少可借鉴的地方。2. Agentic Training 对沙箱提出的四个硬指标在讲 DSec 怎么做的之前得先把需求讲清楚。不然你看到它的设计选择会觉得莫名其妙——为什么不用现成的方案为什么要自己造轮子答案都在需求里。2.1 延迟沙箱启动必须压到训练循环能接受的范围Agentic training 的一个 rollout 大概是这样的模型生成一段代码或一串工具调用环境执行返回结果模型根据结果继续生成下一步。一个完整的 trajectory 可能包含几十甚至上百次交互。如果每次交互都要等沙箱冷启动那训练吞吐会被拖垮。这里的关键数字是沙箱的创建延迟。用 Docker 从零起一个容器拉镜像、初始化文件系统、启动进程顺利的话几秒不顺利的话几十秒。放到训练循环里这个延迟乘以并发数乘以 rollout 步数就是纯粹浪费的 GPU 等待时间。DSec 把沙箱创建做到了亚秒级甚至毫秒级靠的是预热池和快照恢复这个后面细讲。2.2 隔离模型生成的代码是敌意代码这一点很多人一开始意识不到。你可能会想模型生成的代码能有多危险实际上在训练早期模型输出的代码基本是随机噪声什么奇怪的东西都能写出来。我见过模型生成的代码里有while True死循环、有递归爆栈、有往磁盘狂写文件、有 fork 炸弹。到了训练后期模型学会了写正常代码但它探索边界的时候依然会尝试各种极端操作。所以沙箱的隔离不能是软隔离必须是硬隔离。进程隔离、文件系统隔离、网络隔离、资源配额一个都不能少。而且隔离要能扛住恶意代码的主动突破尝试不能只是防君子不防小人。2.3 弹性并发数在训练过程中是波动的训练不是匀速的。不同 batch 的 rollout 长度不一样有的 trajectory 几步就结束了有的要跑上百步。这意味着同时活跃的沙箱数量是动态变化的可能这一秒需要 500 个下一秒需要 2000 个。如果按峰值预留资源平时就浪费如果按均值预留峰值就排队。DSec 的Elastic就体现在这里。它要能根据实时负载快速扩缩容而且扩缩容的粒度要细、速度要快。这背后是一整套调度和资源池化的设计。2.4 可复现同样的输入必须得到同样的输出训练需要可复现性。同一个 trajectory今天跑和明天跑结果应该一致否则你没法判断模型是真的进步了还是环境抖动。这就要求沙箱的状态是干净的、确定的。文件系统的初始状态、环境变量、依赖版本、随机种子全部要可控。这里有个容易被忽略的点沙箱的干净不只是初始状态干净还包括执行过程中的副作用不能泄漏到下一个 rollout。比如上一个 rollout 在/tmp里留了文件下一个 rollout 如果能看到这些文件行为就可能被污染。DSec 用快照和写时复制来解决这个问题保证每个沙箱从同一个确定的基线出发。把这四个指标放在一起看你会发现现成的方案都不太够用。Docker 太重启动慢单纯的进程隔离太弱扛不住恶意代码Kubernetes 的调度粒度太粗扩缩容跟不上训练节奏。这就是 DSec 存在的理由。3. DSec 的架构拆解从快照池到弹性调度理解了需求再看 DSec 的设计就顺了。它的架构可以分成三层来看底层的沙箱运行时、中间的沙箱池和调度器、上层的训练框架接口。我按数据流的方向从下往上讲。3.1 沙箱运行时轻量隔离是怎么做到的DSec 的沙箱运行时没有用完整的虚拟机也没有用标准 Docker 容器而是走了一条更轻的路子。核心思路是用 Linux 的 namespace 做隔离用 cgroup 做资源限制用 seccomp 做系统调用过滤再叠加一层文件系统快照。Namespace 这块DSec 用到了 PID namespace沙箱内看不到宿主机进程、mount namespace独立的文件系统视图、network namespace独立的网络栈、user namespace权限映射。这套组合是容器隔离的标准做法但 DSec 在启动速度上做了优化——它不重新初始化整个文件系统而是从一个预制的快照恢复。快照恢复是 DSec 快的关键。它预先准备好一个黄金镜像里面装好了 Python 运行时、常用库、基础工具链。创建沙箱的时候不是复制整个镜像而是用写时复制copy-on-write挂载这个镜像沙箱内的所有写操作都落到一个独立的可写层。这样创建沙箱只需要建立几个 namespace、挂载文件系统、启动 init 进程耗时能压到毫秒级。资源限制用 cgroup v2 来做。CPU 配额、内存上限、磁盘 IO 带宽、进程数上限全部通过 cgroup 控制。这里有个细节值得注意内存限制不能只设硬上限还要设一个软上限配合 OOM 处理。因为模型生成的代码经常会有内存缓慢增长的情况硬上限触发 OOM 直接杀进程软上限可以先触发回收给沙箱一个优雅退出的机会。Seccomp 过滤是安全的关键一层。DSec 默认只放行沙箱内代码需要的系统调用像ptrace、mount、reboot这类危险调用直接拦截。这样即使模型生成的代码试图做越权操作也会在系统调用层面被挡住。3.2 沙箱池预热、复用与状态重置如果每个 rollout 都从零创建沙箱即使创建只要几毫秒累积起来也是开销。DSec 的做法是维护一个沙箱池池子里预创建一批沙箱处于待命状态。训练框架需要沙箱的时候直接从池子里取用完归还。池子的管理有几个关键设计。第一是预热策略池子的大小根据历史负载预测提前扩容。比如训练脚本里知道接下来要跑一个大批次的 rollout可以提前把池子撑大。第二是复用策略沙箱归还后不是直接销毁而是重置状态后放回池子。重置包括清理可写层、重置环境变量、杀掉残留进程。状态重置这里有个坑。简单的做法是删掉可写层重新挂载但这样会丢失一些缓存下次启动又要重新加载。DSec 的做法是保留一部分只读缓存只清理用户产生的数据。这个平衡点需要根据实际负载调缓存留太多会污染状态留太少又失去复用的意义。池子还有一个健康检查机制。沙箱在复用多次之后可能会因为各种原因变得不稳定比如文件描述符泄漏、僵尸进程堆积。DSec 会定期对池子里的沙箱做健康检查不健康的直接销毁重建。这个检查的频率和深度需要权衡检查太频繁影响性能太稀疏又会放过问题沙箱。3.3 弹性调度负载波动下的资源分配调度器是 DSec 最复杂的部分。它要解决的问题是给定一个集群的资源总量如何在满足隔离和延迟要求的前提下尽可能高地提升资源利用率。DSec 的调度策略我理解是分层的。第一层是节点级的资源分配决定哪些沙箱放到哪些物理节点上。这里要考虑的是资源碎片化问题——如果每个节点都剩一点零碎资源新的大沙箱就放不进去。DSec 用了 bin-packing 的思路尽量把沙箱紧凑地排列减少碎片。第二层是沙箱级的生命周期管理。调度器要跟踪每个沙箱的状态创建中、运行中、空闲、待销毁。根据训练框架的请求决定是复用空闲沙箱还是创建新的。这里的关键是预测——如果能提前知道接下来需要多少沙箱就可以提前准备避免请求到来时才临时创建。第三层是过载保护。当请求量超过集群容量时调度器要有降级策略。DSec 的做法是排队加超时超过一定时间还没拿到沙箱的请求直接失败让训练框架决定是重试还是跳过。这个设计比无限等待要好因为训练循环里卡住一个 rollout 会拖慢整个 batch。3.4 与训练框架的接口怎么把沙箱嵌进训练循环DSec 对上层暴露的接口设计得比较克制。训练框架不需要知道沙箱是怎么创建的、调度是怎么做的它只需要几个基本操作申请沙箱、在沙箱里执行代码、获取执行结果、释放沙箱。这个接口抽象的好处是训练框架和沙箱实现解耦。训练框架可以专注于 rollout 逻辑沙箱的调度和隔离由 DSec 负责。但这也带来一个挑战接口太简单可能无法表达一些复杂的执行需求比如流式输出、交互式执行、多步会话。DSec 应该是通过会话session的概念来解决的一个沙箱可以承载一个多步的 trajectory中间状态保留在沙箱内。接口设计里有个细节值得说执行结果的返回格式。模型生成的代码可能产生大量输出如果全部返回给训练框架会占用大量内存和带宽。DSec 对输出做了截断和摘要只返回关键部分完整输出留在沙箱内供后续查询。这个设计在训练场景下很实用因为训练只需要知道执行成功还是失败、有没有报错不需要完整的 stdout。4. 隔离与安全模型生成的代码到底能造成多大破坏这一节我想单独展开讲因为安全是 agentic training 沙箱最容易被低估的部分。很多团队在搭沙箱的时候第一版往往只考虑了功能安全是后来补的结果补的时候发现架构上已经很难改了。4.1 模型生成代码的威胁模型先明确威胁模型。在 agentic training 场景下沙箱里跑的代码来源有三类第一类是模型直接生成的代码这是最主要的第二类是模型调用的工具这些工具可能是预置的也可能是模型自己写的第三类是模型读写的数据文件这些文件可能被模型修改成恶意内容。这三类来源里模型直接生成的代码威胁最大。因为它的行为完全不可预测而且随着训练进行模型会探索各种边界。我总结了几种常见的破坏行为资源耗尽型死循环吃 CPU、无限递归吃栈、大量分配内存、疯狂写磁盘。这类行为不会突破隔离但会拖垮沙箱本身影响训练吞吐。越权访问型试图读取沙箱外的文件、试图连接外部网络、试图提权。这类行为需要隔离机制来拦截。持久化型在沙箱内留下后门、修改环境配置、污染共享资源。这类行为影响的是下一个使用该沙箱的 rollout。逃逸型利用内核漏洞或配置错误逃出沙箱。这类行为最危险但概率也最低主要靠及时打补丁和最小权限原则来防。4.2 DSec 的纵深防御设计DSec 的安全设计是纵深防御的思路不是靠单一机制而是多层叠加。我把它拆成四层来看。第一层是命名空间隔离。前面讲过PID、mount、network、user 四个 namespace 把沙箱和宿主机隔开。这一层挡住的是看不见的问题——沙箱内的进程看不到宿主机进程沙箱内的文件系统看不到宿主机文件。第二层是 cgroup 资源限制。CPU、内存、磁盘、进程数都有上限。这一层挡住的是用太多的问题——即使代码是死循环也只能吃满自己的配额不会影响其他沙箱。第三层是 seccomp 系统调用过滤。只放行必要的系统调用危险调用直接返回错误。这一层挡住的是做坏事的问题——即使代码试图 mount 文件系统或 ptrace 其他进程也会被拦截。第四层是文件系统快照和写时复制。每个沙箱从同一个只读基线出发写操作隔离在可写层。这一层挡住的是留痕迹的问题——沙箱内的修改不会影响基线也不会影响其他沙箱。这四层叠加起来模型生成的代码能造成的破坏就被限制在沙箱内部。最坏的情况是沙箱自己崩溃但不会影响宿主机和其他沙箱。4.3 那些论文里不会写但实际会踩的坑论文讲的是设计实际落地的时候有一堆细节问题。我列几个自己踩过或者见别人踩过的。第一个坑是文件描述符泄漏。沙箱内的进程如果打开文件不关闭文件描述符会累积。短时间看不出来沙箱复用多次之后就会耗尽。解决办法是在沙箱重置的时候强制清理所有 fd或者限制单个进程的 fd 数量。第二个坑是僵尸进程。模型生成的代码如果 fork 了子进程但不 wait子进程结束后会变成僵尸。僵尸进程不占 CPU 但占进程表项累积多了会导致无法创建新进程。解决办法是在沙箱的 init 进程里做 subreaper自动回收孤儿进程。第三个坑是时间同步。沙箱内的时间如果和宿主机不一致模型生成的代码里如果有时间相关的逻辑行为就会不确定。解决办法是让沙箱共享宿主机的时钟命名空间或者定期同步。第四个坑是网络隔离的副作用。完全断网是最安全的但有些 agent 任务需要访问网络比如查资料、调 API。如果放开网络就要考虑出站流量的过滤和限速防止沙箱被用作攻击跳板。DSec 应该是支持配置化的网络策略默认断网需要时按需放开。第五个坑是快照的一致性。如果快照是在沙箱运行过程中创建的可能捕获到不一致的状态。解决办法是在创建快照前先暂停沙箱或者用文件系统层面的原子快照。5. 弹性计算的实现细节池化、快照与调度策略前面讲了架构和安全这一节聚焦弹性这个关键词把 DSec 在弹性方面的实现细节拆开。5.1 沙箱池的预热与回收策略沙箱池的核心是平衡预热成本和等待成本。预热太多资源浪费预热太少请求来了要等。DSec 的策略我理解是基于历史负载的预测性扩容。具体来说调度器会记录过去一段时间内沙箱请求的速率和并发数用滑动窗口算出趋势。如果趋势是上升的提前扩容趋势是下降的延迟回收。这个预测不需要很准只要方向对就行因为池子本身有一定的缓冲能力。回收策略上DSec 不是立即销毁空闲沙箱而是标记为可回收等资源紧张的时候再真正销毁。这样在负载波动的时候可以快速复用这些空闲沙箱避免频繁创建销毁。这里有个经验值池子的最小规模应该能覆盖一个 batch 的峰值需求最大规模应该能覆盖整个训练任务的峰值需求。中间的部分按需扩缩。这个比例需要根据实际负载调没有通用值。5.2 快照技术毫秒级启动的关键快照是 DSec 实现毫秒级启动的关键。它的原理是预先创建一个包含完整运行环境的基线快照创建沙箱的时候不复制快照而是用写时复制挂载。沙箱内的所有写操作都落到一个独立的可写层读操作直接读基线。这个机制的好处是创建沙箱几乎不需要时间——只需要建立 namespace、挂载文件系统、启动 init 进程。真正的开销在第一次写操作的时候因为要分配可写层的块。但这个开销是分摊到执行过程中的不影响启动延迟。快照的粒度也有讲究。太粗基线太大创建慢太细基线太多管理复杂。DSec 应该是按任务类型分了几种基线比如 Python 任务一种、Node 任务一种、通用工具一种。这样既能覆盖常见场景又不会让基线数量爆炸。快照的更新也是个问题。基线里的依赖需要定期更新但更新基线意味着所有新沙箱都用新基线可能引入不兼容。DSec 的做法应该是版本化基线新任务用新基线老任务继续用老基线平滑过渡。5.3 调度器的负载感知与过载保护调度器的核心任务是把合适的沙箱放到合适的节点上。这里的合适包含几个维度资源匹配节点的剩余资源能满足沙箱需求、亲和性相关的沙箱尽量放在同一节点减少网络开销、分散性不相关的沙箱分散放置避免单点故障。DSec 的调度器应该是用了打分机制对每个候选节点算一个分数选分数最高的。分数由多个因子加权包括资源利用率、负载均衡、亲和性等。权重需要根据实际场景调比如训练场景可能更看重资源利用率生产场景可能更看重稳定性。过载保护是调度器的安全阀。当请求量超过容量时调度器不能无限排队要有降级策略。DSec 的策略是设置请求超时超时的请求返回失败让上层决定怎么处理。这个设计比无限等待好因为训练循环里卡住一个 rollout 会拖慢整个 batch。5.4 与训练循环的协同什么时候该扩什么时候该缩弹性的最终目标是让沙箱的供给跟上训练的需求。这需要训练框架和调度器的协同。训练框架知道自己的 rollout 计划可以在需要大批量沙箱之前通知调度器预热。调度器知道集群的实时负载可以在资源紧张的时候通知训练框架降低并发。这种双向通信是弹性调度的关键。DSec 应该是提供了这样的接口训练框架可以声明接下来 N 秒内需要 M 个沙箱调度器据此提前准备。同时调度器可以反馈当前只能提供 K 个沙箱训练框架据此调整 batch 大小或 rollout 策略。这种协同的价值在于减少等待和浪费。没有协同的话训练框架只能盲目请求调度器只能被动响应双方都在猜对方的意图。有了协同双方可以对齐预期提升整体效率。6. 把 DSec 的思路搬到自己项目里可复现的落地路径讲完了 DSec 的设计最后落到实操。如果你要给自己项目搭一套类似的沙箱基础设施我按从简到繁的顺序给几条路径。6.1 最小可用版本单机沙箱池如果你只是想在单机上跑 agent 训练不需要分布式调度那最小可用版本可以很简单。第一步准备一个基线镜像。用 Docker 或者直接用一个目录里面装好 Python、常用库、基础工具。这个基线要尽量精简只装必要的减少攻击面。第二步写一个沙箱管理进程。它维护一个沙箱池每个沙箱是一个独立的 namespace 组合。创建沙箱的时候用写时复制挂载基线建立 namespace启动 init 进程。第三步暴露一个简单的接口。申请沙箱、执行代码、释放沙箱。执行代码可以用 subprocess 加超时输出做截断。第四步加资源限制。用 cgroup 限制 CPU、内存、进程数。用 seccomp 过滤危险系统调用。这个版本大概几百行代码能搞定适合验证想法。缺点是单机扩展性有限但作为起点足够了。6.2 进阶版本分布式沙箱调度当你需要多机扩展的时候就要引入调度层。第一步把沙箱管理进程改造成 agent部署到每个节点上。agent 负责本节点的沙箱创建和销毁向中心调度器汇报状态。第二步写一个中心调度器。它维护全局的沙箱视图接收训练框架的请求分配到合适的节点。调度算法可以先用简单的轮询或最少负载后面再优化。第三步加健康检查和故障转移。节点挂了上面的沙箱要能迁移或重建。调度器要能感知节点故障把请求转到健康节点。第四步加监控和告警。沙箱的创建延迟、执行成功率、资源利用率这些指标要能实时看到出问题能及时发现。这个版本的工作量就上来了大概需要几千行代码还要考虑分布式一致性问题。建议先用现成的编排工具比如 Kubernetes打底在上面做沙箱层的定制。6.3 生产版本需要考虑的额外问题如果这套东西要上生产还有几个问题要考虑。多租户隔离如果多个训练任务共享一套沙箱集群租户之间的隔离要更严格。资源配额要按租户分配防止一个租户吃光资源。审计和追溯每个沙箱的执行记录要留存出问题能追溯。记录包括谁申请的、跑了什么代码、产生了什么输出、什么时候释放的。成本核算沙箱消耗的资源要能计量按租户或按任务分摊成本。这需要调度器记录每个沙箱的资源使用情况。版本管理基线镜像会更新要能管理多个版本支持灰度发布和回滚。容量规划根据历史负载预测未来需求提前扩容。这需要长期的监控数据和趋势分析。6.4 几个我踩过的坑和对应的解法最后分享几个实操中踩过的坑。坑一沙箱创建太快导致资源竞争。DSec 的毫秒级创建很诱人但如果创建速度超过资源分配速度会出现大量沙箱同时启动争抢资源的情况。解法是加一个创建速率限制平滑启动。坑二快照恢复后的时钟漂移。从快照恢复的沙箱系统时钟可能停留在快照创建的时刻。如果代码里有时间判断行为会异常。解法是恢复后立即同步时钟。坑三cgroup 限制不生效。cgroup v1 和 v2 的行为不一样配置错了限制不生效。解法是明确用 v2并且验证限制确实生效跑一个吃内存的测试看会不会被 OOM。坑四seccomp 过滤太严导致正常代码跑不了。有些库会调用一些看起来危险但实际必要的系统调用。解法是先用宽松策略跑一段时间收集实际用到的系统调用再收紧。坑五沙箱池的健康检查误杀。健康检查如果太激进会把正常但响应慢的沙箱误判为不健康。解法是健康检查要有重试和宽限期不要一次失败就销毁。这套东西搭起来不容易但一旦搭好agentic training 的迭代速度会快很多。DSec 的价值就在于它把这套基础设施的设计和实现都趟了一遍后来者可以站在它的肩膀上少走很多弯路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑