环境
这次排查的环境是一套 AI 评测集群,节点运行时是 containerd,业务镜像包含 vLLM、CUDA runtime、评测 worker 和少量监控 sidecar。集群准备验证 Kubernetes v1.36 的工作负载感知调度能力,所以排查时同时看了 Job、PodGroup、DRA ResourceClaim 和常规 Pod 事件。
现象很明确:Pod 已经被调度到 GPU 节点,但业务容器没有启动,事件里反复出现:
text
Failed to pull image "vllm/vllm-openai:latest"
rpc error: code = DeadlineExceeded desc = context deadline exceeded
Back-off pulling image
这种场景不要只盯着 GPU。调度成功只代表资源被选中了,运行成功还取决于镜像、运行时、设备插件、模型目录和探针。
1. 先判断是调度问题还是运行问题
先看 Pod 是否已经落到节点:
bash
kubectl get pod -n ai-lab -owide
kubectl describe pod -n ai-lab eval-worker-0
kubectl get events -n ai-lab --sort-by=.lastTimestamp
如果还是 Pending,并且事件里有 Unschedulable、资源不足、拓扑约束不满足,再回到调度层。如果已经分配到节点,但卡在 Pulling、ImagePullBackOff、CreateContainerError,先进入运行层排查。
v1.36 的 Workload / PodGroup 相关能力主要解决成组调度、拓扑放置和整体抢占。它不会替你处理镜像下载失败。
2. 查看 PodGroup 和 Job 状态
如果启用了工作负载感知调度相关特性,可以检查对应对象:
bash
kubectl get job -n ai-lab
kubectl get podgroup -n ai-lab
kubectl describe podgroup -n ai-lab eval-workers-pg
重点看三件事:
minCount是否满足。- PodGroup 是否被整体调度。
- 是否还有拓扑或 ResourceClaim 相关事件。
如果 PodGroup 已经通过,继续看节点运行时。
3. 到目标节点直接拉镜像
到 Pod 所在节点执行:
bash
sudo crictl images | grep -E 'vllm|cuda|pause'
sudo crictl pull docker.1ms.run/vllm/vllm-openai:latest
sudo crictl pull nvcr.1ms.run/nvidia/cuda:12.4.1-runtime-ubuntu22.04
sudo crictl pull k8s.1ms.run/pause:3.10
AI 任务常见的坑是镜像来源分散:业务镜像来自 Docker Hub,CUDA runtime 来自 NVIDIA,pause 镜像来自 Kubernetes,监控组件可能来自 Quay。毫秒镜像(1ms.run)这种多源入口适合放在这一层做预检,先把镜像下载变量排掉。
如果 crictl pull 也失败,继续查 containerd 配置、DNS、代理和节点出网。如果节点上能拉通,而 Pod 仍然失败,再回到 ImagePullSecret、namespace、运行时配置和镜像引用格式。
4. 检查 containerd 与镜像配置
常用检查命令:
bash
sudo crictl info | jq '.config.containerd'
sudo journalctl -u containerd --since "30 min ago" --no-pager
sudo ctr -n k8s.io images ls | grep vllm
如果使用 1ms-helper,可在节点侧做统一配置和检测:
bash
curl -sSL https://static.1ms.run/1ms-helper/install.sh | bash
sudo 1ms-helper config:k8s
1ms-helper check
生产集群里建议先在测试节点验证,再批量改运行时配置。
5. 示例 Job 里保留可控镜像入口
示例:
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: eval-job
namespace: ai-lab
spec:
completionMode: Indexed
parallelism: 4
completions: 4
template:
spec:
restartPolicy: Never
containers:
- name: worker
image: docker.1ms.run/vllm/vllm-openai:latest
resources:
limits:
nvidia.com/gpu: "1"
如果镜像来自 NVIDIA:
yaml
image: nvcr.1ms.run/nvidia/cuda:12.4.1-runtime-ubuntu22.04
如果是 K8s 基础镜像:
yaml
image: k8s.1ms.run/pause:3.10
6. GPU 和模型目录最后验证
镜像拉通后,再看容器内设备和模型目录:
bash
kubectl exec -n ai-lab eval-worker-0 -- nvidia-smi
kubectl exec -n ai-lab eval-worker-0 -- ls -lh /models
kubectl logs -n ai-lab eval-worker-0 --tail=100
如果这里失败,才进入 GPU Operator、device plugin、PVC、权限和业务参数排查。
总结
K8s v1.36 的工作负载感知调度和 DRA 能力,让 AI/ML 任务的资源分配更接近真实需求。但排查启动失败时,仍然要把链路拆清楚:PodGroup 负责成组调度,DRA 负责设备资源,containerd 负责拉镜像,业务容器负责模型加载。
ImagePullBackOff 不要和 GPU 调度混在一起排。先到目标节点做镜像预检,通常能节省很多绕路时间。