机器学习平台技术栈之 RDMA Device Plugin
机器学习平台技术栈之 RDMA Device Plugin
在大语言模型(LLM)狂飙突进的时代,训练一个千亿参数的模型动辄需要上千张甚至上万张 GPU。在这个规模下,单节点的算力早已不是唯一的瓶颈,节点间的网络通信能力往往决定了整个集群的计算效率上限。
在分布式训练(如基于 NCCL 的 AllReduce 集合通信)中,GPU 之间需要极其频繁地交换几十甚至上百 GB 的梯度数据。传统的 TCP/IP 协议栈由于其内核态到用户态的内存拷贝(Copy)、上下文切换(Context Switch)开销,导致了极高的延迟和严重的 CPU 负担。为了突破这道网络墙,RDMA(Remote Direct Memory Access,远程直接内存访问) 成为了现代 AI 集群的标配。
而在云原生(Kubernetes)体系下,如何将物理机上的 RDMA 高性能网卡无损地、安全地透传给容器(Pod)使用,是构建 AI 基础设施的关键挑战。这正是 RDMA Device Plugin 的核心使命。
本文将剥茧抽丝,从 TCP/IP 的痛点出发,详细解读 RDMA 的核心概念、K8s 设备插件机制,以及 RDMA Device Plugin 的架构设计与最底层的全链路技术细节,带你真正吃透这块构建高性能机器学习平台不可或缺的基石。
1. 核心概念解析
在深入 RDMA Device Plugin 之前,我们必须先理清底层的硬件与网络概念。
1.1 为什么需要 RDMA?(TCP/IP 的困境)
在传统的 TCP/IP 网络交互中,当应用进程发送数据时,数据流向是:应用缓冲区 (User Space) -> Socket 缓冲区 (Kernel Space) -> 网卡驱动 -> 物理网卡 (NIC)
这个过程经历了多次内存数据拷贝(Data Copy),并且需要 CPU 介入进行协议栈的封装/解封装,带来大量的 CPU 中断和上下文切换。在 400Gbps 乃至 800Gbps 的网络时代,CPU 即便 100% 满载也无法跑满网卡带宽。
RDMA (Remote Direct Memory Access) 的出现彻底改变了这一现状。它允许一台计算机直接读写另一台计算机的内存,**完全绕过操作系统内核 (Kernel Bypass),实现了真正的零拷贝 (Zero-Copy)**。
- Kernel Bypass: 应用直接通过用户态的驱动(User-level verbs API)控制网卡。
- Zero-Copy: 数据直接从应用的内存写入对端物理内存,没有内核缓冲区的参与。
- CPU Offload: 数据传输由网卡(HCA, Host Channel Adapter)直接完成,释放 CPU 资源给核心计算。
1.2 RDMA 的三大网络实现
RDMA 是一种技术思想,在物理链路上主要有三种实现:
- InfiniBand (IB): 专为 RDMA 设计的无损网络架构,性能最好,但需要专用的 IB 交换机和线缆,成本极高。
- RoCE (RDMA over Converged Ethernet): 将 RDMA 报文封装在传统的以太网上。RoCEv2 封装在 UDP/IP 之上,具备良好的路由能力,是目前各大云厂商 AI 计算集群中最主流的方案。
- iWARP: 基于 TCP 实现的 RDMA,虽然兼容性好,但因 TCP 本身的开销,性能逊于前两者,在 AI 领域极少使用。
1.3 SR-IOV (Single Root I/O Virtualization)
当物理机接入了一块高速 RDMA 网卡(如 Mellanox ConnectX-6/7),如何在多台容器或虚拟机之间共享这块网卡呢?
SR-IOV 技术应运而生。它能够将一个物理功能(PF, Physical Function)虚拟出多个相互隔离的虚拟功能(VF, Virtual Function)。
每一个 VF 都可以像独立的物理网卡一样被分配给一个 Pod。由于支持硬件层面的隔离,VF 既享受了原生的 RDMA 性能,又实现了容器间的安全隔离。
1.4 Kubernetes Device Plugin Framework
Kubernetes 默认只管理 CPU 和 Memory。对于 GPU、FPGA、RDMA 等异构计算和通信硬件,K8s 提供了一套被称为 **Device Plugin (设备插件)**的机制。
各个硬件厂商部署自己编写的 Device Plugin DaemonSet 运行在 K8s Node 上,通过 gRPC 协议与本机的 Kubelet 通信,告诉 Kubelet 本机有多少块专属硬件可供分配。
2. 核心概念之间的关系网络
在云原生 AI 训练任务中,RDMA 的使用链路涉及 K8s、CNI 网络插件和设备插件。下图描述了它们之间的复杂协作关系:
1 | graph TD |
- Multus CNI: Kubernetes 默认一个 Pod 只有一个网卡(eth0,用于控制流)。如果又要提供业务控制面,又要使用高达 400G 的 RDMA 数据面网络,就需要 Multus CNI 让 Pod 拥有多张网卡(Multiple Network Interfaces)。
- SR-IOV CNI: 负责将宿主机上虚拟出的 VF 接口,通过 Linux namespace 隔离移动到容器的 network namespace 中,并配置 IP。
- RDMA Device Plugin: 并不配置 IP 和以太网链路,它专职负责向容器挂载能执行 RDMA Kernel Bypass 所必须的字符设备文件(即
/dev/infiniband/*目录下的硬件抽象映射)。
这些组件完美配合,让 Pod 既拥有网卡(配置 NCCL IP binding)又拥有底层字符设备读写权限(开启 verbs direct access)。
3. RDMA Device Plugin 架构设计
Kubernetes 社区广泛使用的是由 Mellanox 维护的 k8s-rdma-device-plugin 以及后续更复杂的 sriov-network-device-plugin。
我们以 RDMA Device Plugin 为例探究其架构。
它主要由以下三个模块构成:
- **Sysfs Watcher (设备发现层)**:监听宿主机的 sysfs 文件系统树(如
/sys/class/infiniband/和/sys/class/net/),发现可用的 RDMA 设备(PF 或 VF),收集设备的拓扑、PciID、NUMA node 节点等信息。 - **Plugin Server (gRPC 接口层)**:实现了 K8s 标准定义的
v1beta1.DevicePlugingRPC 服务接口(包含ListAndWatch和Allocate两个最核心的 API)。 - **Config Manager (策略与配置层)**:根据 K8s configmap 中定义的策略(使用 SR-IOV 还是 MACVLAN 共享,支持什么类型的网络),将底层物理资源重新抽象聚合给上层。
gRPC 交互时序 (架构细节)
1 | sequenceDiagram |
4. 关键技术细节剖析
作为构建集群的技术深度好文,我们还需要将显微镜对准最核心的几个技术细节:到底是什么支撑着这个看似简单的 Device Plugin 走完了最后一公里?
4.1 ListAndWatch:资源注册与 NUMA 感知
在 AI 集群中,GPU 网卡通常会绑定在特定的 PCIe Switch 下,这涉及到 NUMA 架构。跨 NUMA 高速通信会带来巨大的带宽高消耗和延迟的急剧攀升(因为必须走 CPU QPI/UPI 总线)。
RDMA Device Plugin 在向 Kubelet 汇报(ListAndWatch 接口)可以分配的设备列表时,除了返回 DeviceID 之外,更重要的是会上报 Topology 信息(包含了 NUMA Node ID)。
1 | // K8s Device Plugin API definition fragment |
结合 K8s 1.18+ 引入的 **Topology Manager (拓扑管理器)**,Kubelet 会在本地做出对齐策略:如果 Pod 同时申请了 GPU 和 RDMA,Topology Manager 可以保证分配到的 GPU 和 RDMA 网卡必定处在同一个 NUMA Node 上。这正是诸如 GPUDirect RDMA(让 RDMA 芯片直接越过 CPU 读写 GPU 显存)技术得以施展的基石。
4.2 Allocate:注入神秘的字符设备
当一个 Pod 真的被调度到节点上时,RDMA Device Plugin 的 Allocate 的方法会被触发。
RDMA Kernel Bypass 的核心在于 K8s 容器需要直接和内核的 InfiniBand 栈打交道。为了让用户态应用能操控网卡,Linux 内核抽象出了以下几个重要设备文件:
/dev/infiniband/uverbsX:(重要)负责建立 Queue Pairs (QP, 发送/接收队列簇),并进行控制面命令的下发。/dev/infiniband/rdma_cm: RDMA Connection Manager,用于建立类似 TCP/IP 的套接字连接通信(常被 NCCL Socket 模式调用)。/dev/infiniband/issmX: 用于 InfiniBand 网络的子网管理。
在 AllocateResponse 中,Plugin 明确指定这些设备文件不仅要被 Volume Mounts 到容器系统的相同路径下,还要设置 **Linux Device Permissions (cgroups 设备控制)**,使得容器内的进程获得读写的最高权限。
4.3 Lock Memory: CAP_IPC_LOCK 权限
这里隐藏着坑了无数初学者的深水区。
我们在第一卷中提到 RDMA 是 Zero-Copy 的,即网卡直接去内存取数据。但由于操作系统的虚拟内存页面置换机制(Swap/Paging),如果此时应用态的内存页面恰巧被换出了物理内存,RDMA 网卡的 DMA 时钟将产生灾难性的缺页中断,这在硬件传输层面是无法挽回的。
为了防止被 DMA 访问的内存页面遭到内核置换,用户的 AI 训练等程序在使用 RDMA 时必须**锁住内存页面,即 Pin Memory (通过系统调用 mlock)**。然而普通的进程并没有大面积锁定物理内存的权限,它需要 ulimit -l 配置的支持。
在云原生环境中,RDMA 相关的部署往往需要给容器赋予特殊的 Linux Capabilities:
1 | securityContext: |
CAP_IPC_LOCK (Capability Inter-Process Communication Lock) 是进行大页内存操作或调用 verbs 接口在宿主锁定任意大小内存的必要凭证。缺乏这个 Capability,即便 RDMA Device Plugin 注入了 /dev/infiniband 文件,NCCL 在尝试向驱动申请注册 MR (Memory Region) 操作时也会立刻无情报错崩溃。
4.4 Shared Mode (共享模式) vs SR-IOV 模式
在 K8s 中部署带有 RDMA 的业务,Plugin 在配置和配合上提供两种典型的网工模式:
- MacVlan / Ipvlan Shared 模式:
在物理网卡只有一块,且没有开启 SR-IOV 功能时。RDMA Device Plugin 支持通过 Macvlan 将相同的物理 RoCE 块抽象后塞进多个容器。缺点是所有容器共享同一个 PF(物理设备的硬件队列),隔离性极其糟糕,某个用户的容器发起的超高频 RDMA 请求很容易挤爆网卡的限流,导致其他容器连坐。 - SR-IOV 单占模式(生产标配):
通过底层开启 SR-IOV,生成ens1f0v0,ens1f0v1…这些独立的 VF。并且利用sriov-network-device-plugin或 RDMA 增强 plugin,每次Allocate会为 Pod 分配独占的硬件级队列和网卡指针。这提供了与虚拟机一致的安全性和质量保证(QoS),目前无论是阿里云、腾讯云等公有云还是各厂私有超算几乎全部采用这条技术栈。
5. 总结:AI Infra 皇冠上的明珠
在这场愈演愈烈的 AI 算力军备竞赛中,算力的载体不只是高耸入云的 NVIDIA H100 或者是计算集群。由数十个高速交换层搭建成的无阻塞网络拓扑,才是串联起这张人类智慧网络的神经系统。
而 RDMA Device Plugin 以及其背后的 SR-IOV / Multus 生态体系,便是连接高维玄幻的算法世界(PyTorch, Megatron)与冰冷深邃的物理网络协议栈(InfiniBand 交换机)之间的唯一桥梁。
掌握 RDMA 原理和 Kubernetes 异构设备扩展能力,不再是网络或者运维部门的专职,它目前已成为任何一位立志深耕大规模分布式深度学习平台的 AI 系统工程师不可跨越的必修课。借助 Kubernetes 开放的 CNI 和设备发现抽象,我们在云原生的浩瀚宇宙中,终于能够用代码优雅、高效、安全地编排属于我们自己的算力巨兽。





