Docker 网络 IP 地址冲突了的解决方案

1、前置知识

在网络通信中,由于交换机能力的限制和网线长度的物理约束,不可能将所有主机连接到同一个交换机上,并处于同一个二层网络中。此外,主机间的 ARP 广播会导致网络瘫痪。因此,需要将主机拆分到多个子网中,然后通过路由器组成三层网络。

IP 地址由网络地址和主机地址两部分组成。例如,在 10.0.0.1/8 中,10 是网络地址,0.0.1 是主机地址。子网掩码(如 /8)用于区分这两部分。IP 地址实际上是由 32 位二进制组成,x.x.x.x 格式只是为了方便人类阅读而转换成十进制。例如,/8 表示第一段是网络地址,/16 表示前两段是网络地址。

2、问题表现
  • Docker 进程无法启动
  • 容器端口无法访问,抓包显示有入站但没有出站
3、排查

如果你遇到的是 dockerd 无法启动的情况,可以尝试以下排查方法:

  1. 查看日志

    通常可以在日志中看到类似如下的错误信息(具体日志内容根据实际情况而定):

    Error starting daemon: Error initializing network controller: Error creating default "bridge" network: could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network
    
  2. 手动启动 dockerd

    通过查看 Docker 服务的启动命令来进行手动启动。可以使用以下命令查看:

    grep ExecStart /usr/lib/systemd/system/docker.service
    

    通常会看到类似如下的输出:

    ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
    

    然后手动启动 dockerd

    /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
    

    在输出中,你可能会看到错误信息提示无法创建 docker0 网桥。

  3. 检查网络接口

    使用 ip addr 命令查看网络接口,确认是否存在 docker0docker_gwbridge。如果缺少 docker0,基本可以确定是 docker0 无法创建导致 dockerd 启动失败。

4、解决

找到并解决网段冲突问题是关键。

  1. 找到占用的网段

    默认的 docker0 网段是 172.17.0.0/16docker_gwbridge 网段是 172.18.0.0/24。需要确认这两个网段是否被占用。

    • 使用 ping 命令:简单的方法是 ping 一下这些网段的地址,如无响应则可能未被占用。
    • 查看路由表:使用 route -n 命令查看路由表,确认是否有冲突的网段。
  2. 修改 Docker 占用的网段

    在修改前,需要先停止 Docker 进程。如果使用 Docker Service,Docker 会占用四个网段:docker0docker_gwbridgeucp(不常见)、ingress。其中前三个网段可以通过配置文件配置,第四个需要手动创建。

    • 编辑配置文件

      配置文件路径为 /etc/docker/daemon.json,该文件默认不存在,需要手动创建。以下是一个示例配置:

      {
          "bip": "192.168.1.1/24",
          "default-address-pools": [
              {"base": "10.252.0.0/24", "size": 24},
              {"base": "10.252.1.0/24", "size": 24},
              {"base": "10.252.2.0/24", "size": 24}
          ]
      }
      

      注意:default-address-pools 至少要有两项,按顺序依次为 docker0docker_gwbridgeucp。配置三个是最佳实践。

    • 修改 ingress 网段

      ingress 网段需要手动创建。在初始化 Docker Swarm 后,启动 Docker Stack/Service 前,执行以下脚本:

      yes 'y' | docker network rm ingress
      yes 'y' | docker network rm my-ingress 2>&1 | true
      docker network create \
        --driver overlay \
        --ingress \
        --subnet=10.252.3.0/24 \  # 指定 ingress 的网段,不要和 daemon.json 中的网段冲突
        --gateway=10.252.3.2 \
        --opt com.docker.network.driver.mtu=1200 \
        my-ingress
      

      删除 ingress 是异步操作,因此新建一个不同名字的网络以避免重名错误。

    • 清理 Docker 缓存

      在重启 Docker 前,最好清理一下 Docker 的缓存:

      ip link del dev docker0
      ip link del dev docker_gwbridge
      rm -rf /var/lib/docker/network
      
5、案例

在某环境中,将 docker0 配置为 10.252.0.0/24 后,dockerd 无法启动。排查后发现 route -n 中存在如下路由:

Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.0.0        0.0.0.0         255.0.0.0       U     0      0        0 eth0

10/8 被占用,导致与 10.252.0.0/24 冲突。联系网管删除 10/8 路由后问题解决。

6、另一种粗糙简单的解决办法

直接手动创建 docker0 网桥:

ip link add name docker0 type bridge
ip addr add dev docker0 10.252.0.1/24

这种方法最简单,但机器重启后 docker0 会自动被删除,因此不持久。而且,这种方法不一定能解决网段冲突问题,只是让 Docker 能启动。

代码运行结果示例

假设我们按照上述步骤修改了 /etc/docker/daemon.json 文件,并重启了 Docker 服务:

  1. 修改配置文件

    {
        "bip": "192.168.1.1/24",
        "default-address-pools": [
            {"base": "10.253.0.0/24", "size": 24},
            {"base": "10.253.1.0/24", "size": 24}
        ]
    }
    
  2. 重启 Docker 服务

    sudo systemctl restart docker
    
  3. 检查网络接口

    ip addr show docker0
    

    输出:

    3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
        link/ether 02:42:ac:11:00:01 brd ff:ff:ff:ff:ff:ff
        inet 192.168.1.1/24 brd 192.168.1.255 scope global docker0
           valid_lft forever preferred_lft forever
        inet6 fe80::42:acff:fe11:1/64 scope link 
           valid_lft forever preferred_lft forever
    

通过上述步骤,我们成功修改了 Docker 的默认网段,并解决了 IP 地址冲突问题。希望这篇文章对你有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值