首页 > Technology > 正文

K8s 大模型 Pod 反复被重启?Probe 排查

fenij 2026-08-25 43 Technology

在 Kubernetes 上跑大模型推理服务,Pod 动不动就重启,很多时候不是模型本身崩了,而是 Probe 配置太激进。模型加载要几分钟,一次推理可能几十秒,默认的 LivenessProbe 等不及就把容器杀了,形成无限重启循环。这种重启看起来像是应用不稳定,实际上是 K8s 在「好心办坏事」。

判断思路是先确认重启原因:kubectl describe pod 看 Events 是 OOMKilled 还是 Liveness probe failed;再看 previous 日志有没有 panic。如果是 Probe 误杀,调整参数比重构模型快得多。

三种 Probe 的分工

Probe 作用 大模型场景注意
startupProbe 判断容器是否已启动 给足模型加载时间,失败阈值要设大
readinessProbe 决定是否接收流量 应检查 /v1/models 等真实就绪接口
livenessProbe 决定是否重启容器 阈值必须大于 P99 推理耗时,否则误杀
⏱️
2-5min
DeepSeek-V4 模型加载时间
> P99
Liveness 总超时必须大于推理 P99
🔧
/health
liveness 别做真实推理

推荐 Probe 配置

startupProbe:
  httpGet:
    path: /health
    port: 8000
  initialDelaySeconds: 60
  periodSeconds: 15
  failureThreshold: 30   # 最长等 60+15*30=510s
livenessProbe:
  httpGet:
    path: /health
    port: 8000
  initialDelaySeconds: 0
  periodSeconds: 30
  timeoutSeconds: 5
  failureThreshold: 5    # 总超时 150s,必须 > P99 推理延迟
readinessProbe:
  httpGet:
    path: /v1/models
    port: 8000
  initialDelaySeconds: 10
  periodSeconds: 10
  failureThreshold: 3

关键点:liveness 的 periodSeconds × failureThreshold 要大于你的最长推理时间;readiness 用模型列表接口,确认模型已加载再放流量。

排查重启的真实原因

不要只看 Pod 在重启,要分清是谁杀的:

kubectl describe pod deepseek-v4-xxx | grep -A10 Events

如果看到 Liveness probe failed 后跟着 Killing,那就是 Probe 误杀。如果看到 OOMKilled,则是内存 / 显存不够,需要降 batch 或加资源。

再看 previous 容器日志,确认不是应用 panic:

kubectl logs deepseek-v4-xxx --previous --tail 100

资源限制与 HPA 陷阱

Probe 误杀之外,资源不足也是大模型 Pod 重启的常见原因。注意 GPU 显存不受 K8s memory limit 限制,需要单独监控:

# 查看 Pod 资源限制
kubectl describe pod deepseek-v4-xxx | grep -A5 "Limits"

# 查看节点 GPU 显存
kubectl exec -it deepseek-v4-xxx -- nvidia-smi

# 查看 DCGM 指标(需安装 dcgm-exporter)
kubectl top pod deepseek-v4-xxx

如果 kubectl describe pod 里显示 Last State: Terminated, Reason: OOMKilled,说明内存 limit 太小。注意大模型加载时先占 CPU 内存再迁 GPU,memory limit 要留足。

HPA 按 CPU/内存扩容对推理服务不敏感,建议用自定义指标(如请求队列长度或 GPU 利用率)来触发扩容,否则流量突增时扩容跟不上。

日志与监控建议

只靠 kubectl describe 不够,最好把关键指标接进 Prometheus:

  • 推理延迟 P50/P99(判断 liveness 阈值是否合理)
  • GPU 显存占用(防止 OOM)
  • Pod 重启次数(restart count)
  • 排队请求数(决定是否扩容)

应用日志里要打印模型加载完成事件,方便和 readiness 探针的 ready 时间对齐:

INFO  Model loaded in 187s, ready to serve
INFO  /v1/models returns 200

踩坑实录

我部署 vLLM 服务时,startupProbe 只给了 failureThreshold: 10,结果 A100 上模型加载到 85% 就被 kubelet 判定启动失败,Pod 反复重启。扩容到 failureThreshold: 30 后稳定。更坑的是 livenessProbe 默认 periodSeconds: 10, failureThreshold: 3,总超时 30 秒,而长文本生成 P99 latency 刚好 40 秒,推理中的请求还没返回就被杀了。改成 periodSeconds: 30, failureThreshold: 5 后,重启次数从每小时十几次降到 0。

常见问题

问:能不能干脆关掉 livenessProbe?
答:可以,但不推荐。如果服务真卡死,没有 liveness 就不会自动恢复。更好的做法是给它一个独立的 /health 端点,只做 TCP 或轻量 HTTP 检查,不触发推理。

问:startupProbe 和 readinessProbe 都要配吗?
答:慢启动服务建议都配。startupProbe 负责等加载完成,加载期间 readiness 失败不会导致重启;加载完成后 readiness 再决定流量。

问:GPU 显存 OOM 和 Probe 误杀怎么区分?
答:kubectl describe pod 里看 Last State。OOMKilled 的 reason 是 OOMKilled,Probe 误杀是 Error 或 Completed 且 Events 里有 Liveness probe failed。

如果你在 K8s 上跑大模型也遇到反复重启,欢迎在 fenij.com 留言,把 kubectl describe pod 的 Events 贴出来一起分析。

相关完整手册

系统化的排查与配置思路,建议顺手收藏这几篇完整手册: