Docker網絡(host、bridge、none)詳細介紹

Docker網絡(host、bridge、none)

我們會首先學習Docker提供的幾種原生網絡,以及如何創建自定義網絡;然後探討容器之間如何通信,以及容器與外界如何交互。

 Docker網絡從覆蓋範圍可分爲單個host上的容器網絡和跨多個host的網絡,本章重點討論前一種。對於更爲複雜的多host容器網絡,我們會在後面進階技術章節單獨討論。


Docker 安裝時會自動在host 上創建三個網絡,我們可用docker network ls命令查看

docker network ls

none網絡

顧名思義,none網絡就是什麼都沒有的網絡。掛在這個網絡下的容器除了1o,沒有其他任何網卡。容器創建時,可以通過-network=none指定使用none網絡,如圖

docker run -it --network=none busybox

我們不禁會問,這樣一個封閉的網絡有什麼用呢?


其實還真有應用場景。封閉意味着隔離,一些對安全性要求高並且不需要聯網的應用可以使用none網絡。
比如某個容器的唯一用途是生成隨機密碼,就可以放到none網絡中避免密碼被竊取。


當然大部分容器是需要網絡的,我們接着看host網絡。

 

host網絡

連接到host網絡的容器共享Docker host的網絡棧,容器的網絡配置與host完全一樣。
可以通過-network-host 指定使用host網絡

docker run -it --network=host busybox

在容器中可以看到host的所有網卡,並且連hostmame 也是host的。host網絡的使用場景又是什麼呢?

直接使用Docker host的網絡最大的好處就是性能,如果容器對網絡傳輸效率有較高要求,則可以選擇host網絡。當然不便之處就是犧牲一些靈活性,比如要考慮端口衝突問題,Docker host 上已經使用的端口就不能再用了。
Docker host的另一個用途是讓容器可以直接配置host網路,比如某些跨host的網絡解決方案,其本身也是以容器方式運行的,這些方案需要對網絡進行配置,比如管理iptables
 

bridge網絡

Docker安裝時會創建一個命名爲docker0的Linux bridge。如果不指定-network,創建的容器默認都會掛到docker0上

brctl show

當前docker0上沒有任何其他網絡設備,我們創建一個容器看看有什麼變化

一個新的網絡接口vethb56e98c被掛到了docker0上,vethb56e98c就是新創建容器的虛擬網卡。
下面看一下容器的網絡配置

容器有一個網卡eth0@if34,爲什麼不是vethb56e98c呢?

實際上eth0@if34 和veth28c57df 是一對veth pair。 veth pair 是一種成對出現的特殊網絡設備,可以把它們想象成由一根虛擬網線連接起來的一對網卡, 網卡的一頭(eth0@if34) 在容器中,另一頭(veth28c57df) 掛在網橋docker0 上,其效果就是將eth0@if34 也掛在了docker0上。
我們還看到eth0@if34 已經配置了IP 172.17.0.2, 爲什麼是這個網段呢?讓我們通過docker network inspect bridge看- -下bridge 網絡的配置信息

原來bridge 網絡配置的subnet 就是172.17.0.0/16, 並且網關是172.17.0.1. 這個網關在哪兒呢?大概你已經猜出來了,就是docker0

容器網絡拓撲圖

容器創建時,docker 會自動從172.17.0.0/16 中分配-個IP,這裏16 位的掩碼保證有足夠多的IP可以供容器使用。

user-defined網絡

除了none、host、bridge這三個自動創建的網絡,用戶也可以根據業務需要創建user-defined網絡。
Docker提供三種user-defined 網絡驅動:bridge、overlay 和macvlan。overlay 和macvlan用於創建跨主機的網絡

我們可通過bridge 驅動創建類似前面默認的bridge 網絡

docker network create --driver bridge my_net
[root@kvm ~]# docker network create --driver bridge my_net
7428a4d14c67b44be3a7184a5a065303d3688b5b13883526989b7173af881170
[root@kvm ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
br-7428a4d14c67		8000.024221339eb6	no		
docker0		8000.024280532eb0	no		veth6281a8d
virbr0		8000.52540015904b	yes		virbr0-nic

新增了一個網橋br-7428a4d14c67,這裏7428a4d14c67正好是新建bridge網絡my_net的短id。執行docker network inspect查看一下my_net的配置信息,

這裏172.18.0.0/16是Docker自動分配的IP網段。
我們可以自己指定IP網段嗎?
答案是:可以。


只需在創建網段時指定--subnet和-gateway參數

docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net2

這裏我們創建了新的bridge網絡my_net2,網段爲172.22.16.0/24,網關爲172.22.16.1與前面一樣,網關在my net2對應的網橋br-5d863e9778b6上

 

容器要使用新的網絡,需要在啓動時通過--network指定

docker run -it --network=my_net2 busybox

容器分配到的IP爲172.22.16.20到目前爲止,容器的IP都是docker自動從subnet中分配,我們能否指定一個靜態IP呢?
答案是:可以,通過-p指定

docker run -it --network=my_net2 --ip 172.22.16.8 busybox

好了,我們來看看當前docker host的網絡拓撲結構

兩個busybox容器都掛在mynet2上,應該能夠互通

可見同一網絡中的容器、網關之間都是可以通信的。
my_net2與默認bridge網絡能通信嗎?
從拓撲圖可知,兩個網絡屬於不同的網橋,應該不能通信,我們通過實驗驗證一下,讓busybox容器ping 不同網段容器

 

確實 ping不通,符合預期。
“等等!不同的網絡如果加上路由應該就可以通信了吧?”我已經聽到有讀者在建議了這是一個非常非常好的想法。

確實,如果host上對每個網絡都有一條路由,同時操作系統上打開了ip forwarding,host就成了一個路由器,掛接在不同網橋上的網絡就能夠相互通信。下面我們來看看docker host是否滿足這些條件呢?
 

ip r查看host上的路由表:

172.17.0.0/16和172.22.16.0/24兩個網絡的路由都定義好了。再看看ip forwarding:

[root@kvm ~]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

ip forwarding也已經啓用了。條件都滿足,爲什麼不能通行呢?
我們還得看看iptables:

iptavles-save

-A DOCKER-ISOLATION -i br-13ceb40bd8e8 -o docker0 -j DROP
-A DOCKER-ISOLATION -i docker0 -o br-13ceb40bd8e8 -j DROP

原因就在這裏了:iptables DROP掉了網橋dockero與br-13ceb40bd8e8之間雙向的流量。

從規則的命名DOCKER-ISOLATION可知docker在設計上就是要隔離不同的netwrok

那麼接下來的問題是:怎樣才能讓busybox與httpd 通信呢?


答案是:爲httpd容器添加一塊net_my2的網卡。這個可以通過docker network connect命令實現,

docker network connect my_net2 655643ea6894

我們在docker0網段器中查看一下網絡配置

容器中增加了一個網卡ethl,分配了my_net2的IP 172.22.16.3。現在busybox應該能夠訪問docker0網段了,驗證一下

busybox能夠ping到httpd,並且可以訪問httpd的Web服務所示。

(因爲這裏我在docker0網段,用busybox代替的httpd)

 

學習了Docker各種類型網絡之後,接下來我們討論容器與容器、容器與外界的連通問題

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章