d49: Docker网络与虚拟机挂起问题
Docker网络与虚拟机挂起问题
在使用Docker和虚拟机的过程中,我遇到了一个棘手的问题:在恢复挂起的虚拟机后,宿主机原本能够访问的MySQL和Nacos服务突然无法访问了。于是,我开始了一场紧张刺激的排查之旅。
问题排查过程
初步排查
在排查过程中,我首先检查了MySQL和Nacos容器的网络配置。通过以下命令,我发现Nacos容器使用了Docker的默认网络bridge,而MySQL容器则没有:
[root@heima ~]# docker inspect mysql -f '{{range $k,$v := .NetworkSettings.Networks}}{{$k}} {{end}}'
heima-net
[root@heima ~]# docker inspect nacos -f '{{range $k,$v := .NetworkSettings.Networks}}{{$k}} {{end}}'
bridge heima-net
于是,我尝试将MySQL容器也连接到bridge网络,结果发现确实可以访问了:
[root@heima ~]# docker network connect bridge mysql
但它们都连接了heima-net网络,理论上应该可以通信。当时我被一些理论知识误导,没有发现真正的问题所在。于是,我将所有容器都连接到了bridge网络,确实可以通信了。但这样太麻烦了,而且之前它们能够正常工作,说明问题出在其他地方。
进一步排查
经过一系列排查,我发现问题可能出在网络传输上。在添加了以下iptables规则后,问题奇迹般地解决了:
sudo iptables -I DOCKER-USER 1 -d 172.18.0.2 -p tcp --dport 3306 -j ACCEPT
但后来我发现,这并不是网络传输的问题。经过复现问题,我猜测之前乱搞connect连接可能把iptables规则搞乱了。即使断开了连接,端口映射也会有残留的影响。而iptables指令触发了规则重新加载,从而修复了问题。
深入排查
为了找到更根本的解决方法,我分别在虚拟机挂起恢复前后检查了网桥的状态:
-
挂起恢复后,重启Docker前检查:
ip link show | grep -E "(docker|br-|veth)"ip addr show docker0 ip addr show br-73a00eba170ciptables -t nat -nL DOCKER | head -10挂起后的网桥状态如下:
ip addr show br-73a00eba170c 617: br-73a00eba170c: ... state UP ... link/ether 02:42:10:e3:ad:9b brd ff:ff:ff:ff:ff:ff # 缺少 IPv4 地址!只有 MAC 地址 -
重启Docker恢复后:
ip addr show br-73a00eba170c 617: br-73a00eba170c: ... state UP ... link/ether 02:42:10:e3:ad:9b brd ff:ff:ff:ff:ff:ff inet 172.18.0.1/16 brd 172.18.255.255 scope global br-73a00eba170c # ← 有这个!
通过对比,我发现问题的真正原因:虚拟机挂起时,自定义网络网桥br-73a00eba170c的IP地址配置丢失了!虽然网桥接口本身还在,但失去了172.18.0.1/16这个网关IP,导致宿主机无法路由到172.18.0.0/16这个网段。
解决方法
为了解决这个问题,我通过以下命令重新添加了这个网段:
sudo ip addr add 172.18.0.1/16 dev br-73a00eba170c
为了避免每次手动修复,我创建了一个修复脚本:
if ip addr show br-73a00eba170c | grep -q "172.18.0.1"; then
echo "Network already fixed"
else
ip addr add 172.18.0.1/16 dev br-73a00eba170c
echo "Docker network fixed"
fi
此外,还可以通过编写systemd服务来让脚本自动执行。
后续问题及预防措施
第二天,我的虚拟机又出现了问题。通过journalctl -u docker.service查看日志,发现Docker在启动时发现了一些陈旧的(stale)网络沙盒和端点,并且在清理过程中遇到了冲突。这次问题比较严重,补充网络IP或重启Docker都无法解决问题,我只能重启虚拟机。
这可能是因为虚拟机挂起时Docker的网络清理不完全导致的。为了避免类似问题再次发生,我在挂起虚拟机之前执行了以下命令,将所有Docker容器停掉:
sudo docker stop $(sudo docker ps -q)
总结
通过这次经历,我深刻认识到虚拟机挂起可能会导致Docker网络配置丢失,从而引发一系列问题。虽然目前还不清楚为什么虚拟机挂起会导致网段丢失,但通过创建修复脚本和在挂起前停掉Docker容器,可以有效避免这些问题的发生。
更多推荐


所有评论(0)