故障排查学习路径:从方法论到系统、网络、数据库与 K8s

使用方式

排障能力不是“知道更多命令”,而是“用最小代价排除最大范围”。这条路径先建立方法,再按系统、网络、数据与编排分层练习。

四个阶段按依赖顺序排列,每个阶段建议留 2–4 小时:

每道故障题都要留下三样东西:时间线、验证命令、结论。没有记录的过程不算排查。

阶段一:方法论与信息收集

目标:先界定影响范围和变更时间线,再用可证伪的假设驱动排查,而不是随机重启。

阅读顺序:

  1. linux-performance-triage — 按负载、CPU、内存、磁盘、网络分层缩小范围。
  2. k8s-troubleshooting-cheatsheet — Pod、节点、控制面的固定检查顺序。
  3. incident-response-playbook — 分级、指挥、沟通、止损和复盘。
  4. network-troubleshooting-cheatsheet — 从 DNS 到 TLS 的分层检查表。
  5. sre-oncall-checklist — 值班交接、告警确认和升级路径。
  6. observability-roadmap — 需要哪些指标、日志和追踪才能定位问题。
  7. migration-readiness-checklist — 变更前评估,减少“上线即故障”。
  8. connection-timeout — 超时是最常见也最容易误判的现象,先学会拆解。

动手任务:模拟一次“首页 502”的告警。不要改任何配置,只写一张排查卡片:影响范围、开始时间、最近变更、三个假设、每个假设的验证命令。

date -Is
ss -lntp
curl -sS -o /dev/null -w '%{http_code} %{time_total}\n' https://example.com/
journalctl --since '30 min ago' -p warning --no-pager | tail -50
kubectl get events --sort-by=.lastTimestamp 2>/dev/null | tail -20

过关标准:

阶段二:系统与磁盘

目标:看到 CPU、负载、内存、磁盘、inode、文件描述符异常时,能快速判断资源类型和受害进程。

阅读顺序:

  1. cpu-100 — 用户态、内核态、软中断和限流的区分。
  2. load-average-high — 运行队列和不可中断睡眠,负载高不等于 CPU 忙。
  3. no-space-left — 空间、保留块、已删除文件和挂载覆盖。
  4. inode-exhausted — 有空间但无法创建文件。
  5. oom-killed — 内核 OOM Killer 与容器退出码 137。
  6. memory-leak — RSS 持续增长、缓存与真实泄漏的区别。
  7. disk-io-high — 延迟、队列、利用率和云盘语义。
  8. read-only-filesystem — 文件系统错误后的保护性只读。
  9. zombie-process — 已退出但未被回收的进程。
  10. too-many-open-files — 文件描述符泄漏和 ulimit。

动手任务:在测试机上依次制造 CPU 饱和、内存压力和 inode 耗尽,观察 top、vmstat、df -i、dmesg 的变化,并记录每个现象的判别特征。

stress-ng --cpu 2 --timeout 60s
vmstat 1 5
stress-ng --vm 1 --vm-bytes 80% --timeout 60s
dmesg -T | grep -i -E 'oom|killed process'
df -h /tmp && df -i /tmp

过关标准:

阶段三:网络

目标:沿着 DNS、连接、TLS、HTTP、链路 MTU 的路径逐层定位,不把超时都归因于“网络抖动”。

阅读顺序:

  1. connection-refused — 有 RST,通常是没有监听或被防火墙拒绝。
  2. dns-resolution-failed — 解析失败、超时和错误域名的区别。
  3. 502-bad-gateway — 网关收到了上游的无效响应。
  4. tls-handshake-failed — 证书、协议、SNI 和时钟。
  5. mtu-issue — 小包通、大包断的典型现象。
  6. connection-timeout — SYN 无响应、路由黑洞和中间设备丢包。
  7. packet-loss — 偶发失败和重传的关联。
  8. tcp-retransmit — 重传率、RTT 和拥塞窗口。
  9. nat-port-exhausted — 源端口耗尽导致的新连接失败。
  10. conntrack-full — 连接跟踪表满和内核丢包日志。

动手任务:在测试环境分别制造“端口未监听”“DNS 解析失败”“大包被丢”三种故障,用 ss、dig、curl、ping -M do、tcpdump 验证判断。

ss -lntp | grep 8080
curl -v --connect-timeout 2 http://127.0.0.1:8080/
dig @127.0.0.1 example.com
ping -c 3 -M do -s 1472 "$(ip route | awk '/default/ {print $3; exit}')"
tcpdump -ni any 'tcp port 8080 and (tcp[tcpflags] & tcp-rst != 0)'

过关标准:

阶段四:数据库与 Kubernetes

目标:把数据库锁、连接池、消息积压和 Pod 生命周期问题,映射到可检查的状态和指标。

阅读顺序:

  1. mysql-deadlock — 死锁检测、等待图和事务顺序。
  2. redis-memory-full — maxmemory、淘汰策略和内存碎片。
  3. kafka-consumer-lag — 消费速率、分区倾斜和 rebalance。
  4. pod-pending — 调度失败,容器还没有创建。
  5. crashloopbackoff — 容器启动后反复退出。
  6. k8s-dns-failed — CoreDNS、NetworkPolicy 和 resolv.conf。
  7. mysql-slow-query — 执行计划、索引和锁等待。
  8. postgres-connection-exhausted — 连接池、空闲事务和 max_connections。
  9. k8s-pvc-pending — StorageClass、容量和绑定模式。
  10. imagepullbackoff — 镜像不存在、认证失败或网络不可达。

动手任务:用 kind 建一个测试集群,依次制造 Pending、CrashLoopBackOff、ImagePullBackOff 和 PVC Pending,每次先写判断,再用 describe、events、logs 验证。

kind create cluster --name triage
kubectl run bad --image=example.invalid/nope:1.0
kubectl get pod bad -o wide
kubectl describe pod bad
kubectl get events --sort-by=.lastTimestamp
kubectl run crash --image=busybox -- sh -c 'exit 1'
kubectl logs crash --previous

过关标准:

常见误区

读完自测

合上页面,先回答,再展开对照。

  1. 负载很高但 CPU 使用率不高,可能是什么原因?下一步看什么?
  2. Connection refused 和 Connection timed out 分别说明链路走到了哪一步?
  3. Pod 一直 Pending,为什么 kubectl logs 通常没有输出?应该先看什么?
答案
  1. 常见原因是大量进程处于不可中断睡眠(D 状态),通常在等磁盘 IO、NFS 或内核锁。先看 vmstat 的 b 和 wa、iostat -xz 的延迟与队列,再用 ps -eo state,pid,comm | grep '^D' 找具体进程。
  2. Connection refused 表示目标主机回了 RST,链路和端口可达,但没有进程监听或防火墙主动拒绝。Connection timed out 表示 SYN 没有收到任何响应,可能是路由不可达、安全组丢弃、中间设备静默丢包或目标过载。
  3. Pending 表示 Pod 还没有被调度到节点,或者容器还没有创建,所以没有应用日志。先 kubectl describe pod 看 Events,检查资源不足、污点与容忍、亲和性、PVC 未绑定等原因。

相关条目