从云原生走向 AI 原生:一套面向未来的架构方法论 → 阅读《AI 原生基础设施》

单机 Kubernetes 与 GPU Operator:让 GPU 成为可调度资源

草稿

当一块 GPU 能用 nvidia.com/gpu: 1 这样一行资源请求被调度时,它才从“机器的部件”变成“平台的资源”。

你现在有了随时可开的云上 GPU(上一章)和能注入 GPU 的容器(再上一章)。但“哪块卡给谁”仍由人手决定:换节点要改参数、配额靠口头约定、用量无人记账。 Kubernetes 把这些变成 API 与控制循环,而 GPU Operator 把接入 GPU 所需的一整套组件(设备插件、容器运行时配置、监控导出器)变成一次 Helm 安装。本章在单机集群上完成这最后一步,并用一张“能力边界表”告诉你:跑通之后,你真正拥有了什么、还缺什么。

为什么 Kubernetes 是 GPU 的操作系统

回忆上一章:GPU 容器的关键在运行时注入设备与驱动库。Kubernetes 面对的额外问题是多租与调度——集群里的 GPU 分属不同节点,Pod 的创建由调度器而非人决定。K8s 的解法是设备插件(Device Plugin)机制:

  1. 设备插件 DaemonSet 在每个节点上向 kubelet 上报“本节点有 N 块 GPU”(nvidia.com/gpu);
  2. kubelet 把它纳入节点可分配资源(Allocatable),调度器据此决定 Pod 落点;
  3. Pod 请求 nvidia.com/gpu 并被绑定时,kubelet 调用与上一章同源的注入机制把卡交给容器。

这套“上报—调度—注入”的链路是理解后续一切的基础:HAMi 的显存切分、Kueue 的队列治理、MIG 的动态重配,全部挂在这条链路的延长线上。设备抽象的表达力边界(为什么 GPU 不是“另一种 CPU”)见设备资源抽象与演进,各厂商加速器接入 K8s 的统一模式见Kubernetes 管理模型

三种单机集群怎么选

工具GPU 支持特点适用
minikube官方支持,--gpus=all 一个参数部署最简单,节点是 Docker 容器本章实验、快速验证
kind需手动挂载设备节点多节点集群轻量,CI 常用无 GPU 或愿意手工配置者
k3s需配置 containerd 的 nvidia 运行时systemd 服务、最接近生产形态单机常驻、边缘节点
表 1: minikube / kind / k3s 对比

本章用 minikube(路径最短),k3s 作为课后练习:把同样的 GPU Operator 流程搬到 k3s 上,你会遇到真实的 containerd 运行时配置问题——那正是上一章 Toolkit 章节的延续。

GPU Operator 解决了什么

没有 Operator 时,接入一块 GPU 需要:装 nvidia-container-toolkit 并改运行时配置、部署 device plugin、部署 DCGM exporter、(必要时)装驱动——四件事四个版本矩阵,且要逐节点做。GPU Operator 把它们全部 DaemonSet 化:由 Operator 按节点状态自动安装、升级、对齐版本。

本实验的场景是“宿主机已有驱动”(云上 GPU 优化镜像,或按准备 GPU 运行环境一章手动安装),因此安装时显式关闭 Operator 的驱动组件:

--set driver.enabled=false

其余组件(toolkit、device-plugin、DCGM exporter 等)仍由 Operator 管理。何时该让 Operator 连驱动一起管(裸金属、驱动即代码的场景),见GPU Operator的完整讨论。

动手实验:调度你的第一个 GPU Pod

实验目标

在 minikube 单机集群上部署 GPU Operator,让 nvidia.com/gpu 出现在节点可分配资源中,并成功调度一个请求 GPU 的 Pod 跑通 nvidia-smi

前置条件与成本预估

  • 上一章完成的机器:宿主机驱动正常、nvidia-ctk runtime configure --runtime=docker 已执行且 Docker 已重启、docker run --rm --gpus all ... nvidia-smi 通过。
  • 已装 kubectl、Helm、minikube;机器建议 ≥ 4 vCPU / 8 GiB 内存(Operator 全家桶与集群本体都要占资源)。
  • 成本:全程本地/实例内完成,无额外云资源;云实例时长约半小时。

操作步骤

# 步骤 1:启动带 GPU 的单机集群(Docker 驱动,把 GPU 透传给 minikube 节点)
minikube start --driver=docker --gpus=all
kubectl get nodes   # 预期一个 Ready 节点

# 步骤 2:部署 GPU Operator(宿主机已有驱动,关闭 driver 组件)
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia --force-update
helm repo update
helm upgrade --install gpu-operator nvidia/gpu-operator \
  --namespace gpu-operator --create-namespace \
  --set driver.enabled=false

# 步骤 3:等待 Operator 组件就绪(toolkit、device-plugin、dcgm-exporter 等)
kubectl -n gpu-operator get pods --watch
# 预期:所有 Pod Running,其中 nvidia-device-plugin-*. .. 1/1 Running

# 步骤 4:确认 GPU 已进入可分配资源
kubectl get nodes -o jsonpath='{.items[0].status.allocatable.nvidia\.com/gpu}{"\n"}'
# 预期输出:1(单卡机器;多卡则是对应数量)

# 步骤 5:调度第一个 GPU Pod
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: gpu-smoke
spec:
  restartPolicy: Never
  containers:
  - name: cuda
    image: nvidia/cuda:12.4.1-base-ubuntu22.04
    command: ["nvidia-smi"]
    resources:
      limits:
        nvidia.com/gpu: 1
EOF

kubectl wait --for=condition=complete pod/gpu-smoke --timeout=300s
kubectl logs gpu-smoke

验证清单

  • 步骤 3 中 device-plugin Pod 稳定 Running(反复重启说明节点侧注入环境有问题,见下方排障表)
  • 步骤 4 输出与物理卡数一致
  • kubectl logs gpu-smoke 输出的 Driver Version 与宿主机基线卡一致
  • kubectl describe pod gpu-smoke 的 Events 里能看到调度成功与镜像拉取记录
  • 实验数据(卡数、allocatable 值、Pod 日志)记入基线卡

故障排障速查

现象常见原因第一反应
allocatable 输出 0minikube 容器没拿到 GPU / device-plugin 未就绪 / 宿主机驱动异常进节点验证:minikube ssh nvidia-smi;再查 device-plugin 日志
Operator Pod 一直 Pending单机资源不足确认 ≥ 4C/8G;kubectl describe pod 看被谁卡住
gpu-smoke 一直 ContainerCreatingtoolkit 组件未就绪或运行时配置冲突kubectl -n gpu-operator logs -l app=nvidia-container-toolkit;等 toolkit DaemonSet 就绪后重试
Pod 起了但报 insufficient镜像 CUDA 版本高于宿主机驱动上限对照基线卡 CUDA 上限(见“准备 GPU 运行环境”的规则 3),换镜像 tag
minikube start 卡死或报 GPU 相关错误Docker 的 nvidia 运行时未配置或未重启重做上一章三步配置;先用 docker run --rm --gpus all 自证
表 2: 单机 GPU 集群常见故障与第一反应

原理速览

你在步骤 4–5 看到的就是本章开头那条链路:device plugin 上报 → kubelet 更新 Allocatable → 调度器把 gpu-smoke 绑到唯一节点 → kubelet 用 toolkit(Operator 部署的那套)完成与 docker run --gpus 同源的注入。上一章与本章是同一机制在两种编排下的两个投影——理解了这一点,换到任何 K8s 发行版都不再神秘。

清理与止损

kubectl delete pod gpu-smoke
helm uninstall gpu-operator -n gpu-operator && kubectl delete ns gpu-operator
minikube delete --all

云实例若不再使用,执行云上第一台 GPU 机器一章的 terminate 流程并确认零残留。

你还没有得到什么

诚实的能力边界——这也是全书剩余部分的目录:

能力状态答案所在
GPU 以 nvidia.com/gpu 被调度✅ 已拥有本章
一块卡分给多个 Pod / 显存级配额❌ 整卡为最小单位数据平面:MIG、HAMi、DRA
队列、配额、优先级、公平共享❌ 尚无治理控制面:Kueue、Volcano
拓扑感知放置(NVLink/NUMA)❌ 调度器无拓扑视野NUMA 感知调度放置策略
GPU 利用率/显存/健康度的指标语义⚠️ exporter 已部署,语义未建可观测与验收
异构加速器接入(NVIDIA 之外)❌ 仅 NVIDIA 路径加速器全景昇腾案例
表 3: 跑通本章后:已拥有与尚未拥有

总结

上手篇到此完成闭环:环境验证 → 云上开机 → GPU 容器 → 可调度的 GPU Pod。你现在已经拥有一台随时可开、可被 Kubernetes 调度的 GPU 机器,以及一张记录了驱动版本、CUDA 上限、实测 TFLOPS、allocatable 的环境基线卡。上面的边界表就是你的下一步菜单:如果“分卡”是你最迫切的痛点,去数据平面;如果“治理”是,去控制面;如果你想先弄懂每一步背后发生了什么,认识机器与问题会从硅片开始讲起。

创建于 2026/09/14 更新于 2026/09/14 2572 字 阅读约 6 分钟