网络故障要按层验证:先用证据确认请求走到了哪一层,再判断是解析、路由、连接、握手还是应用的问题,而不是从应用日志猜。
网络按 L2 链路、L3 网络、L4 传输、L7 应用分层,每层把上层数据加上自己的头部再交给下层。以太网帧有 MAC,IP 包有源和目的地址,TCP/UDP 有端口和校验和,HTTP/TLS 有方法和证书。分层的价值是每层可以独立实现和替换,排障时也可以逐层取证。
边界在于分层是模型,不是现实。NAT 会改写地址和端口,隧道会再包一层,负载均衡会终止连接,MTU 会让大包在小包能通过时被丢弃。所谓“三层问题”和“七层问题”经常互相伪装:L7 的 502 可能来自 L4 连接被重置,L4 的超时可能来自 DNS。
失败时的表现是症状出现在错误的层:应用报“请求超时”,实际是 DNS 解析慢;Ingress 报 502,实际是后端端口没监听;TLS 握手失败,实际是证书链缺中间证书。排障的第一步是确认当前证据属于哪一层。
IP 负责端到端的逻辑寻址,路由表决定下一跳。Linux 用最长前缀匹配选择路由,直连网段通过 ARP(IPv4)或 NDP(IPv6)解析 MAC,非直连流量发给网关。策略路由、多张路由表、VRF 和容器网络会让“默认路由”不再是唯一答案。
边界在于:能路由不等于能到达。防火墙、安全组、网络策略、反向路径过滤和不对称路由都可能在转发路径上丢包;ARP 冲突、邻居表项过期和网关不可达会表现为间歇性中断。IPv6 还引入了 RA、NDP 和双栈优先级问题。
失败时的表现是 Network is unreachable、No route to host、ARP 冲突告警、跨网段单向通,以及只有某个源地址或某个节点访问失败。用 ip route get、ip neigh、traceroute 和抓包确认路径,比反复重启网络服务有效。
一个 TCP 连接由源 IP、源端口、目的 IP、目的端口四元组唯一标识。服务端在地址和端口上 listen,内核维护 accept 队列;客户端从临时端口范围选择源端口。ss 读的是内核 socket 表,能看到 LISTEN、ESTABLISHED、TIME_WAIT 等状态和收发队列。
边界在于:端口开放不等于服务可用。监听在 127.0.0.1 的服务外部访问不到;backlog 满会拒绝或丢弃新连接;NAT 和连接跟踪会消耗端口与表项;大量短连接会把临时端口耗在 TIME_WAIT。容器和 Pod 还有独立的网络命名空间,宿主机上看到的结果不一定代表容器内。
失败时的表现是 Connection refused(收到 RST,通常是没有监听或被策略拒绝)、Connection timed out(没有回包,可能是丢包、路由或防火墙)、Address already in use(端口被占用),以及连接数上涨但吞吐不涨。refused 和 timeout 是不同证据,不能混为一谈。
DNS 把名字解析成地址。解析器先看 /etc/hosts 和 nsswitch.conf,再按 /etc/resolv.conf 里的 nameserver、search 域和 ndots 发起查询;递归解析器负责 Root、TLD 和权威服务器的查询,并按 TTL 缓存。Kubernetes 里 CoreDNS 提供集群内名字解析,Service 名字和 Headless Service 的返回行为不同。
边界在于:DNS 只解决“名字到地址”,不保证地址可达。解析成功但端口不通、解析到旧 IP、search 域拼接出意外名字、ndots 导致先查集群域再查外部域,都是常见问题。UDP 响应超过 512 字节或截断时会转 TCP,防火墙只放行 UDP 就会表现为间歇失败。
失败时的表现是 Name or service not known、Temporary failure in name resolution、解析耗时高、不同节点解析结果不同,以及应用启动时正常、运行一段时间后失败(缓存或连接池)。用 dig、getent hosts、resolvectl 分别验证解析器和 NSS 路径。
TCP 通过三次握手建立连接、序列号和确认保证可靠传输、滑动窗口做流控、拥塞控制适应网络。关闭连接有 FIN 四次挥手,主动关闭方进入 TIME_WAIT;异常情况用 RST 立即终止。重传、乱序、重复确认和零窗口都是状态机的正常输出。
边界在于:TCP 的“可靠”只保证数据最终按序交付,不保证低延迟。丢包会触发重传,表现为延迟升高而不是应用报错;中间设备可能改写超时、丢弃空闲连接或拦截 RST;keepalive 的默认时间通常远长于应用的超时。SYN 队列、accept 队列和 conntrack 表满,都会在握手阶段失败。
失败时的表现是连接超时、重传率高、connection reset by peer、大量 TIME_WAIT 或 SYN_RECV,以及“小请求正常、大请求卡住”。用 ss -ti、nstat、tcpdump 和内核计数器确认是丢包、重传、队列还是对端关闭。
TLS 在 TCP 之上提供加密、身份认证和完整性。握手阶段协商版本和密码套件、验证证书链、交换密钥;SNI 让一个 IP 承载多个域名;ALPN 协商 HTTP/2 等协议。mTLS 还要求客户端提供证书。证书链、信任库、主机名和有效期共同决定握手是否成功。
边界在于:TLS 失败经常伪装成网络失败。证书过期、缺少中间证书、主机名不匹配、客户端不信任私有 CA、系统时间偏差、协议版本或密码套件不兼容,都会让连接在握手阶段断开。反向代理终止 TLS 时,后端看到的是明文,问题可能出在代理到后端的第二段连接。
失败时的表现是 certificate has expired、unable to get local issuer certificate、handshake failure、protocol version 错误,或者浏览器报错但 curl -k 正常。用 openssl s_client -connect host:443 -servername host 看完整证书链和握手结果。
NAT 通过改写地址和端口让私有网络访问外部,连接跟踪(conntrack)记录五元组映射;MTU 决定单个帧能承载的最大 IP 包,隧道和 overlay 会额外消耗头部。Kubernetes 中 CNI 负责给 Pod 分配地址和配置路由,Service 通过 iptables/IPVS/eBPF 做虚拟 IP 转发,NetworkPolicy 在数据面实现隔离。
边界在于:这三者经常联合制造“偶发、单向、只影响大包”的故障。NAT 端口耗尽会让新连接失败;conntrack 表满会丢弃新流;MTU 不匹配会让握手和小请求正常、大响应卡死(PMTUD 被黑洞时尤其隐蔽)。跨节点 Pod 通信还依赖隧道、路由和防火墙的正确配合。
失败时的表现是 nf_conntrack: table full、NAT 源端口耗尽、跨节点访问偶发超时、ping 小包正常但大包失败、Service 访问时通时不通。排查要同时看 conntrack 使用量、Pod 与节点的 MTU、CNI 路由和 Service 后端。
| 组件 | 读什么 | 写什么 | 失败后的现象 |
|---|---|---|---|
| 应用与 socket | 域名、四元组 | 请求数据、连接状态 | 超时、连接被重置 |
| DNS | 名字、search 域、ndots | A/AAAA/SRV 记录 | 解析失败、解析到旧地址 |
| 路由与邻居 | 目的 IP、路由表 | 下一跳、ARP/NDP 表项 | 无路由、ARP 冲突、单向通 |
| TCP | 序列号、窗口、确认 | 重传、状态迁移 | 超时、重传、RST |
| NAT 与 conntrack | 五元组 | 地址端口映射、表项 | 端口耗尽、表满丢包 |
| TLS | 证书链、SNI、ALPN | 会话密钥 | 握手失败、证书错误 |
| CNI 与 Service | Pod IP、Endpoint | veth、路由、转发规则 | 跨节点不通、Service 偶发超时 |
| 负载均衡与 Ingress | Host、路径、后端 | 转发与连接复用 | 502、504、503 |
请求从应用 socket 出发,先经过 DNS 得到地址,再由路由和邻居找到下一跳,通过 TCP 建立连接,可能穿过 NAT、隧道和负载均衡,最后完成 TLS 握手并进入应用。每一层都有独立的失败模式和证据,按层验证比从日志猜更快。
ping 通就说明网络没问题。正确理解:ICMP 与 TCP/UDP 可能走不同策略,端口、TLS 和应用层仍可能失败。Connection refused 和 Connection timed out 是一回事。正确理解:refused 通常是收到 RST(无监听或被拒绝),timeout 是没有回包,排查方向完全不同。curl 通就代表所有客户端都通。正确理解:源地址、NAT、代理、IPv6、MTU 和防火墙策略都可能因客户端而异。ping 不通 ClusterIP 就是 Service 坏了。正确理解:ClusterIP 是虚拟地址,很多数据面不响应 ICMP,应该用端口和实际协议验证。合上页面,先回答,再展开对照。
curl 报连接超时,如何按层缩小范围?先看哪些证据?ping 通但 curl 仍然超时?至少举两个机制。getent hosts 或 dig 确认 DNS,再用 ip route get 和 ping 确认路由与可达性,用 ss 看连接状态和队列,用 curl -v 区分 TCP、TLS 和 HTTP 阶段,必要时在两端 tcpdump 看 SYN、重传和 RST。