已关闭
[RFC]: k8s-rdma-shared-dev-plugin 支持华为昇腾 UB RDMA 共享模式 #223
lirui2381创建于 4月27日关闭于 9月8日
4月27日 添加了label:rfc
lirui2381
4月27日 评论:
4月27日 评论:
/label add triaged


4月27日 添加了label:triaged
4月27日 修改了issue 的描述
4月27日 关联了里程碑:MindCluster 26.1.0
4月27日 修改了issue 的描述
4月27日 修改了issue 的描述
Atlas_zxp
4月27日 评论:
4月27日 评论:
/label add triaged


4月27日 修改了issue 的描述
5月5日 修改了issue 的描述
5月5日 修改了issue 的描述
lirui2381
5月7日 评论:
5月7日 评论:
没有huawei-ctk,需要删除


lirui2381
5月7日 评论:
5月7日 评论:
MACVLAN 模式支持删除,它没有roce能力


lirui2381
5月7日 评论:
5月7日 评论:
huawei.com/rdma_shared需要指出本质是共享次数,不是真实挂载数量


lirui2381
5月7日 评论:
5月7日 评论:
补充测试点,业务场景可以使用perftest


lirui2381
5月7日 评论:
5月7日 评论:
hca的数量是否可配


5月8日 修改了issue 的描述
此处折叠了21条事件消息 查看更多
9月8日 关闭了 issue
k8s-rdma-shared-dev-plugin 设计文档(华为昇腾 UB RDMA 共享模式)
目录
1. 引言
1.1 背景
在大语言模型(LLM)和高性能计算(HPC)领域,分布式训练任务需要节点间频繁交换数 GB 级别的梯度数据。传统的 TCP/IP 协议栈由于存在内存拷贝和内核态/用户态上下文切换的开销,已成为制约集群计算效率的关键瓶颈。
RDMA(Remote Direct Memory Access,远程直接内存访问)技术允许网卡直接读写对端内存,绕过操作系统内核,实现零拷贝数据传输。在 Kubernetes 环境中,如何将宿主机上的 RDMA 设备安全、高效地提供给容器(Pod)使用,是构建 AI 基础设施的核心挑战。RDMA Shared Device Plugin 正是解决这一问题的关键组件。
1.2 问题描述
在未部署 RDMA 设备插件之前,Kubernetes 集群面临以下问题:
resources.limits中声明对 RDMA 设备的需求,调度器无法基于 UB RDMA 资源容量进行节点选择。/dev/infiniband/uverbsX)挂载到容器内部。RDMA Shared Device Plugin 旨在通过实现 Kubernetes Device Plugin 标准接口,系统性地解决上述问题。
1.3 术语与定义
本文档涉及的核心术语定义如下:
1.4 参考文献
2. 设计目标与约束
2.1 设计目标
2.3 设计约束
ib_uverbs、ib_core等内核模块。/sys文件系统以及/var/lib/kubelet/device-plugins目录。3. 总体架构设计
3.1 架构图
graph TB subgraph ControlPlane[Kubernetes Control Plane] API[API Server] Sched[Scheduler / Volcano] etcd[(etcd)] end subgraph WorkerNode[Worker Node] Kubelet[kubelet] Plugin[RDMA Device Plugin<br/>DaemonSet] Config[ConfigMap<br/>config.json] Kernel[Linux Kernel] RDMA_NIC[RDMA Capable NICs<br/>/sys/class/infiniband/rocep*] end API -- Watch/Update --> Sched Sched -- Bind --> API Kubelet -- gRPC Register/ListAndWatch --> Plugin Plugin -- Read --> Config Plugin -- sysfs discover --> Kernel Kernel --> RDMA_NIC Plugin -- gRPC Allocate --> Kubelet Kubelet -- CRI --> ContainerRuntime ContainerRuntime --> Pod3.2 组件协作
RDMA Shared Device Plugin 以 DaemonSet 形式部署在每个节点上,主要与以下 Kubernetes 组件交互:
3.3 与 Kubernetes 设备插件框架的关系
插件完整实现 Device Plugin 框架定义的 gRPC 接口:
4. 核心模块设计
📌 说明:第 4 章、第 5 章、第 6 章描述的是开源 k8s-rdma-shared-dev-plugin 的通用设计与实现逻辑。华为昇腾 UB 设备的差异化适配(设备发现扩展、UB 总线扫描、自定义筛选器等)请参见第 7 章。
4.1 设备发现模块
插件通过扫描 PCI 总线 上的网络设备作为发现起点,。具体流程分为三个阶段:
阶段一:锁定 PCI 网络设备
扫描
/sys/bus/pci/devices/下所有 PCI 设备,过滤出 PCI 类代码为0x02的设备(即网络控制器)。这一步从硬件层面捕获所有可能的网络设备。阶段二:通过 selectors 筛选
对阶段一发现的设备,读取其 PCI 配置空间属性(如
vendor、device、subsystem_vendor等),并根据 ConfigMap 中定义的selectors进行过滤。支持的筛选条件包括:vendors:厂商 IDdeviceIDs:设备 IDdrivers:驱动名称ifNames:网络接口名称linkTypes:链路类型(ether或ib)只有满足所有
selectors条件的设备才进入下一阶段。阶段三:确认 RDMA 能力
对于通过筛选的设备,插件检查
/sys/bus/pci/devices/<pci-addr>/net/<iface>/device/infiniband/目录是否存在且非空。若存在,则认为该设备具备 RDMA 能力,将其作为可分配的 HCA 设备加入资源池。4.2 设备上报模块 (ListAndWatch)
ListAndWatch是 Device Plugin 框架中的核心 gRPC 流式接口,其设计要点如下:DeviceID标识。Healthy;若设备故障,状态变更为Unhealthy,kubelet 将停止向该设备调度新 Pod。periodicUpdateInterval(默认 60 秒)定期调用DiscoverHostDevices,检测设备变化并通过ListAndWatch流推送更新。ListAndWatch流连接异常中断时,插件应重新发起注册流程。4.3 资源分配模块 (Allocate)
当 Pod 被调度到节点并请求 RDMA 资源时,kubelet 调用
AllocategRPC 接口。插件返回的AllocateResponse包含以下内容:/dev/infiniband/uverbs0,/dev/infiniband/uverbs1, … ,/dev/infiniband/rdma_cm/dev/hugepages→/dev/hugepages4.4 配置管理模块 (ConfigMap)
插件通过挂载的 ConfigMap 进行动态配置,支持多资源配置。ConfigMap 的典型结构如下:
{ "periodicUpdateInterval": 300, "configList": [ { "resourceName": "rdma_shared", "resourcePrefix": "huawei.com", "rdmaHcaMax": 8, "selectors": { "vendors": ["19e5"], "ifNames": ["enp23s0f0", "enp23s0f1"] } } ] }字段说明:
periodicUpdateIntervalconfigListconfigList[].resourceNameresources.limits.<resourceName>申请。configList[].resourcePrefixresourceName拼接后作为完整资源名。configList[].rdmaHcaMaxconfigList[].selectorsvendors、deviceIDs、drivers、ifNames、linkTypes、buses等。configList[].devices4.5 健康检查与周期性更新
/sys/class/infiniband/<device>/ports/1/state)判定设备是否为Healthy(PORT_ACTIVE表示正常)。periodicUpdateInterval间隔内重新扫描设备状态并更新缓存,通过ListAndWatch流推送变化。Unhealthy后,kubelet 停止向该设备调度新 Pod;恢复后重新加入可分配池。4.6 资源模型:节点级共享
本插件采用 共享模式(Shared HCA Mode),将节点上所有可用的 RDMA 设备作为一个整体资源池。当 Pod 请求
huawei.com/rdma_shared资源时:1,表示 1 份额)。Allocate响应中返回节点上所有 RDMA 设备对应的字符设备路径。此模型适用于 AI 训练任务中需要跨 HCA 进行通信的场景,简化了调度逻辑。
5. 工作流程
5.1 插件启动与注册流程
kubelet.sock,发送Register请求。ListAndWatch接口,插件开始向 kubelet 持续推送设备状态。5.2 Pod 调度与设备分配流程
sequenceDiagram participant P as RDMA Plugin participant K as Kubelet participant S as Scheduler / Volcano participant API as API Server participant C as Container Runtime participant Pod as Pod P->>P: 启动 / 周期性扫描 sysfs P->>K: Register (gRPC) K->>P: ListAndWatch 流建立 loop 心跳/状态更新 P-->>K: 设备列表 + 健康状态 end Note over S,API: Pod 创建 (schedule: volcano) S->>API: 绑定节点 (基于资源过滤) API->>K: 通知 Pod 分配 K->>P: Allocate(deviceIDs) P-->>K: AllocateResponse<br/>(返回节点全部 HCA 设备文件) K->>C: CreateContainer (CRI) C->>Pod: 挂载 /dev/infiniband/* (全部) Pod->>Pod: 应用使用所有 RDMA 设备5.3 设备故障处理流程
ListAndWatch流发送更新,将该设备标记为Unhealthy。Healthy,kubelet 重新将其加入可分配池。5.4 基于 ConfigMap 的 HCA 健康感知调度与故障重调度
节点上的 HCA 健康状态通过 ConfigMap 暴露,由
ascend-volcano插件(作为 Volcano 调度器的一个插件)负责读取并用于调度决策和故障重调度。节点预选过滤(Predicate):在调度 Pod 时,读取所有节点的健康 ConfigMap。若节点存在任一不健康 HCA,则将该节点从候选列表中过滤掉,即使其 Allocatable 资源仍有剩余。
通过 Watch 机制监听 ConfigMap 的变化。当某个节点的健康状态从全部健康变为部分不健康时,插件需要识别出运行在该节点上的、请求了 huawei.com/rdma_shared 资源的 Pod,并触发其驱逐与重调度。
6. 配置模型
6.1 ConfigMap 配置结构
插件使用的 ConfigMap 挂载至容器内的
/k8s-rdma-shared-dev-plugin/config.json路径。一个典型的完整配置示例如下:{ "periodicUpdateInterval": 300, "configList": [ { "resourceName": "rdma_shared", "resourcePrefix": "huawei.com", "rdmaHcaMax": 8, "selectors": { "vendors": ["19e5"], "ifNames": ["enp23s0f0", "enp23s0f1"] } } ] }rdmaHcaMax是用来控制节点上能并发运行多少个共享模式 Pod 的“总票数”,不是 Pod 内挂载的设备数量,应该设置为HCA设备的数量。6.2 设备选择器 (Selectors)
插件支持的设备筛选机制(标准字段及扩展字段):
vendors["19e5"](华为)deviceIDs["0222"]drivers["hns"],["mlx5_core"]ifNames["enp23s0f0"]linkTypes["ether"],["ib"]buses(扩展)["pci"],["ub"]7. 华为昇腾 UB RDMA 适配方案
7.1 背景说明
华为昇腾 UB 设备 不在 PCI 总线上,而是通过自定义的
/sys/bus/ub/devices/暴露。标准插件发现逻辑完全基于 PCI 总线扫描,因此无法原生识别 UB 设备。本章描述如何扩展插件以支持 UB 总线上的 RDMA 设备。7.2 标准插件发现流程 vs. UB 设备发现需求
/sys/bus/pci/devices//sys/bus/ub/devices/。vendor,device等vendor,device等。vendor为cc08,device为8200。/sys/bus/pci/devices/{addr}/net/获取ifNames,比如/sys/bus/pci/devices/0000:17:00.0/net/net/子目录,插件需能遍历。/sys/class/net/{iface}/device/infiniband/,比如/sys/class/net/enp23s0f0/device/infiniband//sys/bus/ub/devices/{id}/infiniband/或通过net/间接关联。7.3 发现逻辑修改方案
在插件源代码中,修改
DiscoverHostDevices()函数,增加对 UB 总线的扫描分支(伪代码):func DiscoverHostDevices() []*HostDevice { devices := []*HostDevice{} // 原有 PCI 扫描 for _, pciDev := range scanPCIDevices() { if isNetClass(pciDev) { devices = append(devices, pciDev) } } // 新增 UB 扫描 (如果配置允许) if ubScanEnabled() { for _, ubDev := range scanUBDevices() { // 1. 判断是否为网络/RDMA设备:检查是否存在 net/ 子目录,或 type 字段符合预期 if isUBNetDevice(ubDev) { // 2. 补充属性供 selectors 匹配:读取 ubDev 下的 vendor, device 文件(若存在) // 否则设置默认 vendor=0x19e5 // 3. 关联 RDMA: 检查 ubDev/infiniband/ 或 ubDev/net/*/device/infiniband/ if hasRDMA(ubDev) { devices = append(devices, ubDev) } } } } return devices }7.4 UB 设备筛选器扩展
在 ConfigMap 的
selectors中增加以下字段以便精确筛选:buses["ub"]vendorsID为["cc08"]。deviceIDsID为["8200"]根据 。示例配置(仅筛选 UB 设备且 type=0x1):
{ "configList": [ { "resourceName": "ub_rdma", "resourcePrefix": "huawei.com", "selectors": { "buses": ["ub"], "vendors": ["cc08"], "deviceIDs": ["8200"] } } ] }7.5 Allocate 阶段适配
对于 UB 设备,
Allocate返回的DeviceSpec与 PCI 设备相同,仍为/dev/infiniband/uverbsX及/dev/infiniband/rdma_cm。若华为驱动需要额外设备节点(如/dev/hns_*),可在Allocate响应中追加。8. 安全与隔离
8.1 设备文件权限控制
插件在
Allocate响应中返回的DeviceSpec指定了宿主机设备路径及容器内的访问权限(r、w、m)。容器运行时根据这些指令挂载设备文件。建议的安全实践:
securityContext.privileged: false,仅通过capabilities添加必要的IPC_LOCK权限。8.2 网络命名空间隔离
Linux 的网络命名空间(netns)是实现 RDMA 设备隔离的核心机制。RDMA 子系统支持两种隔离模式:
sharedexclusive本设计推荐使用
shared模式,以支持节点级设备共享。9. 部署与运维
9.1 DaemonSet 部署
插件以 DaemonSet 形式部署,YAML 关键配置:
hostNetwork: true:共享宿主机网络命名空间。volumeMounts:挂载设备插件目录、sysfs 和 ConfigMap。securityContext.privileged: true:需要特权访问硬件设备。9.2 依赖条件
部署插件前,宿主机 MUST 满足以下条件:
ib_uverbs、ib_core、对应网卡驱动如hns)。/var/lib/kubelet/device-plugins目录已存在。# 验证 RDMA 设备就绪 ls /dev/infiniband/ ls /sys/class/infiniband/ ibv_devinfo10. 未来演进
本设计文档的当前版本实现了 节点级共享模式 及 与 Volcano 调度器的基础集成。后续计划在以下方向继续演进:
未来将引入 CDI 规范,实现设备注入的标准化。设备插件仅需返回 CDI 注解,实际挂载由容器运行时根据 CDI 规格文件完成。
附录 A:Pod 使用示例
以下是一个 Pod 申请 RDMA 资源的配置示例:
apiVersion: v1 kind: Pod metadata: name: rdma-training-pod spec: schedulerName: volcano # 可选,若使用 Volcano 基础调度 containers: - name: trainer image: my-rdma-app:latest resources: limits: huawei.com/rdma_shared: 1 # 请求 1 份额,实际获得节点上全部 HCA securityContext: capabilities: add: ["IPC_LOCK"] volumeMounts: - name: devshm mountPath: /dev/shm volumes: - name: devshm emptyDir: medium: Memory附录 B:术语表