问题现象

一次意外的服务器宕机,导致服务器上容器不能访问,在宿主机上也不能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为非混杂模式。

问题总结

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

  1. 主机IP Forward转发没打开。
  2. Docker0网桥的混杂模式未打开。

扩展阅读

混杂模式(英语:promiscuous mode):是指一台机器的网卡能够接收所有经过它的数据流,而不论其目的地址是否是它。一般计算机网卡都工作在非混杂模式下,如果设置网卡为混杂模式需要root权限。

  • Linux下设置

1、设置混杂模式 ifconfig eth0 promisc

2、取消混杂模式 ifconfig etho -promisc

备注:eth0为网卡名