Kubernetes 故障排查实战手册:从 Pod 异常定位到生产级稳定性治理
Kubernetes 故障排查实战手册:从 Pod 异常定位到生产级稳定性治理
核心目标:不只会“查 Pod”,而是建立一套可复制、可扩展、适用于高并发生产环境的 Kubernetes 故障定位与治理体系。
一、为什么很多团队会卡在 Kubernetes 故障排查上
多数团队第一次系统性接触 Kubernetes 故障,往往来自一次线上事故:
- 大促流量上涨后,订单服务频繁重启
- 新版本发布后,部分 Pod 长时间
Pending - 节点资源明明看起来还有富余,应用却反复
OOMKilled Running状态的 Pod 仍然无法对外提供服务- Service、Ingress、容器日志都看了,依然无法快速定位根因
问题的本质在于,Kubernetes 并不是一个单机进程管理器,而是一个分布式控制系统。一个 Pod 的“异常表现”,背后可能横跨多个层面:
- 控制面:
apiserver、scheduler、controller-manager - 节点面:
kubelet、容器运行时containerd/CRI-O - 网络面:CNI、CoreDNS、kube-proxy、Service、Ingress
- 存储面:CSI、PVC/PV、卷挂载
- 应用面:启动参数、线程池、连接池、GC、依赖服务
- 治理面:资源配额、探针配置、HPA、PDB、告警与变更流程
因此,生产级排查不应停留在“背几个命令”,而要形成完整方法论:
- 先判断故障发生在哪一层
- 再沿着 Pod 生命周期定位在哪一个阶段失败
- 用证据链锁定根因,而不是凭经验猜
- 最后把单次事故沉淀为长期治理能力
本文将围绕这个方法论展开。
二、先建立认知底座:Pod 故障到底是怎么产生的
2.1 Pod 不是“容器”,而是一个多组件协同结果
Pod 从提交到可用,至少经历以下链路:
所以 Pod 异常,本质上是在这条链路的某个环节失败。常见映射关系如下:
| 故障表象 | 高概率问题层 |
|---|---|
Pending | 调度、资源、PVC、节点约束 |
ContainerCreating | 镜像、卷挂载、CNI、运行时 |
ImagePullBackOff | 仓库认证、Tag、网络、证书 |
CrashLoopBackOff | 应用启动失败、配置错误、依赖未就绪、探针误杀 |
OOMKilled | 内存限制过小、堆外内存、缓存失控、请求洪峰 |
Running 但不可用 | Readiness 失败、线程池耗尽、下游阻塞、网络故障 |
Terminating 卡住 | Finalizer、preStop、卷卸载、节点异常 |
2.2 Pod 生命周期与排查切入点
一个 Pod 排查,建议始终按生命周期切:
PendingScheduledContainerCreatingRunning but Not ReadyCrash / Restart / OOMTerminating / Evicted / Unknown
只要阶段判断正确,排查范围会立刻收敛。
2.3 为什么 Running 不等于“服务可用”
这是 Kubernetes 初学者最容易踩的坑之一。
Running只表示容器进程已启动Ready才表示 Pod 已加入负载转发- 即使
Ready=true,应用也可能因为线程池打满、数据库连接池耗尽、依赖超时而“假活着”
因此,线上可用性判断至少要同时观察:
- Pod Phase
- Container State
- Readiness 状态
- Service Endpoint 是否包含该 Pod
- 应用级指标:QPS、错误率、P99、线程池、连接池、GC
三、生产级排查原则:先定层,再定点,最后定根因
3.1 先分层,不要一上来就进容器
很多值班事故中,工程师第一反应是:
kubectl logs <pod> kubectl exec -it <pod> -- sh这不一定错,但经常太早。更高效的顺序应该是:
第一步:看“广度”
kubectl get pod -A -o wide kubectl get events -A --sort-by=.lastTimestamp kubectl top pod -A kubectl top node先确认:
- 是单 Pod 问题,还是整批 Pod 问题
- 是单节点问题,还是整集群问题
- 是当前版本问题,还是历史版本也受影响
- 是资源问题,还是网络/配置/镜像问题
第二步:看“归属”
kubectl describe pod <pod> -n <ns> kubectl get pod <pod> -n <ns> -o yaml重点不是看全文,而是抓四类证据:
EventsState / Last StateRestart CountConditions
第三步:看“现场”
kubectl logs <pod> -n <ns> --previous kubectl logs <pod> -n <ns> -c <container> --tail=200 kubectl exec -it <pod> -n <ns> -- sh日志、配置、环境变量、DNS、端口、文件系统、连接状态,都属于现场证据。
3.2 一条实用故障定位链
推荐把每次 Pod 故障都压缩成下面这条诊断链:
状态 -> 事件 -> 上一次退出原因 -> 日志 -> 配置 -> 依赖 -> 节点 -> 集群治理规则
例如:
- 状态:
CrashLoopBackOff - 事件:探针失败,kubelet 重启容器
- 上一次退出原因:ExitCode=137
- 日志:启动期 Full GC,堆外内存上涨
- 配置:
memory limit=512Mi,JVM-Xmx=512m - 依赖:Redis 慢响应导致缓存预热堆积
- 节点:无异常
- 治理规则:探针太激进,资源参数不合理
这样定位出来的结论,不是“Pod 挂了”,而是“启动期探针误杀 + 内存配置不匹配 + 缓存预热策略激进”。
四、核心工具链:生产环境真正高频使用的命令
4.1 快速总览命令
kubectl get pods -A -o wide kubectl get pods -n prod --sort-by=.status.startTime kubectl get events -A --sort-by=.lastTimestamp kubectl top pod -A kubectl top node kubectl get endpoints -n prod kubectl get pvc -A高频用途:
get pods -o wide:看是否集中在某个节点events:看调度失败、镜像失败、探针失败、卷挂载失败top:看资源是否异常陡升endpoints:看 Pod 是否真的进了 Service
4.2 描述类命令
kubectl describe pod <pod> -n <ns> kubectl describe node <node> kubectl describe pvc <pvc> -n <ns> kubectl describe deploy <deploy> -n <ns>describe 的价值在于事件串联,而不是 YAML 漂亮与否。
4.3 日志类命令
kubectl logs <pod> -n <ns> --tail=200 kubectl logs <pod> -n <ns> --previous kubectl logs <pod> -n <