公司刚上线的微服务系统跑在ref="/tag/2020/" style="color:#B2A89E;font-weight:bold;">Kubernetes上,某天突然发现几个服务之间调用失败,日志里全是超时错误。运维小李一查,Pod都在运行,CPU和内存也正常,但就是没法通信。这种情况并不少见,尤其是在复杂的云原生环境中,Kubernetes集群网络不通往往是多种因素交织的结果。
先确认问题范围
第一步不是急着重启组件,而是搞清楚问题影响的范围。是整个集群都通不了,还是只有部分命名空间或某些节点上的Pod有问题?可以先在两个正常运行的Pod里执行ping或curl测试。比如:
kubectl exec -it pod-a -- ping 10.244.2.15
kubectl exec -it pod-b -- curl http://10.244.3.10:8080/health
如果跨节点通信失败,但同节点内正常,那问题很可能出在网络插件或节点路由配置上。
检查CNI插件状态
Kubernetes本身不负责网络实现,靠的是CNI(容器网络接口)插件,比如Calico、Flannel、Cilium。如果这些组件没启动好,网络自然就断了。查看kube-system命名空间下的CNI相关Pod是否处于Running状态:
kubectl get pods -n kube-system | grep -E '(calico|flannel|cilium)'
如果有Pod处于CrashLoopBackOff或Error状态,得进一步看日志。比如Calico的node组件挂了,可能是因为etcd连接失败或证书过期,这时候就要检查配置文件和TLS凭证。
节点路由和防火墙别忽视
有时候网络不通不是K8s的问题,而是底层服务器的锅。比如新部署的节点没打开必要的端口,iptables规则拦掉了VXLAN流量,或者云平台的安全组策略限制了Pod子网之间的通信。阿里云、腾讯云上都有安全组默认禁止非标准端口的情况,而Flannel用的8472端口就容易被误拦。
可以登录到对应Node上,用ip route查看是否有正确的Pod网段路由,再用tcpdump抓包确认数据包是否发出:
tcpdump -i flannel.1 host 10.244.2.0
DNS解析异常也会像网络不通
有些应用报“连接失败”,其实是因为CoreDNS解析不了服务名。比如访问mysql-service.default.svc.cluster.local返回NXDOMAIN,程序以为网络断了,实际上只是域名没对上。这时要检查CoreDNS Pod是否正常,以及每个Pod的/etc/resolv.conf是否正确指向了集群DNS地址。
一个简单的验证方式是进入Pod执行:
kubectl exec -it busybox -- nslookup kubernetes.default
如果解析失败,再查CoreDNS日志有没有大量拒绝记录或循环查询。
NetworkPolicy别乱配
团队里有人加了一条NetworkPolicy,想隔离测试环境,结果不小心把生产数据库的入口给封了。这类策略一旦配置不当,就会导致“明明网络通,却连不上服务”的怪现象。特别是用了Cilium或Calico这种支持三层策略的插件,策略优先级和匹配规则更复杂。
排查时可以用:
kubectl get networkpolicy --all-namespaces
看看有没有限制源IP或端口的规则。有时候一条egress: {}没写全,Pod就连不上外部NTP或镜像仓库。
滚动更新中的临时故障
发布新版本时,旧Pod销毁、新Pod创建的过程中,Service的Endpoint列表可能短暂不一致。特别是用Deployment配合ClusterIP时,kube-proxy需要一点时间同步规则。这时候发起请求的服务可能会打到已经不存在的后端IP上,表现为偶发性超时。
可以查一下Endpoint是否及时更新:
kubectl get endpoints my-service
对比它列出的IP是否和当前运行的Pod一致。如果不一致,可能是kube-proxy异常,或者节点上的iptables/ipvs模式没生效。