最近在公司运维的K8s集群突然出现部分Pod无法跨节点通信的问题,服务调用超时频发。一开始怀疑是网络插件异常,但Calico日志看起来一切正常。经过层层排查,最终发现问题出在节点的路由表项上。
现象定位:从ping不通开始
某天早上,开发反馈一个部署在node-2上的服务无法被node-1上的Pod访问,但node-2自身Pod之间通信正常。第一反应是检查网络策略,确认没有配置误拦。接着在node-1上尝试直接ping node-2上Pod的IP,发现根本不通。
登录到node-1执行 ip route get 10.233.2.15(目标Pod IP),返回的结果居然是走默认网关,而不是通过flannel.1或者cali接口转发。这就奇怪了,正常应该走VXLAN隧道才对。
查看路由表,发现异常缺失
执行命令查看当前路由表:
ip route show
在正常的节点上,能看到类似这样的条目:
10.233.2.0/24 dev cali1234567890 scope link
10.233.3.0/24 via 192.168.2.10 dev flannel.1 onlink
但在出问题的node-1上,缺少了指向node-2所在子网的那条via规则。也就是说,K8s网络插件本该注入的路由项没生效。
翻日志:Calico Node状态异常
查看Calico-node容器日志:
kubectl logs -n kube-system calico-node-xxxxx -c calico-node
发现大量报错:
Failed to program rule: operation Delete failed: no such file or directory
进一步查证发现,该节点的BGP会话未完全建立。而路由项依赖BGP协议同步各节点子网信息。一旦BGP中断,新加入的节点路由就不会被广播出去。
临时修复:手动加路由
为了快速恢复业务,先手动添加缺失的路由:
ip route add 10.233.2.0/24 via 192.168.2.10 dev flannel.1 onlink
加上后,Pod立即可以互通。但这只是权宜之计,重启或网络波动后还会丢。
根因分析:节点重启后MTU不匹配
深入排查发现,该节点之前因硬件维护重启过。而重启后系统加载的网络接口MTU为1450,但Calico配置的是1440。这个微小差异导致VXLAN封装失败,进而使BGP邻居无法维持连接,最终路由项无法同步。
修改Calico的配置,统一所有节点的MTU值:
<!-- 修改 Calico 的 daemonset 或使用 kubectl patch -->
kubectl patch daemonset calico-node -n kube-system --type=strategic \
-p '{'spec':{'template':{'spec':{'containers':[{'name':'calico-node','env':[{'name':'FELIX_VXLANMTU','value':'1450'}]}]}}}}'
预防建议:监控路由表一致性
这类问题不容易被常规健康检查捕获。建议在每个节点部署一个简单的脚本,定期校验是否存在关键CNI路由项,并上报缺失情况。
比如写个cron任务:
*/5 * * * * /bin/sh /opt/check-k8s-routes.sh
脚本内容判断是否包含集群Pod CIDR的路由项,否则告警。
一次看似复杂的网络故障,往往源于一个配置参数的偏差。路由表虽小,却是K8s网络通畅的命脉。