
如何为Agent Substrate配置GPU Worker池nvidia-ctk、CDI与runsc nvproxy实战【免费下载链接】substrateAgent Substrate: the core system项目地址: https://gitcode.com/GitHub_Trending/substrate7/substrateAgent Substrate 是一个面向 Agent 运行时的高密度沙箱系统它把大量 Actor智能体应用复用映射到少量 Kubernetes Worker Pod 上。当你的 Agent 需要调用 GPU 推理或训练任务时就需要为它配置一个GPU Worker 池。本文将带你完整走一遍配置链路用nvidia-ctk 生成 CDI 规范、通过CDI 设备注入把驱动和 GPU 设备节点带入沙箱、最后由runsc nvproxy在 gVisor 内核隔离环境中代理 GPU 调用。掌握这条链路你就能在保持 Substrate 安全默认值的前提下为 Agent 工作负载启用 GPU 加速。一、先理清概念GPU 在 Substrate 架构中的位置 Substrate 的核心思路是Actor 多于 Worker概念说明Actor运行在沙箱中的智能体进程支持挂起/恢复suspend/resumeWorkerPool一组同构 Worker Pod 的声明式资源CRD由控制器自动伸缩Worker Pod真正承载沙箱的物理 Pod资源上限即单个 Actor 的容量SandboxgVisorrunsc或 microVM 沙箱运行时GPU 的接入点是Worker Pod 所在的节点你在WorkerPool中声明nvidia.com/gpu资源Kubernetes 调度器就会把 Worker Pod 放到 GPU 节点并预留设备。相关行为可以在 workerpool_controller_test.go 的测试用例中直接看到——声明 GPU 资源的池子会自动带上nvidia.com/gpu容忍度确保 Pod 能落到打了污点的 GPU 节点。 详细说明见官方 API 指南docs/api-guide.md二、第一步用 nvidia-ctk 生成 CDI 规范 CDIContainer Device Interface容器设备接口是 NVIDIA 生态标准化的设备描述格式。Substrate不依赖 containerd 的 CDI 应用逻辑因为 Actor 容器是在 Pod 内部的沙箱容器中由 ateom 创建的必须自己读取并应用 CDI 规范——这正是 internal/cdi/cdi.go 包注释中解释的设计动机。典型做法是在节点上执行nvidia-ctk cdi generate --output/etc/cdi/nvidia.jsonnvidia-ctk 会为每张卡生成按索引0、按 UUID 和all命名的设备规范里包含三类容器编辑见 internal/cdi/cdi.godeviceNodes要创建进容器的设备节点如/dev/nvidia0、/dev/nvidiactlmountsGPU 驱动库的 bind 挂载如/usr/local/nvidia/lib64env hooks环境变量与createContainer生命周期钩子。一个细节值得注意CDI 规范中设备节点的 major/minor 号经常被省略因为标准 OCI 运行时会自行去宿主机 stat 解析。而 Substrate 的注入发生在 OCI spec 合并阶段所以它自己 stat 宿主机补齐设备号否则沙箱拿到的是无效的0,0字符设备——参见 resolveDevNumbers。三、第二步声明 WorkerPool 的 GPU 资源 ⚙️为 GPU 池配置 WorkerPool 时核心就是三件事资源限额、容忍度、节点标签。apiVersion: ate.dev/v1alpha1 kind: WorkerPool metadata: name: gpu-agent-pool namespace: ate-demo spec: replicas: 2 workerImage: ko://github.com/agent-substrate/substrate/cmd/ateom-gvisor template: resources: limits: nvidia.com/gpu: 1 cpu: 4 memory: 16Gi tolerations: - key: nvidia.com/gpu operator: Exists effect: NoSchedule各字段的作用nvidia.com/gpu: 1——普通 Kubernetes 扩展资源把 Worker Pod 调度到 GPU 节点并预留 1 张卡。目前池级的 GPU 限额仅此作用Actor 侧的设备直通 API 仍在设计中见下文现状说明tolerations——容忍 GPU 节点的污点控制器会把模板中的容忍度原样应用到 Pod 上逻辑在 workerpool_apply.go节点版本标签——数据面只在带ate.dev/substrate-version标签的节点上调度新加入的 GPU 节点必须先打上该标签说明见 README.md。创建后可用 CLI 验证kubectl get workerpool gpu-agent-pool -n ate-demo kubectl get pods -n ate-demo -l ate.dev/worker-poolgpu-agent-pool -o wideWorker Pod 进入 Running 且落在 GPU 节点说明第一步成功 ✅四、CDI 注入实战Substrate 如何把 GPU 送进沙箱 这是整条链路最有 Substrate 特色的部分。gVisor 版 ateom 在构建 Actor 的 OCI bundle 时调用cdiinject.IntoBundle把 CDI 规范合并进沙箱的config.json完整流程在 cmd/ateom-gvisor/internal/cdiinject/inject.go注入步骤做了什么为什么必要解析设备号stat 宿主机补齐 major/minorCDI 故意省略设备号runsc 需要真实值写入 deviceNodes设备节点 cgroup 白名单rwm权限沙箱内核必须显式放行设备bind 挂载驱动库补全type: bindCDI 省略挂载类型runsc 的 gofer 需要它环境变量合并 env并剥掉NVIDIA_VISIBLE_DEVICES防止 runsc nvproxy 再去调用 nvidia-container-cli避免双份注入钩子白名单只放行审核过的createContainer钩子nvidia-ctk 版本不受 Substrate 控制钩子需按沙箱安全姿态审查SONAME 符号链接解析驱动库 ELF 的DT_SONAME并写入 rootfs让libcuda.so.1这类按 SONAME 链接的程序找到真实驱动库其中 SONAME 软链接是个很讲究的细节它逐个读取驱动库的 ELF 头soname.go发现 SONAME 与挂载文件名不一致例如libcuda.so.1指向libcuda.so.580.65.06时在 rootfs 内建相对软链单个库解析失败只会跳过并记日志不会拖垮整个 GPU 池。测试用例 inject_test.go 完整演示了注入后应满足的不变量设备号被正确解析、未知钩子被跳过、NVIDIA_VISIBLE_DEVICES被移除、重复注入是幂等的。五、runsc nvproxygVisor 里的 GPU 调用代理 gVisor 的用户态内核不直接暴露/dev/nvidia*给应用而是通过nvproxy组件在沙箱内代理 NVIDIA 驱动调用沙箱中的应用发起 CUDA/驱动调用请求经由 CDI 注入的设备节点进入 gVisor 内核nvproxy在沙箱内以用户态代理的方式转发到宿主机驱动绕过大部分内核接口。这正是 Substrate 选择CDI 注入 nvproxy组合而非传统 nvidia-container-toolkit 注入的原因设备进入的是沙箱的 OCI spec而不是 Pod 容器且整个过程受 gVisor 的零信任内核边界约束。相关安全假设可以在 docs/threat-model.md 中对照阅读架构全景见 docs/architecture.md。 排障提示如果工作负载报找不到libcuda.so.1优先检查 SONAME 软链是否生成、LD_LIBRARY_PATH是否包含驱动库目录若报0 张 GPU检查NVIDIA_VISIBLE_DEVICES是否已被正确剥离。六、现状说明与验证清单 ⚠️坦诚地说GPU 直通能力仍在演进中。docs/api-guide.md 明确标注Substrate 当前不向 Actor 直通设备——早期的做法是把 Worker Pod 的设备注入到每个 Actor 容器已在新设备 API 设计期间移除因为资源名数量无法表达哪个容器拿设备、如何共享、以及如何恢复到兼容硬件上。当前版本中✅ WorkerPool 的nvidia.com/gpu限额可以放置并预留GPU 节点资源✅ nvidia-ctk CDI 规范、CDI 注入cdiinject、SONAME 软链、nvproxy 配套均已实现并有测试覆盖 Actor 粒度的设备直通 API 正在设计中。验证清单GPU 节点已安装 nvidia 驱动nvidia-ctk cdi generate生成的规范存在节点打了ate.dev/substrate-version标签Worker Pod 调度到 GPU 节点且状态为 Running沙箱 bundle 的config.json中出现设备节点与驱动库挂载幂等不会重复注入工作负载内nvidia-smi/ CUDA 调用经由 nvproxy 正常返回。七、总结一张图理清 GPU Worker 池配置链路 nvidia-ctk cdi generate → /etc/cdi/nvidia.json (CDI 规范) ↓ WorkerPool 声明 nvidia.com/gpu tolerations ↓ atecontroller 调度 Worker Pod 到 GPU 节点 ↓ ateom-gvisor 读取 CDI 规范internal/cdi ↓ cdiinject 合并进沙箱 OCI spec设备号/挂载/env/钩子白名单/SONAME 软链 ↓ runsc nvproxy 在 gVisor 沙箱内代理 GPU 调用按这条链路走下来你的 Agent 就拥有了节点有卡、Pod 占卡、沙箱用卡的完整 GPU 能力。随着 Actor 级设备直通 API 落地这套基础设施CDI 解析 注入会被直接复用——现在搭好 Worker 池就是为那一天做准备。更多背景可参阅 docs/roadmap.md 与 demos/counter/README.md。【免费下载链接】substrateAgent Substrate: the core system项目地址: https://gitcode.com/GitHub_Trending/substrate7/substrate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考