2. K8s GPU基础架构

在Kubernetes集群中调度GPU资源,核心挑战在于如何让kubelet感知到节点上的GPU设备,并将这些设备以标准化资源(如 nvidia.com/gpu)的形式暴露给调度器。本章将深入剖析支撑这一能力的三大基础组件:Device Plugin机制、NVIDIA GPU Operator以及GPU节点标签与污点。

2.1 Device Plugin机制:GPU资源的标准接入点

Kubernetes从1.8版本引入了Device Plugin框架,允许第三方厂商通过插件形式将硬件设备(如GPU、FPGA、InfiniBand)注册到kubelet,并实现设备健康检查与分配。NVIDIA的GPU Device Plugin正是这一框架的标准实现。

2.1.1 工作流程

  1. 注册:Device Plugin启动后,通过gRPC向kubelet注册自身,并上报设备ID、数量及健康状态。
  2. ListAndWatch:kubelet定期调用该接口,获取当前可用的GPU设备列表。若设备故障,插件会将其从列表中移除。
  3. Allocate:当Pod请求 nvidia.com/gpu 资源时,kubelet调用此接口。插件返回设备ID、环境变量(如 NVIDIA_VISIBLE_DEVICES)、卷挂载(如 /usr/local/nvidia)等分配信息。
  4. Pod启动:kubelet根据Allocate返回的信息,设置容器运行时环境,确保容器只能访问被分配的GPU。
关键点:Device Plugin只负责“设备发现与分配”,不参与调度决策。调度器仅根据节点上 nvidia.com/gpu 的剩余容量进行调度。

2.1.2 部署示例

使用DaemonSet部署NVIDIA Device Plugin是最常见的做法:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nvidia-device-plugin-daemonset
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: nvidia-device-plugin-ds
  template:
    metadata:
      labels:
        name: nvidia-device-plugin-ds
    spec:
      containers:
      - image: nvidia/k8s-device-plugin:v0.14.0
        name: nvidia-device-plugin-ctr
        securityContext:
          privileged: true
        volumeMounts:
        - mountPath: /var/lib/kubelet/device-plugins
          name: device-plugin
      volumes:
      - hostPath:
          path: /var/lib/kubelet/device-plugins
          type: DirectoryOrCreate
        name: device-plugin

2.2 NVIDIA GPU Operator:自动化运维的基石

手动部署Device Plugin、驱动、容器运行时、监控组件等步骤繁琐且易出错。NVIDIA GPU Operator通过Operator模式,将GPU集群的运维工作自动化,实现“一键部署、自动升级、健康巡检”。

2.2.1 组件架构

GPU Operator并非单一组件,而是一组协同工作的控制器与DaemonSet:

组件 功能 部署方式
nvidia-driver-daemonset 在GPU节点上安装/升级NVIDIA驱动 DaemonSet
nvidia-container-toolkit-daemonset 配置容器运行时(containerd/Docker)以支持GPU DaemonSet
nvidia-device-plugin-daemonset 注册GPU设备到kubelet DaemonSet
nvidia-dcgm-exporter 暴露GPU指标(温度、显存、利用率)给Prometheus DaemonSet
gpu-feature-discovery 自动检测GPU型号、显存、拓扑,并打上节点标签 DaemonSet
node-feature-discovery 检测节点通用硬件特性(如PCIe、CPU指令集) DaemonSet
最佳实践:在生产环境中,强烈建议使用GPU Operator而非手动部署。Operator会自动处理驱动版本兼容性、节点重启后的组件恢复、以及证书轮换等运维难题。

2.2.2 部署命令

# 使用Helm安装GPU Operator
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update

helm install gpu-operator nvidia/gpu-operator \
  --namespace gpu-operator \
  --create-namespace \
  --set driver.enabled=true \
  --set driver.version="535.154.05"

2.3 GPU节点标签与污点:精细化调度控制

仅有Device Plugin和Operator还不够——调度器需要知道哪些节点有GPU、GPU的型号和显存大小,以及哪些节点应该被预留用于特定工作负载。标签(Labels)和污点(Taints)正是实现这一目标的关键机制。

2.3.1 自动标签:GPU Feature Discovery

GPU Operator中的 gpu-feature-discovery 组件会自动为GPU节点添加以下标签:

标签键 示例值 说明
nvidia.com/gpu.product NVIDIA-A100-SXM4-80GB GPU产品型号
nvidia.com/gpu.memory 81920 显存大小(MiB)
nvidia.com/gpu.count 8 节点上GPU数量
nvidia.com/gpu.compute-capability 8.0 CUDA计算能力
nvidia.com/gpu.family ampere GPU架构家族

2.3.2 污点:隔离GPU节点

默认情况下,非GPU工作负载也可能被调度到GPU节点上,造成资源浪费。通过为GPU节点添加污点,可以确保只有显式容忍该污点的Pod才能运行:

# 为GPU节点添加污点
kubectl taint nodes gpu-node-1 nvidia.com/gpu=present:NoSchedule

# Pod中通过toleration容忍
spec:
  tolerations:
  - key: "nvidia.com/gpu"
    operator: "Equal"
    value: "present"
    effect: "NoSchedule"
注意:如果集群中同时存在不同型号的GPU(如A100与V100),务必使用节点亲和性(nodeAffinity)结合 nvidia.com/gpu.product 标签,将特定工作负载调度到正确的GPU型号上,避免因驱动或CUDA版本不兼容导致Pod启动失败。

2.4 架构总览:从设备到调度

下图展示了GPU资源从物理设备到Pod调度的完整链路:

K8s GPU基础架构:从设备到调度 物理GPU设备层 NVIDIA GPU (A100 / V100 / H100) 通过PCIe或NVLink连接 NVIDIA驱动 (nvidia-smi 可识别) 节点代理层 (每个GPU节点) NVIDIA Container Toolkit → 配置容器运行时 NVIDIA Device Plugin → 向kubelet注册GPU设备 GPU Feature Discovery → 自动打标签 Kubernetes控制平面层 kube-scheduler 根据节点标签与资源容量进行调度 kubelet 调用Device Plugin Allocate接口完成设备分配 污点(Taints)与容忍(Tolerations)控制Pod准入 Pod容器:通过 NVIDIA_VISIBLE_DEVICES 访问指定GPU

2.5 本章小结

  • Device Plugin 是GPU资源接入K8s的标准接口,负责设备注册与分配。
  • NVIDIA GPU Operator 将驱动、运行时、Device Plugin、监控、标签发现等组件自动化,大幅降低运维复杂度。
  • 节点标签与污点 提供了精细化调度控制手段:标签用于识别GPU型号与容量,污点用于隔离GPU节点,防止非GPU工作负载抢占资源。