2、K8s GPU基础概念:Node与GPU拓扑、Device Plugin机制、GPU Operator介绍

2.1 从物理GPU到K8s资源——我踩过的第一个坑

刚接触K8s GPU调度那会儿,我犯过一个低级错误。

我以为只要把GPU插到服务器上,K8s就能自动识别。结果呢?Pod调度上去直接CrashLoopBackOff。后来才明白——K8s本身不认识GPU。它只知道CPU和内存。GPU这种特殊硬件,需要一套机制来“告诉”K8s:嘿,我这有块卡,你可以用。

这套机制,就是今天要聊的核心。

一句话总结:K8s把GPU当作“扩展资源”(Extended Resource)来管理。你需要手动注册、上报、调度。

2.2 Node与GPU拓扑——你的卡到底插在哪?

先说说Node。在K8s里,一台服务器就是一个Node。每个Node上可能插了1块、4块甚至8块GPU。

但问题来了:这些GPU是怎么连接的?

我个人习惯把GPU拓扑分成三种场景:

  • 单卡场景:最简单。一块GPU直连CPU。适合推理服务、小模型训练。
  • 多卡直连(NVLink/NVSwitch):GPU之间高速互联。适合大模型分布式训练。
  • 跨PCIe Switch:GPU通过PCIe Switch连接。延迟稍高,但成本低。

你想想看,如果两个GPU不在同一个PCIe Switch下,通信要走QPI/UPI链路,延迟直接翻倍。我在项目中遇到过,一个8卡A100的节点,因为拓扑没配好,训练速度硬生生掉了30%。

我的建议:部署前先用 nvidia-smi topo -m 看一眼GPU拓扑。如果看到“PIX”或“PXB”这种字眼,说明GPU之间是直连或通过PCIe Switch连接的,性能较好。如果看到“SYS”,那就走的是系统总线,性能差很多。

K8s怎么感知这些拓扑?

嗯,它其实不感知。K8s只知道Node上有多少块GPU,不知道它们怎么连的。拓扑信息需要靠Device Plugin和调度器配合才能利用起来。这部分后面会细说。

2.3 Device Plugin机制——K8s认识GPU的关键

Device Plugin是K8s 1.8引入的机制。说白了,它是一个gRPC服务,运行在Node上,负责两件事:

  1. 上报资源:告诉K8s“我这有4块GPU”。
  2. 分配资源:当Pod要GPU时,告诉K8s“把第2块卡给这个Pod”。

我画了一张流程图,帮你理解这个过程:

Kubelet Device Plugin (gRPC Server) NVIDIA GPU ListAndWatch() nvidia-smi 返回设备信息 Pod 请求GPU资源 Allocate() 返回设备路径 Device Plugin 工作流程 1. Kubelet 启动时调用 ListAndWatch() 获取设备列表 2. Pod 申请 GPU 时,Kubelet 调用 Allocate() 分配具体设备 3. Device Plugin 返回设备文件路径和环境变量

流程其实不复杂。Kubelet启动时,会去注册的Device Plugin socket路径下调用ListAndWatch()。Device Plugin返回当前可用的GPU列表。当Pod申请GPU时,Kubelet再调用Allocate(),Device Plugin返回具体的设备文件路径和环境变量(比如NVIDIA_VISIBLE_DEVICES)。

我曾经踩过一个坑:Device Plugin挂了,但Kubelet不知道。结果Pod调度到那个Node上,一直拿不到GPU。后来我养成了一个习惯——监控Device Plugin的健康状态,用Liveness Probe定期检查。

注意:Device Plugin是DaemonSet部署的。每个Node上必须跑一个。如果某个Node的Device Plugin挂了,那个Node上的GPU资源就不可用了。

2.4 GPU Operator——别再手动装驱动了

说到GPU Operator,我得先吐槽一下手动部署的痛苦。

早期部署GPU工作节点,你需要:

  • 装NVIDIA驱动
  • 装CUDA Toolkit
  • 装Container Toolkit(nvidia-docker2)
  • 配置Docker运行时
  • 部署Device Plugin
  • 配置监控(DCGM)

每一步都可能出问题。我记得有一次,驱动版本和CUDA版本不兼容,折腾了两天。

GPU Operator就是来解决这个问题的。它把上面所有组件打包成一个Operator,通过CRD(Custom Resource Definition)来管理。

核心组件包括:

组件 作用 部署方式
NVIDIA Driver GPU驱动 DaemonSet(自动安装)
CUDA Toolkit CUDA运行时库 DaemonSet
Container Toolkit 容器运行时GPU支持 DaemonSet
Device Plugin GPU资源上报与分配 DaemonSet
DCGM Exporter GPU监控指标导出 DaemonSet
GPU Feature Discovery 自动发现GPU型号、显存等 Job

部署GPU Operator只需要一条命令:

helm install gpu-operator nvidia/gpu-operator \
  --namespace gpu-operator \
  --create-namespace

它会自动检测Node上的GPU型号,安装对应驱动,配置运行时,部署Device Plugin。整个过程大概5-10分钟。

我的经验:GPU Operator默认会安装最新驱动。但如果你有特殊需求(比如vLLM需要特定CUDA版本),可以在Helm values里指定驱动版本。我一般会先查一下vLLM的兼容性矩阵,再决定用哪个版本。

2.5 三者关系——一张图看懂

Node与GPU拓扑是硬件基础。Device Plugin是软件桥梁。GPU Operator是自动化部署工具。

它们的关系是这样的:

Node 与 GPU 拓扑(硬件层) Device Plugin 机制(软件层) GPU Operator(自动化层)

底层是硬件。中间层是Device Plugin,它把硬件抽象成K8s资源。顶层是GPU Operator,它自动化了中间层和底层的部署与运维。

你想想看,如果没有GPU Operator,你要手动处理驱动兼容性、Device Plugin版本、监控部署。有了它,你只需要关注业务本身。

核心要点:

  • GPU拓扑影响性能,部署前用 nvidia-smi topo -m 检查
  • Device Plugin是GPU资源调度的核心,必须保证高可用
  • GPU Operator能大幅降低运维成本,建议生产环境使用

好了,这一章就到这里。GPU的基础概念搞清楚了,下一章我们聊聊更实际的东西——怎么在K8s里真正跑起一个vLLM推理服务。


专注资料整理