4. 验证GPU Pod调度与设备分配

验证GPU Pod调度与设备分配 学习卡片

验证目标与前置检查

本例要验证的是一条完整链路:Pod 声明 nvidia.com/gpu 资源 → 调度器筛选出 GPU 节点并绑定 → kubelet 通过 Device Plugin 分配设备 → 容器内 nvidia-smi 能看到 GPU。开始前先确认节点已注册 GPU 资源:

kubectl get nodes -o custom-columns=\
NAME:.metadata.name,\
GPU:.status.allocatable.nvidia\.com/gpu,\
TAINTS:.spec.taints[*].key

# 期望:GPU 节点在 GPU 列显示 >=1,非 GPU 节点显示 <none>
# 若 GPU 列为 <none>,说明 Device Plugin 未就绪,先排查 DaemonSet

创建请求 GPU 的 Pod

GPU 属于扩展资源,必须显式声明 limits,且 requests 与 limits 必须相等(Kubernetes 对扩展资源的强制约束)。下面这个 Pod 请求 1 张 GPU,并打印容器内可见设备:

apiVersion: v1
kind: Pod
metadata:
  name: gpu-verify
spec:
  restartPolicy: Never
  containers:
    - name: cuda
      image: nvidia/cuda:12.4.0-base-ubuntu22.04
      command: ["bash", "-lc"]
      args:
        - |
          echo "=== CUDA_VISIBLE_DEVICES=$CUDA_VISIBLE_DEVICES ==="
          nvidia-smi -L
          nvidia-smi --query-gpu=index,name,uuid --format=csv
      resources:
        limits:
          nvidia.com/gpu: 1
kubectl apply -f gpu-verify.yaml
kubectl get pod gpu-verify -o wide -w

观察调度与设备分配过程

Pod 从 Pending 到 Running 的过程,正是调度器与 kubelet 协作完成设备分配的过程。用下面命令逐步确认每个环节:

# 1) 调度事件:确认被哪个节点接收、为何被过滤
kubectl describe pod gpu-verify | sed -n '/Events:/,$p'

# 2) 绑定结果:NODE 列应为 GPU 节点
kubectl get pod gpu-verify -o wide

# 3) 容器内设备可见性
kubectl logs gpu-verify

# 4) 节点侧分配账本:已分配设备 UUID 与 Pod 的对应关系
kubectl describe node <gpu-node> | grep -A5 "Allocated resources"
若 Pod 一直 Pending,describe 事件里通常会出现 0/3 nodes are available: 1 Insufficient nvidia.com/gpu,说明 GPU 已被占满或未注册;若出现 node(s) had untolerated taint,则是污点未容忍,属于后续案例的处理范围。

调度与设备分配链路

下图把本例的验证对象串成一条链路:从 Pod 的资源声明出发,经调度器过滤打分、kubelet 调用 Device Plugin 分配,最终落到容器内可见的设备节点上,并标出每一步的验证命令与判读依据。

Pod 资源声明 limits: nvidia.com/gpu: 1 requests = limits kube-scheduler Filter: 节点 GPU 可分配量 Score: 资源均衡 / 亲和性 绑定 Pod → Node kubelet + Device Plugin Allocate() 分配 GPU UUID 写入 CDI / 设备挂载 更新节点分配账本 容器内可见 /dev/nvidia0 CUDA_VISIBLE_DEVICES nvidia-smi -L 验证命令 kubectl get nodes -o custom-columns=...GPU | kubectl describe pod gpu-verify | kubectl logs gpu-verify | kubectl describe node <gpu-node> 调度阶段判读 • NODE 列 = GPU 节点名 • 事件含 Successfully assigned • 无 Insufficient nvidia.com/gpu • 无 untolerated taint 报错 分配阶段判读 • 节点 Allocated resources 中 nvidia.com/gpu 已计入该 Pod • 容器 spec 含 device 挂载 • 分配 UUID 与节点 GPU 一致 容器内判读 • nvidia-smi -L 列出 GPU • CUDA_VISIBLE_DEVICES 非空 • 设备数量 = 请求数量 • 无 "No devices were found" Pending / 分配失败 → 查事件与 Device Plugin

结果判读与常见异常

现象含义下一步
Pod 长期 Pending,事件含 Insufficient nvidia.com/gpu节点 GPU 已全部分配或未注册检查 allocatable 与已分配账本,确认 Device Plugin 正常
事件含 untolerated taintGPU 节点有污点而 Pod 未容忍为 Pod 增加对应 toleration
Pod Running 但 nvidia-smi 报 No devices were found设备未正确挂载进容器检查运行时配置与 Device Plugin 的 CDI/挂载逻辑
nvidia-smi -L 列出多于请求数量的 GPU设备隔离未生效确认 CUDA_VISIBLE_DEVICES 是否被正确注入
扩展资源不支持超卖:nvidia.com/gpu 的 requests 必须等于 limits,且不能小于 1。若写成 requests: 1, limits: 2,API Server 会直接拒绝创建。

清理与复验

kubectl delete pod gpu-verify
# 复验:删除后节点 GPU 分配量应回落
kubectl describe node <gpu-node> | grep -A3 "Allocated resources"

删除 Pod 后,kubelet 会释放该 GPU 的分配记录,节点 Allocated resources 中 nvidia.com/gpu 应回到删除前的空闲值。若未回落,说明存在分配泄漏,需要检查 Device Plugin 与 kubelet 的通信状态。