1. 程式人生 > >DOCKER容器與宿主機同網段互相通訊

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設定會自動消失,需要重新設定。