Kubernetes GPU Deployment 没有空闲 GPU 时如何快速重启所有 Pod
Kubernetes GPU Deployment 没有空闲 GPU 时如何快速重启所有 Pod
环境和问题
环境假设:
- Kubernetes 集群
- Deployment 里的 Pod 申请 GPU,例如
nvidia.com/gpu: 1 - 集群里没有空闲 GPU
- 目标是快速重启这个 Deployment 下面的所有 Pod
这个场景里最容易踩的坑是:直接执行默认的 rollout restart 后,新 Pod 先被创建出来,但因为没有空闲 GPU 一直 Pending,旧 Pod 又还占着 GPU,结果整个重启卡住

先拿到 Deployment 的 selector
不要凭感觉手写 label。先从 Deployment 里确认它实际使用的 selector:
NS=<namespace>
DEPLOY=<deployment-name>
kubectl get deployment -n "$NS" "$DEPLOY" -o jsonpath='{.spec.selector.matchLabels}'
echo
如果输出类似:
{"app":"gpu-worker"}
后面就可以用:
kubectl get pod -n "$NS" -l app=gpu-worker
确认会命中目标 Pod:
kubectl get pod -n "$NS" -l app=gpu-worker -o wide
方法 1: 最快,直接删除 Deployment 下面的 Pod
如果可以接受这批 Pod 短暂不可用,最快方式是直接删 Pod,让 ReplicaSet 自动重建:
kubectl delete pod -n "$NS" -l app=gpu-worker
这个动作的效果是:
- 旧 Pod 被删除
- GPU 资源释放
- Deployment/ReplicaSet 自动创建新 Pod
- 新 Pod 重新申请 GPU 并调度
观察重建过程:
kubectl get pod -n "$NS" -l app=gpu-worker -w
如果只是想重启某一个 Pod,也可以指定 Pod 名:
kubectl delete pod -n "$NS" <pod-name>
方法 2: 更稳,让滚动更新先释放 GPU 再创建新 Pod
如果这是线上服务,不希望一次性删掉所有副本,建议先调整滚动策略:
kubectl patch deployment -n "$NS" "$DEPLOY" -p '{
"spec": {
"strategy": {
"type": "RollingUpdate",
"rollingUpdate": {
"maxSurge": 0,
"maxUnavailable": 1
}
}
}
}'
然后再重启:
kubectl rollout restart deployment -n "$NS" "$DEPLOY"
kubectl rollout status deployment -n "$NS" "$DEPLOY"
这里的关键是:
maxSurge=0:不允许额外多创建 PodmaxUnavailable=1:允许先停 1 个旧 Pod
这样可以先释放旧 Pod 占用的 GPU,再让新 Pod 调度起来
这段 patch 每个字段是什么意思
这条命令本质上是在修改 Deployment 的滚动更新策略:
kubectl patch deployment -n "$NS" "$DEPLOY" -p '{
"spec": {
"strategy": {
"type": "RollingUpdate",
"rollingUpdate": {
"maxSurge": 0,
"maxUnavailable": 1
}
}
}
}'
逐项解释:
kubectl patch deployment:修改某个 Deployment 的配置-n "$NS":指定 namespace"$DEPLOY":指定 Deployment 名称strategy.type=RollingUpdate:继续使用滚动更新,不是一次性全部停掉maxSurge=0:更新过程中不允许额外多创建 PodmaxUnavailable=1:更新过程中允许最多 1 个 Pod 不可用
对普通无状态服务来说,默认滚动更新通常没问题。但 GPU 满载时,默认策略可能会先创建一个新 Pod,新 Pod 需要 GPU,集群又没有空闲 GPU,于是新 Pod 一直 Pending
假设 Deployment 有 3 个 Pod,每个 Pod 用 1 张 GPU,集群刚好只有 3 张 GPU。默认策略可能变成:
先起第 4 个 Pod -> 没有 GPU -> Pending -> 旧 Pod 还占着 GPU -> 更新卡住
改成 maxSurge=0,maxUnavailable=1 后,更新顺序变成:
先停 1 个旧 Pod -> 释放 1 张 GPU -> 起 1 个新 Pod -> 新 Pod Running -> 再处理下一个
所以这段配置的核心价值是:在没有空闲 GPU 的情况下,强制 Kubernetes 先释放旧 Pod 的 GPU,再创建新 Pod,避免默认滚动更新卡在 Pending

方法 3: 全部停掉再重建
如果你明确希望所有旧 Pod 先全部退出,再统一重建,可以把策略改成 Recreate:
kubectl patch deployment -n "$NS" "$DEPLOY" -p '{
"spec": {
"strategy": {
"type": "Recreate"
}
}
}'
再执行:
kubectl rollout restart deployment -n "$NS" "$DEPLOY"
kubectl rollout status deployment -n "$NS" "$DEPLOY"
这个方案比直接删 Pod 更有 Deployment 语义,但会造成这组副本整体短暂不可用
不建议默认使用 force delete
如果 Pod 正常退出,不要一上来就用 --force --grace-period=0
只有在 Pod 长时间卡在 Terminating,并且确认可以强制清理时,才考虑:
kubectl delete pod -n "$NS" -l app=gpu-worker --grace-period=0 --force
风险是:Kubernetes 会从 API 层面立刻删除对象,但节点上的进程不一定已经优雅退出。对 GPU 任务来说,这可能导致任务中断、显存释放延迟或日志不完整
为什么默认 rollout restart 容易卡住
默认 Deployment 策略通常允许 maxSurge,也就是先多起一个新 Pod,再逐步替换旧 Pod
普通 CPU/内存服务通常没问题,因为集群可能还有余量。但 GPU 是离散资源,没有空闲 GPU 时,新 Pod 无法调度:
0/10 nodes are available: insufficient nvidia.com/gpu
这时旧 Pod 还在 Running,新 Pod 一直 Pending,看起来像是重启没反应。根因不是 Deployment 不工作,而是新旧 Pod 的资源交接顺序不适合 GPU 满载场景
快速参考
最快重启,接受短暂不可用:
kubectl delete pod -n "$NS" -l app=gpu-worker
线上更稳的滚动重启:
kubectl patch deployment -n "$NS" "$DEPLOY" -p '{
"spec": {
"strategy": {
"type": "RollingUpdate",
"rollingUpdate": {
"maxSurge": 0,
"maxUnavailable": 1
}
}
}
}'
kubectl rollout restart deployment -n "$NS" "$DEPLOY"
kubectl rollout status deployment -n "$NS" "$DEPLOY"
全部停掉再重建:
kubectl patch deployment -n "$NS" "$DEPLOY" -p '{
"spec": {
"strategy": {
"type": "Recreate"
}
}
}'
kubectl rollout restart deployment -n "$NS" "$DEPLOY"
核心判断:
- 没有空闲 GPU 时,不要直接依赖默认滚动更新
- 想最快,删 Pod
- 想稳一点,用
maxSurge=0,maxUnavailable=1 - 想全量重建,用
Recreate --force --grace-period=0只作为 Pod 卡死时的兜底手段

浙公网安备 33010602011771号