4. Kubernetes GPU管理:NVIDIA GPU Operator、k8s设备插件机制、MIG的配置与使用

聊到Kubernetes里的GPU管理,很多人第一反应就是“装个驱动,挂个设备插件就完事了”。嗯,早期确实是这样。但等你真正管理过几十台、上百台GPU节点,你就会发现——事情没那么简单。

我个人习惯把GPU管理分成三个层次:设备发现、资源调度、资源切分。设备插件解决的是“让K8s知道节点上有GPU”;GPU Operator解决的是“让整个集群的GPU环境自动化”;而MIG解决的是“怎么把一块大GPU掰成几块用”。

咱们一个一个来聊。

4.1 设备插件机制:K8s怎么“看见”GPU的?

Kubernetes本身不认识GPU。它只知道CPU、内存这些通用资源。要让K8s知道节点上有GPU,就得靠设备插件(Device Plugin)。

设备插件是K8s的一种扩展机制。它运行在Pod里,通过gRPC和kubelet通信。说白了,就是设备插件告诉kubelet:“嘿,我这有4块GPU,你看着分配吧。”

NVIDIA官方提供的设备插件叫nvidia-device-plugin。它的工作流程很简单:

  1. 扫描节点上的NVIDIA GPU
  2. 向kubelet注册这些GPU资源(资源名是nvidia.com/gpu)
  3. 当Pod申请nvidia.com/gpu时,kubelet把对应的GPU设备挂载进容器

来看一个典型的部署方式:

kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.14.0/nvidia-device-plugin.yml

部署完之后,你可以在节点上看到:

kubectl describe node <node-name> | grep nvidia.com/gpu

如果显示有数量,说明设备插件工作正常了。

一个小经验: 我遇到过好几次设备插件启动成功,但Pod一直Pending的情况。后来发现是容器运行时没配置好NVIDIA Container Toolkit。记得在每个GPU节点上安装 nvidia-container-toolkit,并配置好Docker或containerd的运行时。

4.2 NVIDIA GPU Operator:把“手工活”变成“自动化”

设备插件解决了资源注册的问题。但GPU节点的运维远不止这些——驱动要装、容器运行时要配、监控要部署、MIG要配置……每个节点手动搞一遍?那运维同学怕是要骂娘了。

这就是NVIDIA GPU Operator的价值。它把GPU相关的所有组件打包成一个Operator,通过K8s原生的方式管理GPU节点。

GPU Operator管理的主要组件包括:

组件 作用
nvidia-driver-daemonset 在每个节点上安装NVIDIA驱动
nvidia-container-toolkit-daemonset 配置容器运行时支持GPU
nvidia-device-plugin-daemonset 向K8s注册GPU资源
nvidia-dcgm-exporter 采集GPU监控指标(温度、显存、利用率等)
nvidia-mig-manager 管理MIG配置(后面会细说)

安装GPU Operator也很简单,用Helm就行:

helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
helm install gpu-operator nvidia/gpu-operator --version v23.9.0

安装完成后,Operator会自动检测集群中的GPU节点,并部署对应的DaemonSet。你几乎不需要手动干预。

我个人的建议: 如果你的集群规模超过10个GPU节点,直接用GPU Operator。别自己手动部署设备插件和驱动。Operator带来的好处不仅仅是自动化——它还能帮你做版本管理、滚动升级、健康检查。我曾经在一个50节点的集群上手动升级驱动,搞了整整两天。换成Operator之后,一条命令搞定。

4.3 MIG(多实例GPU):一块GPU当多块用

聊完设备插件和Operator,咱们进入一个更高级的话题——MIG。

MIG是NVIDIA在Ampere架构(A100、A30)上推出的技术。它允许你把一块物理GPU切分成多个独立的GPU实例。每个实例有自己的显存、缓存和计算单元,互相隔离。

为什么要用MIG?说白了,就是提高利用率。你想想看,一个小模型推理任务,可能只需要2GB显存,但你手里只有一块80GB的A100。直接分配整卡?太浪费了。用MIG切一下,一块A100可以变成7个1g.10gb的实例,每个实例10GB显存,跑7个推理任务,利用率直接拉满。

4.3.1 MIG的配置方式

MIG配置有两种方式:

  • 手动配置: 通过 nvidia-smi mig -cgi 命令在节点上设置
  • 自动配置: 通过GPU Operator的MIG Manager自动管理

手动配置的步骤大致如下:

# 1. 查看支持的MIG配置
nvidia-smi mig -lgip

# 2. 创建MIG配置(例如:3个20GB实例)
nvidia-smi mig -cgi 19,19,19 -C

# 3. 查看MIG实例
nvidia-smi mig -lgi

配置完成后,每个MIG实例在系统里会显示为一个独立的GPU设备。设备插件会自动识别它们,并向K8s注册为独立的nvidia.com/gpu资源。

注意: MIG配置是持久化在GPU上的。一旦配置好,重启节点也不会丢失。但如果你要修改配置,需要先销毁所有MIG实例,再重新创建。这个操作会导致正在运行的Pod中断,所以建议在业务低峰期操作。

4.3.2 在K8s中使用MIG

在K8s里使用MIG,关键是要让设备插件知道你要用哪种MIG配置。这通过设备插件策略来控制。

GPU Operator支持两种MIG策略:

  • single策略: 每个MIG实例作为一个独立的GPU资源。Pod申请1个nvidia.com/gpu,可能拿到一个完整的GPU,也可能拿到一个MIG实例。
  • mixed策略: 允许Pod指定要申请的MIG配置。比如Pod可以声明“我要一个1g.10gb的MIG实例”。

配置mixed策略需要在GPU Operator的values.yaml中设置:

migManager:
  enabled: true
  default: all-disabled
  strategy: mixed

然后在Pod的annotation中指定MIG配置:

apiVersion: v1
kind: Pod
metadata:
  name: mig-pod
  annotations:
    nvidia.com/mig-config: "1g.10gb"
spec:
  containers:
  - name: cuda-container
    image: nvidia/cuda:12.0-base
    resources:
      limits:
        nvidia.com/gpu: 1

这样,调度器就会把这个Pod调度到有可用1g.10gb MIG实例的节点上。

避坑指南: 我曾经在mixed策略下踩过一个坑——Pod的annotation写成了 nvidia.com/mig-config: "1g.10gb",但节点上实际配置的是 1g.10gb+me(带多进程服务的版本)。结果Pod一直Pending。后来查文档才发现,MIG配置名称必须完全匹配。建议在配置前先用 nvidia-smi mig -lgipp 确认一下准确的配置名称。

4.4 本章小结

咱们把Kubernetes GPU管理的三个核心点捋了一遍:

  • 设备插件是基础,让K8s能“看见”GPU
  • GPU Operator是进阶,把GPU运维自动化
  • MIG是优化手段,让GPU利用率更高效

在实际项目中,我建议的落地路径是:先用设备插件跑通基础功能,然后上GPU Operator管理驱动和监控,最后根据业务需求决定是否启用MIG。别一上来就搞MIG,先把基础打牢。

嗯,关于GPU管理就聊这么多。下一节咱们会深入聊聊GPU集群的监控和可观测性——毕竟,没有监控,你都不知道你的GPU到底跑得怎么样。

可可精品资料库