背景
有时候莫名奇妙的在一顿操作后,容器网络就坏了。然后外部无法访问容器的服务了。以前以为是操作了防火墙导致了容器无法被访问。但是最近经过仔细比较,防火墙规则并没有变化,但是容器就无法访问了。
分析
对于容器网络的讨论,在《docker容器网络不通的深度大分析》一文中做了详细的说明。
在防火墙、路由表、网桥等因素都正常的情况下,依然出现了容器网络无法被外部访问的情况。不过在宿主机上,是可以正常访问容器的服务的。
不过,在重启了docker服务之后,容器又可以被正常访问了。
显然,在重启docker服务之后,会自动修复网络的问题。而网络的问题,无外乎IP地址相关、路由表、端口映射这些配置。而这些配置检查后也是没有问题的。同时,在出现了容器网络无法访问的时候,是一直都无法自动恢复,只有重启docker服务才行。
显然,重启docker服务做了一些工作,使容器网络可以正常运转。
经过分析这些这些现象,有一种就是临时的网络设置,在重启docker服务时会自动创建,当网络被重启之后,这个临时设置就被丢失了。也就导致了容器网络无法被访问了。
在宿主机上又可以正常访问容器的服务,只有外部IP无法访问容器的服务。
到此,可以得到一个初步的结论:
1.容器内的服务运行正常
2.容器端口映射正常
3.宿主机和容器之间的网络正常
但是现在还是不能正常在外部访问容器的服务,但是可以确定的是,这个故障是网络相关的。所以先复现一下问题,就重启一下网络,确定重启之后容器网络是否就不行了。
systemctl restart network
执行上面的命令,重启了宿主机的网络。然后容器服务无法被访问了。这个可以证实,目前的问题是和网络相关,而不是容器的某些文件被破坏导致的。
而容器网络除了网桥、防火墙、路由表等,还有一个就是ipv4的转发。
sudo sysctl net.ipv4.ip_forward
如果输出为 net.ipv4.ip_forward = 1,则表示 IPv4 转发已经启用;如果输出为 net.ipv4.ip_forward = 0,则表示 IPv4 转发已禁用。
在重启network之前,这个值为1,重启之后变为0。说明此配置为临时配置,重启网络后丢失。丢失之后,容器网络就无法被外部正常访问了。
重启docker服务,可以观察到此值又变为了1。再重启网络,此值再次变为0。再不重启docker服务的前提下,我们临时开启一下ipv4转发:
sudo sysctl -w net.ipv4.ip_forward=1
执行后,ipv4转发立即生效,容器网络也立即可以被访问了。
如果想此配置永久保存下来,需要修改配置文件/etc/sysctl.conf:
sudo sed -i 's/net.ipv4.ip_forward=0/net.ipv4.ip_forward=1/' /etc/sysctl.conf
sudo sysctl -p
这个命令将会:
使用 sed 来搜索 /etc/sysctl.conf 文件中包含 net.ipv4.ip_forward=0 的行。
如果找到匹配的行,它将被替换为 net.ipv4.ip_forward=1,即将值设为 1。
-i 选项用于在原始文件中直接修改,而不是将结果输出到终端。
请确保在执行此命令之前备份 /etc/sysctl.conf 文件以防意外。
完成后,你需要重新加载 sysctl -p 配置,使更改立即生效。
这样做之后,IPv4 转发就应该已经永久启用了。这样容器再也不怕重启网络了。
总结
重启网络会清除临时的网络配置,对于临时创建的配置的服务来讲,就是一种毁灭性打击。这么重要的配置,需要永久保存,防止网络重启后容器网络就无法转发了。
来源: http://www.yu7s.com/article/20240417144353194.html