同子网下K8s Pod无法访问GCE实例的问题排查请求
我来帮你拆解这个问题——这种Pod能通节点但不通同子网VM的情况,我之前在GCE+K8s环境里遇到过好几次,结合你已经抓了tcpdump,咱们可以从这几个方向一步步排查:
1. 先分析Pod的tcpdump结果,定位流量断点
先在出问题的Pod里执行抓包命令:
tcpdump -i any icmp host 10.101.0.4
重点看两个核心点:
- 有没有ICMP Echo Request包从Pod发出去(源IP是10.101.67.191,目标是10.101.0.4)
- 有没有收到ICMP Echo Reply包(源IP是10.101.0.4,目标是10.101.67.191)
- 如果Request发出去了但没收到Reply:问题大概率在VM的返程路由或防火墙
- 如果Request都没发出去:先检查Pod自身的路由配置
2. 检查Pod的路由表是否正确
在Pod里执行ip route,查看是否存在到子网SA(10.101.0.0/18)的路由规则:
正常情况下应该有一条指向Pod网关(通常是节点分配的Pod网段网关)的路由,比如:
10.101.0.0/18 via 10.101.67.1 dev eth0
如果没有这条路由,说明你的CNI插件(比如Calico、Flannel)没正确配置Pod的路由规则,需要检查CNI的配置文件,确认是否包含了集群所在子网的路由条目。
3. 检查节点的SNAT配置是否生效
节点能ping通VM但Pod不行,最常见的原因是Pod的流量没做SNAT,导致VM收到包后不知道怎么回传给Pod:
在节点上执行以下命令查看SNAT规则:
iptables-save | grep SNAT
正常应该有一条针对Pod网段(10.101.64.0/19)到子网SA的SNAT规则,比如:
-A POSTROUTING -s 10.101.64.0/19 -d 10.101.0.0/18 -j SNAT --to-source 10.101.0.3
这条规则的作用是把Pod的源IP转换成节点的IP(10.101.0.3),这样VM收到包后能正确回包给节点,再由节点转发给Pod。如果没有这条规则,你可以手动添加,或者检查CNI插件的SNAT配置(比如Calico的natOutgoing选项是否开启)。
4. 检查GCE虚拟机的路由和防火墙
登录到IP为10.101.0.4的VM,做两个关键检查:
- 路由表:执行
ip route,看是否存在到Pod网段(10.101.64.0/19)的路由。如果没有,需要添加一条指向节点IP的路由:
或者在GCE VPC层面配置一条路由,把Pod网段的流量指向集群节点所在的子网。ip route add 10.101.64.0/19 via 10.101.0.3 dev eth0 - 防火墙规则:确认VM的防火墙允许来自Pod网段的ICMP(或其他你需要的协议)流量。GCE默认的防火墙规则可能只允许同子网的节点IP访问,需要添加入站规则,允许
10.101.64.0/19网段的流量。
5. 确认节点开启了IP转发
最后检查节点是否开启了IP转发功能,这是节点转发Pod流量的前提:
执行以下命令查看状态:
sysctl net.ipv4.ip_forward
如果返回net.ipv4.ip_forward = 0,需要临时开启:
sysctl -w net.ipv4.ip_forward=1
并修改/etc/sysctl.conf文件,添加net.ipv4.ip_forward=1,确保节点重启后依然生效。
内容的提问来源于stack exchange,提问作者kotrfa

