写点什么

有点奇怪!访问目的网址,主机能容器却不行

  • 2022 年 8 月 01 日
  • 本文字数:2472 字

    阅读完需:约 8 分钟

有点奇怪!访问目的网址,主机能容器却不行

本文分享自华为云社区《《跟唐老师学习云网络》 - 问题定位 - 主机通但容器不通》,作者: tsjsdbd。


本次网络故障:主机可以访问目的网址,但是容器里却不行。问题有点奇怪,让我们跟着唐老师分析的脚步,看看一般网络问题都怎么定位的吧。

问题现象


首先,这个节点上面的 Docker 是全新安装的,系统 Centos 也是刚装的。部门小伙伴报障说,启动 Docker 后,容器里面无法访问网络;但是 Host 主机上访问则明明是好的。


报错:



第一条红线是容器里面,第 2 条红线是主机上。


图示如下:



具体使用场景为,容器中用 apt-get 连华为云的镜像源(mirrors.tools.huawei.com)来安装软件包。但是容器中报错:Temporary failure resolving 'mirrors.tools.huawei.com'。


但是主机连这个源站却是 OK 的。


大家想一下,可能什么原因?


IP Forward 转发


上手开始定位,所以我登录环境,准备启动一个空白容器先试下。


可是一启动容器,马上看到这么一条告警:


docker run -it ubuntu:18.04 /bin/bash

WARNING: IPv4 forwarding is disabled. Networking will not work


可以看到,这个告警信息,正常的容器以前是没有的。所以很明显,这个问题必须先搞定。

查看:


cat /proc/sys/net/ipv4/ip_forward

0


事实也是这样,从主机看待容器,它(容器)就是另一台“电脑”。报文经过主机给到容器,相当于主机帮忙“转发”给容器。所以主机必须要有“报文转发能力”。 ps,不好理解的话,可以回看一下唐老师前面的课程《跟唐老师学习云网络 - 网络命名空间》篇。


所以,我们在主机上面开启 ip_forward 开关:


修改/etc/sysctl.conf ,在文件里增加一条 net.ipv4.ip_forward = 1


然后 sysctl -p /etc/sysctl.conf 生效。


改完后,再启动容器,该 Warning 就消失了。可是发现 DNS 还是无法解析,错误 Temporary failure resolving 'mirrors.tools.huawei.com'仍然存在。

DNS 中 search 字段


容器中不通,那咱们就抓包看看。于是我在如下位置(所有容器报文出去都要经过的地方),即 docker0 上面抓包:



tcpdump -nn -i docker0 port 53


然后容纳中


ping mirrors.tools.huawei.com


发现发出去的查询 DNS 的报文中,为什么要在我询问的域名后面加个尾巴?(下图红线)



还记得《跟唐老师学习云网络 - DNS 电话簿》章节的知识不,/etc/resolv.conf 配置文件中,有个高级参数 search 字段。它可以用来帮你查询域名的时候,往目标域名尾巴上添东西的(即补上后缀)的。这个在 Kubernetes 的 Service 微服务里面,有用到。


So,我们将 /etc/resolv.conf 文件中的 search 字段给注释掉,这个参数暂时没用。


# Generated by NetworkManager

#search novalocal

nameserver 100.79.1.250

nameserver 100.79.1.46


ps,最终验证发现,这个 search 参数,并不是当前容器网络不通的原因。 不过注释掉这个参数,也是合理的,因为我们并不需要 novalocal 后缀。

DNS 不通


继续分析,容器里面无法解析“mirrors.tools.huawei.com”这个域名。那先看容器里面的/etc/resolv.conf 文件,其内容:


# Generated by NetworkManager

#search novalocal

nameserver 100.79.1.250

nameserver 100.79.1.46


可以看到是 copy 了主机 Host 里的/etc/resolv.conf 文件。既然跟主机的 DNS 配置一样,那先看看主机怎么解这个域名。


在 Host 中使用:


nslookup mirrors.tools.huawei.com

** server can't find mirrors.tools.huawei.com: NXDOMAIN


发现,域名也是解不开的。。。囧,那主机上 apt-get 怎么获取到包的?咱们回顾一下《跟唐老师学习云网络 - DNS 电话簿》章节的知识,解开一个域名,是单纯依靠 DNS 服务器的么?



So,赶紧看下 /etc/hosts 文件,发现一条写死的 IP 记录。难怪。。。原来同事之前域名解不开就直接加了“偷懒”路径。(ps,容器也想加这种写死的域名-IP 解析路径,可以使用 docker run --add-host 参数。但是我不想只是规避,而是真的搞定网络问题)


于是找一台能解该域名的机器,把 DNS 服务器地址抄过来,放入 /etc/resolv.conf 配置文件见如下第一个 DNS 服务器记录。


# cat /etc/resolv.conf

# Generated by NetworkManager

#search novalocal

nameserver 10.129.2.34

nameserver 100.79.1.250

nameserver 100.79.1.46


然后把 /etc/hosts 里面的记录删除,再试了下,主机可以解开域名了。


然后重新创建容器,并确认容器中的 /etc/resolv.conf 文件内容也对。


但是发现域名还是不通。。。

混杂模式


既然还是不通,那祭出大杀器 Tcpdump 呗(可以回看《跟唐老师学习云网络 - tcpdump》章节),所以继续在主机的 docker0 上开始抓包分析:


tcpdump -nn -i docker0 port 53


然后容器里面仍然执行:


ping mirrors.tools.huawei.com


但是好奇怪,这次又通了。(于是停掉 tcpdump,跟同事说好了,结果他说还不行呀。我试下,确实又还不行)


试了几次发现,只要我 tcpdump 抓包,网络就通。一旦 tcpdump 停掉,网络就不通。大家想到了什么?


看过唐老师之前 tcpdump 章节的同学应该有印象,tcpdump 命令,会使得网卡进入混杂模式,使它会接受不是属于自己的报文。


没错,通过


cat /sys/class/net/docker0/flags


查询状态(右数第 3 位,0 和 1 表示是否为混杂模式)。


结果为 0x1003


而当开启 tcpdump 时为 0x1103


那么说明问题就是 docker0 在默认情况下,并没有进入混杂模式导致的。


所以,修复方案就是把这个 docker0 的网卡,直接设置为混杂模式:


ifconfig docker0 promisc



ip link set docker0 promisc on


然后验证,一切 OK。


ip link set docker0 promisc off


再 2 次确认一下,将混杂模式关闭后,容器里面继续不通。


到此,整个网络问题搞定。

可能的根因


猜测可能这台机器是新安装的,一开始没有打开 IP Forward 转发开关。然后又是手动安装的 Docker 离线包,导致 docker0 为非混杂模式。


在打开 IP Forward 转发开关后,如果执行如下操作:


ip link delete docker0

systemctl restart docker.service


按理,应该也可以修复问题。

问题总结


本次容器网络不通问题,总结一下,大概:

  1. 主机 IP Forward 转发没打开。 ==》原因 1

  2. conf 中有 search 字段。 ==》干扰项

  3. 主机 DNS 服务器地址设置不对。 ==》原因 2

  4. Docker0 网桥的混杂模式未打开。 ==》原因 3

本次网络故障,未涉及 iptables 相关问题,所以还算简单。感谢阅读。


点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 3
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
有点奇怪!访问目的网址,主机能容器却不行_云计算_华为云开发者联盟_InfoQ写作社区