skip to content
Logo Hetai's blog

pod内间歇DNS解析失败?Networkmanage捣乱Calico!

/ 4 min read

Table of Contents

现象

业务报错

k8s 网络告警频出,定位到告警根因日志,是业务Pod解析两个外部公网域名 timeout 了。

06-29 11:23:43 .015 CONTENT:urllib3 .exceptions.NameResolutionError: HTTPSConnection(host=‘api-inc.domoai.app’, port=443): Failed to resolve ‘api-inc.domoai.app’ ([Errno -3] Temporary failure in name resolution)

7 06-29 11:22:49 .023 CONTENT:urllib3 .exceptions.NameResolutionError: HTTPSConnection(host=‘img.domoai.app’, port=443): Failed to resolve ‘img.domoai.app’ ([Errno -3] Lookup timed out)

测试复现

在问题节点上跑一个带nslookup工具的Pod,由于我们CoreDns的公网域名解析都是交给8.8.8.8,故反复执行这样的命令来测试Dns:nslookup img.domoai.app. 8.8.8.8,同时在该Pod里和宿主机上抓包,tcpdump -n -i any host 8.8.8.8。 能观察到当nslookup img.domoai.app. 8.8.8.8 解析失败时,Pod的请求解析包通过veth设备流到宿主机之后就卡住了,没有进一步的转发出去。Pod没得到回复,每隔5秒重试发包,重试3次之后失败。 image.png

间歇一会,nslookup img.domoai.app. 8.8.8.8 又成功了,这是在宿主机抓包看到的时Pod包进入到宿主机之后,成功nat后几经转发,从calico-xxxxx(位于宿主机的pod对端设备)—> bound1 (虚拟聚合端口,即默认路由的出口端口) —> ens37f0np0 (实际出网物理端口) —> 8.8.8.8,最后回包。 image.png

对比成功解析时宿主机上的数据包流向,解析失败时就是pod的数据包通过calico-xxxx设备到达宿主机后,没有进行下一步的Forward转发流量 —> NAT —> 8.8.8.8 —> 回包 于是聚焦与pod流量进入到宿主机的数据包为什么没有被转发到bound1这个问题上。 要知道对从calico-xxxx设备进来的ip为10.42.212.1的pod流量,内核会做什么处理,可以执行命令:

Terminal window
ip route get 8.8.8.8 from 10.42.212.1 iif calico-xxxx

奇怪的是当间歇到nslookup解析成功时,内核会返回结果,告诉我们下一步路由到192.168.0.1,通过bond1设备。 当间歇到nslookup解析失败时,命令会弹出报错,内核找不到下一跳的路由。这就是为什么我们的包卡在宿主机上,转发不出去的宿主机上的体现。 由此,自然的想到这个问题:为什么会间歇动态的找不到路由,路由是否被说明坏蛋在周期性捣乱,甚至删除路由?

执行下面命令观察能看到pod相关有路由:‘10.42.212.1 dev calidc0cf78e5bd scope link’ ,但是这条路由间歇会消失,消失的时候正好对应pod内nslookup域名解析失败,怀疑是这条路由的消失在作祟,是不是有人删了这条路由?

Terminal window
ip route show | grep 10.42.212.1

执行下面命令,监听内核网络时间,包括:路由表变化、link网卡状态变化、ip地址变化。

Terminal window
ip -ts monitor route link addr

修改NetworkManager的配置,让他不接管calico生成的路由,不让他删掉calico在宿主机删生成的pod回包路由。

/etc/NetworkManager/conf.d/calico.conf
# let go of calico devices from NetworkManager!
cat << EOF > /etc/NetworkManager/conf.d/calico.conf
[keyfile]
unmanaged-devices=interface-name:cali*;interface-name:tunl*;interface-name:vxlan.calico;interface-name:vxlan-v6.calico;interface-name:wireguard.cali;interface-name:wg-v6.cali
EOF
# restart NetworkManager
systemctl restart NetworkManager
Terminal window
kubectl -n do run netshoot-30 \
--rm -it \
--restart=Never \
--image=nicolaka/netshoot \
--overrides='{"spec":{"nodeName":"cm-bm-5090-30"}}' \
-- bash