4、Pod故障场景:OOM Killer、GPU驱动崩溃、容器进程挂死,如何通过Probe检测
说实话,vLLM推理服务最让人头疼的,不是流量大了扛不住,而是Pod莫名其妙就挂了。你查日志,发现是OOM;你重启,发现GPU驱动报错;你盯着看,进程还在但就是不响应请求。这三种情况,我全踩过坑。
今天咱们就聊聊,怎么用Probe把这三种故障都揪出来。
4.1 OOM Killer:内存杀手怎么防?
OOM Killer,说白了就是Linux内核的"杀人机制"。当系统内存不够时,内核会挑一个进程杀掉。vLLM这种吃显存大户,特别容易中招。
我遇到过最惨的一次,是模型加载时显存估算失误,Pod直接被OOM Kill了。K8s检测到Pod退出,自动重启,结果重启后还是OOM,陷入死循环。
怎么检测?用livenessProbe配合exec命令,检查进程是否还活着:
livenessProbe:
exec:
command:
- cat
- /proc/1/status
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
但说实话,这招只能检测进程是否存活。OOM Kill后进程直接没了,K8s自己就能感知到Pod状态变化。真正要防的是即将发生的OOM。
readinessProbe失败,让K8s先把流量切走,再优雅缩容或扩容。
4.2 GPU驱动崩溃:无声的杀手
GPU驱动崩溃,比OOM更隐蔽。进程还在,Pod状态还是Running,但推理请求全部超时。你查kubectl logs,啥也没有;查nvidia-smi,报错说驱动挂了。
为什么会这样?因为GPU驱动是内核模块,它崩溃了,用户态的vLLM进程感知不到。K8s只看进程是否存活,所以Pod一直显示Running。
我建议用livenessProbe配合nvidia-smi命令来检测:
livenessProbe:
exec:
command:
- nvidia-smi
- --query-gpu=index,name,temperature.gpu,utilization.gpu,memory.used,memory.total
- --format=csv,noheader
initialDelaySeconds: 15
periodSeconds: 30
failureThreshold: 2
这个Probe每隔30秒跑一次nvidia-smi。如果驱动崩溃,命令会返回非零退出码,Probe失败,K8s就会重启Pod。
nvidia-smi会卡住(比如驱动半死不活的状态),导致Probe超时。建议设置timeoutSeconds: 10,避免Probe本身成为性能瓶颈。
4.3 容器进程挂死:最头疼的情况
进程挂死,比前两种都难搞。进程在,端口在,但就是不干活。你发请求,它不响应;你查日志,最后一行停在半小时前。
我遇到过vLLM的推理线程死锁,所有请求都卡在队列里。Pod状态正常,但业务方疯狂报警。
这种场景,livenessProbe和readinessProbe都得用上:
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
periodSeconds: 15
failureThreshold: 3
这里的关键是/health端点。vLLM默认提供这个接口,但只检查进程是否活着。我建议你自定义一个健康检查接口,做更深层的检测:
- 检查推理队列长度是否超过阈值
- 检查最近一次推理是否超时
- 检查GPU显存是否泄漏
说白了,就是让Probe去问vLLM:"你还好吗?能干活吗?"而不是只问:"你还活着吗?"
4.4 三种场景的Probe策略对比
| 故障场景 | 推荐Probe类型 | 检测方式 | 关键参数 |
|---|---|---|---|
| OOM Killer | livenessProbe + readinessProbe | 内存使用率监控 + 进程存活检查 | initialDelaySeconds: 30, periodSeconds: 10 |
| GPU驱动崩溃 | livenessProbe | nvidia-smi命令执行 | periodSeconds: 30, failureThreshold: 2, timeoutSeconds: 10 |
| 容器进程挂死 | livenessProbe + readinessProbe | HTTP健康检查 + 自定义深度检测 | periodSeconds: 5 (readiness), 15 (liveness) |
4.5 实战避坑指南
我曾经踩过一个坑:把livenessProbe和readinessProbe的检测逻辑写得太重,导致Probe本身占用了大量CPU。vLLM推理本来就吃资源,Probe再一抢,推理延迟直接飙升。
我的建议是:
- Probe的检测逻辑要轻量,别在里面跑模型推理
- 用
initialDelaySeconds给Pod足够的启动时间,vLLM加载模型可能要几分钟 failureThreshold别设太小,避免网络抖动导致误杀- 日志里记录Probe的检测结果,方便排查问题
4.6 知识体系图
下面这张图,把三种故障场景和对应的Probe策略串起来了。你一看就明白:
嗯,这张图把三种故障和对应的Probe策略都串起来了。你对照着看,应该能快速定位问题。
最后说一句:Probe配置好了,不等于万事大吉。我建议你定期做混沌工程实验,主动注入故障,验证Probe是否真的能检测到。别等到线上出问题了,才发现Probe配置错了。