Docker 網(wǎng)絡(luò) IP 地址沖突這個問題其實稍微有一點點麻煩,網(wǎng)上也沒有看到有比較全面正確的文章, 值得單獨寫一篇記錄一下。
1前置知識
因為交換機的能力有限制,以及網(wǎng)線的連接不可能無限長, 所以我們不可能把所有的主機都連到同一個交換機上,然后處于同一個二層網(wǎng)絡(luò)中。
就算能,主機間的 ARP 廣播也會讓這個網(wǎng)絡(luò)瞬間癱瘓。
所以我們得把主機拆分到一個個的小的子網(wǎng)里,然后通過路由器再并成三層網(wǎng)絡(luò)。
我們俗稱的 IP 地址其實由兩個部分組成,網(wǎng)絡(luò)地址和主機地址。比如?10.0.0.1/8
?中,第一個?10
?是網(wǎng)絡(luò)地址,后面的?0.0.1
?是主機地址。那我怎么知道怎么去拆分這兩段呢?靠的就是子網(wǎng)掩碼,也就是那個?/8
。
IP 其實是由 32 位的二進制組成的,x.x.x.x
?只是為了方便人類閱讀將其轉(zhuǎn)成了十進制。有個簡單粗暴的辦法就是可以認為每一段都是 8 位,所以?/8
?就代表第一段是網(wǎng)絡(luò)地址。
同理,/16
?就代表前兩段都是網(wǎng)絡(luò)地址,10.0.0.0/16
?中, 網(wǎng)絡(luò)地址是?10.0
,后兩位?0.0
?代表每個子網(wǎng)中的主機地址。
比如?10.0.0.1/16
?和?10.0.0.2/16
?是同一個子網(wǎng)的兩個主機。10.0.0.1/16
?和?10.1.0.1/16
?是不同的子網(wǎng)的兩個主機。
這里只是簡單粗暴的介紹下,更多的信息還是自己去查資料了解學(xué)習(xí)。
2問題表現(xiàn)
-
docker 進程無法啟動
-
容器端口無法訪問,抓包顯示為有入站但是沒有出站
3排查
此處針對的是 dockerd 無法啟動的情況,如果 dockerd 能啟動,可以直接跳到解決一節(jié)
首先是看下日志
$?systemctl?status?docker
$?journalctl?-u?docker
$?dmesg?|?grep?docker
一般能看到如下日志:
docker0:?link?is?not?ready
docker_gwbridge:?link?is?not?ready
或者更簡單的排查方法,直接手動啟動 dockerd 看看。啟動方法可以通過?grep ExecStart /usr/lib/systemd/system/docker.service
?查看。
一般來說按如下執(zhí)行就行:
$?/usr/bin/dockerd?--debug
然后能看到最后輸出:
INFO[2021-07-29T02:25:55.811673622Z]?stopping?event?stream?following?graceful?shutdown??error="<nil>"?module=libcontainerd?namespace=moby
failed?to?start?daemon:?Error?initializing?network?controller:?list?bridge?addresses?failed:?PredefinedLocalScopeDefaultNetworks?List:?[10.252.0.0/24?10.252.1.0/24?10.252.2.0/24]:?no?available?network
這時候可以看下?ip addr
,是否有?docker0
?和?docker_gwbridge
,
如果發(fā)現(xiàn)沒有?docker0
,那基本可以肯定是 docker0 無法創(chuàng)建導(dǎo)致 dockerd 啟動失敗了。
4解決
找到占用的網(wǎng)段
默認的 docker0 網(wǎng)段是?172.17.0.0/16
,docker_gwbridge 網(wǎng)段是?172.18.0.0/24
,你需要確認下這兩個網(wǎng)段是否被占用了。
最簡單的方法就是 ping 一下,如果無響應(yīng)的話,那么就說明沒有被占用。
其次就是看一下本機的路由表?route -n
,確認一下有沒有沖突的段。一般來說,你會發(fā)現(xiàn)相關(guān)網(wǎng)段要么已經(jīng)被占用,要么是路由表里存在沖突。
案例
比如在我的環(huán)境里,我給 docker0 配置為?10.252.0/24
,然后 dockerd 起不來。
排查后發(fā)現(xiàn)?route -n
?里有這么一條:
10.0.0.0????????172.21.0.1??????255.0.0.0???????UG????0??????0????????0?eth0
也就是說?10/8
?被占用了,導(dǎo)致和我的?10.252.0/24
?沖突。后來聯(lián)系網(wǎng)管刪除了這條?10/8
?的路由后解決。
修改 docker 占用的網(wǎng)段
以下操作需要先停止 docker 進程
$?systemctl?stop?docker
如果你用 docker service,那么 docker 會占用四個網(wǎng)段:
-
docker0
-
docker_gwbridge
-
ucp(docker engine 占用,不常見)
-
ingress
其中前三個的網(wǎng)段可以通過配置文件配置,第四個只能手動創(chuàng)建。
前三個網(wǎng)段會讀取?/etc/docker/daemon.json
?這個配置文件, 這個文件默認是沒有的,需要手動創(chuàng)建。
{
????"bip":?"",
????"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
?至少要有兩項,按順序依次為:
-
docker0
-
docker_gwbridge
-
ucp
以防萬一的話,配置三個是最好的??。
接下來是修改 ingress,這個比較麻煩,需要手動創(chuàng)建。
我的辦法是在初始化 docker swarm 以后,啟動 docker stack/service 以前,執(zhí)行以下腳本:
-
刪除 ingress
-
刪除 my-ingress(不一定存在,不存在就忽略)
-
新建 my-ingress
$?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?的網(wǎng)段,不要和上面?daemon.json?的網(wǎng)段沖突
??--gateway=10.252.3.2?\
??--opt?com.docker.network.driver.mtu=1200?\
??my-ingress
ingress 是默認名,之所以新建一個名字不一樣的,是因為刪除 ingress 是異步的。如果你刪除 ingress 后立刻新建一個也叫 ingress 的網(wǎng)絡(luò),很可能會報一個重名的錯誤。
重啟 docker 前,最好先清理一下 docker 的緩存:
$?ip?link?del?dev?docker0
$?ip?link?del?dev?docker_gwbridge
$?rm?-rf?/var/lib/docker/network
另一種粗糙簡單的解決辦法
另一種粗糙簡單的解決辦法就是干脆直接手動創(chuàng)建一個 docker0。
這種解決方法最簡單,但是機器 reboot 后 docker0 會自動被刪掉, 所以這方法并不持久。文章來源:http://www.zghlxwxcb.cn/news/detail-546200.html
而且,實際上也不一定能解決網(wǎng)段沖突的問題,只是說 docker 能啟動了而已。文章來源地址http://www.zghlxwxcb.cn/news/detail-546200.html
ip?link?add?name?docker0?type?bridge
ip?addr?add?dev?docker0?10.252.0.1/24
到了這里,關(guān)于Docker 網(wǎng)絡(luò) IP 地址沖突了,該怎么辦呢?的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!