当前位置: 首页 > 科技观察

Docker网络IP地址冲突,怎么办?

时间:2023-03-21 13:42:00 科技观察

这个问题其实有点麻烦,网上也没看到什么全面正确的文章。值得写一个单独的记录。1前置知识因为交换机的能力有限,网线的连接不可能无限长,所以我们不可能把所有的主机都连接到同一个交换机上,然后在同一个二层网络中。即使可以,主机间的ARP广播也会瞬间瘫痪网络。所以我们不得不把主机一个一个地拆分成小的子网,然后通过路由器将它们合并成一个三层网络。我们通常所说的IP地址实际上由网络地址和主机地址两部分组成。例如10.0.0.1/8,前10为网络地址,后面的0.0.1为主机地址。那么我怎么知道如何拆分这两段呢?它依赖于子网掩码,即/8。IP其实是由32位的二进制组成的,x.x.x.x只是为了人的阅读方便转为十进制而已。一个简单粗暴的办法就是认为每一段都是8位,所以/8表示第一段是一个网络地址。同样,/16表示前两段是网络地址。在10.0.0.0/16中,网络地址为10.0,0.0的后两位代表各子网中的主机地址。例如,10.0.0.1/16和10.0.0.2/16是同一子网中的两台主机。10.0.0.1/16和10.1.0.1/16是不同子网上的两台主机。这里只是简单粗略的介绍一下。更多信息请自行查阅资料学习。2.问题是docker进程无法启动。无法访问容器端口。抓包显示有入站没有出站。看日志$systemctlstatusdocker$journalctl-udocker$dmesg|grepdocker一般可以看到如下日志:docker0:linkisnotreadydocker_gwbridge:linkisnotready或者更简单的排查方法,直接手动启动dockerd看看。启动方式可以通过grepExecStart/usr/lib/systemd/system/docker.service查看。一般来说,执行如下:$/usr/bin/dockerd--debug然后可以看到最后的输出:INFO[2021-07-29T02:25:55.811673622Z]stoppingeventstreamfollowinggracefulshutdownerror=""module=libcontainerdnamespace=mobyfailedtostartdaemon:Errorinitializingnetworkcontroller:listbridgeaddressesfailed:PredefinedLocalScopeDefaultNetworksList:[10.252.0.0/2410.252.1.0/2410.252.2.0/24]:noavailablenetwork这时候可以查看ipaddr是否有docker0和docker_gwbridge。创建导致dockerd无法启动。4解决查找占用网段问题。默认docker0网段为172.17.0.0/16,docker_gwbridge网段为172.18.0.0/24。您需要确认这两个网段是否被占用。最简单的方法就是ping,如果没有反应,说明没有被占用。二是查看本地路由表route-n,确认是否有冲突段。一般来说,你会发现相关网段要么已经被占用,要么就是路由表有冲突。比如我的环境,我配置docker0为10.252.0/24,然后dockerd无法启动。经过排查,发现route-n中有这么一行:10.0.0.0172.21.0.1255.0.0.0UG000eth0,意思是10/8被占用了,导致和我的10.252.0/24冲突。后来联系网管删除了10/8路由,解决了。修改docker占用的网段以下操作需要先停止docker进程$systemctlstopdocker如果使用docker服务,那么docker会占用四个网段:docker0docker_gwbridgeucp(dockerengine占用,不常用)ingress前三个网络段可以通过配置文件进行配置,第四段只能手动创建。前三个网段会读取/etc/docker/daemon.json配置文件,默认不存在,需要手动创建。{"bip":"","默认地址池":[{"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_gwbridgeucpto以防万一,配置三个最好😄。接下来就是修改ingress,比较麻烦,需要手动创建。我的解决方案是在初始化dockerswarm之后,启动dockerstack/service之前执行如下脚本:删除ingress删除my-ingress(不一定存在,不存在则忽略)新建my-ingress$yes'y'|dockernetworkrmingress$yes'y'|dockernetworkrmmy-ingress2>&1|true$dockernetworkcreate\--driveroverlay\--ingress\--subnet=10.252.3.0/24\#指定ingress的网段,do与上面daemon.json的网段不冲突--gateway=10.252.3.2\--optcom.docker.network.driver.mtu=1200\my-ingressingress为默认名称。使用不同的名称创建一个新的原因是因为删除入口是异步的。如果删除ingress,马上新建一个名为ingress的网络,很可能会报重名错误。在重启docker之前,最好清理一下docker缓存:$iplinkdeldevdocker0$iplinkdeldevdocker_gwbridge$rm-rf/var/lib/docker/network另一种粗略的解决方案另一种粗略的解决方案是简单地手动创建一个docker0。这个方案最简单,但是机器重启后docker0会自动删除,所以这个方法不耐用。而且,其实不一定能解决网段冲突的问题,只是说明docker可以启动了。iplinkaddnamedocker0typebridgeipaddradddevdocker010.252.0.1/24