你是不是也遇到过这样的情况:想删除一个 Pod,结果它一直卡在 Terminating 状态,怎么也删不掉?最后只能用 --force 强制删除。今天我们聊聊 Pod 优雅终止的完整流程,以及它卡住的 6 种真正原因。
01Pod 优雅终止流程
在 Kubernetes 中删除 Pod 时,API Server 先给 Pod 打上 deletionTimestamp 标记,置为 Terminating 状态。
然后 kubelet 会并行执行两个操作:从 Service 的 Endpoint 中移除 Pod IP,确保流量不再转发过来;同时开始终止容器。
容器终止流程:如果有 preStop 钩子先执行,然后发送 SIGTERM 信号给主进程,等待最多 30 秒(默认terminationGracePeriodSeconds),如果进程没退出,就发 SIGKILL 强制结束。最后清理资源,Pod 才从 API Server 消失。
02六种常见原因
Pod 卡在 Terminating 状态,通常由以下 6 种原因导致:
1. Finalizers 阻塞最常见的卡住原因。有些控制器或扩展组件在 Pod 的 metadata.finalizers 字段添加自己的清理逻辑。如果这些 finalizers 没正确清理,Pod 就会一直卡在 Terminating 状态。
# 查看卡住的 Pod
kubectl get pods -A --field-selector status.phase=Terminating
# 强制移除 finalizers
kubectl patch pod <pod-name> -p '{"metadata":{"finalizers":null}}'
2. 存储卷未解绑如果 Pod 使用了 PersistentVolume,删除时可能遇到存储卷无法正常卸载的问题。这通常是因为节点上的 kubelet 无法与存储后端通信,或者有进程还在使用这个挂载点。
3. preStop 钩子阻塞preStop 钩子本是为了让应用优雅关闭,但如果它出了问题,反而会成为关闭障碍。比如 preStop 脚本里有死循环、依赖外部服务但网络不通、或者执行时间超过了 terminationGracePeriodSeconds。
# 预防配置示例
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
terminationGracePeriodSeconds: 60
containers:
- name: app
image: myapp:latest
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "echo '正在优雅关闭...'; sleep 10"]
4. 进程不响应 SIGTERM有些应用没正确处理 SIGTERM 信号,收到信号后不退出。这种情况在自定义的 init 进程或者某些老旧软件中比较常见。应用开发者需要确保应用能正确处理终止信号。
5. 节点故障如果节点本身出了问题,比如 kubelet 进程崩溃、节点网络断开、或者节点资源耗尽,Pod 的终止流程就无法正常进行。这时候 Pod 会一直卡住,直到节点恢复或者强制删除。
6. 控制器未处理Deployment 或 StatefulSet 等控制器在缩容时,需要先处理完 Pod 的终止流程,才能继续下一步。如果控制器的协调循环出了问题,或者有其他资源依赖,也可能导致 Pod 卡住。
03排查与解决
遇到 Pod 卡在 Terminating 时,可以这样排查:
1.先看看是不是 finalizers 的问题
2.检查 preStop 钩子是否正常
3.确认节点状态是否健康
4.查看存储卷是否能正常卸载实在解决不了,就强制删除:
kubectl delete pod <pod-name> --grace-period=0 --gate
但要小心,强制删除可能会留下一些"孤儿"资源,需要手动清理。
04最佳实践
为了避免这些问题:
1.合理设置 terminationGracePeriodSeconds,给应用足够的关闭时间
2.确保 preStop 钩子简单可靠,不做复杂操作
3.应用要正确处理 SIGTERM 信号
4.定期检查集群健康状态
Pod 优雅终止是 Kubernetes 中看似简单实则复杂的过程。理解它的工作原理,知道可能出问题的地方,能帮你更快定位和解决问题。下次再遇到 Pod 删不掉的情况,按上面的思路排查一下。
作者介绍:
我是老卢,一个在运维领域摸爬滚打了七年的90后,专注 k8s、DevOps、云原生、AIOps 技术。白天搬砖踩坑,晚上码字分享。相信技术改变生活,坚持输出有温度的文章。