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

incident-cni-mtu

新节点池 CNI MTU 配置漂移叠加 ICMP 被过滤,造成“小请求正常、大响应卡死”的跨节点黑洞。

现象

某业务集群新增一个节点池后,部分服务出现间歇性超时。典型表现是:小请求正常,返回体较大时卡住;跨节点调用 P99 飙升,入口出现 504;同一个节点上的 Pod 互访完全正常。TLS 握手有时也会卡在证书传输阶段,看起来像应用或证书问题。

排查时发现几个互相矛盾的信号:DNS 解析正常,TCP 端口可以连通,ping 小包也通;但 curl -v 在 TLS 握手或响应体传输阶段停住,ss -ti 显示大量重传。受影响的服务只分布在部分节点上,而且故障方向不对称:由新节点池中的 Pod 发出的报文容易失败,由旧节点池中的 Pod 发出的报文基本正常。

在发送端抓包能看到大包已经发出,接收端却收不到;同时链路上没有出现对应的 ICMP “fragmentation needed”。这几个现象组合在一起,已经很像路径 MTU 发现被黑洞化。

时间线

时间 事件
T+0 新节点池上线约十分钟后,跨节点接口超时告警
T+5m 应用日志只有 upstream timeout,先按应用和下游依赖排查
T+10m DNS、Ingress、Service 均正常,同节点 Pod 互访正常,怀疑点收窄到跨节点链路
T+16m 用 ping -M do -s 逐级测试,1472 字节失败、1400 字节成功
T+22m 两端抓包确认大包在接收端缺失,且没有 ICMP fragmentation needed
T+30m 对比两批节点的 CNI MTU,发现新池为 1500、旧池为 1450
T+38m 修正新池 CNI MTU,并在隧道层增加 MSS clamp
T+50m 大包跨节点恢复,504 消失
T+70m 全量节点核对 MTU,重启相关 Pod 使 veth 生效
T+2h 增加节点启动自检和跨节点大包探测

影响面

新节点池承载了约四分之一的服务副本,跨节点大包流量在约五十分钟内不稳定。小于路径 MTU 的请求和健康检查大多正常,因此流量仍会被负载均衡打到这些 Pod 上,形成“健康检查通过、真实请求失败”的错配。入口 504、客户端重试和下游超时叠加,放大了故障观感。

同节点访问和旧节点池之间的访问不受影响,导致故障看起来像随机发生,定位成本很高。没有持久化数据丢失,但部分请求可能被重试多次,需要确认业务幂等性;长连接和 TLS 会话恢复也出现了额外失败。

误导线索

最初的判断是应用超时或 DNS 问题。理由是只有部分请求失败,日志里是 upstream timeout,而且 DNS 解析、端口连通性都正常。ping 小包成功进一步强化了“网络没问题”的结论。

真正推翻这个判断的证据有四条:

  1. 故障与报文大小相关,而不是与请求内容相关。 小响应稳定成功,大响应稳定失败;这不是业务逻辑或 DNS 能解释的模式。
  2. 方向不对称。 新节点池发出的报文封装后超过底层 MTU,旧节点池发出的报文刚好在阈值内,所以只有一个方向的大包被丢弃。链路故障通常不会如此精确地按方向和大小区分。
  3. ping -M do -s 1472 失败、-s 1400 成功。 这直接把可用路径 MTU 卡在 1428 到 1499 之间(约 1450),和 VXLAN 封装开销吻合。
  4. 抓包显示大包发出但未到达,且没有 ICMP fragmentation needed。 说明不是应用没发,也不是接收端拒绝,而是路径中间静默丢弃,且 PMTUD 反馈被过滤。

另一个干扰项是告警前后有 CNI Pod 重启。团队一度把它当成根因,但重启后问题依旧,而且 CNI Pod 重启本身可能是因为无法连接 apiserver,属于伴随现象。

根因

直接原因是新节点池的 CNI MTU 配置漂移。旧节点池按 VXLAN 封装把 Pod 网络 MTU 设为 1450,新节点池的模板却使用了 1500。底层网卡 MTU 是 1500,新节点上的 Pod 发出 1500 字节报文,经 VXLAN 封装后约为 1550 字节,超过底层链路可承载的大小,被静默丢弃。

路径 MTU 发现依赖 ICMP type 3 code 4(fragmentation needed)通知发送端减小报文,但安全组和边界防火墙没有放行这类 ICMP,形成了 PMTUD 黑洞。发送端收不到反馈,TCP 继续按 1500 MTU 对应的 MSS(1460)重传,表现为“连接建立成功、传输大包时卡死”。

促成条件包括:

需要强调:MTU 不是“越大越好”。覆盖网络必须按封装方式扣除开销,VXLAN 通常扣 50 字节,IP-in-IP 扣 20 字节,WireGuard 等加密方式还要更多;底层网络如果启用了 jumbo frame,两端也必须一起调整。

修复

先确认路径 MTU,再改配置。以下命令在 Pod 内执行;如果镜像没有 ping,可以用临时调试容器:

# 从新节点池的 Pod 测旧节点池的 Pod
kubectl exec -it <pod-new> -- ping -M do -s 1472 -c 3 <pod-old-ip>
kubectl exec -it <pod-new> -- ping -M do -s 1400 -c 3 <pod-old-ip>
kubectl exec -it <pod-new> -- tracepath <pod-old-ip>

# 查看 Pod 网卡 MTU
kubectl exec -it <pod-new> -- ip link show eth0
kubectl exec -it <pod-old> -- ip link show eth0

在节点上核对隧道和 CNI 配置:

ip -d link show vxlan.calico
ip -d link show cilium_vxlan
ip -d link show flannel.1
cat /run/flannel/subnet.env

# 按所用 CNI 选择对应命令
kubectl -n kube-system get cm cilium-config -o jsonpath='{.data.mtu}'
calicoctl get felixconfiguration default -o yaml | grep -i mtu

修复时把所有节点池的 CNI MTU 统一为“底层 MTU 减去封装开销”。以 1500 底层 + VXLAN 为例,Pod MTU 设为 1450;如果底层是 9000,也要保证所有节点、交换机和云网络路径一致。修改 CNI 配置后,重启对应节点上的 CNI Pod,并确认 veth 和隧道接口的 MTU 都已更新;已有 Pod 可能需要重建才能拿到新的 veth MTU。

在隧道层增加 MSS clamp 作为兜底,范围限定在 Pod 网段,避免影响其他流量:

sudo iptables -t mangle -A FORWARD -s <pod-cidr> \
  -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1400

同时放行必要的 ICMP,至少允许 type 3 code 4 到达发送端;安全组、边界防火墙和网络策略都要检查。临时可以在受影响节点开启 TCP MTU 探测:

# tcp_mtu_probing 是 per-netns 的;节点上设置不会影响 Pod
sudo nsenter -t <pod-pid> -n sysctl -w net.ipv4.tcp_mtu_probing=1

这只是缓解手段,不能替代正确的 MTU 配置。验证时要同时测试两个方向的大包,而不是只从一个方向 ping:

kubectl exec -it <pod-new> -- curl -sS -o /dev/null -w '%{http_code} %{size_download}\n' \
  http://<service-old>/large-response
kubectl exec -it <pod-old> -- curl -sS -o /dev/null -w '%{http_code} %{size_download}\n' \
  http://<service-new>/large-response

确认 504 消失、重传率回落、两个方向的 MTU 探测都通过后,再逐步恢复流量。

预防

相关命令

参考链接

读完自测

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

  1. 为什么“小请求正常、大响应卡死”比“全部请求失败”更像 MTU 问题?
  2. VXLAN 模式下,底层 MTU 1500 时 Pod MTU 应该设为多少?为什么?
  3. 为什么已经配置了正确的 MTU,仍然需要放行 ICMP fragmentation needed?
答案
  1. MTU 问题只影响超过路径 MTU 的报文。小请求和健康检查能通过,大响应或 TLS 证书传输会触发丢包和重传,表现为与报文大小相关的间歇性失败。
  2. 通常设为 1450。VXLAN 封装会增加约 50 字节(外层 IP、UDP、VXLAN 头和内层以太网头),1500 减去 50 才是 Pod 网络可安全使用的 MTU。
  3. 路径中可能存在比节点网卡更小的链路或隧道;当报文超过实际路径 MTU 时,需要 ICMP fragmentation needed 通知发送端调整 MSS。若 ICMP 被过滤,PMTUD 失效,即使本地 MTU 配置正确也可能出现黑洞。
微信小程序码:扫码打开命令速查小程序

小程序版

微信扫码,随时查命令