记一次K8S Flannel VXLAN网络跨节点Pod通信问题排查

记一次K8S Flannel VXLAN网络跨节点Pod通信问题排查

📅 2024-12-02 | 🖱️
🔖 kubernetes, 🔖 flannel

问题 #

今天一个用户的K8S集群出现了问题。用户反馈集群中的业务Pod之间无法通信。在业务Pod中,执行 nslookup 目标Pod的service name时无法解析。

该K8S集群的信息如下:

  • Kubernetes版本:1.29.2
  • 容器网络:Flannel(backend type: VXLAN)

用户检查了CoreDNS的Pod,都正常运行。

排查 #

初步怀疑是容器之间的网络出现了问题。

在业务Pod的容器中,尝试执行 nslookup <目标Pod service name> <CoreDNS pod ip>,逐一尝试了CoreDNS的所有Pod IP,但都无法解析。例如:

1# foo-api.prod.svc.cluster.local 为目标Pod的Service name
2# 10.244.0.240 为 CoreDNS Pod IP
3nslookup foo-api.prod.svc.cluster.local 10.244.0.240

进一步怀疑是跨主机节点的Pod间网络通信出现了问题。为了验证这个假设,手动在 10.244.0.240这个CoreDNS Pod所在的主机节点上启动了一个用于调试Pod,并在该Pod中执行:

1nslookup foo-api.prod.svc.cluster.local 10.244.0.240

得到以下结果:

1Server:         10.244.0.240
2Address:        10.244.0.240:53
3
4Name:   foo-api.prod.svc.cluster.local
5Address: 10.105.21.231

可以解析成功,说明CoreDNS正常工作,问题可能出在跨节点的Pod通信上。

接下来,查看目标服务所有的Endpoint:

1kubectl get endpoints foo-api -n prod
2NAME        ENDPOINTS                         AGE
3foo-api   10.244.2.80:8080,10.244.3.47:8080   279d

进一步测试,在同一主机节点上,可以访问 10.244.2.80:8080

1curl http://10.244.2.80:8080
2<some response>

但是在不同主机节点上无法访问10.244.2.80:8080

1curl http://10.244.2.80:8080
2curl: (7) Failed to connect to 10.244.2.80 port 8080: Couldn't connect to server

跨节点Pod之间的通信确实存在问题。

检查各个节点的Flannel Pod都正常运行。这个K8S集群的Flannel的backend type是VXLAN。VXLAN是一种通过UDP封装的内核封包协议,它使用UDP端口 8472 来传输封装数据包。

继续排查,查看各节点的iptables规则,确认没有针对UDP端口8472的限制。因此可能会是云主机虚拟化平台(如Openstack)的安全组的限制?

使用tcpdump进一步排查 #

为了进一步验证,选择了两个K8S节点 172.16.10.173172.16.10.85,并使用 tcpdump 抓包来检查 Flannel 的 VXLAN 数据包是否能够正确传输。

  1. 172.16.10.173 节点上执行以下命令,捕获发送到本节点的VXLAN封装UDP数据包:
1tcpdump -nn -i ens4 udp and port 8472 and dst host 172.16.10.173 -vvv

ens4 为Flannel使用的网络接口,这条命令将捕获所有目标地址为172.16.10.173,端口为 8472的UDP数据包。

  1. 172.16.10.85节点上执行以下命令,捕获从172.16.10.85发出的VXLAN封装UDP数据包:
1tcpdump -nn -i ens4 udp and dst host 172.16.10.173 -vvv

这条命令将捕获从172.16.10.85发往172.16.10.173:8472s的VXLAN封装UDP数据包。

接着,在 172.16.10.85上的Pod中curl访问 172.16.10.173上的目标Pod的HTTPs服务。观察到在172.16.10.85节点上的tcpdump可以捕获到目标为172.16.10.173:8472的UDP包(封装中带有目标Pod的IP),但是在172.16.10.173节点上的tcpdump没有任何反应。

这表明从172.16.10.85发出的VXLAN数据包没有到达172.16.10.173,从而导致跨节点的通信失败。

最后让用户检查虚拟化平台的安全组配置,确实最近调整过。让用户在安全组中加入以下规则:

  • 针对172.16.10.0/24开放UDP 8472端口。

添加规则后,跨节点的Pod通信恢复正常。

总结 #

通过这一过程,排查出Kubernetes集群中跨节点Pod通信失败的原因是虚拟化平台(如Openstack)的安全组阻止了VXLAN封装的数据包。解决方案是为虚拟化平台的安全组添加开放UDP 8472端口的规则,从而恢复了跨节点Pod之间的通信。通过tcpdump的抓包分析,确认了VXLAN数据包没有被正确传输,从而找到了问题的根源。

© 2024 青蛙小白 | 总访问量 | 总访客数