1. 智能体训练的"环境问题"比算力问题更难解
1.1 三个典型坑:状态污染、动作副作用、不可复现
大规模智能体训练和我以前做过的模型训练完全不是一回事。模型训练是喂数据算梯度,任务边界清晰;智能体训练则是让模型在环境里不断试错,调用工具、读取反馈、调整策略,每一步都可能产生不可控的副作用。正因如此,训练基础设施的形态也被迫改变——不能再简单地把一堆GPU、一张网卡和几个容器拼起来就开跑,你需要一个能在隔离、弹性、成本和质量之间找到平衡的沙箱底座。DeepSeek分享的弹性计算方案DSec,正是冲着这个痛点来的,它被设计成一种面向大规模高效智能体训练的沙箱基础设施。
我最早做智能体训练时犯过一个低级错误:直接把所有exploration跑在同一个K8s集群的普通Pod里。结果训练到一半,某个智能体误调了系统命令,把共享临时目录里的数据全删了,整个batch全部失败。这就是智能体训练最典型的坑——状态污染。多个智能体同时和同一个环境文件交互、共享工作目录、写同一个临时文件,轻则训练结果互相干扰,重则整个实验报废。更隐蔽的是动作副作用:智能体可能会执行写文件、启动进程、访问外部API、发起网络请求等操作,这些动作在一个不隔离的环境里就是灾难源头。
另一个我经常踩的是不可复现。模型训练算一遍随机种子就拿到结果,但智能体训练里环境本身有状态,执行顺序不同、网络响应快慢不同,都会导致完全不同的轨迹。如果沙箱没有日志和快照机制,你根本没法定位是模型策略错了,还是环境被上一次实验污染了。所以现在我们团队内部有一条硬规矩:凡是智能体训练任务,必须标配"一任务一沙箱、状态可回收、执行可回溯"。DSec的思路其实也正是这样,它把每一个训练会话当成一个临时、可丢弃、可重建的沙箱实例,而不是像传统HPC那样把节点租出去用到底。
1.2 为什么虚拟机太重、裸容器又太薄
既然要隔离,第一反应是开虚拟机。OpenStack或者云上的VM实例确实隔离彻底,但成本也彻底。智能体训练的特点是高频次、短任务、大量并发探索,一个任务可能只要跑两三分钟就要换一个环境,VM动辄几十秒的启动时间直接把吞吐拖垮。更不用说VM本身还要占一大块内存做Guest OS,在一台物理机上跑几十个轻量任务时,浪费非常可观。做过调度的人都知道,虚拟机方案在智能体场景属于"高射炮打蚊子",安全但笨重。
反过来,纯Docker容器又太薄。Docker底层共享宿主机内核,隔离只是namespace和cgroups的组合,进程列表、网络协议栈、内核模块这些关键边界其实并没有真正隔开。我见过不止一次容器内的训练进程通过执行mount操作或者利用内核漏洞拿到宿主机的读写权限。智能体训练环境里又有大量不可信代码和外部工具调用,这种"薄壳"根本扛不住。所以DSec这类基础设施在底层选型时,通常不会走极端,而是把安全目标定位在"比容器强一个量级、比虚拟机轻一个量级"。
现在比较成熟的折中路线有几条:Google的gVisor用用户态内核拦截系统调用,启动快但部分系统调用有性能损耗;AWS的Firecracker是微虚拟机,内存占用控制在几MB级别,可以做到VM级隔离但又有接近容器的冷启动速度;Kata Containers则是把轻量虚拟机嵌进容器运行时。这几类方案各有取舍,DSec在社区讨论里被提到较多的是基于轻量虚拟化或系统调用拦截的方案,因为智能体经常要跑浏览器、操作数据库、执行代码解释器,这些场景对system call多样性要求高,纯WebAssembly沙箱这类方案短期内还覆盖不了。底层选型的核心逻辑很简单:安全边界越强,环境互信成本越低,才敢让智能体去碰真实工具。
2. DSec核心设计思路拆解
2.1 沙箱作为一等调度单元
传统调度器管的是Pod、虚机、容器,而DSec这类基础设施在做的事情是把"沙箱实例"提升为一等调度单元。什么意思?就是你的调度对象不再是一块抽象的CPU或者一个固定的工作节点,而是一个包含运行环境、工具链、网络策略、存储快照、会话生命周期在内的整体。我需要多少并发探索,就先拉起多少沙箱,训练完成后整个沙箱连同中间状态一起回收,而不是在节点上留一堆残留进程和缓存等待下次复用。
把这个逻辑落到实践里,本质上是给沙箱定义了一套CRD(自定义资源)。以Kubernetes为基础的话,你会在里面声明sandbox spec:镜像地址、启动命令、资源请求、超时时间、环境变量、挂载路径、允许访问的外部域名列表。调度器根据这些声明去找合适节点,而不是让每个智能体任务去手工指定"我要一台有GPU的机器、还要一个安装好Python环境的目录"。这一点非常关键,因为大规模训练下,任务类型可能成百上千,如果每次都要业务方自己装配环境,平台就失去了弹性意义。
我建议把沙箱实例的生命周期分成四段:创建、运行、冻结、销毁。创建要快,最好做到镜像预热后几百毫秒拉起;运行期间指标被采集,日志被持久化;冻结并不是暂停容器,而是把环境状态快照保存下来,方便做轨迹复盘或者热迁移;销毁必须彻底,包括临时网络设备、数据卷、内核态残留全部清理干净。DSec这种面向智能体训练的沙箱基础设施,最大的价值也正是把这四段流程标准化,让上层训练框架不用关心环境如何来、如何走。
2.2 弹性扩缩容:从"资源池"到"流量驱动"
常规扩容逻辑是看CPU、内存利用率。但在智能体训练场景,这两个指标经常失真。因为很多沙箱任务是I/O密集形,比如调用外部工具、等待HTTP响应、解析文档,CPU几乎跑不满;还有一批任务在等GPU分配,CPU空转但队列已经堆积。如果你只按CPU利用率扩容,永远是慢半拍。
DSec这类系统的弹性策略更接近"流量驱动":看任务队列深度、每任务的等待时长、沙箱冷启动耗时和目标吞吐。我在实际搭建时用的是队列长度作为主信号:Redis里维护一个pending任务队列,当队列里等待的任务数超过某个阈值,就触发扩容;当队列接近清空,开始缩容。同时要引入冷却时间,避免任务波动导致沙箱数量反复横跳。另一个容易忽略的信号是冷启动延迟。如果镜像很大,或者要提前拉起浏览器、数据库实例,扩容的收益会被初始化时间吃掉。所以最好有"预创建池"机制:高峰来临前就保有一定数量的空闲热沙箱,任务一到直接绑定。
扩缩容还要考虑训练的稀疏性。智能体探索经常会遇到一个batch结束、下一个batch还没下发的小窗口,这时候如果缩容太激进,热沙箱全部回收,启动开销分摊到每个任务上,整体效率反而下降。我后来加了"最低保底数量"和"缩容延迟时间"两个参数,保底数量按历史基线曲线设定,缩容延迟控制在5到10分钟,实测弹性和成本控制都比较稳。
2.3 资源配额与公平调度
大规模智能体训练几乎都是多团队共享一套集群,这时候公平调度比绝对利用率更重要。一个问题很常见:一个团队一次性提交了5000个探索任务,把集群资源全霸占,其他团队的实验被活活饿死。还有一批长期运行的每日评测任务,和临时的探索任务抢资源,影响线上效果回归。DSec方案在这方面的做法通常是两层调度:第一层按团队/项目做配额路由,第二层在配额内做任务优先级排序。
我建议配额维度至少包括三项:并发沙箱数、GPU等价占用量、月度聚合算力。并发沙箱数防止一个实验瞬间碾完整个池子;GPU等价占用量把CPU任务、GPU任务统一折成标准单位;月度聚合算力则适合做预算管理,让团队知道自己的探索任务已经烧了多少钱。队列上可以拆成高优、普通、低优三档,高优给线上回归和紧急问题复现,普通给日常训练,低优给批量探索。低优任务可以被抢占,被抢占后不是直接杀掉,而是让沙箱状态快照后被打回队列尾部,下次恢复。
这种公平调度在初期搭建时不显眼,一旦集群规模到了几百个节点,就会发现它才是稳定性的核心。我也曾经试图不做配额,靠大家自觉,结果两周后集群上全是新奇探索任务,线上评测排队三小时,最后还是老老实实把配额系统补上。
3. 从零实现一个轻量DSec雏形:我的实操记录
3.1 组件选型与网络拓扑
接下来我完整还原一次本地落地的过程。这里用的是单机实验版本,但架构可以平滑扩展到多机,读者可以直接照搬思路。
我选的基础组件如下:K3s(轻量Kubernetes)做编排,gVisor做沙箱运行时,Redis做任务队列和状态暂存,Registry预热镜像,Prometheus+Grafana做可观测性。云上环境可以换成标准K8s和阿里云/腾讯云的弹性容器实例,但核心逻辑不变。选K3s是因为单机部署快,资源占用低,api兼容标准K8s,后面迁移不用改配置。gVisor的选择是看重它的runsc沙箱拦截能力,在不可信代码执行场景下比普通runC更靠谱。
网络拓扑上,我把节点分成两块:控制面节点跑API Server、调度器和控制器;计算面节点跑沙箱Pod。沙箱Pod默认没有出网能力,只有显式配置了externalEgressAllowed的域名才会被代理放行。所有训练任务的输入输出不依赖共享目录,而是通过对象存储/Redis中转,这样天然切断了宿主文件系统耦合。上网代理我单独用了一组Egress网关Pod,所有外部HTTP请求统一走这里,方便审计和限速。这套拓扑的价值在于:即使某个智能体拿到网络权限做了危险操作,影响面也被限制在单次会话。
3.2 沙箱运行时的关键配置
下面是一份我放出来的沙箱运行时配置模板,用途是跑"代码生成+执行验证"类智能体任务。核心要注意的字段我都加了注释。
apiVersion: dsec.example.io/v1 kind: Sandbox metadata: name: code-agent-run-123 spec: runtimeClassName: gvisor-sandbox # 指定gVisor运行时 image: registry.example.com/sandbox/python-tool:3.11-v1 command: ["/bin/bash", "-c", "python main.py --task_id=${TASK_ID}"] resources: requests: cpu: "1" memory: "2Gi" limits: cpu: "2" memory: "4Gi" lifecycle: ttlSecondsAfterReady: 900 # 就绪后最多存活15分钟 maxIdleSeconds: 120 # 处于空闲状态2分钟后自动回收 securityContext: seccompProfile: "runtime/default" capabilities: drop: ["ALL"] readOnlyRootFilesystem: true allowDevices: false egressWhitelist: - "*.openai.com" - "*.anthropic.com" - "pypi.org" - "registry.example.com"重点说三个参数。ttlSecondsAfterReady和maxIdleSeconds一定要配合使用,前者保证任何情况不会出现僵尸任务,后者把已经跑完但没人回收的沙箱及时销毁;只配一个容易失控。readOnlyRootFilesystem我踩过坑,一开始没开启,智能体训练脚本里一个临时文件写入就永久污染了整个镜像层,开启之后所有写操作统一落到临时卷,销毁时自动清掉。egressWhitelist不是传统防火墙那种精确到端口的方式,而是按域名后缀匹配,因为智能体经常要访问动态域名,但这种白名单需要配合Egress网关做SNI校验,防DNS重绑定绕过,否则白名单等于裸奔。
GPU任务的沙箱配置会多一段device请求和控制,但总体结构一致。我建议把这份模板参数化,固化到平台后台表单里,业务方只需要选"任务类型、镜像、最大运行时间、出网范围"四个字段就能拉起一个沙箱,否则工程团队会被各种定制需求淹没。
3.3 弹性调度策略配置
弹性策略我用了KEDA,它原生支持以Redis队列长度和Prometheus指标作为扩缩容信号。部署方式不是重点,直接放ScaledObject配置:
apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: agent-sandbox-scaler spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: sandbox-worker minReplicaCount: 2 maxReplicaCount: 50 cooldownPeriod: 120 triggers: - type: redis metadata: address: redis.example.com:6379 listName: agent:pending_tasks listLength: "10" activationListLength: "2" authenticationRef: name: redis-auth - type: prometheus metadata: serverAddress: http://prometheus.example.com metricName: sandbox_task_waiting_seconds threshold: "30" query: | avg_over_time( sandbox_task_waiting_seconds{pod=~"^sandbox-worker.*$"}[2m] )我把listLength目标值设为10,意思是队列长度超过10就扩一个副本;activationListLength为2,低于2就缩,这个组合能避免一个任务也触发扩容的抖动。cooldownPeriod设120秒,控制每次扩缩容之间的间隔,防止任务到达的瞬时尖刺带来频繁变更。Prometheus trigger是兜底信号,专门处理"队列短但等待时间长"的情况,比如某个任务卡在镜像拉取、依赖下载,队列虽然不长但任务已经等了一分钟。两个信号同时生效,扩缩容行为的鲁棒性高不少。
我在试这套配置时把minReplicaCount设成了0,结果凌晨低峰一个请求进来后,冷启动要等30秒到60秒,体验极差。后来改成2,保持两个常驻热沙箱,启动延迟降到小于2秒,成本增加忽略不计。生产环境还应该在HPA的behavior字段里设置scale-down stabilization,我目前用的是600秒,因为沙箱不是无状态HTTP服务,快速销毁会打断正在跑的探索轨迹,造成大量无效计算。
3.4 训练任务提交与生命周期管理
生命周期管理是DSec里最容易被低估的部分。我上一套方案只用Deployment,任务提交之后靠容器内进程自己结束,结果大量游离沙箱和资源泄漏。后来我改成两层结构:外层是"任务控制器",内层是"沙箱执行器"。任务提交到Redis队列,控制器消费后创建Sandbox CRD,Sandbox进入Running状态后由Kubelet拉起实际容器。每个任务都带一个任务ID,结束前会把日志、指标、最终状态写到Grafana追踪系统,并在CRD里打上完成标记。
沙箱销毁时有一个必须处理的顺序问题:先停业务进程,再snapshot状态,最后清理Pod。如果逆序操作,会丢失智能体最后的决策记录。我用了一个简单的Finalizer逻辑,在Sandbox CRD删除前先触发snapshot controller,整个过程大概是:
# 提交任务 taskctl submit --image python-tool --task_code 'xxxx' --timeout 900 --egress pypi.org # 查看任务状态 taskctl get sbx-code-agent-run-123 --namespace team-a # 输出: PHASE=running READY=1 RESTARTS=0 TTL=864/900 # 强制回收(一般用不到,但手工介入时很有用) taskctl delete sbx-code-agent-run-123 --with-snapshot=false这套命令只看结果很平常,但背后每个设计都有原因:--timeout是任务CTL层面的超时,会和沙箱的ttlSecondsAfterReady做min运算,两个机制互备,避免任何单点造成任务悬挂;--with-snapshot=false则是在确认任务已经失败且不需要复盘的场景下,直接销毁,省掉快照存储开销。
4. 把成本和安全当成一等项目
4.1 最少权限:沙箱里没有"多余root"
智能体沙箱的安全基线,我总结成一句话:不给任何用不上的权限。默认配置里我要把所有capabilities全部drop,只保留最底层的NET_BIND_SERVICE用来监听端口;文件系统只读,临时写入全部映射到内存盘或者临时卷;禁止挂载宿主机目录;allowPrivilegeEscalation显式设为false。这些配置写在一份默认安全模板里,所有沙箱创建时自动继承。
有不少读者问,为什么智能体训练需要这么严?因为智能体训练环境里跑的不是你写死的Python脚本,而是模型根据环境反馈动态生成的动作序列。它可能真的需要执行任意代码,理论上一个prompt就能诱导模型写出一个绕过限制的命令。我在一次实测中,模型被要求"修改系统时间以便通过测试",它确实尝试执行了date命令;如果没有沙箱权限隔离,这个动作虽然对主机无伤,但如果换成rm -rf命令,后果就不一样了。
网络访问权限也要走最小化。我前面提到egress白名单,这里补一句:白名单配好后需要验证代理层确实在做SNI拦截,而不是只做IP过滤。之前我们只做了IP白名单,结果智能体直接访问一个被允许的域名背后的IP,就绕过了限制。后来代理层改成先解析DNS再从允许域名列表验证SNI,才真正堵住。域名级白名单的粒度还是粗,有些工具需要访问用户上传的任意文件链接,这时候就要加内容过滤或者让工具调用走一个封装后的API网关,而不是放原始出网请求。
4.2 沙箱逃逸的排查与加固
无论用什么隔离方案,盲目信任运行时都是大忌。gVisor已经做了很多拦截,但历史上也出现过绕过案例;内核级漏洞永远存在。我自己处理的真实事件里,最常见的问题不是内核漏洞,而是配置错误导致逃逸。有一次我忘了在Sandbox CRD里设置seccompProfile,结果runsc意外回退到默认容器运行时,容器内执行mount时直接获得了宿主机资源。排查过程花了很长时间,最终发现是创建沙箱时传入了不支持的配置,runtimeClass悄然回退。
加固策略可以分三层。第一层是运行时兜底,在所有节点部署runtimeClass准入校验,凡是不匹配指定runsc版本的Pod直接拒绝创建,杜绝"我想用gVisor结果却跑在runC"这类静默故障。第二层是行为基线,采集沙箱内系统调用序列,对超出训练场景的可疑行为(例如ptrace、mount、访问内核模块文件)做告警和自动隔离。第三层是定期内核补丁和运行时升级,这一层容易被忽略,等到出了问题才升级,业务已经受损了。推荐至少每两周把沙箱运行时镜像重建一次,重新打补丁再重新预热。
如果真发生了逃逸嫌疑,第一时间不要删除沙箱,应该先冻结现场,导出内存和日志,然后停止训练集群入口,最后再容器化取证。删除动作会把最关键的系统调用序列和文件变更记录一起带走,我之前因为手快删了现场,后来复盘只能靠残缺日志拼凑结论,非常被动。
4.3 成本归属与闲置回收
大型智能体训练的成本大头不是GPU本身,而是GPU旁边那些永远不释放的CPU沙箱。因为很多探索任务在GPU等待队列里排队,但排队的机器上的CPU沙箱却已经跑完了,没人回收。我引入了一套按任务维度的计费模型:每个Sandbox实例的创建、运行、快照、网络流量全部打上task_id标签,聚合到成本报表。定期跑一个"成本标兵"报告,把成本最高的前20个任务列出来,然后由业务方解释。这招的效果比任何资源上限都实际。
闲置回收不要等到平台层做强制清理,应该在业务层就设好规则。我现在的经验是三类任务需要不同回收策略:交互式实时调试任务给30分钟闲置时限;批量探索任务给15分钟;评测任务给60分钟并允许单独申请延长。如果统一给太多时间,集群长期处于被僵尸沙箱占用的状态;给太少,会让正在长推理的任务意外被杀。闲置判定也不能只看CPU,一个任务可能在等外部API响应,CPU是0但工作还在进行,所以要以"连续N分钟没有新增日志事件"作为收回条件,而不是CPU使用率。
弹性实例的引入是成本优化的大杀器。智能体训练任务天然可重试、可抢占,所以我把大批探索任务安排到竞价实例上,只有需要长期运行、不能中断的主评测任务用包年包月稳定实例。两个池子的配比我调到7比3,探索任务占便宜,核心任务保稳定。加上前面提到的热沙箱预创建池,也选竞价实例来承载,进一步摊薄成本。
5. 大规模训练里我踩过的坑(排查目录)
5.1 问题速查表
| 症状 | 根因 | 对策 |
|---|---|---|
| 任务大量超时,队列堆积但集群CPU不高 | 镜像冷启动太慢,沙箱初始化吃掉大量时间 | 开启预创建池,预热镜像到节点,统计初始化耗时拆分快递放缓存 |
| 沙箱内访问外部API一半概率失败 | DNS解析绕过了Egress网关,走了宿主DNS | 强制所有Pod使用EgressDNS,禁止节点级DNS直连 |
| 两个任务互相覆盖输出文件 | 沙箱间共享了持久卷 | 默认不共享卷,改用Redis或对象存储中转 |
| 训练结果完全不可复现 | 环境随机性未记录,快照丢失了初始seed | 启动时把随机种子和环境hash写入日志,结束前自动快照 |
| 扩容一直触发,但任务吞吐没变 | 队列长度信号和实际处理能力不匹配 | 改为按等待时间扩缩容,加入任务预估耗时 |
| 缩容后处理性能骤降 | 冷却时间太短,频繁销毁热沙箱 | 增大scale-down stabilization,引入最低保底数量 |
这张表现在贴在团队wiki首页,凡是遇到类似问题先来查表再深挖。实践经验里很多"疑难杂症",往上追三层其实都是基础设施层的配置细节,而不是训练算法本身的bug。
5.2 案例一:环境初始化瓶颈导致扩容跟不上
第一次跑千级并发探索时,我发现扩容指标已经到了50个副本,但队列任务等待时间还是持续上涨。查看日志后发现每个新沙箱冷启动平均要40秒,其中20秒花在下载base镜像层,10秒花在启动Python环境和工具包,真正拉起进程只要几秒。HPA扩容是按照最终就绪Pod数触发的,可一大批Pod根本没有进入Ready状态,后续扩容被block住。
我的处理分三步。第一步,镜像分层优化,把不动的大依赖打成基础层并预置到每个节点,业务镜像只保留游戏插件和新人包,从40秒降到10秒;第二步,增加预创建池,维护两个常驻热沙箱,队列有任务时直接绑定,同时KEDA收到的信号变成热沙箱消费速率,不再被初始化时间干扰;第三步,把初始化步骤下沉到节点daemon,比如Python虚拟环境、工具链、浏览内核组件,提前在节点启动,沙箱创建时直接挂载。三步做完,P95冷启动时间降到3秒以内。
这个问题的教训非常直白:弹性扩容的前提是"单位实例启动时间可控",否则系统越扩越虚、排队越扩越长。任何高并发场景上线前,都要先做一次镜像层级的冷启动压测,不要以为配置好HPA就万事大吉。
5.3 案例二:沙箱内DNS/网络延迟导致训练中断
有一阵子训练任务频繁报"连接外部工具超时",但外部服务本身没有故障。排查后发现所有沙箱流量都走了Egress网关,网关连接数在高峰时被撑爆,引起半开连接堆积。更隐蔽的是,沙箱内DNS解析没有走Egress代理链,直接发到了宿主机,宿主机又转给公共DNS,这一跳既慢又容易丢包。
我在Egress网关外层加了连接池、持久连接和IO超时时间;沙箱DNS统一指到一个内网CoreDNS,所有解析请求都经过这里,再由它决定是否转发到上游。为了让外部API调用更稳定,把部分高频率使用的域名直接走了直连白名单,省去一层代理转发。测试下来网络超时率从5%降到0.2%左右,训练中断率明显下降。
这里还想补充一个细节:智能体训练里的网络超时不能简单重试,因为重试可能改变环境状态,产生和原有轨迹不同的结果。所以在沙箱里设置网络超时后,要打上"环境可能不一致"标签,让训练框架决定是否废弃当前轨迹。基础设施层太积极自动重试,反而会污染数据。
5.4 案例三:队列中任务大量超时,全在等待GPU被释放
我们有一个团队提交了2000个带GPU的智能体任务,但是GPU资源池只有50块卡,任务在队列里平均等30分钟,大量任务直接TTL超时。当时控制台看起来像是调度器死掉了,实际上是高优任务没做配额限制,GPU请求全部被一个团队占满。
后来在调度器里加了GPU复用策略:允许同一块GPU上并行挂载两个轻量训练实例,按显存和时间片双维度保证公平。又设置了团队级别并发上限,超过上限的任务直接被拒绝而不是排队,因为排队任务会持续占用内存和调度器监控资源。被拒绝的任务进入一个"半自动调度"队列,由团队负责人决定是升优先级还是取消。这个机制上线后,GPU利用率从55%提升到76%,任务超时率大幅下降。
这类问题的核心思路:排队不是免费的,每个过度排队都在消耗调度器吞吐和用户信心。与其让所有任务都无限排队,不如给一个明确的"资源不可用"信号,让业务方快速调整策略。DSec这类基础设施在弹性调度里也需要有这个"快速失败"能力,它能避免雪崩,也能让资源流量更健康。
6. 写在最后:基础设施必须比算法更现实
这套沙箱基础设施从单机折腾到几十节点,前后迭代了大半年,踩过不少坑。我个人最深的体会是,智能体训练的技术难点从来不在模型端,而是基础设施能不能把"环境可信、调度弹性、成本可算、过程可溯"这四件事一次性解决好。你可以在单机上用容器硬跑,但一旦任务规模到几千并发,任何环境的微小污染、调度延迟、网络抖动都会被无限放大。DSec这个名字在社区里被讨论,本质上就是大家已经意识到,智能体训练需要一套比传统云原生更务实的底座。
最后再分享一个小技巧:无论你的方案叫不叫DSec,至少在基础设施层面把"沙箱实例"做成可观测的一等对象,所有日志、指标、成本都用同一个沙箱ID串联。这一步越早做,后面排查问题的效率就会高一个数量级。不要等训练规模上去了再补可观测性,那时候你连问题根因是什么都找不到。