记一次K8S Flannel VXLAN网络跨节点Pod通信问题排查
📅 2024-12-02 | 🖱️
问题 #
今天一个用户的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.173
和 172.16.10.85
,并使用 tcpdump
抓包来检查 Flannel 的 VXLAN 数据包是否能够正确传输。
- 在
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数据包。
- 在
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数据包没有被正确传输,从而找到了问题的根源。