尧图精选

海光DCU接入Kubernetes全实践:整卡/共享/vDCU模式与DeepSeek推理部署

🕒 发布时间:2026/9/17 6:26:57 📁 来源:尧图网络
搞过 AI 集群的人应该都会有同样的体会硬件到位不是结束而是另一个开始。海光 DCU 这种国产加速卡单卡算力数据看着并不差但真正决定生产价值的是它能不能像 NVIDIA GPU 一样被 Kubernetes 调度、被 AI 平台纳管、被不同团队安全地共享。这篇文章记录的是我最近做的一轮完整适配把一批海光 DCU 接入现有 K8s 集群在 CubeStudio 平台上打通整卡、共享、两种 vDCU 虚拟化三种资源模式最后还在这套环境里跑通了 DeepSeek 推理服务。整个过程踩了不少坑也沉淀出一套可复用的标准动作下面完整拆给你看。1. 先把大逻辑捋清楚DCU 进 K8s 到底靠什么1.1 一卡一容器不算难难的是像 GPU 一样被调度很多人第一次接触国产加速卡以为只要在容器里装上驱动、把设备映射进去就完事了。如果只是单机单卡跑个实验确实可以这么干直接挂/dev/dri或者/dev/hygon设备号容器里就能看到卡。但一旦上了 K8s问题立刻变复杂你怎么告诉调度器这个 Pod 需要一张 DCU你怎么限制一个 Pod 只能看到 1 张卡而不会把机器上 8 张卡全部映射进去你又怎么保证两个 Pod 不会同时抢一张卡导致任务互相打死这些问题在 NVIDIA GPU 时代是靠一整套生态解决的Device Plugin 上报nvidia.com/gpu扩展资源调度器依据资源数值做分配容器运行时通过环境变量和钩子把对应卡挂进容器。海光 DCU 要进 K8s走的其实是同一条路只是把背后的驱动栈从 CUDA 换成了海光的 DTK 软件栈。明白了这一点后面所有的操作就都有章可循了。1.2 标准三步走驱动 → Device Plugin → 扩展资源DCU 接入 K8s 的完整链路我习惯拆成三层来理解第一层是物理驱动层。海光 DCU 的驱动和 DTK 工具包必须装到集群的每个计算节点上这是所有上层能力的基础。装完之后节点上能看到/dev/hygon_dcu这类设备文件用dcu-smi这类工具能查到卡的型号、显存和算力状态。第二层是 Kubernetes 设备接入层核心是 Device Plugin。它常驻在每个计算节点上通过 gRPC 向 kubelet 上报节点上有多少张 DCU同时负责在 Pod 调度到本节点后把具体的设备文件和环境变量注入到容器里。这个组件的关键点是它把物理设备转换成了可调度的扩展资源。第三层是调度消费层。有了扩展资源Pod 就能在 YAML 里声明要几张卡比如hygon.com/vdcu: 1。调度器看到这个字段后会筛选出满足条件的节点再结合 Device Plugin 做最终的设备绑定。三层各司其职哪一层出了问题表现都不一样。驱动没装好设备文件都看不到Device Plugin 挂了节点上的 DCU 资源会直接消失调度器配置不对Pod 可能一直 Pending。排查的时候按这个分层去定位效率会高很多。1.3 CubeStudio 在这套架构里的位置Device Plugin 解决的是K8s 能调度 DCU的问题但生产实践中你还需要一个 AI 平台来处理更高层级的事情多团队怎么共享有限的卡资源训练任务和推理任务怎么编排配额怎么管理平台怎么让普通算法工程师不用直接写资源 YAML而是通过界面或 SDK 就能提交任务CubeStudio 在这里承担的就是平台层角色。它运行在 K8s 之上底层天然继承了 Pod、Deployment、Namespace 这些调度语义但对上层暴露出的是资源池训练任务推理服务配额这类更贴近 AI 用户的概念。DCU 接入 K8s 之后CubeStudio 只要把资源类型注册进去就能把三种模式统一管理起来。这次适配我最看重的一点就是整卡、共享、vDCU 三种模式在平台侧是否能无缝切换毕竟真实业务从来不是单一模式跑到底。2. 环境准备这一步把坑提前踩完2.1 硬件与软件栈清单先说环境。我这次用的节点配置是双路海光 CPU 8 张海光 DCU 加速卡操作系统是麒麟 V10 SP3内核版本 4.19 以上。Kubernetes 集群版本是 1.28容器运行时用的 containerd 1.7。这里提前交代清楚是因为后面所有排查都要基于这套版本组合版本不匹配是国产加速卡踩坑的头号来源。软件栈方面核心是海光 DCU 的 DTK 工具包。它相当于 DCU 生态里的 CUDA Toolkit里面包含了驱动适配层、编译工具链、运行时库和基础数学库。另外还需要准备对应的 Device Plugin 组件不同的 DCU 型号和 DTK 版本对应的 Device Plugin 版本可能不同这个一定要对着官方兼容性矩阵来选别想当然用最新版。有些朋友问我为什么不用 Docker其实用也能用但 containerd 在配置 Device Plugin 的钩子时路径更清晰生产环境也更主流。容器运行时和 Device Plugin 之间通过 Unix Socket 通信containerd 的配置文件和 Docker 的路径差异是实测中最容易踩的坑之一。2.2 DTK 安装的第一步验证DTK 安装过程本身不复杂解压、执行安装脚本、配置环境变量但安装完的验证环节值得多说两句。有些时候安装脚本报错不明显你以为装好了实际上驱动根本没生效。我的建议是分三步验证。第一步先用dcu-smi检查物理卡状态正常情况下能看到 8 张卡的型号、温度、显存占用第二步检查设备文件是否存在确认/dev/hygon_dcu这类关键设备节点已经创建第三步跑一个简单的算子测试直接在节点上执行一个小矩阵乘法程序确认计算链路通了。前两步只能证明卡被识别了第三步才能证明算力真的可用。这一轮我在第二个节点上就遇到过驱动装完但/dev设备节点不生成的情况日志里也没有明显报错。最后翻出来是内核模块和当前内核版本头文件不匹配重新用dkms编译一遍才解决。所以内核和 DTK 版本的匹配关系一定要提前确认这是国产卡环境里出现频率最高的隐性问题。2.3 容器运行时检查和 Device Plugin 部署驱动就绪后接下来是在 K8s 里部署 Device Plugin。这里我强烈建议在部署之前先做一个空跑测试直接在节点上手动启动一个容器用--device把 DCU 设备映射进去跑一下dcu-smi确认容器内能正常访问卡。这个测试通过之后再部署 Device Plugin否则出了问题你很难定位是运行时的问题还是 Device Plugin 的问题。Device Plugin 本身在 K8s 里通常以 DaemonSet 方式部署给每个节点都拉起一个副本。它的核心职责有两个启动时通过 ListAndWatch 接口向 kubelet 上报资源数量收到 kubelet 的 Allocate 请求后把设备文件、环境变量注入到 Pod。部署完成之后立刻在节点上执行kubectl describe node如果看到类似hygon.com/vdcu的资源条目并且数值等于物理卡数说明设备接入这层已经打通了。这里有个细节值得留意Device Plugin 上报的资源名称是可以自定义的但要和调度消费端保持一致。我正在用的资源名是hygon.com/vdcu这个命名会贯穿后续所有 Pod YAML 和 CubeStudio 资源池的配置中途改名会带来一堆不必要的麻烦。3. 整卡 / 共享 / vDCU 三种接入模式的实现与选型3.1 整卡模式隔离性最好但浪费也最明显整卡模式最直观Pod 声明hygon.com/vdcu: 1调度器就把一整张 DCU 分给这个 Pod独享显存和算力。这种模式的优势是任务之间完全隔离互不干扰性能波动最小特别适合大模型训练、超大 Batch 推理这类吃满整张卡的场景。但整卡模式的代价也很现实如果你的模型推理只需要 6GB 显存而一张卡有 64GB那剩余的大几十 GB 就完全浪费了。AI 平台的 GPU 利用率上不去绝大多数情况都是整卡配额导致的结果。尤其是在多租户场景下A 团队的推理服务只要半张卡你非要给他一整张前面排队的 B 团队就得一直等着。资源明明够但任务就是起不来这种体验非常糟糕。所以在平台侧我通常建议把整卡模式定位成高优任务专用通道而不是默认模式。训练任务、大模型服务这类需要稳定算力和完整显存的工作负载走整卡其他场景优先考虑共享或者 vDCU。3.2 共享模式提高利用率但隔离性要靠平台补共享模式解决的就是利用率问题。多个 Pod 可以打到同一张物理卡上每个 Pod 按显存和算力配额来使用。这种模式下平台或者调度器需要在 Pod 调度时做两件事一是显存配额校验确保同一卡上的所有 Pod 显存之和不超过物理卡总显存二是算力控制防止某个 Pod 抢占过多计算资源导致邻居任务变慢。这里有个生产环境必须注意的点共享模式对任务的稳定性要求很高如果某个任务的显存申请不准确、出现显存泄漏很容易把同一张卡上其他任务拖垮。所以我会在平台侧做一张同卡负载表任何共享调度都要先查这张表评估当前卡上已有任务的显存占用和计算压力再决定是否允许新的 Pod 调度上去。这个机制在 CubeStudio 里可以通过自定义调度策略实现也是我这次适配重点验证的功能之一。还有一种更细的做法是把共享和 cgroup 限制结合起来对 CPU 内存和显存做双重限制。CPU 内存限制走 K8s 原生机制显存限制则需要 Device Plugin 在分配时做拦截这个逻辑写起来不难但要在 Allocate 阶段处理到位否则 Pod 能被调度上去却分不到合法的显存区间运行起来必挂。3.3 两种 vDCU 虚拟化模式的实际区别vDCU 是这次适配里最值得深挖的部分因为它回答了一个关键问题如何在保持一定隔离性的前提下把一张大卡拆成多个逻辑卡给不同任务用。据我实际验证目前比较常见的是两种实现路线我分别叫它们算力切分型和时间片共享型。算力切分型 vDCU 是把一张物理 DCU 的计算单元和显存按比例切分成多个 vDCU 实例每个实例拥有独立的计算上下文和显存区间逻辑上就像一张独立的小卡。这种模式的隔离性接近整卡模式性能可预测性强缺点是资源粒度比较固定一旦切出来哪怕某个 vDCU 上的任务不用资源也不好临时借给隔壁。比较适合运行时间长的常驻推理服务。时间片共享型 vDCU 则是在一张物理卡上按时间片轮转多个任务轮流使用计算单元显存空间统一管理。这种模式的资源利用率最高、切分最灵活但缺点是当多个任务同时高负载时会出现明显的性能争抢单个任务的吞吐波动较大。比较适合开发调试、短时测试这类对延迟不敏感的工作负载。这两种模式在 CubeStudio 里被统一建模成不同的 vDCU 规格管理员创建资源池时可以选择启用哪一种。我在验证时专门跑了对比实验同样的模型用算力切分型跑 QPS 非常平稳用时间片共享型跑整体吞吐更高但每个请求的延迟毛刺更多。没有绝对的好坏只有合不合适。3.4 三种模式怎么选直接给张对照表模式隔离性资源利用率性能稳定性适用场景整卡最强偏低最稳定大模型训练、高优任务共享显存算力配额中等较高受邻居影响常规推理、中等负载服务vDCU 算力切分强中等偏高接近整卡水平常驻推理、多租户隔离vDCU 时间片共享较弱最高波动较大开发调试、批量短任务选型建议很简单有长稳运行需求、对延迟敏感的线上服务优先 vDCU 算力切分或整卡集群利用率长期偏低、任务以短时为主就放开共享和时间片共享模式训练任务直接走整卡别折腾。平台侧最好把三种模式同时开放让用户在提交任务时按需选择这才是 AI 平台的完整形态。4. CubeStudio 平台侧适配实操4.1 注册 DCU 资源池与配额CubeStudio 接入了 K8s 扩展资源之后第一步是在平台里创建 DCU 资源池。这一步的输入是资源类型和总量底层本质上是给不同 Namespace 打上资源配额标签。以我的实践为例我会先建一个dcu-prod资源池里面配置整卡和 vDCU 两种规格再把不同的项目组加到资源池里分别给配额。配额管理是平台侧最容易忽略、但实际影响最大的环节。如果不做配额某个团队一口气把集群所有 DCU 全占了其他团队的任务直接 Pending 到超时。CubeStudio 的做法是基于 K8s 的 ResourceQuota 做了一层封装你可以给每个团队设置整卡总数、vDCU 总数、共享模式最大用量等维度的配额。我习惯把配额分成保障额度和弹性额度两种核心业务走保障额度弹性额度按需申请。这里我特别留意了配额变更对已有任务的影响。K8s 原生配额变化不会影响已经运行的 Pod只会拦截新提交的任务这是符合预期的行为。平台侧要做的就是把这个变化及时同步到队列和用户界面上否则用户提交任务被拒了但看不到原因反馈体验会很差。4.2 训练任务和推理任务的调度策略差异一个成熟的 AI 平台必须把训练任务和推理任务分开编排因为两者的资源特征完全不同。训练任务生命周期长、对稳定性要求极高跑了一半被抢占是最伤的推理任务生命周期长短不一、对延迟敏感但单个任务资源需求通常较小。在 DCU 集群上我把训练任务默认绑定整卡模式同时在调度策略里关闭抢占。CubeStudio 的任务调度支持优先级队列我设置了两个队列一个训练队列一个推理队列。训练队列的任务只要申请了整卡除非节点故障否则不会被调度器迁走推理队列的任务则允许在流量高峰时快速扩容低峰时缩容。还有一个小细节推理服务的调度要考虑同卡亲和性也就是让同一套服务的多副本尽量打散到不同物理卡上避免一张卡挂了导致整个服务雪崩。CubeStudio 的调度器在这里可以配置反亲和规则我实际验证下来规则生效后服务的可用性提升明显。4.3 日常工作负载在平台上的实际效果适配完成之后我验证了几个典型场景。第一个场景是提交一个模型训练任务使用整卡模式观察任务能否被正确调度到指定节点日志流转是否正常第二个场景是同时提交多个推理任务使用 vDCU 算力切分模式验证不同模型能否共享一张物理卡第三个场景是模拟开发调试环境用时间片共享模式让多个并行任务共用一张卡观察性能波动是否在可接受范围。实测下来CubeStudio 在这三种场景下的表现都符合预期。最让我满意的其实是用户侧的体验算法工程师不用关心底层 DCU 是怎么被调度和切分的只要在界面里选择资源规格提交任务就行。平台会自动把请求转换成对应的 K8s 资源声明底层 Device Plugin 完成设备绑定。复杂的硬件细节被封装在平台和 K8s 层这是 AI 平台该有的样子。5. 在 DCU 集群上部署 DeepSeek 推理服务5.1 部署方案选型别一上来就选大模型设备接入层的活儿干完接下来这步是大家最关心的怎么在 DCU 上把 DeepSeek 跑起来。这里我必须先泼一盆冷水很多朋友一听到 DeepSeek第一个念头就是把 V3 全量模型拉下来跑。但全量版本的显存需求不是几张卡能扛住的部署复杂度和成本都不是一般团队能承受的。更务实的路线是从 DeepSeek 的蒸馏版本入手比如 DeepSeek-R1-Distill 系列的 7B 或 32B 模型。这个系列在保持较强推理能力的同时模型体积小得多量化之后单卡或者双卡就能跑起来特别适合资源有限的 DCU 集群做验证。先把链路跑通后续如果业务确实需要更大模型再考虑多卡张量并行部署。推理框架方面DCU 的软件栈对 ROCm 生态兼容所以主流的推理框架都能通过 ROCm 后端跑起来。我这次选择的是 vLLM它在大模型推理场景下的性能调优成熟度最高对连续批处理和 PagedAttention 的实现都很完善社区问题也容易搜到答案。如果后续要做复杂的多轮对话和 Agent 调度也可以考虑 SGLang但作为第一版部署vLLM 足够用了。5.2 模型下载、启动与 K8s 服务暴露模型文件可以通过 ModelScope 平台下载这是国内环境最稳妥的渠道。下载完成后把模型目录放到每个计算节点都能访问的共享存储上。这里有个坑要提醒模型文件很大如果每个节点都放一份存储成本浪费严重而且更新模型版本时很容易出现节点间版本不一致。我用的是 NFS 共享存储挂载所有节点访问同一份权重文件既省空间又方便管理。要注意 NFS 的 I/O 性能不能太差否则加载模型时间会很长。模型准备就绪后先手动验证一次推理把命令写清楚vllm serve /mnt/models/deepseek-r1-distill-7b \ --port 8000 \ --tensor-parallel-size 1 \ --max-model-len 8192启动成功后用 curl 发一个请求测试接口确认能正常返回。手动验证通过后再把它封装成 K8s 的 Deployment在 Pod YAML 里声明 DCU 资源resources: limits: hygon.com/vdcu: 1这里做了一次关键验证同一个 vLLM 服务在整卡模式和 vDCU 模式下都能正常启动说明 DCU 设备层面对应用是透明的应用只需要认资源声明就够了。服务再对接一个 K8s Service将 8000 端口暴露到集群内部方便 CubeStudio 平台统一注册其他业务团队的代码就能直接通过服务名调用。5.3 性能验证与几个值得调的参数服务部署起来只是第一步真正的活儿是调优。我测试时的核心指标有三个首 Token 延迟、生成吞吐和并发请求下的稳定性。整卡模式下7B 模型在 DCU 上的生成吞吐基本能达到硬件规格对应水平切换到共享模式后单任务吞吐会有所下降但整体资源利用率上来了换算到单位卡时成本反而更低。几个影响性能的关键参数我先列出来--max-model-len最大序列长度设太大会造成显存浪费设太小长对话直接截断一般按业务最长场景加上余量来设。--gpu-memory-utilizationGPU 显存利用率上限默认是 0.9。如果你要在同一张卡上跑多个副本这个值要相应调低留出余量。--max-num-seqs并发序列数决定连续批处理能塞进多少请求。太大会导致显存不足太小吞吐上不去要靠压测调整。--enable-auto-tool-choice如果业务要打通 Agent 场景记得开启工具调用支持否则函数调用类请求会报错。--port服务端口容器内和 Service 端口要对应得上。参数调优没有标准答案我建议把 Benchmark 脚本固化下来每调一次参数就记录一次数据形成压测基线后可追溯。6. 常见问题与排障实录6.1 我踩过的几个坑第一坑是调度资源名不一致。最开始我在 Device Plugin 里把资源名配成了hygon.com/dcu但 CubeStudio 资源池里填的是hygon.com/vdcu结果所有任务都 Pending看事件到处找原因最后发现就是资源名对不上。这类问题排障最简单的方法是在提交任务后马上看 Pod 的 Events调度器会非常明确地提示不满足资源条件。第二坑是共享模式下显存管理失灵。有一段时间任务频繁 OOM但每张卡看起来都有空闲显存。排查下来是同一张卡上的不同容器共享显存但没有任何机制做显存隔离保护一个任务超量申请就把其他任务的显存空间挤占掉了。解决方案是在平台侧增加显存配额校验同时又对 Device Plugin 的分配逻辑做了兜底确保同一卡上的多个容器显存区间不重叠。第三坑是节点负载不均。一开始所有任务都往同一两个节点上调度其他节点空闲。检查后发现是 Device Plugin 的资源上报正常但是集群调度器的节点打分策略没有针对 DCU 做优化部分节点因为有其他 CPU 或内存压力被优先排除了。我在 CubeStudio 里给 DCU 资源设置了更高的权重调度分布明显均匀多了。6.2 快速排障速查表现象可能原因排查方向节点上 DCU 资源显示为 0Device Plugin 未运行或上报失败检查 DaemonSet Pod 日志确认 Socket 通信正常Pod 一直 Pending资源名不一致或节点无可用配额看 Events核对资源名与节点总量容器内看不到 DCU 设备Allocate 钩子未生效检查 Device Plugin 的分配逻辑确认运行时钩子配置共享模式下任务 OOM显存区间重叠或超量申请加显存隔离逻辑校验同卡负载推理吞吐偏低并发参数过小或模型加载慢调大 max-num-seqs检查共享存储 I/O这套表格我通常直接贴在运维文档里新同事遇到问题先按表排查能省下大量重复沟通的时间。实际上大部分 DCU 接入问题都不是硬件问题而是配置不一致、版本不匹配、组件间约定没对齐这三大类规范化和文档化能提前规避一半以上的坑。最后再分享一个我实际操作中的体会DCU 接入 K8s 和 AI 平台这件事最难的永远不是单个组件的安装而是把驱动、Device Plugin、调度器、平台、应用这一整条链路打通之后还能稳定运行、随时排障。这是一条非常典型的生态补齐路径也需要一套完整的监控告警来保障——把卡的温度、显存、利用率指标都纳入 Prometheus设置合理的告警阈值比任何事后排查都管用。上述内容如果能让你少踩几个坑这趟适配就是值得的。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →