事情本身不复杂,线索都在日志里。自建 K8s 1.25,Ubuntu 20.04,Calico 用 VXLAN 模式,Pod 里 ping 小包正常,curl 下载大文件卡在 0 字节,抓包看到 1450 字节以上的包没有响应,节点网卡 MTU 是 1500,tunl0 也是 1500。
第一反应是「中间设备丢弃了需要分片的 ICMP,PMTU 发现失效」,验证下来不成立。
把日志和配置对完,能解释这个现象的基本就这几处。VXLAN 封装多出 50 字节开销,Pod 网卡 MTU 仍按 1500 配置。还有一种是Calico 的 veth MTU 没有跟随 IPPool 配置下发。
另外,应用自己设置了 DF 位,大包被链路直接丢掉。
第一件事是确认 Pod 网卡和隧道的 MTU
kubectl exec -it web -- ip link show eth0 && ip link show tunl0
然后让 Calico 按封装开销下发 MTU
kubectl patch configmap calico-config -n kube-system --type merge -p '{"data":{"veth_mtu":"1450"}}'
再往下重建 Pod 让新 MTU 生效
kubectl rollout restart deploy web
剩下的就是验证大包路径不再被丢
kubectl exec -it web -- ping -M do -s 1400 -c 3 10.96.0.10
同样的操作我在测试机上先走了一遍,线上只做验证过的部分。
恢复的判定其实很直接。Pod 内 ping -M do -s 1400 全部返回,下载大文件速度正常,tcpdump 里不再出现无响应的大包。
容易忽略的是,MTU 要按最窄的一段链路算,跨公网或经过 IPSec 时开销更大,别只照抄 1450 这个值。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
