问题
今天一个用户的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,但都无法解析。例如:
# foo-api.prod.svc.cluster.local 为目标Pod的Service name
# 10.244.0.240 为 CoreDNS Pod IP
nslookup foo-api.prod.svc.cluster.local 10.244.0.240进一步怀疑是跨主机节点的Pod间网络通信出现了问题。为了验证这个假设,手动在 10.244.0.240这个CoreDNS Pod所在的主机节点上启动了一个用于调试Pod,并在该Pod中执行:
nslookup foo-api.prod.svc.cluster.local 10.244.0.240得到以下结果:
Server: 10.244.0.240
Address: 10.244.0.240:53
Name: foo-api.prod.svc.cluster.local
Address: 10.105.21.231可以解析成功,说明CoreDNS正常工作,问题可能出在跨节点的Pod通信上。
接下来,查看目标服务所有的Endpoint:
kubectl get endpoints foo-api -n prod
NAME ENDPOINTS AGE
foo-api 10.244.2.80:8080,10.244.3.47:8080 279d进一步测试,在同一主机节点上,可以访问 10.244.2.80:8080:
curl http://10.244.2.80:8080
<some response>但是在不同主机节点上无法访问10.244.2.80:8080:
curl http://10.244.2.80:8080
curl: (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数据包:
tcpdump -nn -i ens4 udp and port 8472 and dst host 172.16.10.173 -vvvens4 为Flannel使用的网络接口,这条命令将捕获所有目标地址为172.16.10.173,端口为 8472的UDP数据包。
- 在
172.16.10.85节点上执行以下命令,捕获从172.16.10.85发出的VXLAN封装UDP数据包:
tcpdump -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数据包没有被正确传输,从而找到了问题的根源。