如何解決docker-compose網(wǎng)段路由沖突,docker-compose自定義網(wǎng)絡(luò)
問題復(fù)現(xiàn)
網(wǎng)上這個問題出現(xiàn)的挺多的,我也總結(jié)一下,因為里面涉及到的網(wǎng)絡(luò)基礎(chǔ)知識比較多的,正好我一直不懂這一塊,需要大補
問題
openvpn掛vpn連接遠程主機,發(fā)現(xiàn)無法ping通遠程主機IP:172.20.2.52,以前一直可以遠程登錄
問題排查
先route一波查看一下路由表,看一下主機訪問172.20.2.52的路由路徑
root@ubuntu:/etc/openvpn# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default bogon 0.0.0.0 UG 600 0 0 wlp2s0 link-local 0.0.0.0 255.255.0.0 U 1000 0 0 br-3b2a750ddc03 172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0 172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-e2cde023b4a7 172.19.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-94d6396c6c12 172.20.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-3b2a750ddc03 192.168.43.0 0.0.0.0 255.255.255.0 U 600 0 0 wlp2s0
發(fā)現(xiàn)和目標IP 172.20.2.52相似的目標網(wǎng)段為172.20.0.0,看后面的接口為br-3b2a750ddc03,也即是說數(shù)據(jù)被轉(zhuǎn)發(fā)到這個接口下,這貌似是個docker創(chuàng)建的網(wǎng)橋,懷疑是docker網(wǎng)橋占用了172.20網(wǎng)段,查看以下docker網(wǎng)絡(luò)
root@ubuntu:/etc/openvpn# docker network ls NETWORK ID NAME DRIVER SCOPE 22021490da82 bridge bridge local e2cde023b4a7 harbor_harbor bridge local e4aa16aea5df host host local 3b2a750ddc03 milvus bridge local 2d89edc384b1 none null local 94d6396c6c12 test_default bridge local
看到3b2a750ddc03為命名為milvus的docker網(wǎng)絡(luò),原來是milvus的容器創(chuàng)建的網(wǎng)橋,進一步檢查網(wǎng)絡(luò)內(nèi)部信息
root@ubuntu:/etc/openvpn# docker network inspect 3b2a750ddc03
可以看到所屬的容器id和容器名
"Containers": {
"22b638b8d2f05f3f8b17c62c63c00cd67ec60887fe20be19cc8f6bfb278c123b": {
"Name": "milvus-standalone",
"EndpointID": "e14a0676adba99908ab113a866650752e0e3ca21381d54ea43f6f4a33aca0fe0",
"MacAddress": "02:42:ac:19:00:04",
"IPv4Address": "172.20.0.4/16",
"IPv6Address": ""
},
"39ef60cd098c20efc62f6668375988786d1874a0f1711c15b947e46bd4da80be": {
"Name": "milvus-etcd",
"EndpointID": "34104d54ae9d3e4834fafb8d7c475d5690acff08955e7d08686999c78ccb220f",
"MacAddress": "02:42:ac:19:00:03",
"IPv4Address": "172.20.0.3/16",
"IPv6Address": ""
},
"d55dc8c8e4cce63ceb386e24ee05e27099826ec0c892aa77bb4998a99e9a67a6": {
"Name": "milvus-minio",
"EndpointID": "4eb0c415c175b7780a94ed72d09a574bad9797039a122a942bcac0e391186cfa",
"MacAddress": "02:42:ac:19:00:02",
"IPv4Address": "172.20.0.2/16",
"IPv6Address": ""
}
},
可見這個網(wǎng)絡(luò)接口下目標主機只有172.20.0.2,172.20.0.3,172.20.0.4三臺主機IP,以及172.20.0.1網(wǎng)關(guān),因此ping 172.20.2.52根本ping不通。
milvus的三個容器虛擬IP以及網(wǎng)關(guān)服務(wù)占用了172.20網(wǎng)段,openvpn創(chuàng)建的網(wǎng)段也是172.20.0.0,因此在路由中產(chǎn)生網(wǎng)段沖突,無法轉(zhuǎn)發(fā)到openvpn的對應(yīng)網(wǎng)絡(luò)接口,同理從172.17、18、19、20都是docker創(chuàng)建出來的網(wǎng)絡(luò)接口和網(wǎng)段,如果有其他網(wǎng)絡(luò)服務(wù)處在相同網(wǎng)段可能導(dǎo)致無法路由到
解決方案
(1)路由表添加細路由
在路由尋址時會根據(jù)目標IP在路由表中相同網(wǎng)絡(luò)ID(網(wǎng)段)的記錄,根據(jù)該記錄將數(shù)據(jù)轉(zhuǎn)發(fā)給下一個路由器,如果路由表中存在多條相同網(wǎng)絡(luò)ID的記錄,根據(jù)最長匹配算則最吻合的一個,因此增加一個172.20.2.0/24的目標網(wǎng)段即可,使用route add進行添加,添加目的地網(wǎng)段為172.20.2.0/24,網(wǎng)絡(luò)接口為tun0
root@ubuntu:/etc/openvpn# route add -net 172.20.2.0/24 dev tun0
tun0是openvpn創(chuàng)建的網(wǎng)絡(luò)接口,使用ifconfig查看
root@ubuntu:/etc/openvpn# ifconfig
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 10.0.1.65 netmask 255.255.255.255 destination 10.0.1.66
inet6 fe80::7778:a3ae:badc:d759 prefixlen 64 scopeid 0x20<link>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1 bytes 48 (48.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
再看一下路由已經(jīng)成功添加了一條細路由
root@ubuntu:/etc/openvpn# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default bogon 0.0.0.0 UG 600 0 0 wlp2s0 link-local 0.0.0.0 255.255.0.0 U 1000 0 0 br-3b2a750ddc03 172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0 172.18.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-e2cde023b4a7 172.19.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-94d6396c6c12 172.20.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-3b2a750ddc03 172.20.2.0 0.0.0.0 255.255.0.0 U 0 0 0 tun0 192.168.43.0 0.0.0.0 255.255.255.0 U 600 0 0 wlp2s0
此時再ping 172.20.2.52已經(jīng)可以ping通
root@ubuntu:/etc/openvpn# ping 172.20.2.52 PING 172.20.2.52 (172.20.2.52) 56(84) bytes of data. 64 bytes from 172.20.2.52: icmp_seq=1 ttl=126 time=45.2 ms 64 bytes from 172.20.2.52: icmp_seq=2 ttl=126 time=43.1 ms
(2)刪除docker-compose網(wǎng)橋路由
另一種方法是找到docker網(wǎng)橋?qū)?yīng)的容器應(yīng)用之后直接刪除容器,則對應(yīng)的網(wǎng)絡(luò)接口和路由都會刪除,進入milvus工程目錄使用docker-compose停止和刪除容器即可
root@ubuntu:~/docker/compose/milvus# docker-compose down Removing milvus-standalone ... done Removing milvus-minio ... done Removing milvus-etcd ... done Removing network milvus
查看route路由表172.20.0.0網(wǎng)段已經(jīng)消失,ifconfig,docker network ls都已經(jīng)查不到對應(yīng)的網(wǎng)絡(luò)接口,此時再重啟openvpn即可
(3)修改docker-compose.yml配置網(wǎng)絡(luò)
docker-compose默認會給每個應(yīng)用從172.18.0.0依次往后匹配網(wǎng)段,只要容器沒有被刪除則一直占用網(wǎng)絡(luò),如果刪除后重啟則依次采用新的網(wǎng)段之前的不再使用,因此很容易造成路由沖突,可以在單個docker-compose.yml文件中增加networks配置,設(shè)置網(wǎng)段為10.103.0.0/16
networks:
default:
name: milvus
ipam:
driver: default
config:
- subnet: 10.103.0.0/16
重啟docker-compose,此時路由和docker網(wǎng)絡(luò)都切換為了10.103.0.0/16網(wǎng)段
root@ubuntu:~/docker/compose/milvus# docker network ls|grep milvus 4a772f696084 milvus bridge local root@ubuntu:~/docker/compose/milvus# route |grep br-4a772f696084 10.103.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-4a772f696084
root@ubuntu:~/docker/compose/milvus# docker network inspect 4a772f696084
"Containers": {
"71248b9185a5279bfd6a1c67d2a318554217beb94b8f5c0d9f837fc8480911dc": {
"Name": "milvus-minio",
"EndpointID": "2c39a39329eca0389eb6204e64f67869dedd787ea17d067fc23c9dd0f179dafa",
"MacAddress": "02:42:0a:67:00:03",
"IPv4Address": "10.103.0.3/16",
"IPv6Address": ""
},
"78adbd5868226361033c74532ea57d4fcbb5ef13f81fdd4e4fec531c19a9b629": {
"Name": "milvus-standalone",
"EndpointID": "711bb663135135189852e1ba39ab7c58b2acf84f5a5bb53fca00425efd08a234",
"MacAddress": "02:42:0a:67:00:04",
"IPv4Address": "10.103.0.4/16",
"IPv6Address": ""
},
"9d221d4fb00ff8a1dd8d95e3ed8198f134f2177ccccbb32f393595a29e1d884b": {
"Name": "milvus-etcd",
"EndpointID": "79bc5d0ffacb5a124ee5a2452c33346c871f6564bc446c21ba59516d080cfd19",
"MacAddress": "02:42:0a:67:00:02",
"IPv4Address": "10.103.0.2/16",
"IPv6Address": ""
}
(4)修改docker全局配置文件
修改全局docker網(wǎng)絡(luò)配置,docker自動分配的網(wǎng)段使用12.11.0.0/16,每個子網(wǎng)掩碼劃分為 255.255.255.0
root@ubuntu:~/docker/compose/milvus# cat /etc/docker/daemon.json
{
"insecure-registries": ["http://192.168.1.28:80"],
"default-address-pools" : [
{
"base" : "12.11.0.0/16",
"size" : 24
}
]
}
重啟docker
root@ubuntu:~/docker/compose/milvus# systemctl daemon-reload root@ubuntu:~/docker/compose/milvus# systemctl restart docker
再重新啟動docker-compose,項目切換為指定的網(wǎng)段
root@ubuntu:~/docker/compose/milvus# docker-compose up -d
Creating network "milvus" with the default driver
Creating milvus-etcd ... done
Creating milvus-minio ... done
Creating milvus-standalone ... done
root@ubuntu:~/docker/compose/milvus# docker network inspect
"Config": [
{
"Subnet": "12.11.2.0/24",
"Gateway": "12.11.2.1"
}
]
},
"ConfigOnly": false,
"Containers": {
"335d4fb5fb97e3daaf4246dd76c6a90809ac841c36c05360baeab2e20b0ef0a1": {
"Name": "milvus-standalone",
"EndpointID": "5c51dd328f3baa31183512b40872ae3e281b6a339c702ac6ccdda893320299df",
"MacAddress": "02:42:0c:0b:02:04",
"IPv4Address": "12.11.2.4/24",
"IPv6Address": ""
},
"7311706aaaa23143297632afcb482f0585afcf5de8abc3af33e737c29af2b659": {
"Name": "milvus-minio",
"EndpointID": "10068465e847919b212089d0057ea3b860ffc00df817768ebe1e7f7305e9180f",
"MacAddress": "02:42:0c:0b:02:03",
"IPv4Address": "12.11.2.3/24",
"IPv6Address": ""
},
"a3e69162650f63b12e491e44fc8268768bb6ef252cc80ccb9636cc7f621980da": {
"Name": "milvus-etcd",
"EndpointID": "610ebfc3e0f090edea8b1d076b5930ce25770e227d1db4071a26d21ee5715e50",
"MacAddress": "02:42:0c:0b:02:02",
"IPv4Address": "12.11.2.2/24",
"IPv6Address": ""
}
},
不僅是docker-compose,docker run啟動的容器的虛擬IP也變更為指定的網(wǎng)段
相關(guān)知識
(1)網(wǎng)絡(luò)基礎(chǔ)知識(網(wǎng)關(guān)、路由器)
網(wǎng)關(guān):網(wǎng)關(guān)是一個邏輯概念,網(wǎng)關(guān)是一個結(jié)點,是一個網(wǎng)絡(luò)連接到另一個網(wǎng)絡(luò)的關(guān)口,實質(zhì)上是一個網(wǎng)絡(luò)通向其他網(wǎng)絡(luò)的IP地址。
兩個不同網(wǎng)段的網(wǎng)絡(luò)結(jié)點之間通信需要使用網(wǎng)關(guān),如果網(wǎng)絡(luò)A的主機發(fā)現(xiàn)目標主機不在本地網(wǎng)絡(luò)中就會把數(shù)據(jù)包發(fā)送到A的網(wǎng)關(guān),再轉(zhuǎn)發(fā)給網(wǎng)絡(luò)B的網(wǎng)關(guān),再轉(zhuǎn)發(fā)給網(wǎng)絡(luò)B。
路由器:路由器是物理設(shè)備,路由器可以作為網(wǎng)關(guān)使用,通常指的網(wǎng)關(guān)就是路由器的IP。
主機1.1要發(fā)送數(shù)據(jù)包給主機4.1,因為IP地址不再同一網(wǎng)段,主機會將數(shù)據(jù)包發(fā)送給本網(wǎng)段的網(wǎng)關(guān)路由器A。
路由器A接收到數(shù)據(jù)包,查看數(shù)據(jù)包IP中的目標IP地址,在查找自己的路由表,數(shù)據(jù)包的目標IP地址是4.1,屬于4.0網(wǎng)段,路由器A在路由表中查到4.0網(wǎng)段轉(zhuǎn)發(fā)的接口是SO接口。
于是,路由表A將數(shù)據(jù)包從SO接口轉(zhuǎn)發(fā)出去。到達了網(wǎng)關(guān)路由器B,用同樣的轉(zhuǎn)發(fā)方法,從EO口轉(zhuǎn)發(fā)出去,4.1主機接收發(fā)這個數(shù)據(jù)包。

(2)docker網(wǎng)橋模式
(3)docker-compose網(wǎng)絡(luò)模式
docker-compose中可以設(shè)置網(wǎng)絡(luò),如果不顯示設(shè)置網(wǎng)絡(luò)這些容器都會被加入app_default網(wǎng)絡(luò),比如工程目錄為test,則啟動后的網(wǎng)絡(luò)名為test_default,使用docker network ls可以查看網(wǎng)絡(luò)列表,docker network inspect <network id>可以查看對應(yīng)網(wǎng)絡(luò)的配置。
如果想要工程有特有的網(wǎng)段以及容器有特有的IP則需要在docker-compose.yml中設(shè)置自定義要網(wǎng)絡(luò),例子如下
version: '3'
services:
mysql:
image: mysql
restart: always
volumes:
- ./mysql:/home
environment:
- MYSQL_ROOT_PASSWORD=gp123456
networks:
mynet1:
ipv4_address: 172.100.0.5
flask:
build: ./flask
volumes:
- ./flask:/home
links:
- mysql:mysql
environment:
- MYSQL_USER=xiaogp
- MYSQL_PASSWORD=gp123456
- MYSQL_DB=pira
ports:
- "5000:5000"
networks:
mynet1:
ipv4_address: 172.100.0.6
networks:
mynet1:
ipam:
config:
- subnet: 172.100.0.0/16
具體的寫法是在最下面設(shè)置一個工程全局的網(wǎng)絡(luò),并且在各個容器服務(wù)的最下面引用,在全局下使用subnet設(shè)置網(wǎng)段,各容器使用ipv4_address設(shè)置IP。
重新啟動后docker網(wǎng)絡(luò)已經(jīng)固定為172.100.0.0/16網(wǎng)段,各容器IP也改為自定義IP
root@ubuntu:~/docker/docker-compose/test_1# docker network inspect 393d21db53d0
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.100.0.0/16"
}
]
},
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"b2a5571aadaca0e52812b2016967b20e79d02dea6d70c422c8746ee510256c64": {
"Name": "test_1_flask_1",
"EndpointID": "e9d73b5841b24d01fd03e74dbbb5b40e9c9b884b2497073fd1b482d08aa4c89c",
"MacAddress": "02:42:ac:64:00:06",
"IPv4Address": "172.100.0.6/16",
"IPv6Address": ""
},
"e57d400253c9e97c5f8816a1832e4c105329c72611b691d2d4bd0ce1e8626cb3": {
"Name": "test_1_mysql_1",
"EndpointID": "f306029d9ab4c67014cbfd665523735ed968cca984b62a0bb00946635ee82d27",
"MacAddress": "02:42:ac:64:00:05",
"IPv4Address": "172.100.0.5/16",
"IPv6Address": ""
}
},
(4)路由尋址規(guī)則
當TCP/IP需要向某個IP地址發(fā)起通信時,它會對路由表進行評估,以確定如何發(fā)送數(shù)據(jù)包。評估過程如下:
1.目的IP地址和路由表中每一個路由項的網(wǎng)絡(luò)掩碼進行相與計算,如果相與后的結(jié)果匹配對應(yīng)路由項的網(wǎng)絡(luò)地址,則記錄下此路由項
2.當計算完路由表中所有的路由項后,擇優(yōu)選擇其中一條路由規(guī)則
- 最長匹配路由:TCP/IP選擇記錄下的路由項中的最長匹配路由(網(wǎng)絡(luò)掩碼中具有最多“1”位的路由項)來和此目的IP地址進行通信。
- 最低躍點數(shù):如果存在多個最長匹配路由,那么選擇具有最低躍點數(shù)的路由項。
- 優(yōu)先級高低:如果存在多個具有最低躍點數(shù)的最長匹配路由,那么:均根據(jù)最長匹配路由所對應(yīng)的網(wǎng)絡(luò)接口在網(wǎng)絡(luò)連接的高級設(shè)置中的綁定優(yōu)先級來決定(一般有線(eth0) > 無線 (wlan0) > 移動信號(4G))
(5)Linux route路由操作
每一個linux系統(tǒng)中都具有IP路由表,它存儲了本地計算機可以到達的網(wǎng)絡(luò)目的地址范圍和如何到達的路由信息,本地計算機上的任何TCP/IP通信都受到路由表的控制,linux通過route 命令查看 Linux 內(nèi)核的路由表。
| 字段 | 操作符 |
|---|---|
| Destination | 目標網(wǎng)絡(luò)或目標主機。Destination 為 default(0.0.0.0)時,表示這個是默認網(wǎng)關(guān),所有數(shù)據(jù)都發(fā)到這個網(wǎng)關(guān) |
| Gateway | 網(wǎng)關(guān)地址,0.0.0.0 表示當前記錄對應(yīng)的 Destination 跟本機在同一個網(wǎng)段,通信時不需要經(jīng)過網(wǎng)關(guān)。如果沒有就顯示星號(*) |
| Genmask | U: 該路由可以使用。 |
| H: 該路由是到一個主機 | |
| G: 該路由是到一個網(wǎng)關(guān)(路由器)。如果沒有設(shè)置該標志,說明目的地 是直接相連的 | |
| R: 恢復(fù)動態(tài)路由產(chǎn)生的表項 | |
| D: 該路由是由改變路由(redirect)報文創(chuàng)建的 | |
| M: 該路由已被改變路由報文修改 | |
| !:這個路由將不會被接受。 | |
| Metric | 路由距離,到達指定網(wǎng)絡(luò)所需的中轉(zhuǎn)數(shù) |
| Ref | 路由項引用次數(shù) |
| Use | 此路由項被路由軟件查找的次數(shù) |
| Iface | 網(wǎng)卡名字,例如 eth0 |
(6)docker網(wǎng)絡(luò)操作
docker network ls:查看docker網(wǎng)絡(luò)列表docker network inspect <network id/name>:查看某個docker網(wǎng)絡(luò)詳情docker network rm:刪除docker網(wǎng)絡(luò)docker network disconnect:斷開docker網(wǎng)絡(luò)docker network prune:清楚無用的網(wǎng)絡(luò)
使用案例:
(1)查看所有driver=bridge的docker網(wǎng)絡(luò)
root@ubuntu:~# docker network ls --filter driver=bridge NETWORK ID NAME DRIVER SCOPE 33868f4f5f1c bridge bridge local e2cde023b4a7 harbor_harbor bridge local 4fab000d4ed4 milvus bridge local 64634f55cf1b test_1_default bridge local 393d21db53d0 test_1_mynet1 bridge local
(2)刪除已經(jīng)無效的網(wǎng)絡(luò)
root@ubuntu:~# docker network rm 64634f55cf1b 64634f55cf1b
如果喲啊刪除正在使用的網(wǎng)絡(luò),需要先斷開連接再刪除網(wǎng)絡(luò)
docker network disconnect <network> <container>
# 先使用inspect查到網(wǎng)絡(luò)名和容器名 root@ubuntu:~# docker network disconnect test_1_mynet1 test_1_mysql_1 root@ubuntu:~# docker network ls NETWORK ID NAME DRIVER SCOPE 33868f4f5f1c bridge bridge local e2cde023b4a7 harbor_harbor bridge local e4aa16aea5df host host local 4fab000d4ed4 milvus bridge local 2d89edc384b1 none null local 393d21db53d0 test_1_mynet1 bridge local root@ubuntu:~# docker network rm test_1_mynet1 test_1_mynet1
(3)清理無效網(wǎng)絡(luò),想通過這種方法清除歷史曾經(jīng)使用過的網(wǎng)段,但是沒有達到預(yù)期效果,以后再研究
root@ubuntu:~# docker network prune -f
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
docker部署Vaultwarden密碼共享管理系統(tǒng)的實現(xiàn)(圖文)
Vaultwarden是一個開源的密碼管理器,它提供了類似于Bitwarden的功能,允許用戶安全地存儲和管理密碼、敏感數(shù)據(jù)和身份信息,本文主要介紹了docker部署Vaultwarden密碼共享管理系統(tǒng)的實現(xiàn),感興趣的可以了解一下2023-10-10
詳解利用ELK搭建Docker容器化應(yīng)用日志中心
這篇文章主要介紹了詳解利用ELK搭建Docker容器化應(yīng)用日志中心,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04
一次Docker中Redis連接暴增的問題排查實戰(zhàn)記錄
這篇文章主要給大家介紹了一次Docker中Redis連接暴增的問題排查的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2020-06-06

