openFuyao Ascend NPU DRA 设计文档
本文档由历史文件 总览(design)、CDI(cdi-design)、NPU 信息模型(npu-info) 合并为单一入口。同目录下 npu-hard-vnpu-scheduling-design.md 为硬切分 VNPU 专项设计。
1、NPU切分机制分析
deviceplugin、DRA-gpu、DRA-computedomain
deviceplugin:k8s机制,单节点粒度的、设备粒度的扩展资源管理机制。原生的deviceplugin插件只支持到卡粒度。
小于1卡的分配:官方有MIG硬切分方案,最大支持7份。社区有软切分方案,hami及runai都使用基于用户态劫持的软切分方案。 DRA是下一代的设备管理方案,相比deviceplugin,可以支持更灵活的调度算法、多规格设备混部、支持共享、以及虚拟设备池化,并面向多种设备、池化管理持续演进。gpu的DRA插件包含两个:
基础的gpu插件:支持单个gpu卡的多种切分和调度能力。 支持池化gpu组网的ComputeDomain插件:支持基于NVLink的ComputeDomain跨节点NPU池调度能力。 常见算力管理方案对比:
| 对比维度 | deviceplugin切分 | deviceplugin整卡 | DRA-gpu | DRA-computedomain |
|---|---|---|---|---|
| 资源模型 | 单纯计数vendor.com/gpu: 1 | 单纯计数vendor.com/gpu: 1 | 结构化对象 | 结构化对象 |
| 调度范围 | 单机 | 单机 | 集群调度,单机资源绑定 | 集群调度,集群资源绑定,池化调度 |
| 匹配算法 | 单个资源模型/单个条件 | 单个资源模型/单个条件 | CEL,灵活的匹配模型,支持多条件 支持按量消费 |
CEL,灵活的匹配模型,支持多条件 |
| 调度粒度 | 切分最小单位 | 单卡 | 多种切分粒度,取决于资源声明 | 多种切分粒度 |
2、DRA机制简介
基本概念与用法参考官方文档:https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/dynamic-resource-allocation/
如下图所示,dra涉及2个组件需要开发。
DRA基本架构
3、DRA开发指南
dra插件基本的逻辑和流程可以参考NV的gpu-dra插件,代码量约4W。考虑到DRA刚GA,只有基础能力,很多增强能力还在孵化,需要持续投入插件能力构建。
3.1 dra-gpu功能及流程: 原生DRA流程--GPU--详细
3.2 dra-compute-domain功能及流程 原生DRA流程--ComputeDomain
4、NPU DRA开发规划
参考DRA机制中,开发任务分解如下:
image
dra驱动对设备驱动的依赖主要包含:
初始化时获取上报的资源种类和资源信息(可以包含多不同类型的资源)。比如,NV包含单卡、MIG分区设备、vfio设备等。 对每个POD进行资源分配时需要对设备进行各种配置(包括单节点的设备配置、跨节点的池化协同和配置等)。比如,NV包含配置卡的独占模式、时分的周期等参数。 这个取决于NPU卡的分区、切分相关、资源模式等的配置能力支持情况。
4.1 NPU deviceplugin 现状
ascend-device-pluginascend-device-plugin

5、未来演进
DRA特性演进:
截至目前(2025 年 11 月),Kubernetes 社区中与 动态资源分配(DRA) 相关的 KEP(Kubernetes Enhancement Proposal)共有以下 9 项,涵盖核心机制、调度增强、网络支持、健康状态等多个方向:
✅ 已毕业(GA)或稳定(Stable)的 KEP
| KEP 编号 | 标题 | 状态 | 说明 |
|---|---|---|---|
| KEP-4381 | DRA 核心功能(结构化参数) | ✅ Stable(1.34) | 使 kube-scheduler 和 Cluster Autoscaler 无需依赖外部驱动即可处理资源分配 。 |
| KEP-3939 | Job 的 Pod 替换策略 | ✅ Stable(1.34) | 控制 Job 是否等待旧 Pod 完全终止后再创建新 Pod,提升资源使用效率 。 |
🧪 Beta 阶段的 KEP
| KEP 编号 | 标题 | 状态 | 说明 |
|---|---|---|---|
| KEP-4680 | 为设备插件和 DRA 添加资源健康状态到 Pod 状态 | Beta(1.33) | 将设备健康信息(如 GPU 故障)暴露到 Pod status,支持调度器感知设备状态 。 |
| KEP-5075 | DRA:可消耗容量(Consumable Capacity) | Alpha(1.34) | 支持对共享设备资源(如 GPU 内存)进行容量限制和分配跟踪 。 |
🧪 Alpha 阶段的 KEP
| KEP 编号 | 标题 | 状态 | 说明 |
|---|---|---|---|
| KEP-3063 | 使用控制平面控制器进行 DRA | Alpha | 引入控制器模式管理 ResourceClaim 生命周期,增强可扩展性 。 |
| KEP-4817 | DRA 资源声明状态支持标准化网络接口数据 | Alpha | 支持在 ResourceClaim 中暴露网络接口信息(如 MAC、IP),用于多网卡场景 。 |
| KEP-5004 | DRA 驱动处理扩展资源请求 | Alpha | 允许 DRA 驱动处理非设备类资源(如带宽、存储)请求 。 |
🔍 其他相关 KEP(间接支持 DRA)
| KEP 编号 | 标题 | 状态 | 说明 |
|---|---|---|---|
| KEP-1790 | 从卷扩容失败中恢复 | Stable(1.34) | 支持在卷扩容失败后减小请求容量重试,间接提升 DRA 存储资源容错性 。 |
| KEP-2340 | 监视缓存提供一致的数据视图 | Alpha | 提升调度器对 ResourceSlice 等对象的可扩展性,间接支持 DRA 调度性能 。 |
🔚 总结
目前 DRA 的 KEP 生态已初步成型,核心功能(KEP-4381)已在 1.34 毕业为 Stable,后续增强主要集中在:
- 资源健康感知(KEP-4680)
- 共享资源容量管理(KEP-5075)
- 网络设备支持(KEP-4817)
- 扩展资源类型支持(KEP-5004)
这些 KEP 共同构建了 DRA 在 AI/ML、网络、异构资源调度等场景下的完整能力。
Kubernetes v1.34:DRA 消耗容量,该功能在 Kubernetes 1.34 中作为一项 alpha 功能引入,特性开关: DRAConsumableCapacity
https://kubernetes.io/blog/2025/09/18/kubernetes-v1-34-dra-consumable-capacity/
6、参考
1、常见NPU虚拟化技术
在大类上计算虚拟化技术有这3种: 软件模拟、直通独占(如网卡独占、显卡独占)、直通共享(如vCPU 、vGPU)。但对于显卡GPU而言我总结细化出至少这6种分类(其中第四、五种都是第三种的具体实现):
第一种、软件模拟(eg sGPU), 又叫半虚拟化。 第二种、直通独占 (pGPU) , 有的文章翻译为透传 。Openstack/KVM/ESX等IaaS场景用到。 第三种、直通共享 (基于SR-IOV技术虚拟出vGPU) , 在技术上分类叫全虚拟化 。三个大厂有部分型号GPU支持,具体型号见 https://open-iov.org/index.php/GPU_Support 。这是AMD首先搞出来的,但似乎他们后来也转向GPU分片虚拟化了,这个网站AMD的产品反而没几款。 第四种、GPU分片虚拟化(mediated passthrough),也属于全虚拟化技术。其热度很高,基于VFIO mediated passthrough framework的GPU虚拟化方案。该方案由NVIDIA提出,并联合Intel一起提交到了Linux kernel 4.10代码库,该方案的kernel部分代码简称mdev模块。把会影响性能的访问直接passthrough给虚拟机,把性能无关,功能性的MMIO访问做拦截并在mdev模块内做模拟。商业产品有NVIDIA GRID vGPU 与Intel的GVT-g系列,前者不开源,后者大部分开源。 第五种、多实例 GPU (MIG) 技术,也属于全虚拟化技术。MIGNvidia 搞出的新技术,可将单个 GPU 分区为最多 7个完全的隔离vGPU实例,减少资源争抢的延时,提高物理 GPU 利用率。但可惜目前仅昂贵和国内禁售的NVIDIA A100 GPU 支持。 第六种。Time-Slicing GPU (时间共享GPU)。把本来再空间上并行(时间独占)的成百上千的GPU流水线进行的时间维度的分割和共享。各个GPU厂家都有类似的技术。英伟达的技术文档:https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/gpu-sharing.html 。 注意,以上第四种是收费的,所以企业用户要去英伟达官网购买license。英伟达又卖硬件又卖软件license,赚钱能力真强。 第五种MIG则是买到昂贵的A100卡就能用了,不需要license。 普通玩k8s的企业,则用免费的Time-Slicing GPU (时间分片共享GPU) 。
2、业界切分方案对比
| 对比维度 | k8s-device-plugin(经典 DP) | k8s-dra-driver-gpu(DRA 驱动) |
|---|---|---|
| 项目定位 | 把“节点上有几张卡”告诉 kubelet,让调度器能按整数加减做最简单的“有/无”过滤 | 把“节点上有什么卡、还能怎么切、切完给谁”登记成 ResourceSlice,供调度器做属性/拓扑/配额级精确匹配 |
| 资源模型 | 只暴露标量:nvidia.com/gpu: 8nvidia.com/mig-1g.5gb: 7 |
结构化对象: ResourceSlice → Device → attributes{显存、MIG、UUID、NUMA、PCIe 拓扑…} DeviceClass 用 CEL 表达式筛选 |
| 分配粒度 | 整卡或“静态 MIG”一份实例; 一卡只能给一个 Pod |
动态 MIG:Pod 来时才切,用完即删; 支持显存分片、vGPU、时间片等任意粒度(取决于实现) |
| 生命周期 | 节点启动即上报;Pod 删了卡仍被“占着”,直到下一个 Pod 来 | 控制面集中账本;Pod 删除 → ResourceSlice 状态变 allocatable,立即可回收 |
| 调度器感知 | 零感知 GPU 型号、显存、NUMA;只能“数个数” | 感知一切属性:型号、显存、拓扑、亲和性;支持 PrioritizedList、超卖策略 |
| 参数化/策略 | 靠 Annotation/ConfigMap 带外传参;不同租户策略写死在插件里 | 带内参数:在 DeviceClass 里声明 sharingStrategy、memory、cores;租户只引用即可 |
| 与 K8s 核心耦合 | 只依赖 kubelet 插件机制,核心零改动 | 需要 1.26+ 的 DRA 特性门 + 调度器插件,核心参与 ResourceClaim 生命周期 |
| 实现组件 | 单 DaemonSet 即可 | 双组件: ① 中心 Controller(处理 ResourceClaim) ② 节点 Kubelet-plugin(生成/删除 ResourceSlice) |
| 对老 workload 兼容 | 原生支持:requests/limits 写nvidia.com/gpu: 1 就能跑 |
需改 YAML:把 gpu 请求换成 ResourceClaimTemplate;1.34 提供“扩展资源映射”可逐步迁移 |
| 典型使用场景 | 单卡训练、推理,节点规格统一,追求部署简单 | 多租户、多规格 GPU 混布,需共享、热切分、拓扑感知、按显存计费 |
| 性能/吞吐 | 高:纯整数减法,无额外调度开销 | 低:要遍历 ResourceSlice 并执行 CEL 过滤;社区正加缓存优化 |
| 项目地址 | https://github.com/NVIDIA/k8s-device-plugin | https://github.com/NVIDIA/k8s-dra-driver-gpu |
| 对比维度 | NVIDIA vGPU(官方软切分) | HAMi(开源软切分) |
|---|---|---|
| 切分原理 | 在 Hypervisor 里插入 NVIDIA 虚拟化层,显存固定分区,算力分时复用 | 在容器内替换libvgpu.so,CUDA API 劫持,显存/算力都软件限额 |
| 隔离级别 | 硬件认证 + 驱动级,强隔离,故障域小 | 纯用户态库拦截,隔离性弱,CUDA 崩溃可能影响他人 |
| 切分粒度 | 受限于 License Profile(如 1Q、2Q、4Q),显存与算力成固定档位 | 1% 算力 + 1 MiB 显存步长,任意组合,Pod 级自填gpumem/gpucores |
| 资源模型 | 节点上报nvidia.com/vgpu-***,需 vCenter/OpenStack 配合 |
节点把一张卡“膨胀”成 N 份(默认 10),仍用nvidia.com/gpu,再加 gpumem/gpucores 描述配额 |
| 调度方式 | 传统 Device-Plugin 整数相减,不支持超卖 | 自带调度器,支持显存超卖、算力超卖、多卡拼接 |
| 性能损耗 | 官方数据 2-5%,显存独占、算力时间片 | 官方测试平均 ≤10%,算力限制为周期均值,显存限额实时生效 |
| GPU 兼容性 | 仅限 Tesla/A 系列/H 系列等数据中心卡,需购买 License | 所有支持 CUDA 的 NVIDIA 卡(包括消费级 RTX),无需 License |
| K8s 原生性 | 需 KubeVirt 或独立 vGPU Operator,部署链路长 | 标准 Helm 安装,与 GPU-Operator 并存即可 |
| 成本 | License 费用 + 数据中心卡溢价 | 完全开源,0 授权费 |
| 能力维度 | Device-Plugin | DRA |
|---|---|---|
| 资源模型 | 纯计数:vendor.com/gpu: 1 调度器只看到“张数” |
结构化对象:ResourceClaim + DeviceClass 可携带属性、拓扑、能力、共享策略 |
| 分配粒度 | 整张 GPU(或静态 MIG) 一卡只能给一个 Pod |
任意切片:MIG 实例、显存分片、时间片、vGPU 支持多 Pod 共享同一物理卡 |
| 调度器感知 | 不感知卡型号、显存、NUMA 只能“有无”过滤 |
通过 CEL 表达式按属性、拓扑、亲和性等精确预选 支持 PrioritizedList(A100→V100→T4 顺序回退) |
| 资源生命周期 | 与 kubelet 绑定:启动即上报,关机即消失 Pod 用完也不释放给其他人 |
控制面集中账本:ResourceSlice 动态增删 Pod 删除即回收,可“按需切分、用完即走” |
| 参数化/策略 | 带外配置:靠 Annotation/ConfigMap 传参 不同租户策略硬编码在插件里 |
带内参数:DeviceClass 里声明 sharingStrategy、memory 等 租户只在 ResourceClaim 里引用即可 |
| 并行调度吞吐 | 高:简单整数相减 | 低:要遍历 ResourceSlice 并执行 CEL 过滤 社区正优化调度器缓存 |
| 实现复杂度 | 单组件:节点起个 gRPC 服务即可 | 双组件:中心 Controller + 节点 Kubelet-plugin 需实现 ResourceSlice/Claim 控制器 |
| 与现存 Workload 兼容 | 原生支持:直接写 requests/limits | 需改 YAML:把 gpu 请求换成 ResourceClaimTemplate 1.34 提供“扩展资源映射”可逐步迁移 |
| 典型适用场景 | 单卡训练、推理,节点数固定,配置简单 “能用就行”的集群 |
多租户、多规格 GPU 混布,需共享、热切分、拓扑感知 GPU 云或 AI 平台型产品 |
| 维度 | single 模式 | mixed 模式 |
|---|---|---|
| 资源名 | 所有切片统一叫nvidia.com/gpu |
每种切片单独叫nvidia.com/mig-<g>g.<mem>gb,例如 nvidia.com/mig-1g.10gb |
| 节点要求 | 同一节点上所有 GPU 必须切成完全相同的 MIG profile(例如 8 张卡全是 7×1g.5gb) | 同一节点上允许每张卡切不同 profile,甚至允许部分卡不切(回退成整卡) |
| 适用场景 | 集群节点规格统一,只想让老脚本继续写nvidia.com/gpu: 1 就能拿到任意切片 |
多规格混布、需要精确指定“我要 1g.5gb 还是 3g.40gb”的精细调度 |
| 调度器视角 | 只能看到整数张“小 GPU”,无法区分显存大小 | 能看到具体型号,可按显存/算力大小做亲和性调度 |
| 配置示例 | --set mig.strategy=single |
--set mig.strategy=mixed |
3、DRA切分样例及参考链接
DRA示例:以下示例创建了一台配备两个 L4 GPU 的 g2-standard-24 机器。
apiVersion: v1 items:
-
apiVersion: resource.k8s.io/v1beta1 kind: ResourceSlice metadata:# lines omitted for clarity
spec: devices:
- basic: attributes: architecture: string: Ada Lovelace brand: string: Nvidia cudaComputeCapability: version: 8.9.0 cudaDriverVersion: version: 12.9.0 driverVersion: version: 575.57.8 index: int: 0 minor: int: 0 productName: string: NVIDIA L4 type: string: gpu uuid: string: GPU-4d403095-4294-6ddd-66fd-cfe5778ef56e capacity: memory: value: 23034Mi name: gpu-0
- basic: attributes: architecture: string: Ada Lovelace brand: string: Nvidia cudaComputeCapability: version: 8.9.0 cudaDriverVersion: version: 12.9.0 driverVersion: version: 575.57.8 index: int: 1 minor: int: 1 productName: string: NVIDIA L4 type: string: gpu uuid: string: GPU-cc326645-f91d-d013-1c2f-486827c58e50 capacity: memory: value: 23034Mi name: gpu-1 driver: gpu.nvidia.com nodeName: gke-cluster-gpu-pool-9b10ff37-mf70 pool: generation: 1 name: gke-cluster-gpu-pool-9b10ff37-mf70 resourceSliceCount: 1 kind: List metadata: resourceVersion: ""
https://docs.cloud.google.com/kubernetes-engine/docs/how-to/set-up-dra?hl=zh-cn
https://docs.cloud.google.com/kubernetes-engine/docs/how-to/deploy-dra-workloads?hl=zh-cn
https://blog.csdn.net/zhengmx100/article/details/136809717
4、nvidia-smi的Compute Mode参数含义:
The compute mode flag indicates whether individual or multiple compute applications may run on the GPU.
"Default" means multiple contexts are allowed per device.
"Exclusive Process" means only one context is allowed per device, usable from multiple threads at a time.
"Prohibited" means no contexts are allowed per device (no compute apps).
"EXCLUSIVE_PROCESS" was added in CUDA 4.0. Prior CUDA releases supported only one exclusive mode, which is equivalent to "EXCLUSIVE_THREAD" in CUDA 4.0 and beyond.
For all CUDA-capable products.
Ascend NPU DRA Plugin 设计与实现概述
目标
实现符合 Kubernetes Dynamic Resource Allocation (DRA) 的设备插件,用于管理 Ascend NPU/GPU 资源,支持:
- 设备发现与上报给 kubelet(DRA driver)。
- 容器环境与设备节点的 CDI 注入。
- ResourceClaim/ResourceClaimTemplate 参数的 Webhook 校验。
组件与入口
cmd/ascend-npu-dra-kubeletplugin: DRA driver,可执行文件ascend-npu-dra-kubeletplugin.- CLI 参数:节点名、CDI 目录、设备数、profile(gpu/npu)、driver-name、健康检查端口等。
- 核心结构:
driver(持有 kubelet helper、DeviceState)。
cmd/ascend-npu-dra-webhook: Validating Admission Webhook,可执行文件ascend-npu-dra-webhook.- 校验 ResourceClaim/Template 的 opaque parameters,当前注册 GPU profile 校验器。
- Profiles(设备画像):
internal/profiles/gpu、internal/profiles/npu。- 提供设备枚举、配置 Schema/Validate、ApplyConfig 生成 CDI 编辑。
- 公共 API:
api/定义 GpuConfig(共享策略)、GroupNameopenFuyao、Versionv1alpha1。
设备发现(NPU 为例)
入口:internal/profiles/npu/profile.go -> discoverPhysicalDevices
- 优先使用 dcmi(当前实现通过
npu-smi info,可扩展为 cgo dcmi 接口)枚举设备,构造resourceapi.Device。 - dcmi 失败则回退扫描
/dev/davinci*,读取 sysfs(如/sys/class/ascend/deviceN/model、driver/version)。 - 再失败则生成模拟设备(按节点名+numNPUs 生成 uuid)。
- 返回
resourceslice.DriverResources,按 nodeName 构造 pool/slice。
通常只在插件启动时做一次设备发现并上报即可,理由: kubelet DRA helper会把启动时的 DriverResources 注册并维持;多数场景下 NPU/GPU 拓扑是稳定的。 已准备的 ResourceClaim 依赖 checkpoint/CDI spec 记录,重新发现并变更设备集合可能导致已分配设备失效,需小心。 需要重复探测/上报的场景: 硬件热插拔/卡故障恢复,或驱动重载导致设备集合变化。 想暴露健康状态或容量变化(温度/health/fault),需要重新 PublishResources。 如果要动态刷新: 需要在驱动侧监测变更(定时或事件),更新 driverResources,调用 helper 的 PublishResources(需要确认 helper 提供接口或重启插件),同时保证 checkpoint/CDI 清理/重建的原子性,防止已分配 claim 失效。 简单方案:检测到设备集变化时重启插件,重新发现并上报。
GPU 画像:直接生成模拟 GPU 资源,附带容量和属性。
配置处理
- Profile 实现
ConfigHandler:SchemeBuilder:注册配置类型(GpuConfig)。Validate:校验配置。ApplyConfig(config, results, params):为设备分配结果生成PerDeviceCDIContainerEdits及可选的 vNPU checkpoint 映射(params可含Allocatable、VNPUManager、EnableHardVNPU等)。
- GpuConfig 支持共享策略(TimeSlicing / SpacePartitioning),默认 timeslicing。
- NPU 复用 GpuConfig 结构,ApplyConfig 注入 NPU 环境变量与设备节点。
DeviceState 工作流
文件:cmd/ascend-npu-dra-kubeletplugin/state.go
- 初始化:
- 调用 profile.EnumerateDevices() 获取
driverResources。 - 创建 CDIHandler,写公共 CDI spec。
- 初始化 checkpoint manager,准备 claim checkpoint。
- 构建 allocatable 设备表。
- 调用 profile.EnumerateDevices() 获取
- Prepare(claim):
- 解码 claim 中针对本 driver 的 opaque configs(class/claim 源,按优先级)。
- 默认插入空配置以保证兜底。
- 将配置应用到对应的 allocation results,得到 per-device ContainerEdits。
- 为 claim 写 CDI spec(包含 common + 具体设备),更新 checkpoint,返回 prepared 设备列表。
- Unprepare(claimUID):
- 删除 claim CDI spec,清理 checkpoint 条目。
- 硬切分(硬 vNPU)的实现风险与已知限制(同 claim 重复设备名、Prepare 部分失败、整卡边界、
chipId、AICore 校验与运行时集成等):见专项文档 npu-hard-vnpu-scheduling-design.md §11。
CDI 注入
实现文件:cmd/ascend-npu-dra-kubeletplugin/cdi.go
- 公共 spec:设备名
common,注入节点名和 driver name 环境变量。 - Claim spec:设备名
<claimUID>-<deviceName>,ContainerEdits = claim env + profile 生成的 per-device edits。 - CDI QualifiedName:
vendor = k8s.<driverName>,class = <profile>。 - Driver 在 PrepareResult 中返回
CDIDeviceIDs,kubelet 挂载对应 CDI edits 进入容器。
DRA 与 CDI 的关系(概念)
在 Kubernetes DRA 机制中,CDI (Container Device Interface) 是连接「资源调度层」与「容器运行层」的桥梁。DRA 插件完成 Claim 分配后,生成 CDI 规范文件(通常为 JSON),告知容器运行时(containerd / CRI-O)需要挂载哪些设备节点、符号链接与环境变量。
CDI 文件结构示例
CDI 文件通常位于 /etc/cdi/ 或 /var/lib/cdi/。示例如下:
{
"cdiVersion": "0.5.0",
"kind": "huawei.com/npu",
"devices": [
{
"name": "npu-0",
"containerEdits": {
"deviceNodes": [
{ "path": "/dev/davinci0" },
{ "path": "/dev/davinci_manager" },
{ "path": "/dev/hisi_hdc" },
{ "path": "/dev/devmm_svm" }
],
"envs": [
"ASCEND_VISIBLE_DEVICES=0",
"NPU_MODEL=Ascend910B"
],
"mounts": [
{
"hostPath": "/usr/local/Ascend/driver/lib64",
"containerPath": "/usr/local/Ascend/driver/lib64",
"options": ["ro", "nosuid", "nodev"]
}
]
}
}
]
}
关键组成部分
- Device Nodes:按分配到的芯片索引暴露
/dev/davinciX等;通常还需管理类节点(如/dev/davinci_manager)以完成驱动初始化。 - Mounts:将主机驱动库(
.so)挂载进容器,减轻镜像体积并统一驱动版本。 - Envs:如
ASCEND_VISIBLE_DEVICES,供上层框架识别可见芯片。
DRA 与 CDI 的交互流程(概要)
- 确定分配结果(如某 Pod 绑定某物理 NPU)。
- 插件生成 CDI 规格(设备路径、env、可选 mounts)。
- 向 kubelet 返回 CDI 设备 ID(如
vendor.com/npu=npu-0)。 - 运行时根据 CDI 的
containerEdits修改容器配置,完成注入。
Driver 与 kubelet 交互
文件:cmd/ascend-npu-dra-kubeletplugin/driver.go
NewDriver: 启动 helper,发布 driverResources,启动健康检查。PrepareResourceClaims: 逐 claim 调用 state.Prepare,收集 per-claim 结果,整体不失败(错误记录在 per-claim Err)。UnprepareResourceClaims: 逐 claim 调用 state.Unprepare,同样返回 per-claim 错误,整体不失败。HandleError: 非可恢复错误触发主上下文取消。
健康检查
文件:cmd/ascend-npu-dra-kubeletplugin/health.go
- 可选 gRPC 服务;探测 kubelet registration socket 与 DRA socket,返回 SERVING/NOT_SERVING。
Webhook 校验
文件:cmd/ascend-npu-dra-webhook/main.go, resource.go
- 路径
/validate-resource-claim-parameters,解码 AdmissionReview。 - 支持 ResourceClaim / ResourceClaimTemplate 的 v1/v1beta1/v1beta2。
- 针对 driver 名匹配的 opaque config 解码成 profile 配置对象,调用
Validate;失败返回 AdmissionResponse 拒绝。
关键参数与路径
--cdi-root(默认/etc/cdi):存放 CDI spec。--kubelet-registrar-directory-path、--kubelet-plugins-directory-path: 注册与插件数据目录。--device-profile:gpu或npu。--driver-name: DRA driver 名(影响 CDI vendor 前缀)。
流程摘要(Prepare)
- kubelet 调用 Prepare -> driver.PrepareResourceClaims
- DeviceState.Prepare:
- 读取 checkpoint,若已准备直接返回。
- 获取并解码 opaque configs -> ApplyConfig 生成 per-device CDI edits。
- 写 claim CDI spec,更新 checkpoint。
- 返回 PrepareResult(Requests/Pool/Device/ CDIDeviceIDs)。
回滚与清理(Unprepare)
- kubelet 调用 UnprepareResourceClaims。
- DeviceState.Unprepare:
- 读取 checkpoint,若无记录直接返回。
- 删除 claim CDI spec,删除 checkpoint 条目。
昇腾芯片、设备形态与 CEL 字段设计
在昇腾(Ascend)生态中,**芯片(Processor/NPU)是算力核心,而设备(Device/Product)**则是芯片的工程化载体(如加速卡、服务器、集群)。
了解它们之间的对应关系对于开发 DRA 插件至关重要,因为你需要根据不同的设备类型来上报不同的资源属性(如单卡、多卡、是否有 HCCS 互联等)。
1. 核心芯片与设备系列的映射关系
华为将昇腾设备统一命名为 Atlas 系列,主要分为“推理”和“训练”两大产品线:
| 芯片系列 | 核心定位 | 典型设备名称 (Atlas) | 产品形态 |
|---|---|---|---|
| 昇腾 310 / 310P | 低功耗推理 | Atlas 200 / 300I / 500 | 开发者套件、推理加速卡、边缘小站 |
| 昇腾 910 / 910B / 910C | 高性能训练 | Atlas 300T / 800 / 900 | 训练加速卡、AI 服务器、计算集群 |
| 昇腾 610 (MDC) | 智能驾驶 | MDC 610 / MDC 810 | 车载计算平台 |
2. 具体对应案例 (DRA 插件设计参考)
在编写 DRA 插件时,你通常会遇到以下几种具体设备,它们在 NPU-SMI 命令中返回的属性会有所不同:
- Atlas 300T (训练卡):
- 对应芯片:昇腾 910。
- 形态:标准 PCIe 卡,通常安装在第三方服务器或 Atlas 800 (型号 9000) 服务器中。
- DRA 关键点:需要识别 PCIe 带宽和多卡间的 HCCS 连接。
- Atlas 800 训练服务器:
- 对应芯片:通常含有 8 颗 昇腾 910。
- 形态:整机。
- DRA 关键点:这类设备通常具有极其复杂的拓扑结构(如 8 卡全互联),在 CEL 字段中应包含
topology-group。
- Atlas 200 DK (开发者套件):
- 对应芯片:昇腾 310。
- 形态:嵌入式板卡。
- DRA 关键点:通常不支持虚拟化切分,内存较小(8GB/16GB)。
3. 如何在代码中建立对应
在 DRA 插件中,你可以通过调用 dsmi 接口或解析 npu-smi info 的输出来自动映射:
- Chip ID -> Chip Name: 例如
0x21对应Ascend 910。 - Board ID -> Device Model: 根据板卡 ID 识别是
Atlas 300T还是Atlas 800。 - Slot ID / Bus ID: 用于确定在服务器机箱中的物理位置,进而推断 NUMA 亲和性。
在设计昇腾 NPU 的 DRA 插件时,针对不同型号的芯片(如 310 系列与 910 系列),CEL 字段的设计必须体现硬件能力的分层。由于 310 侧重推理,910 侧重训练,它们的底层架构差异直接决定了哪些字段是“通用”的,哪些是“专属”的。
以下是针对不同芯片系列在 CEL 字段设计上的差异化分析:
1. 通用核心字段 (Common Fields)
无论哪种芯片,这些基础属性必须存在,以便进行基础调度。
driver.huawei.com/chip-family:Ascend310vsAscend910。driver.huawei.com/chip-name: 具体型号,如910B3,310P3。driver.huawei.com/mem-capacity: 显存大小。driver.huawei.com/numa-node: PCI 挂载的 NUMA 节点(支持 NUMA 亲和的关键)。
2. 差异化字段分析
A. 昇腾 910 系列 (侧重训练/大模型)
910 系列通常以“集群”或“多卡”形式工作,其 CEL 字段需侧重高性能互联。
driver.huawei.com/hccs-available(Boolean): 是否支持华为高速片间互联。driver.huawei.com/hccs-bandwidth(Int): HCCS 的带宽等级,用于筛选高性能训练节点。driver.huawei.com/topo-group-id(String): 标识哪些 NPU 处于同一个 HCCS 环内(全连接组)。- CEL 场景: 用户请求 8 张卡,且要求
device.attributes['topo-group-id'] == 'ring-0',确保模型并行时的通信延迟最低。
- CEL 场景: 用户请求 8 张卡,且要求
driver.huawei.com/p2p-enable(Boolean): 是否支持跨 PCIe 的 Peer-to-Peer 内存访问。
B. 昇腾 310/310P 系列 (侧重推理/边缘)
310 系列更强调高密度和媒体处理能力。
driver.huawei.com/dvpp-engines(Int): 视频预处理(DVPP)硬件引擎的数量。- CEL 场景: 视频流处理任务要求
device.attributes['dvpp-engines'] >= 4。
- CEL 场景: 视频流处理任务要求
driver.huawei.com/vdec-capacity(Int): 视频解码帧率能力(如 1080p 帧数)。driver.huawei.com/venc-capacity(Int): 视频编码能力。driver.huawei.com/is-out-of-box(Boolean): 针对 Atlas 200 等设备,标识是否为开箱即用的嵌入式环境。
3. 虚拟化与切分字段 (VNPU)
这是 DRA 插件最复杂的逻辑所在。昇腾 910 和 310P 支持不同粒度的虚拟化(Virtual NPU)。
| 字段名称 | 910 (训练切分) | 310P (推理切分) |
|---|---|---|
vcore-type |
侧重 AI Core 切分 (如 1/2, 1/4) | 侧重算力控制 (如 100%, 50%) |
vmem-type |
静态 HBM 切分 (8G, 16G, 32G) | 灵活的内存配额 |
vcfg-id |
对应特定的v_npu_configID |
对应固定的模板 ID |
CEL 示例 (针对虚拟化需求):
JavaScript
// 请求一个具有至少 16G 显存的虚拟 NPU 实例
device.attributes['driver.huawei.com/is-virtual'] == true &&
device.attributes['driver.huawei.com/vmemory-gb'] >= 16
4. 总结:字段映射表建议
为了兼容性,建议在 DRA 插件中通过一个 Capability 掩码或 Map 来动态上报:
| 芯片系列 | 必须支持的 CEL 字段 | 可选/专属字段 |
|---|---|---|
| Ascend 910 系列 | numa-node,pci-address,mem-capacity |
hccs-bandwidth,topo-group,rdma-ip |
| Ascend 310 系列 | numa-node,pci-address,mem-capacity |
dvpp-capability,vdec-fps,venc-fps |
字段设计汇总(基于20260131与计算讨论纪要)
| 公共字段 | 310专属 | 910专属 | 字段 | 含义 |
|---|---|---|---|---|
| physical-id | 属性:物理设备(芯片,不是卡)编号。nup-smi 25以上版本,npu-smi info 输出的Phy-ID字段 | |||
| chip-name | 属性:具体型号,如910B3, 310P3。npu-smi info -t board -i id -c chip_id 输出的Chip Name字段 |
|||
| numa-node | 属性:PCI 挂载的 NUMA 节点(支持 NUMA 亲和的关键) | |||
| topology-group | 属性:用于标识哪些卡在同一个 HCCS 环/全连接网内 | |||
| mem-capacity | 是 | 容量:显存大小 | ||
| ddr-capacity | 是 | 容量:内存大小 |
复杂字段:
拓扑关系:查询设备CPU和NPU的亲和性关系、多NPU之间的拓扑结构。
npu-smi info -t topo
NPU0 NPU1 NPU2 NPU3 NPU4 NPU5 NPU6 NPU7 CPU Affinity
NPU0 X SYS SYS SYS PHB SYS SYS SYS 144-167
NPU1 SYS X SYS SYS SYS PHB SYS SYS 96-119
NPU2 SYS SYS X SYS SYS SYS PHB SYS 48-71
NPU3 SYS SYS SYS X SYS SYS SYS PHB 0-23
NPU4 PHB SYS SYS SYS X SYS SYS SYS 144-167
NPU5 SYS PHB SYS SYS SYS X SYS SYS 96-119
NPU6 SYS SYS PHB SYS SYS SYS X SYS 48-71
NPU7 SYS SYS SYS PHB SYS SYS SYS X 0-23
Legend:
X = Self
SYS = Path traversing PCIe and NUMA nodes. Nodes are connected through SMP, such as QPI, UPI.
PHB = Path traversing PCIe and the PCIe host bridge of a CPU.
HCCS = Connection traversing HCCS.
NA = Unknown relationship.
5. 实现建议
在编写插件时,建议根据芯片的 DeviceID 走不同的 Gatherer 逻辑:
- Detect Chip: 通过
dsmi_get_device_type获取芯片型号。 - Conditional Attribute Injection:
- 如果是 910,调用 HCCS 拓扑接口填充互联字段。
- 如果是 310,调用媒体引擎接口填充 DVPP 字段。
- NUMA Linking: 统一通过
/sys/class/pci_bus/.../numa_node补全 PCIe 亲和性。
后续可扩展点
- 将 dcmi 探测切换为 cgo 调用
dcmi_c.go(需补齐 common/tool 包与 dcmi 头/库)。 - Webhook 增加 NPU profile 校验器。
- 根据 dcmi 信息填充更精细的容量/健康指标。
- 针对不同的NPU卡型号,可能需要不同的硬件探测逻辑。
- NPU的硬件属性需要定义,参考GpuInfo中定义的字段。要根据昇腾的实际情况进行调整
- NPU的硬件是否要分类分层次定义。比如GPU先定义整卡(物理)、其次是MIG(虚拟)、再次是vfioDeviceInfo(PCIe直通),三种是三选一。
- NPU的CDI注入模板如何实现?