返回首页

9.1 排查方法论与工具

在 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 问题通常不是孤立的。你要学会把故障放进一条路径里看:

  1. 请求是否到达入口
  2. 入口是否转发到 Service
  3. Service 是否关联到正确的 EndpointSlice
  4. 后端 Pod 是否 Ready
  5. Pod 内应用是否真的在监听目标端口
  6. 节点、容器运行时、网络插件是否工作正常

同样地,控制面问题也可以按路径拆解:

  1. YAML 是否正确提交到 API Server
  2. 对象是否成功创建
  3. Scheduler 是否完成调度
  4. kubelet 是否拉起容器
  5. Probe 是否通过
  6. 业务进程是否正常提供服务

第四步:做“验证”,让证据支持结论

经验丰富的工程师不会因为看到一条日志就立刻认定根因,而是会做交叉验证。

比如你怀疑是探针导致重启,至少要同时看到:

  • 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 一下就很明显,比如:

  • FailedScheduling
  • Back-off restarting failed container
  • Readiness probe failed
  • FailedMount
  • FailedToPullImage

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 失败
  • 镜像拉取失败
  • 挂载失败

思路是:

  1. get 看状态
  2. describe 看事件和容器状态
  3. logs --previous 看上一次退出前日志
  4. events 还原时间线

组合 2:Service 不通

官方的 Service 调试文档建议先确认 Pod 是否健康、是否监听正确端口,再检查 Service、后端端点与代理链路;必要时结合 kubectl logskubectl 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 进去也没有 curlpsss 等工具,这时不要硬扛,直接切到 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. 先链路,后组件:不要按组件背命令,要按请求路径定位

一个推荐的排障模板

你可以把下面这份模板直接当成值班时的排障记录卡片:

## 故障标题
- 时间:
- 发现方式:用户反馈 / 告警 / 巡检
- 影响范围:
- 业务症状:

## 初步判断
- 最近变更:
- 首个异常对象:
- 是否集中在某节点 / 某命名空间 / 某服务:

## 排查路径
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 异常、网络故障,还是节点问题,都会更容易定位。


📝 版权声明:本文为原创技术博客,转载请注明出处。

如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!

上一篇

8.1 Operator 模式与 CRD 开发(Go + kubebuilder)

下一篇

9.5 实战故障复盘