如何解決docker-compose網段路由沖突,docker-compose自定義網絡
問題復現(xiàn)
網上這個問題出現(xiàn)的挺多的,我也總結一下,因為里面涉及到的網絡基礎知識比較多的,正好我一直不懂這一塊,需要大補
問題
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相似的目標網段為172.20.0.0
,看后面的接口為br-3b2a750ddc03
,也即是說數(shù)據(jù)被轉發(fā)到這個接口下,這貌似是個docker創(chuàng)建的網橋,懷疑是docker網橋占用了172.20網段,查看以下docker網絡
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網絡,原來是milvus的容器創(chuàng)建的網橋,進一步檢查網絡內部信息
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": "" } },
可見這個網絡接口下目標主機只有172.20.0.2,172.20.0.3,172.20.0.4三臺主機IP,以及172.20.0.1網關,因此ping 172.20.2.52根本ping不通。
milvus的三個容器虛擬IP以及網關服務占用了172.20網段,openvpn創(chuàng)建的網段也是172.20.0.0,因此在路由中產生網段沖突
,無法轉發(fā)到openvpn的對應網絡接口,同理從172.17、18、19、20都是docker創(chuàng)建出來的網絡接口和網段,如果有其他網絡服務處在相同網段可能導致無法路由到
解決方案
(1)路由表添加細路由
在路由尋址時會根據(jù)目標IP在路由表中相同網絡ID(網段)的記錄,根據(jù)該記錄將數(shù)據(jù)轉發(fā)給下一個路由器,如果路由表中存在多條相同網絡ID的記錄,根據(jù)最長匹配算則最吻合的一個,因此增加一個172.20.2.0/24
的目標網段即可,使用route add
進行添加,添加目的地網段為172.20.2.0/24,網絡接口為tun0
root@ubuntu:/etc/openvpn# route add -net 172.20.2.0/24 dev tun0
tun0是openvpn創(chuàng)建的網絡接口,使用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
再看一下路由已經成功添加了一條細路由
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已經可以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網橋路由
另一種方法是找到docker網橋對應的容器應用之后直接刪除容器,則對應的網絡接口和路由都會刪除,進入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網段已經消失,ifconfig,docker network ls都已經查不到對應的網絡接口,此時再重啟openvpn即可
(3)修改docker-compose.yml配置網絡
docker-compose默認會給每個應用從172.18.0.0依次往后匹配網段,只要容器沒有被刪除則一直占用網絡,如果刪除后重啟則依次采用新的網段之前的不再使用,因此很容易造成路由沖突,可以在單個docker-compose.yml文件中增加networks配置,設置網段為10.103.0.0/16
networks: default: name: milvus ipam: driver: default config: - subnet: 10.103.0.0/16
重啟docker-compose,此時路由和docker網絡都切換為了10.103.0.0/16網段
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網絡配置,docker自動分配的網段使用12.11.0.0/16,每個子網掩碼劃分為 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,項目切換為指定的網段
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也變更為指定的網段
相關知識
(1)網絡基礎知識(網關、路由器)
網關:網關是一個邏輯概念,網關是一個結點,是一個網絡連接到另一個網絡的關口,實質上是一個網絡通向其他網絡的IP地址。
兩個不同網段的網絡結點之間通信需要使用網關,如果網絡A的主機發(fā)現(xiàn)目標主機不在本地網絡中就會把數(shù)據(jù)包發(fā)送到A的網關,再轉發(fā)給網絡B的網關,再轉發(fā)給網絡B。
路由器:路由器是物理設備,路由器可以作為網關使用,通常指的網關就是路由器的IP。
主機1.1要發(fā)送數(shù)據(jù)包給主機4.1,因為IP地址不再同一網段,主機會將數(shù)據(jù)包發(fā)送給本網段的網關路由器A。
路由器A接收到數(shù)據(jù)包,查看數(shù)據(jù)包IP中的目標IP地址,在查找自己的路由表,數(shù)據(jù)包的目標IP地址是4.1,屬于4.0網段,路由器A在路由表中查到4.0網段轉發(fā)的接口是SO接口。
于是,路由表A將數(shù)據(jù)包從SO接口轉發(fā)出去。到達了網關路由器B,用同樣的轉發(fā)方法,從EO口轉發(fā)出去,4.1主機接收發(fā)這個數(shù)據(jù)包。
(2)docker網橋模式
(3)docker-compose網絡模式
docker-compose中可以設置網絡,如果不顯示設置網絡這些容器都會被加入app_default網絡,比如工程目錄為test,則啟動后的網絡名為test_default,使用docker network ls
可以查看網絡列表,docker network inspect <network id>
可以查看對應網絡的配置。
如果想要工程有特有的網段以及容器有特有的IP則需要在docker-compose.yml中設置自定義要網絡,例子如下
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
具體的寫法是在最下面設置一個工程全局的網絡,并且在各個容器服務的最下面引用,在全局下使用subnet設置網段,各容器使用ipv4_address設置IP。
重新啟動后docker網絡已經固定為172.100.0.0/16網段,各容器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地址和路由表中每一個路由項的網絡掩碼進行相與計算,如果相與后的結果匹配對應路由項的網絡地址,則記錄下此路由項
2.當計算完路由表中所有的路由項后,擇優(yōu)選擇其中一條路由規(guī)則
- 最長匹配路由:TCP/IP選擇記錄下的路由項中的最長匹配路由(網絡掩碼中具有最多“1”位的路由項)來和此目的IP地址進行通信。
- 最低躍點數(shù):如果存在多個最長匹配路由,那么選擇具有最低躍點數(shù)的路由項。
- 優(yōu)先級高低:如果存在多個具有最低躍點數(shù)的最長匹配路由,那么:均根據(jù)最長匹配路由所對應的網絡接口在網絡連接的高級設置中的綁定優(yōu)先級來決定(一般有線(eth0) > 無線 (wlan0) > 移動信號(4G))
(5)Linux route路由操作
每一個linux系統(tǒng)中都具有IP路由表,它存儲了本地計算機可以到達的網絡目的地址范圍和如何到達的路由信息,本地計算機上的任何TCP/IP通信都受到路由表的控制,linux通過route 命令查看 Linux 內核的路由表。
字段 | 操作符 |
---|---|
Destination | 目標網絡或目標主機。Destination 為 default(0.0.0.0)時,表示這個是默認網關,所有數(shù)據(jù)都發(fā)到這個網關 |
Gateway | 網關地址,0.0.0.0 表示當前記錄對應的 Destination 跟本機在同一個網段,通信時不需要經過網關。如果沒有就顯示星號(*) |
Genmask | U: 該路由可以使用。 |
H: 該路由是到一個主機 | |
G: 該路由是到一個網關(路由器)。如果沒有設置該標志,說明目的地 是直接相連的 | |
R: 恢復動態(tài)路由產生的表項 | |
D: 該路由是由改變路由(redirect)報文創(chuàng)建的 | |
M: 該路由已被改變路由報文修改 | |
!:這個路由將不會被接受。 | |
Metric | 路由距離,到達指定網絡所需的中轉數(shù) |
Ref | 路由項引用次數(shù) |
Use | 此路由項被路由軟件查找的次數(shù) |
Iface | 網卡名字,例如 eth0 |
(6)docker網絡操作
docker network ls
:查看docker網絡列表docker network inspect <network id/name>
:查看某個docker網絡詳情docker network rm
:刪除docker網絡docker network disconnect
:斷開docker網絡docker network prune
:清楚無用的網絡
使用案例:
(1)查看所有driver=bridge的docker網絡
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)刪除已經無效的網絡
root@ubuntu:~# docker network rm 64634f55cf1b 64634f55cf1b
如果喲啊刪除正在使用的網絡,需要先斷開連接再刪除網絡
docker network disconnect <network> <container>
# 先使用inspect查到網絡名和容器名 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)清理無效網絡,想通過這種方法清除歷史曾經使用過的網段,但是沒有達到預期效果,以后再研究
root@ubuntu:~# docker network prune -f
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
docker部署Vaultwarden密碼共享管理系統(tǒng)的實現(xiàn)(圖文)
Vaultwarden是一個開源的密碼管理器,它提供了類似于Bitwarden的功能,允許用戶安全地存儲和管理密碼、敏感數(shù)據(jù)和身份信息,本文主要介紹了docker部署Vaultwarden密碼共享管理系統(tǒng)的實現(xiàn),感興趣的可以了解一下2023-10-10一次Docker中Redis連接暴增的問題排查實戰(zhàn)記錄
這篇文章主要給大家介紹了一次Docker中Redis連接暴增的問題排查的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2020-06-06