因为这台服务器是我配置的,防火墙虽然开着但我已经开启端口访问了,所以肯定不是因为防火墙阻断连接的缘故。但由于这篇文章是篇踩坑排查文档,所以还是把这种情况写出来了
然而FirewallD和Docker相处的并不是特别好,当FirewallD启动(或重新启动)时,会从iptables中删除DOCKER链,造成Docker不能正常工作:
FirewallD
CentOS-7 introduced firewalld, which is a wrapper around iptables and can conflict with Docker.
When firewalld is started or restarted it will remove the DOCKER chain from iptables, preventing Docker from working properly.
When using Systemd, firewalld is started before Docker, but if you start or restart firewalld after Docker, you will have to restart the Docker daemon.
摘自Docker官方文档《
CentOS - Docker Documentation
》
在CentOS 7中,如果设置使用systemd开机自启动Docker服务是不会有问题的,因为Docker在systemd配置文件中明确注明了“After= firewalld.service”,以保证Docker daemon 在FirewallD启动后再启动。
(Docker:惹不起我还躲不起吗)
但每当用户手动重启过FirewallD服务之后,FirewallD服务会将Docker daemon写入iptables的DOCKER链删除,所以需要手动重新启动一次Docker daemon服务,让Docker daemon服务重建DOCKER链。
不过问了组里另外两个研发,都说没有动过。查看了shell的history也没找到对应的记录。
这就很奇怪了。不过经过一段时间的蹲点排查之后,我终于发现了一个新的原因:
情况三:没有启用IP_FORWARD
因为一直没法定位出问题的所在,所以我们研发组都是发现不能正常访问仓库时,手动登陆宿主机重启Docker daemon服务。
在有一次登录到宿主服务器上准备重启Docker daemon服务前,我突然想起之前在用Docker的时候还碰到过另一个问题:如果宿主机没有启用IP_FORWARD功能,那Docker容器在启动时会输出一条警告消息:
WARNING: IPv4 forwarding is disabled. Networking will not work.
并且将不能在启动的容器中访问外部网络,容器对外暴露的端口外部也不能正常访问:
会不会是因为宿主机的IP_FORWARD功能没有启用所以才引起的这个故障呢?
果然,输出表示当前系统的IP_FORWARD功能处于停用状态!
可是问题来了,当时启动容器的时候都是好的啊,什么都没有输出,怎么用着用着IP_FORWARD功能就被禁用了呢?
等等,Docker daemon服务在启动的时候会自动设置iptables设置,难不成它还会检查IP_FORWARD设置,并帮我临时启用吗?
带着这个假设,我手动重启了一下Docker daemon服务:
果然,Docker daemon服务在启动过程中会检查系统的IP_FORWARD配置项,如果当前系统的IP_FORWARD功能处于停用状态,会帮我们临时启用IP_FORWARD功能,然而临时启用的IP_FORWARD功能会因为其他各种各样的原因失效…
虽然具体造成本次故障的原因现在还没有确凿的证据定位出,但我现在严重怀疑是因为重启网络服务造成的。因为出问题的服务器宿主机上运行着我们研发组正在开发的Web项目,其中有一个功能是修改网卡IP地址,这个功能在修改完网卡IP后,会自动调用下面的命令重启网络服务:
Docker daemon服务在启动的时候会帮帮我们调整很多的配置项,比如这次出事儿的IP_FORWARD配置。
Docker daemon启用IP_FORWARD功能是因为Docker容器默认的网络模式(bridge/网桥模式)会给每个容器分配一个私有IP,如果容器需要和外部通信,就需要使用到NAT。NAT需要IP_FORWARD功能支持,否则无法使用。这也解释了为什么会出现在IP_FORWARD功能停用的情况下,使用bridge模式的容器内外均无法访问的情况。
只是在Linux下,出于安全考虑,默认是停用IP_FORWARD功能的,Docker daemon服务在启动时会检查IP_FORWARD功能是否已经启用,如果没有启用的话,Docker daemon会
悄无声息
的
临时启用
此功能,然而临时启用的IP_FORWARD功能并不能持久化,会因为其他命令的干扰导致失效。
不过这次的事情告诉了我一个小道理:当出现问题的时候,不要慌,要结合经验大胆的做出假设并验证,治标治本。
2018年11月5日 22:42:26