文章

Device Plugin 与 DRA 对比

Device Plugin 与 DRA 对比

GPU 集群中两种核心资源分配机制的深度对比:传统 Device Plugin vs 新一代 Dynamic Resource Allocation。理解两者的差异,是 K8s GPU 调度体系升级的关键。


一、架构对比:一图看懂

┌─────────────── Device Plugin 模型 ───────────────┐
│                                                    │
│  Pod                  Scheduler          Kubelet   │
│  ┌──────────┐       ┌──────────┐      ┌─────────┐ │
│  │resources:│       │只看节点    │      │Allocate │ │
│  │  nvidia. │──────>│有 2 个    │─────>│GPU 0,1  │ │
│  │  com/gpu │       │GPU 就行   │      │给 Pod   │ │
│  │  : 2     │       │          │      │         │ │
│  └──────────┘       └──────────┘      └─────────┘ │
│                       ↑  不知道 GPU 在哪个         │
│                       │  NUMA / PCIe switch!       │
│  nvidia-device-plugin: "节点有 8 个 GPU"           │
│  (只报告数量,不报告属性和拓扑)                     │
└────────────────────────────────────────────────────┘

┌─────────────── DRA 模型 ─────────────────────────────┐
│                                                       │
│  ResourceClaim        Scheduler          Kubelet      │
│  ┌──────────────┐   ┌──────────────┐   ┌──────────┐  │
│  │ selectable:  │   │匹配属性+拓扑  │   │分配 GPU  │  │
│  │  model: A100 │──>│+ NUMA亲和性  │──>│0,1 并挂载│  │
│  │  memory: 80  │   │              │   │到容器    │  │
│  │  count: 2    │   └──────────────┘   └──────────┘  │
│  └──────────────┘                                     │
│                                                       │
│  ResourceSlice: "GPU-0: A100/80GB, NUMA0;             │
│                  GPU-1: A100/80GB, NUMA0; ..."        │
│  (调度器感知每个设备的属性和拓扑位置)                   │
└───────────────────────────────────────────────────────┘

二、维度对比:逐项拆解

2.1 核心能力

维度Device PluginDRA谁更优
调度感知❌ 只报告节点 GPU 数量✅ 感知每个设备属性 + 拓扑位置DRA
属性筛选❌ 所有 GPU 同质selectableAttributes 按型号/显存/代数筛选DRA
NUMA 亲和⚠️ 需额外 Topology Manager,且不支持跨 Pod 协调✅ 调度器原生感知 NUMA,跨 Pod 协调DRA
NVLink 拓扑感知❌ 不知道哪些 GPU 通过 NVLink 互联✅ 可通过设备属性标注 NVLink groupDRA
子资源分配⚠️ MIG 通过独立资源名暴露 (nvidia.com/mig-1g.10gb),笨重✅ 原生支持 Partition / TimeSlicingDRA
多 Pod 共享❌ 同一 GPU 只能给一个 Pod(TimeSlicing 是 workaround)✅ 通过 sharing strategy 原生支持DRA
生命周期管理绑定到 Pod:Pod 删 → GPU 释放独立于 Pod:ResourceClaim 可保留DRA
RDMA / NIC 管理❌ 无法管理✅ 统一框架管理 GPU + NICDRA
Cluster Autoscaler❌ 不支持模拟调度✅ 结构化参数可模拟DRA

2.2 运维维度

维度Device PluginDRA
部署复杂度✅ 简单:部署 nvidia-device-plugin DaemonSet⚠️ 中:需 DRA driver + DeviceClass + ResourceSlice 管理
成熟度✅ 10 年生产验证⚠️ K8s v1.26 Alpha → v1.34 GA,生产案例仍在积累
驱动支持✅ 所有 GPU 厂商⚠️ NVIDIA 已支持,AMD/Intel 进行中
社区生态✅ Helm chart、GPU Operator 一键部署⚠️ Operator 正在适配
故障排查✅ 文档丰富,问题可搜索⚠️ 报错信息较新,社区方案少
与 Volcano 集成✅ Volcano 原生支持 nvidia.com/gpu⚠️ 需额外适配
多版本 K8s 兼容✅ 全版本⚠️ 核心 API 需 v1.34+,旧版本 API 已废弃

2.3 性能维度

维度Device PluginDRA
调度延迟✅ 毫秒级(简单计数)⚠️ 毫秒级+(属性匹配 + 拓扑约束)
分配延迟✅ 毫秒级(kubelet 直接调 Allocate)⚠️ 毫秒级(多一层 ResourceClaim 状态机)
GPU 利用率优化⚠️ 调度器不感知拓扑,可能分配效率低✅ 调度器全域优化,提升整体利用率
碎片化控制❌ MIG 配置后固定,动态调整需重启✅ 可通过 ResourceSlice 动态调整

三、典型场景决策

3.1 训练场景

场景:大模型训练,需要 8 卡 TP(张量并行)
需求:8 个 A100 80GB,同节点,NVSwitch 全互联

Device Plugin:
  resources:
    nvidia.com/gpu: 8
  → 可能分配到 [GPU0,GPU1,GPU2,GPU3,GPU4,GPU5,GPU6,GPU7]
  → 无法保证 8 卡都有 NVLink 全互联(部分可能是 PCIe)

DRA:
  selectableAttributes:
    - attribute: model      → "A100"
    - attribute: memoryGB   → "80"
    - attribute: nvlink-group → "nvswitch-0"  ← 精确指定 NVSwitch 组
  count: 8
  allocationMode: All
  → 保证 8 卡在同一 NVSwitch domain,TP 性能最优

结论:训练场景 DRA 更强,能精确控制拓扑。

3.2 推理场景(多租户)

场景:推理集群,需要 4 个实例,每个 1 个 MIG 切片(1g.10gb)

Device Plugin:
  暴露资源: nvidia.com/mig-1g.10gb
  Pod 请求: nvidia.com/mig-1g.10gb: 1
  → 4 个 Pod 各拿 1 个 MIG slice
  → 但如果某个节点只剩 2 个 slice,调度器不知道

DRA:
  ResourceClaimTemplate(每个 Pod 自动创建)
  sharing:
    strategy: Partition
  → 调度器知道每个节点剩余多少个 slice
  → 可以跨节点优化放置

结论:推理多租户 DRA 更优雅,但 Device Plugin + MIG 也能用。

3.3 混合 GPU 集群

场景:集群同时有 A100 和 H100,训练任务要 H100,推理要 A100

Device Plugin:
  → 需要 nodeSelector + 节点打标签区分
  → 或通过不同 resource name 暴露

DRA:
  selectableAttributes:
    - attribute: model
      value: "H100"
  → 原生属性筛选,不需要维护节点标签

结论:异构 GPU 集群 DRA 能大幅简化管理。

四、实战 YAML 对比

4.1 最简场景:请求 1 个 GPU

Device Plugin:

apiVersion: v1
kind: Pod
metadata:
  name: simple-job
spec:
  containers:
  - name: app
    image: nvidia/cuda:12.4-runtime-ubuntu22.04
    resources:
      limits:
        nvidia.com/gpu: 1

DRA:

# 1. 先创建 ResourceClaim
apiVersion: resource.k8s.io/v1
kind: ResourceClaim
metadata:
  name: simple-gpu
spec:
  devices:
    requests:
      - name: gpu
        deviceClassName: nvidia-gpu
        count: 1
---
# 2. Pod 引用
apiVersion: v1
kind: Pod
metadata:
  name: simple-job
spec:
  containers:
  - name: app
    image: nvidia/cuda:12.4-runtime-ubuntu22.04
    resources:
      claims:
        - name: gpu
  resourceClaims:
    - name: gpu
      source:
        resourceClaimName: simple-gpu

Device Plugin 方案更简洁,DRA 多了 ResourceClaim 这个抽象层——简单场景下这是额外开销。

4.2 复杂场景:指定 A100 80GB × 2,同 NUMA node

Device Plugin:(难以精确实现)

apiVersion: v1
kind: Pod
metadata:
  name: pinned-job
spec:
  containers:
  - name: trainer
    image: pytorch/pytorch:2.4
    resources:
      limits:
        nvidia.com/gpu: 2
        cpu: 32
        memory: 128Gi
  # 需要额外配置 Topology Manager + CPU Manager Policy
  # + nodeSelector 限定 A100 节点
  nodeSelector:
    gpu-type: a100          # 手动打标签
    gpu-memory: "80"        # 手动打标签
  # ⚠️ 无法保证 2 个 GPU 在同一 NUMA node!

DRA:

apiVersion: resource.k8s.io/v1
kind: ResourceClaim
metadata:
  name: pinned-gpu
spec:
  devices:
    requests:
      - name: gpu
        deviceClassName: nvidia-gpu
        count: 2
        allocationMode: All             # 必须同时分配
        selectableAttributes:
          - attribute: model
            value: "A100"               # 原生属性筛选
          - attribute: memoryGB
            value: "80"
      - name: gpu-numa
        deviceClassName: nvidia-gpu-numa
        constraints:
          - sameNUMANode: true          # 同 NUMA node(需驱动支持)

4.3 共享场景:多 Pod 分时复用同一个 GPU

Device Plugin (Time-Slicing workaround):

# nvidia-device-plugin ConfigMap
data:
  config.yaml: |
    version: v1
    sharing:
      timeSlicing:
        resources:
          - name: nvidia.com/gpu
            replicas: 4    # 1 个 GPU 暴露为 4 个虚拟 GPU
# Pod 请求「虚拟 GPU」
apiVersion: v1
kind: Pod
spec:
  containers:
  - resources:
      limits:
        nvidia.com/gpu: 1  # ← 实际是 1/4 时间片

⚠️ 问题:kubelet 和调度器看到的都是 4× GPU,不知道它们共享同一物理 GPU。显存不隔离,OOM 风险。

DRA:

apiVersion: resource.k8s.io/v1
kind: DeviceClass
metadata:
  name: nvidia-gpu-shared
spec:
  config:
    - opaque:
        driver: nvidia.com
        parameters:
          apiVersion: gpu.resource.k8s.io/v1alpha1
          kind: GPUConfig
          sharing:
            strategy: TimeSlicing          # 原生共享策略
            timeSliceInterval: 100ms
---
apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
  name: shared-gpu
spec:
  spec:
    devices:
      requests:
        - name: gpu
          deviceClassName: nvidia-gpu-shared
          count: 1
          sharing:
            strategy: TimeSlicing
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: inference-pool
spec:
  replicas: 4
  template:
    spec:
      containers:
      - name: server
        resources:
          claims:
            - name: gpu
      resourceClaims:
        - name: gpu
          source:
            resourceClaimTemplateName: shared-gpu

✅ 优势:调度器知晓共享关系,可精确控制每个物理 GPU 上最多多少共享 Pod,避免过载。


五、版本演进与兼容性

K8s v1.25 及以前:
  └── 只能用 Device Plugin

K8s v1.26-v1.30:
  └── DRA Alpha(旧 API,已废弃)
  └── Device Plugin 仍然主力

K8s v1.31-v1.33:
  └── DRA 结构化参数(新 API)Alpha → Beta
  └── Device Plugin 共存

K8s v1.34+ (2025.08):
  └── DRA 核心 API GA: resource.k8s.io/v1
  └── ★ 生产可用的分水岭 ★
  └── Device Plugin 继续可用,不受影响

K8s v1.35+ (2025.12):
  └── DRA 扩展:可分区设备、设备污点
  └── GPU 场景全面可用

K8s v1.36+ (2026.04):
  └── AdminAccess GA、优先替代 GA
  └── 原生 ResourceClaim(Pod 内嵌声明)Alpha

六、迁移指南

6.1 渐进式迁移策略

阶段 1:双轨运行(v1.34+)
  ├── 保留 nvidia-device-plugin(现有工作负载不受影响)
  └── 部署 NVIDIA DRA Driver(新工作负载试用)

阶段 2:新负载切 DRA
  ├── 新训练 Job → 用 DRA 的拓扑感知
  ├── 推理 Pool → 用 DRA 的共享策略
  └── 旧 Job 继续用 Device Plugin

阶段 3:全量迁移
  ├── 验证所有场景覆盖
  ├── 逐步下掉 MIG 资源名暴露
  └── 移除 nvidia-device-plugin(仅保留 DRA driver)

6.2 NVIDIA DRA Driver 部署

# 1. 安装 NVIDIA DRA Driver(Helm)
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm install nvidia-dra-driver nvidia/k8s-dra-driver \
  --namespace nvidia-dra \
  --create-namespace \
  --set driver.version=0.8.0

# 2. 创建 GPU DeviceClass
kubectl apply -f - <<EOF
apiVersion: resource.k8s.io/v1
kind: DeviceClass
metadata:
  name: nvidia-gpu
spec:
  selectableAttributes:
    - name: model
    - name: memoryGB
    - name: architecture
  config:
    - opaque:
        driver: nvidia.com
        parameters:
          apiVersion: gpu.resource.k8s.io/v1alpha1
          kind: GPUConfig
EOF

# 3. 验证 ResourceSlice 自动创建
kubectl get resourceslices
# NAME          NODE     DRIVER      DEVICES
# node1-gpu     node1    nvidia.com   8
# node2-gpu     node2    nvidia.com   8

6.3 迁移注意事项

注意事项说明
Volcano 兼容性Volcano 对 DRA 支持有限,当前建议训练任务仍用 Device Plugin + Volcano
GPU OperatorGPU Operator 以 Device Plugin 为核心,DRA driver 需独立部署
MIG 迁移MIG 配置仍通过 nvidia-mig-manager 管理,DRA 通过 ResourceSlice 暴露 slice
监控不变DCGM + dcgm-exporter 不受影响,GPU 监控链路不变
资源名变化nvidia.com/gpuResourceClaim 引用,K8s Dashboard 需要适配

七、什么时候用哪个?

用 Device Plugin 如果你:
  ✅ K8s < v1.34
  ✅ 简单场景(固定 GPU 数量,不需要拓扑控制)
  ✅ 使用 Volcano 等第三方调度器
  ✅ 团队对 Device Plugin 已经很熟悉

用 DRA 如果你:
  ✅ K8s ≥ v1.34
  ✅ 异构 GPU 集群(A100 + H100 + B200 混合)
  ✅ 需要拓扑感知(同一 NVSwitch/NUMA 节点)
  ✅ 推理多租户需要精确的共享策略
  ✅ 需要 GPU + RDMA NIC 协同分配
  ✅ 新集群,从零开始

当前(2026 年中)推荐:
  训练集群:Device Plugin 为主(成熟),DRA 作为 POC 试点
  推理集群:DRA 试点(共享策略优势明显)
  异构集群:尽快评估 DRA(属性筛选是刚需)

关联知识

参考资源

学习时间

阶段时间备注
内容创建2026-06-30完整 Device Plugin vs DRA 对比

状态标记

📖 已掌握 — 架构差异、能力对比、场景决策、迁移策略 📝 待补充 — AMD/Intel GPU 的 DRA 驱动支持进展、实际生产迁移案例