资讯动态

海光DCU接入Kubernetes完整指南:整卡、vDCU虚拟化与DeepSeek推理实践

发布时间:2026/9/17 19:28:55 来源:尧图企业网站定制
上个月帮一家单位做AI平台规划的时候我发现一个特别典型的现象机房里躺着一批还没拆封的海光DCU服务器采购的时候大家对标的是A100可真到算法团队上手那一步K8s完全不认这张卡。作业调度上去直接CrashLoopBackOff日志翻来翻去就是找不到设备更别提用DeepSeek这类大模型做推理了。很多人以为国产加速卡接入Kubernetes就是装个驱动的事实际走下来你会发现从设备识别、资源上报、调度策略到CubeStudio这类AI平台的配额管理是一条完整的技术链路。这篇文章我就把海光DCU接K8s、接平台的实操过程完整拆开覆盖整卡独占、共享模式、两种vDCU虚拟化方案以及在DCU上部署DeepSeek推理服务的完整流程。内容偏实操所有命令和配置都以我这次实际跑通为准版本差异会单独说明。1. 先弄懂 DCU 接入 K8s 的完整链路再动手1.1 从“卡在服务器里”到“任务跑在资源池”的三层结构海光DCU接入K8s表面看是装驱动、部署几个组件的事但它涉及三个完全不同的层次。第一层是物理设备层。DCU通过PCIe插在服务器上操作系统里能看到设备节点通过dcu-smi能看到卡的健康状态、显存占用、算力使用率。这一层解决的是“驱动能不能识别卡”的问题。第二层是集群资源层。K8s本身并不知道什么叫“GPU”或“DCU”它只认识CPU、内存这种原生资源。要让调度器能够感知DCU、并按需分配给Pod必须借助Device Plugin机制。Device Plugin是由K8s提供的一套标准扩展接口设备厂商实现这个接口就能把自己的硬件抽象成一种“扩展资源”Extended Resource比如hygon.com/dcu。调度器看到这个资源名就会把它当成一种可计数的整数资源来调度。第三层是平台应用层。K8s只管资源分发但算法工程师并不想面对YAML和命令行。CubeStudio这类AI平台会封装一层把资源池、配额、镜像、Notebook、训练作业这些概念做成可视化界面用户点几下就能申请到一张卡或一块vDCU。这三层必须打通任何一层掉链子最终表现都是“任务跑不起来”。我见过不少团队卡在第二层和第三层的衔接上底层Device Plugin起来了资源也上报了但平台的资源配额模型不认这个资源名用户界面里依然看不到DCU。1.2 整卡、共享、vDCU 三种模式到底在调度什么接入方式的选择直接决定了资源池的利用率和隔离效果。我这次实际验证了三种调度方式整卡独占、共享型vDCU、切分型vDCU。很多人第一次接触这个概念会有点绕我用大白话拆一下。整卡独占最简单一张物理DCU同一时刻只分配给一个Pod。这种模式没有性能干扰问题排查故障也容易但问题在于浪费。如果一个小模型的推理服务只需要4GB显存你却给它一整张32GB的卡剩下28GB就闲置了。很多单位的DCU利用率上不去根因就在这里。共享型vDCU解决的是浪费问题。一张物理DCU可以虚拟出多个vDCU实例多个Pod共用同一张卡的计算单元。这种共享通常是基于时间片或权重调度的——类似操作系统里的多进程轮流用CPU。优点是利用率高缺点是无法做到强隔离一个跑满算力的任务会把同卡的其他任务拖慢。切分型vDCU则走另一个方向把物理DCU的计算单元和显存切成多个互不干扰的分区每个分区有独立的算力配额和显存配额硬件层面隔离。这种方式类似把一整层写字楼隔成独立的小办公室每个租户有自己的门锁互不侵犯。三种模式的对比我放在后面章节详细讲这里先建立一个整体认知整卡是基础兜底方案共享型vDCU适合推理和低频任务切分型vDCU适合多租户场景和训练任务。2. 环境准备驱动、DTK 容器镜像与集群前置条件2.1 宿主机驱动与 DTK 版本对齐海光DCU的软件栈核心是DTK也就是DCU Toolkit。它提供类似CUDA的工具链、运行时库和HIP编程接口。在接入K8s之前宿主机上的驱动和DTK版本必须对齐否则后面容器里跑程序会出现各种匪夷所思的报错。我的建议是先看官方版本的兼容矩阵确认三件事内核版本的兼容范围、容器运行时版本、以及你要跑的AI框架比如PyTorch所需的DTK版本。这个步骤不要跳。我这次吃过亏宿主机驱动版本较新但某一个AI框架镜像要求的DTK版本较旧结果算出来的结果都是错的。驱动安装完成之后用dcu-smi验证设备状态能看到每张卡的型号、驱动版本、温度、显存总量就基本OK。$ dcu-smi ----------------------------------------------------------------------- | DCU Summary: | ----------------------------------------------------------------------- | 0 Hygon Z100 Driver Version: 6.2 Memory: 32768MiB | | 1 Hygon Z100 Driver Version: 6.2 Memory: 32768MiB | -----------------------------------------------------------------------2.2 容器镜像体系跑 DCU 任务到底该用哪层镜像这部分是新手最容易晕的地方。K8s里运行DCU任务容器里必须包含两样东西DTK/HIP的运行时库以及你需要的AI框架PyTorch、vLLM等。有两个常见做法。第一直接用海光官方提供的DTK基础镜像里面预装了HIP运行时和相关库然后在上面叠加PyTorch等框架。第二使用ROCm系的镜像改造因为DCU的编程模型和ROCm生态是对齐的很多ROCm镜像经过调整可以直接用。但我不建议自己在基础Ubuntu镜像里手动装DTK库依赖关系太复杂踩坑成本很高。更稳妥的方式是提前在一个基准节点上测试镜像确认容器内能识别DCU设备。判断标准很简单——在容器里执行dcu-smi或rocm-smi能正常输出。下面这个验证是我每次都会做的$ docker run --rm --device/dev/dri --group-add video \ registry.example.com/dtk:6.2-py3.10-torch2.1 \ bash -c dcu-smi -L这里有两个细节。第一需要把设备节点映射进容器如果用了Device Plugin或特定的CRI运行时这个映射是自动完成的手动docker run时就要用--device参数指定。第二用户需要加入video组才能访问GPU设备节点在K8s里通常通过configmap或runtimeclass配置。2.3 集群侧前置条件节点标签与调度标识集群侧的准备相对简单但有一个容易被忽略的点建议给所有DCU节点打上统一的标签比如gpuhygon-dcu。这样在调度时可以通过nodeSelector精确控制哪些负载可以跑在DCU节点上避免普通CPU任务占用了这些珍贵的机器。$ kubectl label node dcu-node-01 gpuhygon-dcu $ kubectl label node dcu-node-02 gpuhygon-dcu另外一个需要提前确认的点是集群里的资源配额和LimitRange会不会影响到DCU设备的申请。有些平台会为namespace设置默认的资源限制如果默认了CPU和内存上限但DCU设备不算在配额里就可能出现用户申请了4张卡却因为CPU配额超限而调度失败排查起来非常隐蔽。3. 整卡模式接入实操Device Plugin 与 Extended Resource 逐步落地3.1 部署 DCU Device Plugin把物理卡变成资源数字整卡接入的核心工作就是部署Device Plugin。Device Plugin是K8s官方提供的设备管理机制它运行在每个节点上由Kubelet调用负责向API Server上报节点上有多少张DCU卡以及响应Pod调度时的设备分配请求。海光官方提供了Device Plugin的部署文件通常是一个DaemonSet。部署之前要确认kubelet的--feature-gatesDevicePluginstrue已经开启。新版K8s默认开启但如果集群是从老版本升级上来的这个开关可能还关着会导致插件注册失败。部署文件的核心部分大致长这样实际使用时以官方release为准apiVersion: apps/v1 kind: DaemonSet metadata: name: dcu-device-plugin namespace: kube-system spec: selector: matchLabels: name: dcu-device-plugin template: metadata: labels: name: dcu-device-plugin spec: hostNetwork: true containers: - name: dcu-device-plugin image: registry.example.com/hygon/dcu-device-plugin:latest imagePullPolicy: IfNotPresent securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] volumeMounts: - name: device-plugin mountPath: /var/lib/kubelet/device-plugins - name: sys mountPath: /sys volumes: - name: device-plugin hostPath: path: /var/lib/kubelet/device-plugins - name: sys hostPath: path: /sys部署完之后查看Pod状态和日志确认没有报权限错误或注册失败。$ kubectl -n kube-system get pods -l namedcu-device-plugin $ kubectl -n kube-system logs dcu-device-plugin-xxxxx3.2 验证资源上报从 node 状态看卡片Device Plugin正常注册后K8s会以扩展资源的形式在节点状态里展示DCU数量。用kubectl describe node就能看到$ kubectl describe node dcu-node-01 | grep -A5 Capacity Capacity: cpu: 96 memory: 754929384Ki hygon.com/dcu: 8 Allocatable: hygon.com/dcu: 8看到hygon.com/dcu: 8就说明整卡资源上报成功。这里的资源名并不是标准规定死的具体的名字取决于Device Plugin的实现可能是hygon.com/dcu、dcu.hygon.com/gpu或其他写法。在平台对接时这个资源名就是唯一的ID后面配置配额和模板都会用到它。这一步有个常见坑节点状态里看不到资源。绝大多数情况是Device Plugin与kubelet的socket通信出了问题或者插件在注册时上报的资源名重复。可以先看Device Plugin的日志再去节点上检查socket文件是否存在。不要一上来就重启kubelet重启kubelet虽然经常能解决但会影响节点上所有Pod动静太大。3.3 用整卡跑第一个 Pod验证设备映射链路资源上报成功以后写一个最简单的Pod验证完整链路。注意Pod里必须显式申请DCU资源调度器才会把Pod分配到有DCU的节点并触发Device Plugin分配设备。apiVersion: v1 kind: Pod metadata: name: dcu-test spec: nodeSelector: gpu: hygon-dcu containers: - name: dcu-test image: registry.example.com/dtk:6.2-py3.10-torch2.1 command: [/bin/bash, -c] args: - dcu-smi -L python -c import torch; print(torch.cuda.device_count()) resources: limits: hygon.com/dcu: 1如果设备映射链路正常日志里会打印出DCU型号并且PyTorch识别到的设备数为1。这里要注意一点在容器里PyTorch是否识别DCU取决于你安装的PyTorch是否带DCU支持。海光社区和官方都有专门适配过的PyTorch发行版直接用官方镜像最省事。整卡模式本身没有太多技术含量但它是一切复杂方案的地基。如果整卡模式都不稳定后面所有虚拟化和共享的方案都没有意义。所以我会建议任何单位在尝试vDCU之前先把整卡模式完整跑通包括在多个节点上同时运行Pod、扩容缩容、节点重启后的自动恢复等。4. vDCU 两种虚拟化模式共享切分的原理、配置与实战选择4.1 vDCU 到底解决了整卡模式的什么痛点整卡模式的浪费问题非常突出。我之前在测试环境做过统计一个中型团队跑深度学习训练单卡的利用率平均不到30%推理服务更低。大多数任务是短时、低频、小显存占用却占着整卡无法释放。vDCU的价值就是把这个资源粒度做细。但“虚拟化”这个词听上去很美好落实到调度器上就面临一个尖锐的矛盾K8s扩展资源的调度单位是整数不能调度半张卡。要让多张vDCU共享一张物理卡必须引入自定义调度逻辑——这正是两种vDCU虚拟化模式分岔的地方。4.2 模式 A算力共享型 vDCU时间片/权重复用第一种vDCU模式走的是“算力共享”路线。多个vDCU实例映射到同一张物理DCU上共享计算单元和显存底层驱动按时间片或权重进行调度。你可以把它理解为同一台电脑上多个虚拟机共享CPU——每个vDCU看到的是一张完整的卡但实际计算资源是按配额轮转的。这种模式的配置通常在Device Plugin或调度器扩展里完成。通常会有一个CRD定义vDCU模板大意如下apiVersion: dcu.hygon.com/v1 kind: VirtualDCU metadata: name: vdcu-shared-small spec: type: shared physicalSelector: matchLabels: gpu: hygon-dcu schedulingPolicy: policy: weight weight: 20在用这个vDCU模板创建Pod时资源申请变成hygon.com/vdcu: 1。调度器会检查目标节点上有没有物理DCU、当前共享比例是否饱和如果超卖阈值不允许就排队等待。优点很明显实现相对简单一张卡可以被无限多个轻量任务复用当然有上限适合大量小推理任务、开发调试、批量评测这类负载。缺点也很致命无法隔离故障和性能。当一个任务把算力跑满同卡的其他任务时延会显著上升甚至出现“一颗老鼠屎坏了一锅汤”的局面。我实际测试下来共享型vDCU适合内部研发环境不建议在生产级对外服务上用。如果你要为多个客户提供服务算力干扰问题会让你难以承诺SLA。4.3 模式 B资源切分型 vDCU硬件级隔离分区第二种vDCU模式走的是“空间切分”路线。把物理DCU的计算单元和显存切分成多个独立分区每个vDCU独占一个分区硬件层面隔离。这种模式对应的概念大家更熟悉NVIDIA的MIG、A100的多实例GPU就是这种思路。切分型vDCU的配置逻辑和共享型完全不一样。它需要指定显存大小、算力比例并且物理卡在切分前可能处于某种“整卡模式”切分后需要重置设备才能生效。配置示例大致长这样apiVersion: dcu.hygon.com/v1 kind: VirtualDCU metadata: name: vdcu-slice-16g spec: type: sliced memory: 16GiB compute: 50这里compute: 50表示这个分区占用物理卡50%的计算资源memory: 16GiB表示独立分配16GB显存。当你用到两张slice vDCU物理卡上就同时存在两个独立分区互不可见。切分模式的优点非常突出强隔离。一个分区跑满算力甚至程序崩溃不会影响其他分区显存配额是硬限制不会出现某个任务把显存吃光导致同卡其他任务OOM的情况。缺点是灵活性差切分粒度受限不能像共享模式那样任意超卖而且切分后的物理卡如果跑大模型单分区显存可能不够用。4.4 两种 vDCU 模式的选择框架我整理了一张对比表方便你做技术选型参考维度共享型 vDCU切分型 vDCU隔离级别逻辑隔离算力共享物理隔离算力/显存独立显存视图所有实例共享整卡显存每个实例独享固定显存算力保证权重抢占不保证稳定时延稳定但上限固定超卖能力支持可大幅超卖不支持切多少用多少适用负载开发调试、低频推理、批处理生产推理、多租户训练故障隔离无一个任务可能拖垮同卡任务有某个分区异常不影响其他分区配置复杂度较低较高涉及物理卡切分选择时我的经验是先看业务类型再看团队运维能力。如果你的团队是自研产品的算法团队任务是训练和评测推荐优先用切分型vDCU稳定和省心如果你的场景是大量小体量推理请求且能接受偶发性能波动共享型vDCU能帮你大幅提升利用率。混合部署也常见——同一批物理卡一部分切成隔离分区给重要业务一部分留给共享池做弹性。5. CubeStudio 平台适配从纳管 DCU 到算法工程师自助使用5.1 CubeStudio 在 AI 平台中的定位到这里底层已经打通K8s能看到DCU资源Pod能申请到卡片整卡、vDCU都能按需调度。但如果你直接把这个K8s集群丢给算法工程师他们大概率会崩溃。K8s的YAML语法、镜像构建、资源配额管理、数据卷挂载每一项都是学习成本。CubeStudio这类AI平台做的工作就是把K8s包装成“像云主机一样”的自助服务出口。从我的理解来看它通常覆盖三件事算力资源池的可视化纳管、开发环境的快速创建比如Notebook、训练和推理作业的编排与监控。DCU的接入实际上是让CubeStudio能够识别并调度前面部署好的DCU扩展资源。5.2 配置 DCU 资源池与配额分配在CubeStudio里管理员通常需要先创建一个“资源池”或“GPU资源组”把带有DCU标签的节点纳管进去。这一步是对接的关键本质上就是把K8s的节点标签和资源类型映射到平台的资源池定义里。我的建议是拆分成两个池子一个是整卡/切分型vDCU池用于正式训练和生产推理另一个是共享型vDCU池用于开发和测试。两个池子的配额策略完全不同前一个走“按卡数申请、独占使用”的逻辑后一个走“按vDCU份数申请、共享使用”的逻辑。配额这块我强烈建议在平台层就设置好上限不要依赖K8s命名空间的ResourceQuota。原因是很多平台的配额逻辑和K8s原生的Quota并不完全一致用户界面显示有卡实际调度却失败会非常打击使用信心。平台层的配额管理能让用户在页面上直观看到自己还能申请几张卡已经用了多少。5.3 资源模板设计如何把 vDCU 暴露给不同团队CubeStudio这类平台通常支持“资源模板”或“套餐”的概念。管理员可以预置几种规格让用户按需选择。我在实际项目中是这样设计的开发调试型1个共享型vDCU限制使用时长最多8小时适合Dev环境调试标准训练型1个切分型vDCU32GB显存适合中号模型训练大模型训练型4个切分型vDCU独享整卡适合百亿级参数微调推理服务型自动匹配共享型vDCU允许水平扩容挂载已部署模型路径这种模板的好处是用户不需要理解“什么是vDCU”或“什么是Extended Resource”只需要选择“多大显存、几张卡、跑多久”。底层调度时平台把模板翻译成K8s的资源请求和被调度资源名。5.4 Notebook 和训练任务真正跑起来的链路从用户点击“创建Notebook”到容器真正跑在DCU上中间经过的链路值得每一个平台运维人员搞清楚用户请求到达CubeStudio后端平台根据用户选择的资源模板生成K8s Pod定义在Pod的resources里写入DCU或vDCU的申请量。Pod被提交给K8s API Server后调度器根据可分配资源、节点标签、亲和性策略选择一个匹配的DCU节点。Kubelet收到Pod绑定信息调用容器运行时创建容器。如果挂载了Device Plugin设备节点会在容器启动时自动注入。容器内部DTK运行时库识别到设备PyTorch/vLLM等框架完成初始化。这条链路里的每一个环节都可能出问题。我排过的最隐蔽的问题是在第4步——平台生成的Pod里没有带nodeSelector调度器把Pod扔到了一个没有DCU的CPU节点上容器启动后找不到设备报错信息却显示“CUDA driver version is insufficient”让人完全摸不着头脑。所以平台侧的模板定义里必须显式带上nodeSelector: gpuhygon-dcu不给调度器自由发挥的空间。6. 在 DCU 上部署 DeepSeek蒸馏模型的推理实操6.1 选型为什么用 R1-Distill-Qwen-32B 而不是 671BDeepSeek现在是一个绕不开的话题但部署哪个模型需要冷静考虑。DeepSeek-V3/R1这种671B参数的MoE模型推理需要大规模多卡集群对卡间互联带宽要求非常高一般团队很难在生产环境跑好。更现实的选择是DeepSeek-R1的蒸馏版本比如基于Qwen的7B、14B、32B蒸馏模型参数量从70亿到320亿不等单机多卡甚至单卡就能推理。我这次选择的是DeepSeek-R1-Distill-Qwen-32B量化为AWQ 4bit后模型权重大约18GB加上KV Cache和运行开销两张32GB的DCU用张量并行可以稳定跑起来。7B和14B的蒸馏版当然更轻量但推理质量有明显差距特别在复杂推理任务上32B的表现接近可用的水平。6.2 推理框架与镜像准备DCU上的推理框架选型目前比较可行的是vLLM和SGLang但都要选择带ROCm/DCU支持的版本。镜像的构建思路是以DTK基础镜像为底座安装对应框架的ROCm分支再把模型文件挂载进去。模型权重我建议提前使用ModelScope魔搭社区下载到本地然后通过hostPath或PVC挂载进容器不要在每次Pod启动时现场下载既慢又容易失败。下载命令大致如下具体参数以ModelScope当前CLI为准# 在节点或能访问存储的跳板机上执行 pip install modelscope modelscope download --model deepseek-ai/DeepSeek-R1-Distill-Qwen-32B-AWQ --local_dir /data/models/DeepSeek-R1-Distill-Qwen-32B-AWQ6.3 部署一个大模型推理服务Deployment Service 完整示例下面这个Deployment是我实际调试后简化出来的版本。注意两点申请的是两张整卡hygon.com/dcu: 2因为张量并行需要独占卡不能用共享型vDCU模型目录用hostPath直接指向节点上的下载目录。apiVersion: apps/v1 kind: Deployment metadata: name: deepseek-r1-32b namespace: ai-prod spec: replicas: 1 selector: matchLabels: app: deepseek-r1-32b template: metadata: labels: app: deepseek-r1-32b spec: nodeSelector: gpu: hygon-dcu containers: - name: vllm image: registry.example.com/dtk/vllm:dtk6.2-rocm command: [/bin/sh, -c] args: - vllm serve /models/DeepSeek-R1-Distill-Qwen-32B-AWQ --served-model-name deepseek-r1-32b --tensor-parallel-size 2 --max-model-len 8192 --gpu-memory-utilization 0.9 --port 8000 ports: - containerPort: 8000 resources: limits: hygon.com/dcu: 2 requests: hygon.com/dcu: 2 volumeMounts: - name: models mountPath: /models env: - name: NCCL_DEBUG value: WARN volumes: - name: models hostPath: path: /data/models type: Directory然后把推理服务暴露给外部apiVersion: v1 kind: Service metadata: name: deepseek-r1-32b-service namespace: ai-prod spec: type: NodePort selector: app: deepseek-r1-32b ports: - name: http port: 8000 targetPort: 8000 nodePort: 32080部署完成后用一行命令验证服务是否可用$ curl http://node-ip:32080/v1/chat/completions \ -H Content-Type: application/json \ -d { model: deepseek-r1-32b, messages: [{role: user, content: 解释一下什么是Kubernetes的Device Plugin}], max_tokens: 512 }如果返回了包含content字段的JSON说明整条链路已经通了。6.4 性能观察吞吐、时延与显存占用服务跑起来之后一定要做一次基础的性能摸底否则无法判断这张卡“够不够用”。我在实测中主要关注三个指标首Token延迟、生成吞吐量、显存占用率。首Token延迟在满负载下如果大于5秒对于对话类体验就会明显变差吞吐量决定了你能同时支撑多少个并发请求显存占用率则告诉你当前配置是否还有余量去加大--max-model-len或提升并发。观察手段再强调一次dcu-smi可以看实时的显存和算力使用率框架自带的/metrics端点配合Prometheus可以长期监控。我建议任何团队在模型上线前至少压测24小时确认没有内存泄漏和偶发超时再对外开放服务。7. 现场踩过的坑与调优经验7.1 镜像里缺 HIP 库initContainer 拷贝驱动的正确姿势第一个坑也是最典型的容器起来后报找不到libamdhip64.so。原因很简单你用了纯PyTorch基础镜像里面没有DCU的HIP运行时库。网上很多教程会让你在镜像里重新安装DTK但这样镜像会特别大而且版本更新以后难以维护。更优雅的方式是用initContainer从DTK镜像里拷贝运行时库到共享卷业务容器启动时挂载这个卷。这样业务镜像保持了最小化驱动和运行时库的版本管理也集中在initContainer里。initContainers: - name: copy-dtk-libs image: registry.example.com/dtk:6.2-minimal command: [cp, -r, /opt/dtk/lib, /opt/dtk/lib64, /dcu-libs/] volumeMounts: - name: dcu-libs mountPath: /dcu-libs这个方案还有个好处宿主机驱动升级时只需更新initContainer的镜像tag业务Pod重建后自动用上新版本不用重新构建每个算法镜像。7.2 vDCU 显存切分后 OOM 却查不到日志切分型vDCU模式下遇到的一个隐蔽问题是任务在容器内报OOM显存不够但dcu-smi显示整卡显存还有剩余业务的日志里也没有明确错误。原因在于切分型vDCU给任务分配的是“显存分区”dcu-smi默认显示的是物理整卡的显存总量和已用量而不是当前分区视角。解决方法是使用vDCU视角的工具或命令查看当前上下文里的显存分配。这个细节文档里容易忽略实际运营时却非常影响排查效率。我的建议是在平台侧把“vDCU实例”和“物理卡”的监控指标分开展示任务报错时先看它在哪个vDCU分区再去看该分区的配额和占用而不是盯着整卡的显存。7.3 多卡任务调度到同一节点集合通信库的隐性问题部署DeepSeek用了--tensor-parallel-size 2要求调度器把任务调度到同一节点的两张卡上。K8s原生调度器并不懂这个逻辑。如果两张卡分布在两个节点模型初始化时集合通信就会失败或极慢。解决办法是在Pod上配置Pod亲和性让同一个多卡任务的所有容器都调度到同一个节点。相对于先调度第一个容器再调度第二个官方推荐的做法是给同类任务打上相同的标签然后用podAffinity强制同节点。spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - deepseek-r1-32b topologyKey: kubernetes.io/hostname如果你用的CubeStudio或自研平台支持多卡任务一定要确认平台层是否正确生成了这个亲和性配置。我见过不止一次底层K8s已经有DCU平台也显示有卡但大模型任务一直起不来最后发现是多卡跨节点导致的。7.4 调度器层面的“卡型亲和”与碎片整理最后一个经验是关于资源碎片。切分型vDCU模式下一张32GB物理卡如果先分配了一个12GB的vine再分配一个16GB的vDCU剩余空间只有4GB既不够再分一个12GB也无法组成16GB形成碎片。时间一长整张卡看起来“有资源”但实际能分配的vDCU组合越来越少。这个问题目前没有完美的自动解法。我的经验是在平台层面建立“整卡回收”机制每隔一段时间把同一节点上散落的小vDCU迁移整合让碎片空间重新聚合成大段连续资源。配合监控看板的“可分配vDCU组合”指标来发现碎片严重的节点。这个过程需要谨慎操作迁移前必须确认任务有断点续训能力否则不要轻易动正在运行的任务。另外一个比较土但有效的办法是给不同大小的vDCU规划不同的节点池。比如把32GB的卡统一切成4个8GB只让8GB任务在这个节点池跑另一个节点池保持整卡模式专门接大模型训练。这样虽然牺牲了一些灵活性但运维大脑负担会轻很多问题的可预测性大大提升。最后说几句实际的体会整套海光DCU接K8s和AI平台的方案走下来我的核心感受是技术链路不算短但每一步都有迹可循真正考验人的不是某个单独环节而是整个系统的整体设计和排查能力。选择什么样的虚拟化和调度策略没有一个放之四海而皆准的答案最终还是回到你的业务形态上。如果你的团队以训练为主老老实实整卡加切分型vDCU稳定压倒一切如果以推理为主共享型vDCU能帮你省下大把硬件成本前提是你能接受时延波动并且愿意在监控和隔离上多花心思。另外想提醒一句不要迷信某一种“官方推荐”配置机器到手后一定先做一轮真实业务负载的压测用你的模型、你的数据、你的并发量去说话。很多坑是压测压出来的不是在方案评审时想出来的。希望这篇实操记录能帮你少走一些弯路。

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

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

免费获取报价