K8s GPU 推理服务 ImagePullBackOff 排查与预热

一、环境和问题

这次记录一个 GPU 推理服务扩容时遇到的启动问题。

环境大致如下:

项目 内容
编排 Kubernetes
节点运行时 containerd
推理服务 vLLM OpenAI API
GPU 节点 新增节点池
现象 Pod 已调度,但容器一直没有 Running

先看 Pod 状态:

bash 复制代码
kubectl get pod -n inference -o wide
text 复制代码
infer-api-7fdbb8c9d9-q2p6x   0/1   ContainerCreating   gpu-node-08

继续看事件:

bash 复制代码
kubectl describe pod infer-api-7fdbb8c9d9-q2p6x -n inference
text 复制代码
Pulling image "vllm/vllm-openai:latest"
Failed to pull image: context deadline exceeded
Warning  Failed  kubelet  Error: ErrImagePull
Warning  Failed  kubelet  Error: ImagePullBackOff

这里不要直接排查模型文件和推理参数。Pod 还没进入运行阶段,当前问题在镜像拉取。

二、先把启动链路拆开

GPU 推理服务启动可以拆成四段:

阶段 检查点 常见命令
调度 Pod 是否落到 GPU 节点 kubectl get pod -o wide
镜像 镜像是否能拉取 kubectl describe podcrictl pull
运行时 NVIDIA runtime、device plugin、RuntimeClass kubectl describe node
推理 模型加载、接口健康检查、batch 参数 kubectl logs

如果事件里已经出现 ImagePullBackOff,优先处理第二段。

三、整理镜像来源

推理服务通常不只有业务镜像,还会包含 CUDA、监控、K8s 基础组件和 initContainer。可以先把 Deployment / Helm values 里的镜像列出来:

bash 复制代码
kubectl get deploy infer-api -n inference -o jsonpath="{..image}"

按来源分组后,做一次预检:

bash 复制代码
docker pull docker.1ms.run/vllm/vllm-openai:latest
docker pull nvcr.1ms.run/nvidia/cuda:12.4.1-runtime-ubuntu22.04
docker pull quay.1ms.run/prometheus/prometheus:latest
docker pull k8s.1ms.run/pause:3.10

毫秒镜像(1ms.run)在这里解决的是多源镜像入口和拉取稳定性问题。它不参与 GPU 调度,也不改变 vLLM 的推理行为。

这一步通过后,至少说明 Docker Hub、NVIDIA、Quay、K8s 这些来源的基础镜像链路可以先过。

四、containerd 节点上用 crictl 验证

Kubernetes 节点实际由 containerd 拉镜像,所以建议在目标节点上再执行:

bash 复制代码
crictl pull docker.1ms.run/vllm/vllm-openai:latest
crictl pull nvcr.1ms.run/nvidia/cuda:12.4.1-runtime-ubuntu22.04
crictl pull quay.1ms.run/prometheus/prometheus:latest
crictl pull k8s.1ms.run/pause:3.10

查看本地缓存:

bash 复制代码
crictl images | grep -E "vllm|cuda|prometheus|pause"

如果这里失败,Deployment 扩容后仍然大概率进入 ImagePullBackOff

如果这里通过,再继续看:

bash 复制代码
kubectl describe node gpu-node-08
kubectl get events -n inference --sort-by=.lastTimestamp
kubectl logs -n inference deploy/infer-api

五、预热前后对比

这次调整后,我把镜像预热放到了扩容前:

项目 预热前 预热后
新节点首次扩容 Pod 卡在 ContainerCreating 镜像阶段提前验证
排查方向 模型、GPU、网络混在一起看 先排除镜像拉取
回滚演练 新节点仍可能首次拉镜像 关键镜像已有缓存
值班处理 看到 ImagePullBackOff 才介入 发布前暴露镜像来源问题

这个对比不是为了证明推理更快,而是为了让问题边界更明确。

六、DaemonSet 预热示例

GPU 节点多的时候,可以用一个临时 DaemonSet 触发预热。示例只演示思路,生产环境建议固定 tag 或 digest。

yaml 复制代码
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: gpu-image-prewarm
  namespace: ops
spec:
  selector:
    matchLabels:
      app: gpu-image-prewarm
  template:
    metadata:
      labels:
        app: gpu-image-prewarm
    spec:
      nodeSelector:
        accelerator: nvidia
      tolerations:
        - operator: Exists
      initContainers:
        - name: pull-vllm
          image: docker.1ms.run/vllm/vllm-openai:latest
          command: ["sh", "-c", "python -V || true"]
        - name: pull-cuda
          image: nvcr.1ms.run/nvidia/cuda:12.4.1-runtime-ubuntu22.04
          command: ["sh", "-c", "nvidia-smi || true"]
        - name: pull-metrics
          image: quay.1ms.run/prometheus/prometheus:latest
          command: ["sh", "-c", "prometheus --version || true"]
      containers:
        - name: hold
          image: k8s.1ms.run/pause:3.10

部署和观察:

bash 复制代码
kubectl apply -f gpu-image-prewarm.yaml
kubectl rollout status daemonset/gpu-image-prewarm -n ops
kubectl get pod -n ops -o wide

预热完成后,再进行推理服务扩容。

七、排查顺序

遇到 GPU 推理服务启动失败,可以按下面顺序排查:

  1. kubectl get pod -o wide 确认 Pod 是否已经调度到 GPU 节点。
  2. kubectl describe pod 查看是否是 ErrImagePullImagePullBackOff
  3. 按来源整理镜像,先做 docker pull 预检。
  4. 在目标节点上用 crictl pull 复现真实拉取路径。
  5. 镜像阶段通过后,再看 RuntimeClass、GPU device plugin、模型目录和应用日志。
  6. 生产发布前固定 tag 或 digest,不要长期依赖 latest

八、总结

GPU 推理服务冷启动慢,不一定是模型慢,也不一定是调度慢。

如果 Pod 已经调度到 GPU 节点,但事件里反复出现 Pulling imagecontext deadline exceededImagePullBackOff,先把镜像阶段拆出来处理。

镜像预热解决的是启动链路最前面的不确定性。先让 Docker Hub、NVIDIA、Quay、K8s 这些来源的镜像稳定通过,再排查 GPU 运行时和推理参数,问题会清楚很多。

相关推荐
吴爃2 小时前
Spring Boot 项目在 K8S 中的打包、部署与运维发布实践
运维·spring boot·kubernetes
人工智能培训4 小时前
工程科研中的AI应用:结构力学分析技巧
人工智能·深度学习·机器学习·docker·容器
子木HAPPY阳VIP4 小时前
信创UOS,Docker 完整操作部署(Dockerfile部署方式)&排错整合
linux·运维·redis·nginx·docker·容器·tomcat
The Straggling Crow4 小时前
Monitoring 2026-04-30
kubernetes
AOwhisky5 小时前
Kubernetes调度与服务暴露:从“定时任务”到“服务发现”的完全指南
linux·运维·云原生·容器·kubernetes·服务发现
Cyber4K5 小时前
【Kubernetes专项】温故而知新,重温技术原理(6)
云原生·容器·kubernetes
叶总没有会6 小时前
Docker:项目部署
运维·docker·容器
爱学习 爱分享6 小时前
docker 本地装瀚高 4.5 数据库
数据库·docker·容器
ZStack开发者社区6 小时前
ZStack dGPU:让虚拟机里的 GPU 也能按需切分
云计算·gpu算力