docker宿主机不能ping通容器内部ip,使用tcpdump抓包后则能ping通
文章目录
问题现象
一次意外的服务器宕机,导致服务器上容器不能访问,在宿主机上也不能ping通容器内的ip。
问题定位
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
于是,在主机上面开启 ip_forward 开关:
修改/etc/sysctl.conf ,在文件里增加一条net.ipv4.ip_forward = 1
然后sysctl -p /etc/sysctl.conf 生效。
改完后,再启动容器,该Warning就消失了,但是在宿主机上也不能ping通容器内的ip。
tcpdump抓包
既然还是不通,那祭出大杀器Tcpdump呗,在宿主机的docker0上开始抓包分析:
tcpdump -nn -i docker0
然后在宿主机上再次执行ping命令:
ping 172.17.0.5
64 bytes from 172.17.0.1: seq=1104 ttl=64 time=0.203 ms
64 bytes from 172.17.0.1: seq=1105 ttl=64 time=0.166 ms
发现莫名其妙的通了,停掉tcpdump后,发现又不能ping通,试了几次发现,只要我tcpdump抓包,网络就通。一旦tcpdump停掉,网络就不通。
问了度娘后,才知道tcpdump命令,会使得网卡进入混杂模式,使它会接受不是属于自己的报文。
没错,通过
cat /sys/class/net/docker0/flags
0x1103
查询状态(右数第3位,0和1表示是否为混杂模式)。
结果为0x1003
当开启tcpdump时为0x1103,关闭tcpdump时为0x1003
那么说明问题就是docker0在默认情况下,并没有进入混杂模式导致的。
所以,修复方案就是把这个docker0的网卡,直接设置为混杂模式:
ifconfig docker0 promisc
或
ip link set docker0 promisc on
然后验证,一切OK。
ip link set docker0 promisc off
再次确认一下,将混杂模式关闭后,容器里面继续不通。
到此,整个网络问题搞定。
可能的原因
猜测可能这台机器是新安装的,一开始没有打开IP Forward转发开关。然后又是手动安装的Docker离线包,导致docker0为非混杂模式。
问题总结
本次容器网络不通问题,总结一下,大概:
- 主机IP Forward转发没打开。
- Docker0网桥的混杂模式未打开。
扩展阅读
混杂模式(英语:promiscuous mode):是指一台机器的网卡能够接收所有经过它的数据流,而不论其目的地址是否是它。一般计算机网卡都工作在非混杂模式下,如果设置网卡为混杂模式需要root权限。
- Linux下设置
1、设置混杂模式 ifconfig eth0 promisc
2、取消混杂模式 ifconfig etho -promisc
备注:eth0为网卡名