在 Kubernetes 里排障,最怕的不是问题复杂,而是一上来就“凭感觉乱试”。真正高效的方式,是先把症状描述清楚,再缩小影响范围,沿着请求链路逐步验证,最后把结论沉淀成可复用的方法。Kubernetes 官方文档在调试运行中 Pod 时,也反复强调通过对象状态、事件、日志和容器内观测来交叉验证,而不是只盯着单个命令输出::cite[458]。
9.1.1 故障排查的基本步骤:现象、范围、路径、验证
可以把大多数问题都放进下面这 4 步框架:
| 步骤 | 要回答的问题 | 常见动作 |
|---|---|---|
| 现象 | 到底哪里“不对” | 确认报错、失败时间、影响接口、影响对象 |
| 范围 | 影响了谁、影响到什么程度 | 判断是单 Pod、单节点、单命名空间还是全局问题 |
| 路径 | 请求链路走到了哪一步 | 沿着用户请求或控制链路逐段检查 |
| 验证 | 你的判断是否能被证据证明 | 用事件、日志、配置、连通性测试交叉验证 |
第一步:先描述“现象”,不要急着下结论
很多人会说“Pod 挂了”“网络坏了”“节点炸了”,这些都不是现象,而是判断。现象应该尽量客观:
- 哪个服务不可用
- 返回的是超时、拒绝连接还是 5xx
- 从什么时候开始出现
- 是所有请求都失败,还是只有部分流量失败
- 变更发生在故障前还是故障后
例如,与其说“Service 有问题”,不如说:
payment服务在prod命名空间内访问超时- 仅集群内调用失败,Ingress 入口也返回 502
- 故障发生在 14:05 左右,14:00 刚发布过新版本
这样的描述,才便于后续缩小范围。
第二步:识别“范围”,先判断是局部还是系统性问题
排障的效率,很多时候取决于你是否足够早地回答了下面几个问题:
- 只有一个 Pod 异常,还是整个 Deployment 都异常?
- 只有一个节点上的工作负载受影响,还是跨节点普遍异常?
- 只有某个命名空间出问题,还是全局服务都异常?
- 只有应用层报错,还是控制面也无法访问?
这里推荐的第一组命令:
kubectl get pods -A
kubectl get pods -A -o wide
kubectl get deploy,statefulset,daemonset -A
kubectl get svc -A
kubectl get nodes
如果你发现异常 Pod 都集中在同一个节点,排查方向就会明显偏向节点侧;如果多个命名空间同时出现镜像拉取失败,那更像是镜像仓库、网络出口或凭据问题。
第三步:沿着“路径”排查,不要平面化地看问题
Kubernetes 问题通常不是孤立的。你要学会把故障放进一条路径里看:
- 请求是否到达入口
- 入口是否转发到 Service
- Service 是否关联到正确的 EndpointSlice
- 后端 Pod 是否 Ready
- Pod 内应用是否真的在监听目标端口
- 节点、容器运行时、网络插件是否工作正常
同样地,控制面问题也可以按路径拆解:
- YAML 是否正确提交到 API Server
- 对象是否成功创建
- Scheduler 是否完成调度
- kubelet 是否拉起容器
- Probe 是否通过
- 业务进程是否正常提供服务
第四步:做“验证”,让证据支持结论
经验丰富的工程师不会因为看到一条日志就立刻认定根因,而是会做交叉验证。
比如你怀疑是探针导致重启,至少要同时看到:
describe pod中存在 probe failure 相关事件logs --previous能看到容器在被重启前后的日志- 容器内健康检查命令复现失败
- 修复探针参数后,Pod 恢复稳定
只有这样,结论才足够可靠。
9.1.2 kubectl 常用排障命令体系
真正高频使用的排障命令,远没有想象中那么多。建议你按“看状态、看细节、看日志、进现场、做验证”来记忆。
1)看状态:先建立全局认知
kubectl get pods -A
kubectl get pods -n prod -o wide
kubectl get svc,endpointslices -n prod
kubectl get nodes
kubectl get events -A --sort-by='.metadata.creationTimestamp'
get 适合回答“现在谁异常”“异常分布在哪”“有哪些对象已经明显不对”。例如 Pod 生命周期里,Pending 表示 Pod 已被 API 接受但尚未完全运行,是否因为调度、镜像或初始化失败,需要继续往下看::cite[373]。
2)看细节:用 describe 把对象展开
kubectl describe pod web-7d8b6c9d8f-abcde -n prod
kubectl describe node worker-01
kubectl describe svc payment -n prod
kubectl describe ingress payment-gateway -n prod
describe 最重要的价值,不是“看配置”,而是同时看到:
- 对象基础信息
- 条件状态(Conditions)
- 调度信息
- 挂载信息
- 最近事件(Events)
很多问题只看 get 看不出来,但 describe 一下就很明显,比如:
FailedSchedulingBack-off restarting failed containerReadiness probe failedFailedMountFailedToPullImage
3)看日志:区分当前日志与上一次日志
Kubernetes v1.32 的 kubectl logs 仍然是最直接的容器输出查看方式,可用于单容器、多容器、上一次崩溃实例以及带标签聚合查看::cite[457]。
kubectl logs pod-name -n prod
kubectl logs pod-name -n prod -c app
kubectl logs pod-name -n prod --previous
kubectl logs -f deploy/payment -n prod --all-containers=true
kubectl logs -l app=payment -n prod --all-containers=true --prefix
几个经验要点:
- 容器不断重启时,优先看
--previous - 多容器 Pod 一定要指定
-c - 发布后批量异常时,用
-l按标签聚合更快 - 看日志前先确认时区和时间窗口
4)进现场:exec 与 debug
如果日志不足以解释问题,就需要进入容器或注入调试容器。Kubernetes v1.32 官方文档明确指出:当 kubectl exec 不够用,或者容器已经崩溃、镜像本身缺少调试工具时,可以使用 ephemeral container / kubectl debug 进行交互式排查::cite[458]。
kubectl exec -it pod-name -n prod -- /bin/sh
kubectl exec -it pod-name -n prod -c app -- env
kubectl exec pod-name -n prod -- cat /etc/resolv.conf
kubectl debug pod-name -n prod -it --image=busybox:1.36 --target=app
5)做验证:不要只“看”,还要“试”
kubectl exec -it pod-a -n prod -- nc -vz payment 8080
kubectl exec -it pod-a -n prod -- nslookup payment
kubectl exec -it pod-a -n prod -- wget -qO- http://payment:8080/healthz
kubectl exec -it pod-name -n prod -- ss -lntp
排障不是信息浏览,而是证据验证。你怀疑 DNS 异常,就做解析测试;你怀疑应用没监听端口,就进入容器看监听状态;你怀疑 Service 没有后端,就检查 EndpointSlice。
一张表记住常用排障命令
| 目标 | 推荐命令 | 主要用途 |
|---|---|---|
| 看对象概况 | kubectl get |
快速识别异常对象 |
| 看对象细节 | kubectl describe |
查看 Conditions、Events、调度与挂载信息 |
| 看容器输出 | kubectl logs |
分析启动失败、运行时报错、探针异常 |
| 进入容器 | kubectl exec |
查看环境变量、配置、网络、进程 |
| 注入调试容器 | kubectl debug |
处理 distroless、已崩溃或工具缺失场景 |
| 看服务端点 | kubectl get svc,endpointslices |
判断 Service 是否选到后端 |
| 看节点状态 | kubectl get/describe node |
查看 Ready、压力、污点与资源情况 |
| 看时间线 | kubectl get events |
关联故障触发顺序 |
9.1.3 describe、logs、events、exec 的组合打法
很多 Kubernetes 故障,最有效的方法不是单个命令,而是“四板斧联动”。
组合 1:Pod 起不来
kubectl get pod web-abcde -n prod
kubectl describe pod web-abcde -n prod
kubectl logs web-abcde -n prod --previous
kubectl get events -n prod --sort-by='.metadata.creationTimestamp'
这组命令适合:
- CrashLoopBackOff
- OOMKilled
- Probe 失败
- 镜像拉取失败
- 挂载失败
思路是:
get看状态describe看事件和容器状态logs --previous看上一次退出前日志events还原时间线
组合 2:Service 不通
官方的 Service 调试文档建议先确认 Pod 是否健康、是否监听正确端口,再检查 Service、后端端点与代理链路;必要时结合 kubectl logs 与 kubectl exec 进入 Pod 内部验证::cite[298]。
kubectl get svc payment -n prod
kubectl describe svc payment -n prod
kubectl get endpointslices -n prod -l kubernetes.io/service-name=payment
kubectl get pods -n prod -l app=payment -o wide
kubectl logs -n prod -l app=payment --all-containers=true
kubectl exec -it client-pod -n prod -- wget -S -O- http://payment:8080/healthz
组合 3:DNS / 网络问题
kubectl get pods -n kube-system
kubectl logs -n kube-system -l k8s-app=kube-dns
kubectl exec -it client-pod -n prod -- cat /etc/resolv.conf
kubectl exec -it client-pod -n prod -- nslookup kubernetes.default
kubectl exec -it client-pod -n prod -- nc -vz payment.prod.svc.cluster.local 8080
DNS 调试官方文档的核心建议,就是先验证测试 Pod 的解析行为,再确认 DNS Pod 是否运行、DNS Service 是否存在,以及容器内 /etc/resolv.conf 是否符合预期::cite[285]。
组合 4:容器里看不见问题时,升级到 debug
如果应用镜像是 distroless,exec 进去也没有 curl、ps、ss 等工具,这时不要硬扛,直接切到 kubectl debug:
kubectl debug pod-name -n prod -it --image=nicolaka/netshoot --target=app
然后再执行:
ip addr
ip route
nslookup payment
curl -v http://payment:8080/healthz
ss -lntp
9.1.4 如何建立一套可复用的排障思维框架
一个成熟的排障思维框架,至少要具备 3 个特点:
- 先事实,后判断:先记录现象,再提出假设
- 先范围,后深入:先判断影响面,再决定排查深度
- 先链路,后组件:不要按组件背命令,要按请求路径定位
一个推荐的排障模板
你可以把下面这份模板直接当成值班时的排障记录卡片:
## 故障标题
- 时间:
- 发现方式:用户反馈 / 告警 / 巡检
- 影响范围:
- 业务症状:
## 初步判断
- 最近变更:
- 首个异常对象:
- 是否集中在某节点 / 某命名空间 / 某服务:
## 排查路径
1. 对象状态:
2. 事件时间线:
3. 容器日志:
4. 容器内验证:
5. 网络 / 存储 / 权限 / 节点侧检查:
## 结论
- 根因:
- 证据:
- 临时止血动作:
- 长期改进项:
建议形成固定的“问题分类法”
日常排障时,可以把问题先粗分成 5 类:
- 调度类:Pending、FailedScheduling、亲和性 / 污点 / 资源不足
- 运行类:CrashLoopBackOff、OOMKilled、Probe 失败
- 网络类:DNS、Service、NetworkPolicy、Ingress、CNI
- 节点类:NotReady、磁盘压力、容器运行时异常、kubelet 异常
- 变更类:配置错误、镜像问题、权限变更、证书过期
这样你看到问题时,不会无从下手,而是能快速落到对应的命令组合和检查清单上。
把排障能力从“个人经验”变成“团队资产”
真正高水平的团队,不是依赖某个同学“经验丰富”,而是把经验沉淀成:
- 标准排障 SOP
- 常见故障检查表
- 故障案例库
- 复盘模板
- 发布前检查项
当这些东西逐步完善后,你会发现排障越来越像“有章可循的工程活动”,而不是“靠运气猜”。
本章小结
本章最重要的,不是多记几个命令,而是建立一套稳定的方法论:
- 先看现象,避免先入为主
- 再看范围,判断是局部故障还是系统性故障
- 沿着链路逐步拆解,而不是随意跳点
- 使用
get + describe + logs + events + exec/debug形成组合打法 - 每次排障结束后,把经验沉淀为模板和检查表
当你掌握这套方法后,后面无论是 Pod 异常、网络故障,还是节点问题,都会更容易定位。
📝 版权声明:本文为原创技术博客,转载请注明出处。
如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!