首页
›
指南
›
学习路径
›
故障排查学习路径
故障排查学习路径:从方法论到系统、网络、数据库与 K8s
使用方式
排障能力不是“知道更多命令”,而是“用最小代价排除最大范围”。这条路径先建立方法,再按系统、网络、数据与编排分层练习。
四个阶段按依赖顺序排列,每个阶段建议留 2–4 小时:
先读 :先读方法论页面,再读具体故障页;每读一个故障,写下它的典型现象和第一检查点。
再做 :在一次性的虚拟机或测试集群里复现故障,不允许在生产环境制造问题。
后测 :只看现象描述,说出下一步查什么、为什么查这里。
每道故障题都要留下三样东西:时间线、验证命令、结论。没有记录的过程不算排查。
阶段一:方法论与信息收集
目标 :先界定影响范围和变更时间线,再用可证伪的假设驱动排查,而不是随机重启。
阅读顺序 :
linux-performance-triage — 按负载、CPU、内存、磁盘、网络分层缩小范围。
k8s-troubleshooting-cheatsheet — Pod、节点、控制面的固定检查顺序。
incident-response-playbook — 分级、指挥、沟通、止损和复盘。
network-troubleshooting-cheatsheet — 从 DNS 到 TLS 的分层检查表。
sre-oncall-checklist — 值班交接、告警确认和升级路径。
observability-roadmap — 需要哪些指标、日志和追踪才能定位问题。
migration-readiness-checklist — 变更前评估,减少“上线即故障”。
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、文件描述符异常时,能快速判断资源类型和受害进程。
阅读顺序 :
cpu-100 — 用户态、内核态、软中断和限流的区分。
load-average-high — 运行队列和不可中断睡眠,负载高不等于 CPU 忙。
no-space-left — 空间、保留块、已删除文件和挂载覆盖。
inode-exhausted — 有空间但无法创建文件。
oom-killed — 内核 OOM Killer 与容器退出码 137。
memory-leak — RSS 持续增长、缓存与真实泄漏的区别。
disk-io-high — 延迟、队列、利用率和云盘语义。
read-only-filesystem — 文件系统错误后的保护性只读。
zombie-process — 已退出但未被回收的进程。
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
过关标准 :
能解释 load average 高但 CPU 空闲的可能原因,并知道看哪个指标确认。
能区分空间不足、inode 不足和只读文件系统,三者的报错和处理不同。
知道容器里 OOMKilled 应该先看 cgroup 限制还是节点内存。
阶段三:网络
目标 :沿着 DNS、连接、TLS、HTTP、链路 MTU 的路径逐层定位,不把超时都归因于“网络抖动”。
阅读顺序 :
connection-refused — 有 RST,通常是没有监听或被防火墙拒绝。
dns-resolution-failed — 解析失败、超时和错误域名的区别。
502-bad-gateway — 网关收到了上游的无效响应。
tls-handshake-failed — 证书、协议、SNI 和时钟。
mtu-issue — 小包通、大包断的典型现象。
connection-timeout — SYN 无响应、路由黑洞和中间设备丢包。
packet-loss — 偶发失败和重传的关联。
tcp-retransmit — 重传率、RTT 和拥塞窗口。
nat-port-exhausted — 源端口耗尽导致的新连接失败。
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)'
过关标准 :
能区分 Connection refused、Connection timed out 和 502 分别发生在哪一层。
知道 DNS 解析成功不代表 TCP 能连上,TCP 能连上也不代表 TLS 和 HTTP 正常。
能解释“小包通、大包不通”为什么要先怀疑 MTU 和分片。
阶段四:数据库与 Kubernetes
目标 :把数据库锁、连接池、消息积压和 Pod 生命周期问题,映射到可检查的状态和指标。
阅读顺序 :
mysql-deadlock — 死锁检测、等待图和事务顺序。
redis-memory-full — maxmemory、淘汰策略和内存碎片。
kafka-consumer-lag — 消费速率、分区倾斜和 rebalance。
pod-pending — 调度失败,容器还没有创建。
crashloopbackoff — 容器启动后反复退出。
k8s-dns-failed — CoreDNS、NetworkPolicy 和 resolv.conf。
mysql-slow-query — 执行计划、索引和锁等待。
postgres-connection-exhausted — 连接池、空闲事务和 max_connections。
k8s-pvc-pending — StorageClass、容量和绑定模式。
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
过关标准 :
能按 Pod 生命周期区分 Pending、ImagePullBackOff、CrashLoopBackOff 和 OOMKilled。
知道 Pending 时为什么通常没有应用日志,应该先看哪类事件。
能说清数据库死锁和连接耗尽是两类不同问题,分别看什么视图。
常见误区
一上来就重启服务,破坏现场,之后无法确认根因。
把第一个相关性当成根因,不再验证其他假设。
只看一个指标,比如 CPU 高就认定是 CPU 问题。
排障过程中同时改多个变量,无法判断哪个改动生效。
忽略最近变更、证书到期、配额和容量这些高频诱因。
故障恢复后不记录时间线和验证结果,复盘时只剩模糊记忆。
在生产环境直接做破坏性实验。
读完自测
合上页面,先回答,再展开对照。
负载很高但 CPU 使用率不高,可能是什么原因?下一步看什么?
Connection refused 和 Connection timed out 分别说明链路走到了哪一步?
Pod 一直 Pending,为什么 kubectl logs 通常没有输出?应该先看什么?
答案
常见原因是大量进程处于不可中断睡眠(D 状态),通常在等磁盘 IO、NFS 或内核锁。先看 vmstat 的 b 和 wa、iostat -xz 的延迟与队列,再用 ps -eo state,pid,comm | grep '^D' 找具体进程。
Connection refused 表示目标主机回了 RST,链路和端口可达,但没有进程监听或防火墙主动拒绝。Connection timed out 表示 SYN 没有收到任何响应,可能是路由不可达、安全组丢弃、中间设备静默丢包或目标过载。
Pending 表示 Pod 还没有被调度到节点,或者容器还没有创建,所以没有应用日志。先 kubectl describe pod 看 Events,检查资源不足、污点与容忍、亲和性、PVC 未绑定等原因。
相关条目
相关命令
← traefik-vs-nginx
troubleshoot-mental-model →