DOCKER容器與宿主機同網段互相通訊
相關閱讀:
博主最近在解決docker與宿主機同網段通訊的問題,寫此文章記錄一下整個過程。
遇到的問題
博主用兩臺docker容器做datanode,當時配置Docker網路時,使用了Bridge模式,docker0網段(172.0.1.x),宿主機網段(192.1.1.x),使用外部客戶端請求下載HDFS檔案,去指定的datanode上拉去資料時,外部客戶端無法連線到內部的docker容器,丟擲的等待超時異常,並重試下載,更換請求的下載地址為可連線的宿主機datanode後, 才成功下載資料。
於是,想要對docker的網路配置進行修改,將docker容器的IP地址設定成與宿主機同網段,並且相互連通。
這裡先要來說一下docker網路的四種方式:
1.Host模式:
Host 模式並沒有為容器建立一個隔離的網路環境。
該模式下的Docker 容器會和Host宿主機共享同一個網路namespace, Docker Container可以和宿主機一樣,使用宿主機的eth0,實現和外界的通訊。
Host模式特點包括:
- 容器沒有隔離的 network namespace
- 容器的 IP 地址同 Docker host 的 IP 地址
- 注意:容器中服務埠號不能與Host宿主機上已經使用的埠號相沖突
- host 模式能夠和其它模式共存
2.Container模式
Container網路模式是 Docker 中一種較為特別的網路的模式。處於這個模式下的 Docker 容器會共享其他容器的網路環境,因此,至少這兩個容器之間不存在網路隔離,而這兩個容器又與宿主機以及除此之外其他的容器存在網路隔離。
3.None模式
None 網路就是什麼都沒有的網路。掛在這個網路下的容器除了 lo,沒有其他任何網絡卡。需要我們自行去配置。
4.Bridge模式
Docker 容器預設使用Bridge模式的網路。
Docker的Bridge模式和VM虛擬機器的Bridge模式不同,雖然也叫Bridge,但實質上類似於VM的NAT模式。
原理是在宿主機上虛出一塊網絡卡bridge0,然後所有容器會橋接在這塊網絡卡的網段上。預設情況下容器能訪問外部網路,但外部網路無法訪問容器,需要通過暴露容器埠的方式(docker run -p)讓外部網路訪問容器內的服務。
看完了上面的介紹,當前使用的Bridge模式不適合場景,修改網路配置。
寫一下曾經試過的幾種方法:
注意:
如果你需要宿主機與Docker容器互通,前面兩種辦法不要試!!!不好使!!!
如果你僅需要Docker容器與宿主機網段相同,容器與其他同網段節點相互通訊,不與宿主機進行通訊,可以使用第一種方法!!
第一種辦法:
建立docker macvlan
Docker官方在1.12版本之後引入了macvlan網路驅動,可以更簡單的為容器配置橋接網路
介紹一下macvlan:
macvlan的原理是在宿主機物理網絡卡上虛擬出多個子網絡卡,通過不同的MAC地址在資料鏈路層進行網路資料轉發的,它是比較新的網路虛擬化技術,需要較新的核心支援(Linux kernel v3.9–3.19 and 4.0+)
引數說明:
-d macvlan 建立macvlan網路,使用macvlan網路驅動
–subnet 指定宿主機所在網段
–gateway 指定宿主機所在網段閘道器
-o parent 繼承指定網段的網絡卡
測試一下:執行容器
使用宿主機去ping 192.168.1.100,這時,問題出現了
目的地址不可達,使用別的機器去ping 192.168.1.100,ping通了,進入容器內,也ping不同宿主機。
使用macVLAN模式的容器,無法ping通宿主機,宿主機也無法ping通該容器,對其他同網段的伺服器和容器都可以聯通。
第二種辦法:
在網上找到的另一種辦法,編輯網絡卡配置檔案
重啟網路的時候,整個網路都down了,需要去機房弄伺服器接顯示器修改,查詢相關資料的時候,帖子大多是複製貼上的,不知道該他們真正的試過了沒有,此方法並不靠譜。
第三種辦法:
使用pipework為docker容器配置獨立IP
安裝pipework
建立兩個容器例項,並不需要預設docker0網橋分配的172.17.0.1網段,設定為–net=none
docker run -itd –name test1 –net=none -h test1 centos /bin/bash
docker run -itd –name test1 –net=none -h test2 centos /bin/bash
接下來,使用pipework命令為容器設定固定IP
pipework包含了200多行的shell指令碼
通過network namespace,veth pair以及linux bridge完成容器網路的設定,執行過程大概包括:
檢視主機是否包含br0網橋,如果不存在就建立,向容器例項test1新增一塊網絡卡,並配置固定IP:192.168.1.53,若test1已經有預設的路由,則刪除掉,將@後面的192.168.1.1設定為預設路由的閘道器,將test1容器例項連線到建立的br0上。
進入test1容器中,測試與test2容器和閘道器的連通性
說明上面的配置沒有問題
但是這時,還沒有完,宿主機是ping不同容器的
宿主機有兩個網絡卡,em1和em2,em1作為管理口192.168.1.50,em2沒有使用,現在,我們只需要將宿主機的em2網絡卡新增到br0網橋即可
然後再進行相關的測試
使用宿主機去ping 52/53
進入容器去ping宿主機
再使用window主機去測試
到這裡,問題總算解決了,在ambari上新增兩臺新配置的容器節點,並分配datanode角色,將原有的bridge網路節點刪除即可,外部客戶端請求下載HDFS檔案不再丟擲異常
注意:pipework目前還有缺陷,容器重啟後IP設定會自動消失,需要重新設定。