解决一个calico网络pod内ping不通问题
问题
遇到一个问题,有用户发现自己的应用无法调用一个集群外的服务。目标服务ip是100.125.1.xx
在容器内ping测试,发现直接ping不通。
在node节点上ping测试,发现可以ping通。
通过tcpdump进行抓包进行分析
根据calico的网络原理,可知。pod的流程会通过pod内的veth-peer转到node上对应的calixxxx网卡上
先说说怎么找容器和node上上成对的网卡

看到容器内部id为4的网卡,后面对应了3268
那么你在对应的node节点上,就会找到对应的id为3269的网卡

对calixxxx网卡进行抓包
1 | tcpdump -i calixxxx host 100.125.1.xx |

没有收到响应。
按理说,calixxxx网卡会把流量交给eth0发出去
继续对eth0网卡抓包
1 | tcpdump -i eth0 host 100.125.1.xx |

发现也没有收到响应
在node上ping,同时抓包

发现是正常。
对比两个报文。注意到正常的报文source是node节点的ip,而从pod内ping的报文,sourceip还是pod的ip。这不对啊。
这响应报文肯定回不来了。
为什么会这样
按理说出去的podip应该进行snat,而snat是由iptables负责的。
赶紧去查看iptables规则
1 | iptabls -t nat -L |
发现最下面有这么一条
1 | Chain cali-nat-outgoing (1 references) |
看到这条规则,豁然开朗。这条规则的意思是
1 | 对 源IP是calico地址池内的,并且 目的ip不是calico地址池内的流量。要就行nat转换 |
这是非常合理的,问题出就出来我这里要访问的外部ip,它匹配了我的pod网段。。。
cali40masq-ipam-pools也就是我们calico网段的配置
1 | kubectl -n kube-system get ippool default-ipv4-ippool -oyaml |
也可以去ipset里查看这个cali40masq-ipam-pools
1 | ipset list |
所以,当我们在pod内ping的时候,源ip在100.64.0.0/10这个网段,并且更关键的是目的ip也在这个网段里了,所以不进行nat转换。podip原样出去了,因为podip在k8s集群之外并没有对应的路由规则,所以目的服务器返回的包,肯定是回不来的。所以我们这边收不到响应。
所以这个问题的关键就是,外部服务的ip段和我们配的容器ip段有重叠。