集群搭建流程
对,这个问题问到核心了:K8s 接管 GPU 机器,本质上不是“把 GPU 收进来”,而是先把服务器收进集群,再通过 GPU 插件把每台机器上的 GPU 资源上报给 K8s。
整体流程是:
GPU 服务器
↓
安装 OS / 驱动 / 容器运行时
↓
加入 Kubernetes 集群,成为 Node
↓
安装 NVIDIA Device Plugin
↓
Device Plugin 发现本机 GPU
↓
把 GPU 数量上报给 kubelet
↓
kubelet 上报给 API Server
↓
K8s Scheduler 可以调度 GPU Pod
第一步:先有一个 K8s 控制面
K8s 集群通常有两类节点:
Control Plane:控制面
Worker Node:工作节点
控制面负责:
API Server:所有操作入口
Scheduler:决定 Pod 放在哪台机器
Controller Manager:维护集群状态
etcd:保存集群数据
工作节点负责:
kubelet:节点代理,向控制面汇报状态
containerd / Docker:运行容器
kube-proxy / CNI:网络
NVIDIA 驱动和 GPU 插件:暴露 GPU
你可以理解成:
Control Plane 是总部
Worker Node 是工厂车间
kubelet 是每个车间派驻的联络员
第二步:每台 GPU 机器加入集群
比如用 kubeadm 搭 K8s,控制面初始化后会生成一个 join 命令:
kubeadm join 10.0.0.10:6443 \
--token xxxxxx.xxxxxxxxxxxxxxxx \
--discovery-token-ca-cert-hash sha256:xxxxxxxx
你在每台 GPU 服务器上执行这个命令,它就会加入集群。
加入过程大概是:
1. GPU 服务器连接 API Server
2. 提交自己的身份和证书请求
3. 控制面批准后,机器成为 Node
4. kubelet 开始持续上报节点状态
5. API Server 记录这个节点
然后你在控制面执行:
kubectl get nodes
就能看到所有机器:
NAME STATUS ROLES AGE
gpu-node-01 Ready worker 10m
gpu-node-02 Ready worker 10m
gpu-node-03 Ready worker 10m
这一步叫:K8s 收录机器为 Node。
注意:这时 K8s 只知道“有这些机器”,还不一定知道“机器上有几张 GPU”。
第三步:每台 GPU 机器安装 NVIDIA 驱动
K8s 自己不负责驱动。
你必须先让宿主机能识别 GPU:
nvidia-smi
如果宿主机都看不到 GPU,K8s 也不可能调度 GPU。
所以节点上要有:
NVIDIA Driver
CUDA runtime 可选
containerd / Docker
NVIDIA Container Toolkit
第四步:安装 NVIDIA Device Plugin
K8s 默认只认识这些资源:
cpu
memory
ephemeral-storage
pods
它默认不认识:
nvidia.com/gpu
所以要安装 NVIDIA Device Plugin。
它一般以 DaemonSet 形式部署:
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.16.2/deployments/static/nvidia-device-plugin.yml
DaemonSet 的意思是:
每个 GPU 节点上都跑一个插件 Pod。
Device Plugin 做的事情是:
扫描本机 GPU
和本机 kubelet 通信
把 GPU 注册为扩展资源
告诉 kubelet 本机有几张 GPU
比如一台机器有 8 张 GPU,插件会让 kubelet 上报:
nvidia.com/gpu: 8
然后你看节点信息:
kubectl describe node gpu-node-01
会看到类似:
Capacity:
cpu: 128
memory: 1024Gi
nvidia.com/gpu: 8
Allocatable:
cpu: 128
memory: 1024Gi
nvidia.com/gpu: 8
到这里,K8s 才真正知道:
这台机器有 8 张 GPU 可以调度。
第五步:GPU 资源怎么被 Pod 使用
用户提交 Pod 时声明:
resources:
limits:
nvidia.com/gpu: 1
意思是:这个容器需要 1 张 GPU。
完整例子:
apiVersion: v1
kind: Pod
metadata:
name: gpu-test
spec:
containers:
- name: cuda
image: nvidia/cuda:12.4.1-base-ubuntu22.04
command: ["nvidia-smi"]
resources:
limits:
nvidia.com/gpu: 1
K8s Scheduler 看到这个 Pod 后,会找一台还有 GPU 余量的节点。
比如:
gpu-node-01 有 8 张,已分配 8 张,不可用
gpu-node-02 有 8 张,已分配 4 张,还剩 4 张,可以用
gpu-node-03 有 8 张,已分配 0 张,可以用
Scheduler 选择一个节点后,kubelet 会在该节点启动容器。
然后 NVIDIA Container Runtime 会把对应 GPU 设备挂进容器里。
容器内就能看到 GPU:
nvidia-smi
K8s 是怎么“收录全部机器”的
更准确地说,K8s 收录机器靠的是每台机器上的 kubelet。
流程是:
控制面 API Server 在那里等
每台机器安装 kubelet
每台机器执行 join
kubelet 带着证书和身份去注册
API Server 接收注册信息
Node 对象被创建
kubelet 持续上报心跳和资源
K8s 里的 Node 对象大概保存:
节点名
IP
操作系统
CPU 数量
内存容量
容器运行时
节点标签
污点
可分配资源
健康状态
GPU 扩展资源
所以你看到的:
kubectl get nodes
本质上是 API Server 从 etcd 里读出所有已注册的 Node 对象。
GPU 信息是怎么进 K8s 的
普通资源是 kubelet 自己上报:
CPU
内存
磁盘
Pod 数量
GPU 是 Device Plugin 上报给 kubelet:
NVIDIA Device Plugin
↓
kubelet Device Plugin Manager
↓
Node.Status.Capacity / Allocatable
↓
API Server
↓
Scheduler
这就是为什么没有 NVIDIA Device Plugin 时,你可能看到:
节点 Ready
nvidia-smi 正常
但 kubectl describe node 看不到 nvidia.com/gpu
因为 GPU 没注册成 K8s 可调度资源。
一句话总结
K8s 接管 GPU 机器分两步:
第一步:kubelet 把服务器注册成 Node
第二步:NVIDIA Device Plugin 把 GPU 注册成 nvidia.com/gpu 资源
所以完整链路是:
物理 GPU 服务器
↓ kubeadm join / 节点注册
K8s Node
↓ NVIDIA Device Plugin
nvidia.com/gpu 扩展资源
↓ Scheduler
GPU Pod 调度
↓ NVIDIA Container Runtime
容器使用 GPU
你把这个链路记住,K8s 管 GPU 集群这件事就通了。
