
1. 项目概述与整体技术栈1.1 这次要解决什么问题去年开始我就在跟进国产加速卡的落地海光DCU是其中绕不开的一张卡。真正把它用起来不能只停留在单机跑几个算子而是要把它接进Kubernetes集群让上层AI平台能统一调度、多租户共享、按需申请资源。这个链路我踩了不少坑尤其是两种vDCU虚拟化的区别网上资料写得普遍含糊。这篇文章面向的人群很明确正在做国产算力与K8s集成、准备把海光DCU纳入AI平台统一管理的平台工程师以及需要在DCU上部署DeepSeek这类大模型推理服务的算法同学。读完你会得到一条从驱动安装、Device Plugin部署、整卡调度、vDCU虚拟化到CubeStudio适配和DeepSeek服务上线的完整实操路径。整体上我们要做的东西可以拆成三层。最底层是物理DCU和驱动中间是Kubernetes的资源抽象与调度最上层是CubeStudio平台和具体的模型推理任务。每一层都有独立的对接点但只要逐个打通后面的使用体验和用NVIDIA GPU没什么本质差别。1.2 全套技术栈与选型逻辑先把我这次用的技术栈整体列出来方便你对照自己的环境做替换。层级选型说明加速卡海光DCUZ100系列单卡显存视型号而定我这边是32GB HBM2E版本驱动与开发栈DTKDCU Toolkit海光的类CUDA工具包包含HIP运行时、BLAS、DNN等库容器运行时Containerd 1.7 / Docker取决于集群原有配置DCU Device Plugin对主流运行时都兼容Kubernetes1.26 ~ 1.30建议不低于1.26低版本对Device Plugin API支持较差设备接入海光 DCU Device Plugin将DCU资源以Extended Resource形式上报给Kubelet虚拟化vDCU双模式硬件级实例切分和软件共享调度两种方案AI平台CubeStudio基于K8s的MLOps平台负责Notebook、训练任务、模型服务推理框架vLLMHIP/ROCm版本对DeepSeek等主流开源模型支持比较完善模型DeepSeek-R1-Distill-Qwen系列根据显存选择7B/14B/32B选这套方案的理由很直接。海光官方提供了DTK和Device Plugin这部分是硬性依赖不必自己造轮子。vLLM是目前大模型推理里开源生态最成熟的框架对ROCm/HIP后端的支持一直在迭代实测在DCU上跑DeepSeek蒸馏版可用性很高。CubeStudio本身构建在K8s生态上和标准Kubernetes资源模型天然兼容所以在资源层接入DCU之后平台层几乎不需要改代码。有一个容易忽略的点我提前说DCU的Device Plugin不是Helm仓库里随便找一个就能用的必须跟驱动版本匹配。我第一版试过社区里某个第三方插件结果资源上报正常但容器里一调用DCU就报驱动版本错误后面排查了很久才发现是插件调用了不兼容的API。1.3 前置知识Device Plugin 和 Extended Resource要理解整个适配过程必须先搞明白Kubernetes是怎么感知GPU这类异构设备的。Kubelet本身不认识DCU它只认识CPU和内存。为了让调度器知道某台节点上有几张DCU卡需要用到Device Plugin框架和Extended Resource机制。Device Plugin是一个实现了特定gRPC接口的DaemonSet部署在每台DCU节点上。Kubelet启动时会向/var/lib/kubelet/device-plugins/目录下的Unix Socket发起连接插件通过这个连接上报设备ID列表。Kubelet拿到列表后会把这些设备对应的Extended Resource数量写入节点状态。比如节点上有4张卡调度器就能看到类似hygon.com/dcu: 4这样的资源。调度阶段kube-scheduler根据Pod声明的资源请求做过滤和打分。Pod要使用DCU只需在resources里声明resources: limits: hygon.com/dcu: 1当调度器把Pod绑定到节点后Kubelet在创建容器时会再次调用Device Plugin的Allocate接口。插件在这个接口里返回设备路径、环境变量、挂载点等信息。Kubelet根据这些信息把/dev/dcu0之类的设备文件挂载进容器并注入必要的环境变量。理解这个流程很重要因为后面所有虚拟化方案本质上都是在Device Plugin这一层做文章。整卡模式是插件直接上报物理卡数量vDCU模式是插件先创建虚拟设备再把虚拟设备当成卡上报给Kubelet。所以资源上报成功并不代表虚拟化做对了关键要看Allocate阶段返回给容器的设备路径是不是虚拟设备。2. 环境准备与基础软件栈安装2.1 硬件与系统环境要求我这次使用的是一台双路x86服务器插了两张海光DCU Z100。操作系统是Ubuntu 22.04 LTS内核版本5.15。如果你用的是其他发行版比如KylinOS或CentOS流程基本一致只是包管理命令需要对应调整。硬件层面要注意几个点。主板需要开启Above 4G Decoding和Resizable BAR否则DCU的显存映射会有问题。IOMMU建议开启尤其是在后面用硬件级vDCU的时候IOMMU分组影响到虚拟设备实例能否成功创建。供电方面单张Z100的功耗不低服务器电源余量要留足不然高负载时可能出现意外复位。系统层面建议提前确认:# 查看内核版本 uname -r # 查看CPU是否开启SMT lscpu | grep -i smt # 查看PCIe设备 lspci | grep -i computeDCU一般会显示在lspci的Display controller或者Processing accelerators分类下。如果看不到设备大概率是PCIe链路没有正确识别需要检查插槽和BIOS设置。2.2 安装驱动与 DCU ToolkitDTK驱动和DTK的安装是整条链路的基础。海光的软件栈和NVIDIA的比较类似驱动负责管理硬件DTK负责提供开发库和运行时。实际安装时需要从海光官方渠道获取与你系统内核版本匹配的驱动包和DTK安装包。安装顺序建议先驱动后DTK。以我这次环境为例大致步骤是# 安装编译依赖 sudo apt update sudo apt install -y gcc make dkms linux-headers-$(uname -r) # 安装DCU驱动以实际拿到驱动的run包为准 sudo bash hygon-dcu-driver-version.run # 重启或重新加载驱动模块 sudo reboot # 安装DTK sudo bash dtk-version.run # 配置环境变量 echo export PATH/opt/dtk/bin:$PATH ~/.bashrc echo export LD_LIBRARY_PATH/opt/dtk/lib:/opt/dtk/lib64:$LD_LIBRARY_PATH ~/.bashrc source ~/.bashrc安装完成后用dcu-smi验证能否正确识别设备。这是我每次装机后第一个执行的命令它类似NVIDIA的nvidia-smi。dcu-smi正常情况下会输出每个DCU的设备ID、显存总量、利用率、温度等信息。如果输出报错或者看不到设备先不要继续往下走重点排查驱动模块是否加载lsmod | grep -i dcu dmesg | grep -i dcu | tail -20这里我有个经验装驱动前一定要确认内核头文件版本和当前内核完全一致。很多人装完驱动后dcu-smi显示No devices原因就是升级内核后头文件过期了驱动模块编译时用的还是旧内核的接口。2.3 节点标签与资源上报测试驱动就绪后需要在Kubernetes节点上打好标记方便后续调度。DCU接入一般会用到两类标签一类标识节点具备DCU能力另一类标识虚拟化模式。# 给节点打上DCU能力标签 kubectl label node node-name hygon.com/dcutrue # 如果后续要区分虚拟化模式可以加一层 kubectl label node node-name hygon.com/vdcu-modehardware # 或者 kubectl label node node-name hygon.com/vdcu-modeshared打完标签后先做一个快速验证直接在节点上跑一个临时容器确认DCU设备可以挂载进容器。这一步可以避开Device Plugin纯粹验证驱动层面在容器环境下的可用性。docker run --rm --device /dev/dcu0 \ -v /opt/dtk:/opt/dtk \ -e LD_LIBRARY_PATH/opt/dtk/lib:/opt/dtk/lib64 \ your-base-image:latest \ /opt/dtk/bin/dcu-smi命令能输出DCU信息说明容器环境下设备透传没问题。如果这一步就失败问题几乎一定在驱动或设备权限上不用急着去排查K8s层面的东西。3. 整卡模式接入 Kubernetes3.1 部署 DCU Device Plugin驱动就绪之后第一步先把DCU以整卡模式接进来。整卡模式最直接也最容易排查问题。它的逻辑就是插件把每张物理DCU当做一个独立设备上报Pod申请一张卡插件就把一张完整的卡挂载给这个Pod。部署DCU Device Plugin先确认Kubernetes集群的Device Plugin API版本。K8s 1.26以上的集群一般走v1beta1协议插件兼容性较好。海光官方提供的Device Plugin一般以DaemonSet方式部署并且通过YAML方式分发给用户。我这次用的是从海光容器镜像仓库拉取的官方插件镜像。部署前先配置一个ConfigMap用来指定插件上报的资源名称和设备发现策略apiVersion: v1 kind: ConfigMap metadata: name: dcu-device-plugin-config namespace: kube-system data: config.json: | { resourceName: hygon.com/dcu, deviceListMode: full, enableCDI: false }这个配置里最关键的是resourceName。它决定了K8s节点上最终暴露的资源名。Kubernetes规范要求Extended Resource名称必须以域名前缀开头所以hygon.com/dcu是一个合法命名。deviceListMode表示插件上报全部物理设备不做切分。暂时先不用开CDI等虚拟化阶段再考虑。然后部署DaemonSetapiVersion: 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: nodeSelector: hygon.com/dcu: true hostNetwork: true tolerations: - key: CriticalAddonsOnly operator: Exists containers: - name: dcu-device-plugin image: your-registry.hygon.com/dcu-device-plugin:version imagePullPolicy: IfNotPresent securityContext: privileged: true volumeMounts: - name: device-plugin mountPath: /var/lib/kubelet/device-plugins - name: sysfs mountPath: /sys - name: devfs mountPath: /dev - name: config mountPath: /etc/dcu-device-plugin env: - name: NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName volumes: - name: device-plugin hostPath: path: /var/lib/kubelet/device-plugins - name: sysfs hostPath: path: /sys - name: devfs hostPath: path: /dev - name: config configMap: name: dcu-device-plugin-config这里必须开privileged权限因为插件要访问宿主机的设备节点和系统文件权限不够会导致设备枚举失败。nodeSelector确保插件只运行在有DCU标签的节点上避免在普通节点上白白占用资源。3.2 通过 Extended Resource 暴露 DCUDaemonSet启动后插件会与每个节点上的Kubelet建立gRPC连接。正常情况下几秒内节点状态里就会出现新的Extended Resource。验证方式很直接kubectl describe node node-name | grep -A5 Capacity输出中应该能看到类似Capacity: cpu: 128 memory: 503752Mi hygon.com/dcu: 2如果这里没有hygon.com/dcu先看插件Pod日志。我遇到过最常见的两类情况一是节点的/var/lib/kubelet/device-plugins/目录权限不对Kubelet无法创建Socket二是插件镜像版本和DTK版本不匹配插件枚举设备时直接panic。从kubectl describe node看到资源后还要确认Allocatable中也是2。Capacity和Allocatable理论上只差系统预留资源但DCU这类扩展资源一般不参与预留计算两个值应该一致。3.3 整卡任务的调度与验证资源上报成功后写一个简单的测试Pod验证整张卡能否在容器里正常工作。我用的是PyTorch加DCU版的验证方式跑一个简单的张量计算apiVersion: v1 kind: Pod metadata: name: dcu-test spec: restartPolicy: Never containers: - name: dcu-test image: your-registry.hygon.com/pytorch:2.1-dtk command: [python3, -c] args: - | import torch print(DCU count:, torch.cuda.device_count()) a torch.randn(1024, 1024, devicecuda) b torch.randn(1024, 1024, devicecuda) c torch.matmul(a, b) print(Matmul OK, c.sum().item()) resources: limits: hygon.com/dcu: 1注意PyTorch容器里虽然写的是cuda但在DCU适配过的PyTorch版本里HIP层会把这个调用映射到DCU设备上。如果容器环境中torch.cuda.device_count()返回1并且矩阵乘法正常输出说明整卡模式已经打通。这里有一个容易踩的坑如果你用的是官方PyTorch镜像没有集成DTK的运行时库运行时会报找不到libamdhip64.so。解决办法有两个一是直接用海光适配过的PyTorch镜像二是通过环境变量指定LD_LIBRARY_PATH把DTK的库目录挂载进容器。最省事的做法是第一种。测试完成后把Pod删除整卡模式就验证结束了。接下来要做的是资源利用率优化也就是vDCU的关系。4. 两种 vDCU 虚拟化方案深度拆解4.1 vDCU 方案一硬件级实例切分整卡模式的问题是显而易见的一个只有1GB显存请求的小任务也会占牢一整张32GB的卡。对于很多场景来说这种浪费是没法接受的。海光DCU提供了vDCU虚拟化能力用来解决这个问题。vDCU的第一种模式是硬件级实例切分我习惯叫它硬件切片。它的原理和NVIDIA MIG类似在硬件层面把一个物理DCU的计算单元和显存划分成多个独立的虚拟设备实例。每个vDCU实例拥有隔离的计算单元、显存带宽和显存容量一个实例崩溃不太会影响到同卡上的其他实例。创建硬件级vDCU实例需要用到海光提供的管理工具一般在DTK安装包里自带。常见的方式是通过dcu-smi或者专门的vdcu-admin命令。不同驱动版本语法上有些差别但整体思路一致。我这次用的命令大致是# 查看物理DCU是否支持硬件vDCU dcu-smi -q -d vdcu # 创建两个vDCU实例每个分配16GB显存 dcu-smi vdcu create -d 0 -n 2 --mem 16Gi创建完成后dcu-smi会多出虚拟设备节点。这些虚拟节点通常会以/dev/dcu0_v0、/dev/dcu0_v1的形式出现也可能是一组BDFBus-Device-Function编号。关键是让Device Plugin识别到这些虚拟设备而不是物理卡。硬件级切分适合对性能和隔离性有要求的场景。比如一个团队需要同时跑两个不同的模型推理服务它们之间的显存和算力要严格隔离那么硬件级vDCU是最稳妥的方案。缺点是灵活性稍差vDCU实例的规格一般是固定档位不能像软件共享那样做到随意的比例分配。这里我必须强调在配置硬件级vDCU之前一定确认BIOS里IOMMU已经开启。否则vDCU创建会报IOMMU group相关的错误。这是我在实际环境里踩过的坑倒腾了很久才定位到是BIOS层面没有打开虚拟化辅助功能。4.2 vDCU 方案二软件共享调度第二种vDCU模式是软件共享调度。区别于硬件切分它不做物理隔离而是通过驱动层的软件仲裁让多个任务共享同一张物理DCU。这种模式的工作方式可以类比操作系统的分时复用。每个使用DCU的任务仍然认为自己独占设备但驱动在后面做时间片轮转和显存分配。海光的Device Plugin在共享模式下会把一张物理卡虚拟成多个资源单元上报。每个Pod拿到的是一个逻辑上的DCU实际底层共享同一物理设备。共享调度在Device Plugin配置里通常通过annotation或者额外的资源名区分。我这次的做法是给插件增加第二个资源名例如hygon.com/dcu-shared并配置允许的共享比例apiVersion: v1 kind: ConfigMap metadata: name: dcu-device-plugin-config-shared namespace: kube-system data: config.json: | { resourceName: hygon.com/dcu-shared, deviceListMode: timeSlicing, timeSlicing: { replicas: 4 } }replicas: 4的意思是每个物理DCU最多划分成4个共享资源单位。Pod申请hygon.com/dcu-shared: 1实际获得的是一张物理卡四分之一的资源配额。这里所谓的四分之一主要是软性限制显存方面还可以通过驱动参数设置上限避免某个任务的显存把整卡打满。软件共享模式的优点是灵活、创建快、支持细粒度配额资源利用率高。缺点是任务之间没有硬性隔离一个任务的显存泄漏或计算密集操作可能影响到同一张卡上的其他任务。所以它更适合内部工具、Notebook实验、低优先级的批处理任务。4.3 两种 vDCU 的适用场景与选型建议两种vDCU模式并不是非此即彼的关系。在同一个集群里完全可以同时存在硬件级vDCU实例和软件共享资源。我整理了一张选型对照表很方便做决策对比维度硬件级vDCU软件共享调度隔离级别计算单元显存硬隔离逻辑隔离共享物理卡性能干扰低高受邻居任务影响创建速度较慢部分场景需要重置驱动极快运行时即创建灵活性固定规格档位任意比例切分适用场景生产推理、多团队独立服务Notebook、内部测试、批处理从实际运维角度看我的建议是混合使用。对外提供稳定的模型推理服务时用硬件级vDCU保证SLA和隔离性。内部开发和实验场景用软件共享最大化卡利用率。比如我这边线上DeepSeek推理服务跑在硬件级vDCU上算法组的Notebook统一走共享池两边互不干扰。需要额外提一点切换vDCU模式时最好重启Device Plugin让资源数量重新上报。否则可能出现kubelet缓存中仍然是旧的资源数量导致调度器看到的能力和节点实际情况不一致。通用的做法是kubectl rollout restart daemonset/dcu-device-plugin -n kube-system然后观察节点状态确认资源数量按预期变化。5. CubeStudio 平台接入与资源适配5.1 CubeStudio 平台结构与 DCU 对接入口CubeStudio是一个基于Kubernetes的MLOps平台提供Notebook、分布式训练、超参搜索、模型服务等能力。它的设计思路是复用Kubernetes的调度能力不在底层重新发明一套资源管理系统所以一切能被K8s调度的资源都能被CubeStudio管理。接入DCU的入口在平台的资源配额和模板配置两处。CubeStudio有自己的项目Project和资源池ResourcePool概念。资源池对应Kubernetes的Namespace外加一组资源配额。要让某个项目使用DCU只需要在这个项目对应的Namespace上创建包含DCU资源名和数量的ResourceQuota。5.2 平台级资源配置配额、标签与容忍我这次的做法是在CubeStudio的项目里新建一个独立Namespace然后创建资源配额kubectl create namespace ai-dcu-project kubectl apply -f - EOF apiVersion: v1 kind: ResourceQuota metadata: name: dcu-quota namespace: ai-dcu-project spec: hard: hygon.com/dcu: 8 requests.hygon.com/dcu: 8 EOF这里把整张卡的资源配额设成了8如果是共享模式就设成32具体数值根据你的vDCU副本数来。设置配额后CubeStudio创建的训练任务Namespace一旦超出配额就会调度失败平台界面会有明显的资源不足提示。但配额只是第一层。要让调度器真正把DCU任务放到正确的节点上还需要在任务模板里加nodeSelector或nodeAffinity。CubeStudio的训练任务模板通常允许配置PodTemplateSpec的定制字段我在里面加上了节点亲和性affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: hygon.com/dcu operator: In values: - true如果DCU节点上有Taint记得在模板里加上对应的Toleration。很多DCU节点会打污点来防止普通CPU任务被调度上去我这边给DCU节点打了hygon.com/dcutrue:NoSchedule所以必须在任务模板里显式容忍否则任务一直处于Pending。5.3 Notebook 交互开发与训练任务实操CubeStudio的Notebook模块是算法工程师使用频率最高的入口。创建一个使用DCU的Notebook核心是在Notebook镜像配置里选择带DTK运行时的镜像并在资源申请中填写DCU资源。比如要创建一个申请1个共享DCU、8GB显存限制的Notebook资源请求部分这样配置resources: requests: hygon.com/dcu-shared: 1 limits: hygon.com/dcu-shared: 1Notebook镜像如果无法直接拉取海光官方镜像可以先在节点上手动拉好然后在平台的镜像仓库配置中引用。镜像里必须包含DTK运行时以及PyTorch或TensorFlow的DCU适配版本。平台创建的Pod不会自动注入DTK的环境变量所以最好在镜像的Dockerfile里预先设置ENV LD_LIBRARY_PATH/opt/dtk/lib:/opt/dtk/lib64 ENV PATH/opt/dtk/bin:$PATH训练任务的原理和Notebook类似。CubeStudio对PyTorchJob、TFJob等CRD的渲染最终都会变成Pod。只要PyTorchJob的Pod模板中声明了hygon.com/dcu资源调度器就会自动完成DCU分配。训练任务里如果用到多卡需要在模板声明多张卡并且在训练脚本里通过环境变量感知到设备echo $CUDA_VISIBLE_DEVICESDCU的Device Plugin在Allocate阶段会为容器设置CUDA_VISIBLE_DEVICES环境变量值比如是0或0,1。训练代码里通过它来指定当前进程使用的设备和NVIDIA环境下的多进程启动方式一致。6. DeepSeek 推理服务部署6.1 模型选型与显存规划DCU接进平台后总要有实际业务跑起来才有价值。这次我选择部署DeepSeek推理服务一方面是因为它现在是开源大模型里关注度非常高的模型另一方面是想验证DCU在真实生产级推理负载下的表现。DeepSeek有多个版本完整版V3参数量达到671B不是单张DCU能跑动的。实践中更适合部署的是DeepSeek-R1的蒸馏版本特别是基于Qwen架构的DeepSeek-R1-Distill-Qwen-7B、14B和32B。这些版本虽然参数量小一些但推理能力和通用性依然不错适合在单卡或者两张卡上部署。显存规划我用了一个粗算公式模型权重显存大约是参数量乘以2字节FP16。7B模型大约14GB14B大约28GB32B需要64GB。除此之外还要加上KV Cache和推理框架的运行时开销。所以对于单张32GB的DCU7B模型可以轻松放下还能留出足够KV Cache空间14B模型比较勉强可能需要开启量化或限制上下文长度32B模型则必须用两张卡做张量并行或者使用INT8/INT4量化。我这次的部署目标是稳定优先所以选了DeepSeek-R1-Distill-Qwen-7B用整卡推理留足显存余量。6.2 基于 vLLM 的 DCU 推理部署推理框架我选了vLLM。它支持HIP/ROCm后端可以直接复用DTK的运行时。在DCU上跑vLLM关键是镜像选对推荐使用官方提供的支持ROCm的vLLM镜像或者海光适配过的版本。先看镜像是否包含HIP支持docker run --rm your-registry.hygon.com/vllm:rocm python -c import torch; print(torch.cuda.is_available())输出True才能继续。部署DeepSeek用Deployment加Service的方式。模型文件提前放在共享存储或者节点本地磁盘上挂载到容器里的/models路径。我的Deployment配置大致是这样的apiVersion: apps/v1 kind: Deployment metadata: name: deepseek-r1-7b namespace: ai-dcu-project spec: replicas: 1 selector: matchLabels: app: deepseek-r1-7b template: metadata: labels: app: deepseek-r1-7b spec: nodeSelector: hygon.com/dcu: true containers: - name: vllm image: your-registry.hygon.com/vllm:rocm command: [python3, -m, vllm.entrypoints.openai.api_server] args: - --model - /models/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B - --tensor-parallel-size - 1 - --gpu-memory-utilization - 0.9 - --max-model-len - 8192 - --port - 8000 ports: - containerPort: 8000 resources: limits: hygon.com/dcu: 1 volumeMounts: - name: model-storage mountPath: /models env: - name: HIP_VISIBLE_DEVICES value: 0 volumes: - name: model-storage persistentVolumeClaim: claimName: deepseek-model-pvctensor-parallel-size在单卡场景设为1即可。gpu-memory-utilization设为0.9表示vLLM会使用90%的可用显存作为KV Cache池剩下10%留给运行时。max-model-len限制了最大上下文长度过长会导致显存不足过短会影响长文本效果8K是我测试后比较平衡的值。有一个细节值得注意HIP_VISIBLE_DEVICES环境变量在DCU环境下对应的是物理设备编号vLLM启动时会用它确定使用哪张卡。多卡部署时这个变量的值要和tensor-parallel-size对应。比如用两张卡就设置HIP_VISIBLE_DEVICES0,1并配合部署两个副本的张量并行模式。6.3 推理验证与性能调优要点服务启动后通过Service暴露端口然后用curl做一个简单的OpenAI兼容接口调用curl -X POST http://service-ip:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: DeepSeek-R1-Distill-Qwen-7B, messages: [ {role: user, content: 解释一下什么是Kubernetes} ], max_tokens: 512, temperature: 0.6 }正常情况下会返回包含choices字段的JSON响应。如果返回超时或显存OOM第一件事是看vLLM容器日志里面会有非常明确的错误信息比如可用显存不足、模型权重加载失败等。调优方面我实测下来几个参数比较值得关注。--max-model-len默认值如果设置过高会导致KV Cache预留占用大量显存降低并发能力--gpu-memory-utilization太低会浪费显存太高则在多任务并发时容易OOM需要按实际负载调整。如果QPS要求高可以增加--max-num-seqs参数控制同时处理的请求数量。还有一个提升并发的小技巧在vLLM服务前面加一个简单的负载均衡器比如Kubernetes Service默认的ClusterIP就自带简单的负载均衡。多副本部署DeepSeek服务时可以每个副本申请一个vDCUService会均匀分发请求这样能有效提升整体吞吐。7. 常见问题与排查经验7.1 调度器不识别 DCU 资源这是接入过程中遇到最多的问题表现是Pod一直Pending事件信息显示0/2 nodes are available: 2 Insufficient hygon.com/dcu或者干脆说没有这个资源。排查路径很固定。先看节点Capacity里有没有相关资源kubectl describe node node-name | grep -A8 Capacity没有的话确认Device Plugin Pod是否Runningkubectl get pod -n kube-system | grep dcu # 查看插件日志 kubectl logs -f -n kube-system dcu-plugin-pod插件日志里会直接说明问题比如Device plugin socket connect failed或者Failed to get device list。我遇到过的原因有两个一是插件镜像和驱动不配套导致设备枚举失败二是DaemonSet的nodeSelector和节点标签不一致插件根本没调度到DCU节点上。7.2 vDCU 创建失败与驱动版本不匹配创建硬件级vDCU时报错的情况也常见报错内容通常和IOMMU、驱动版本、设备状态有关。我遇到过的典型报错是Failed to create vDCU: device not idle意思是物理DCU正在被其他进程占用。Device Plugin如果已经把这卡分配给了某个Pod物理设备就无法被再次切分。解决方法是先停止所有使用该DCU的任务释放物理设备然后重新执行vDCU创建命令。如果是IOMMU相关报错比如vDCU requires IOMMU enabled去BIOS里找VT-d或者AMD IOMMU选项打开后重装系统引导。这里有个细节部分服务器主板在启用IOMMU后还需要在Linux内核启动参数里加上iommupt否则直通性能会受影响。驱动版本的问题相对隐蔽。插件的Device List模式、vDCU管理工具和驱动必须严格配套。海光的软件发布节奏比较快如果驱动、DTK、Device Plugin三者的版本各差一个迭代就可能出现vDCU创建成功但容器挂载后无法识别设备的情况。我的做法是把整条链路的版本固定记录在维护文档里升级时整体更换不单独升级某一个组件。7.3 共享模式显存溢出与性能干扰软件共享模式最大的坑是显存溢出。多个任务共享一张物理卡驱动虽然会做显存分配但如果你不配置显存上限一个任务可以把整卡显存全部吃掉其他任务直接OOM。解决办法是在共享模式的ConfigMap里配置显存限制。我这边给共享vDCU配置了每副本最大显存比如32GB物理卡分成4个副本每个副本最大显存8GB。如果某个任务申请时发现无法满足8GB限制调度器就不会把任务放上来而是等待其他任务释放。性能干扰是另一个问题。软件共享模式下一个密集计算任务会挤占大部分算力导致同卡上的其他任务延迟飙升。这类问题没有完美的解决办法只能从任务调度上做文章。我目前的做法是把在线推理服务放在硬件级vDCU上确保性能稳定把训练和Notebook实验放在软件共享资源上允许一定程度的性能波动这样整体体验比较平衡。最后再分享一个我个人的运维心得。DCU接入K8s和AI平台这件事技术链条不算长但对版本一致性要求极高。驱动、DTK、Device Plugin、vLLM镜像任何一个环节版本漂移都可能出现让人百思不得其解的奇怪问题。我后来给集群做了标准化模板所有节点的驱动版本、DTK版本、插件版本完全一致升级流程固定出问题的概率一下子降了很多。另外建议在建设初期就把DCU的监控做起来dcu-smi的数据可以采集到Prometheus这样显存使用率、卡温度、利用率都能提前预警省去很多半夜救火的麻烦。