Docker網絡解讀

libnetwork

docker在1.9版本之後,引入了一套docker network子命令來管理docker網絡。這允許用戶可以根據他們應用的拓撲結構創建虛擬網絡並將容器接入其所對應的網絡。

具體來說,docker網絡是通過一個叫libnetwork的東西來進行管理的,用docker network命令對docker網絡進行操作實際上是與libnetwork Api進行交互。

libnetwork內置有五種網絡驅動,分別是:bridge驅動、host驅動、overlay驅動、remote驅動、null驅動。這些網絡驅動爲docker提供了多種網絡模式。下面我們簡單說說各驅動的作用:

bridge驅動

bridge驅動即爲通常說的橋接模式,此驅動爲Docker的默認驅動,該驅動的作用爲將Docker容器連接到docker默認創建的docker0網橋上面,如果未指定--network選項,創建的容器將默認指向docker0,該驅動即對應docker的bridge網絡模式,通過NAT地址轉換使容器和外界進行通信。

可使用如下命令查看docker0網橋,該網橋會在docker安裝後自動配置:

ip addr

圖片描述

我們可以看到默認的docker0網橋ip爲172.17.0.1/16,在某些情況下假如我們宿主機網段與docker0網段相同,我們用bridge模式默認的docker0網橋會與宿主機產生網段衝突問題,這時候只需要更改docker0默認的網段或者使用docker容器的--network選項選擇用戶自定義的網橋即可解決。

host驅動

該驅動將docker容器與宿主機網絡處於同一個network namespace下,docker容器將使用宿主機的網卡、ip和端口信息,故容器與外界不進行NAT地址轉換,增加了網絡性能,但是缺點是宿主機上已使用的端口docker容器不能再使用,該驅動對應docker的host網絡模式。

overlay驅動

此驅動採用IETE標準的VXLAN方式,具體VXLAN實現方式這裏暫不說明,該驅動主要用於創建容器的跨主機網絡,對應docker的user-defined網絡模式。

remote驅動

這個驅動用於用戶向libnetwork提供自定義的網絡插件,並沒有實現任何網絡功能。

null驅動

null驅動即爲docker容器的none網絡模式,該模式併爲docker容器提供任何網絡配置,只有docker容器自身的lo網卡,該模式一般用於一些特定的情況。

bridge網絡模式的實現方式

我們常用的docker網絡模式一般都是bridge模式,下面我們來分析docker是如何實現橋接網絡的。

首先我們可以通過如下命令查看docker0網關:

route -n

圖片描述

從如上命令可以看出所有指向ip爲172.17.0.0/16的數據包都從docker0網卡轉發。

然後我們用docker run命令啓動一個容器名爲demo,進入容器demo,同樣用ip addr或ifconfig命令查看網卡,我們可以看到如下兩個網卡:
圖片描述

lo網卡和eth0網卡。lo網卡即爲容器自身的迴環網卡,eth0網卡ip爲172.17.0.3/16,和宿主機網卡docker0在同一網段,這時我們用route -n命令查看demo容器的網關如下:
圖片描述

可以看出demo的eth0網卡與宿主機的docker0網卡是相互連通的。

這時退出demo容器再來用ip addr查看宿主機的網絡設備,會發現有一塊以“veth”開頭的網卡,如veth5653371,我們可以猜測veth5653371與demo容器內的eth0網卡是一對veth設備(veth pair總是成對出現),veth設備的作用爲用來連接兩個不同的network namespace,故docker0不是單純的網卡而是網橋了,這就是docker的bridge網絡模式的實現方式,通過連接docker0網橋來實現宿主機和容器的網絡互通。

iptables規則實現端口映射

我們知道了docker的bridge網絡模式的網絡互通方式,那麼docker是如何實現宿主機和容器的端口映射的呢?這一切都靠配置iptables規則來實現,具體表現如下:

Docker安裝完成後,將默認在宿主機系統上增加一些iptables規則,用iptables-save命令查看以下規則:

-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

上面這條規則關係着Docker容器和外界的通信,含義是:將源地址爲172.17.0.0/16的數據包(即Docker容器發出的數據),當不是從docker0網卡發出時做SNAT。這樣docker容器訪問外部的流量會認爲是宿主機發出的。

同理,docker容器和宿主機的端口映射也是通過iptalbes映射來實現的,假設我們啓動一個容器將其端口8080映射到宿主機端口8080上,我們可以看到如下規則:

-A POSTROUTING -s 172.17.0.3/16 -d 172.17.0.3/16 -p tcp -m tcp --dport 8080 -j MASQUERADE
-A DOCKER -d 172.17.0.3/16 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8080 -j ACCEPT

該規則將訪問宿主機8080端口的流量轉發到172.17.0.3/16(即demo容器的etho網卡)上,所以docker是通過配置iptalbes規則來實現端口映射的。

不同宿主機容器網絡互通

到目前爲止,我們所講的docker網絡環境僅僅是對單機而言的,要實現不同宿主機的網絡互通常常有多種方式,我這裏選用的是flannel來實現不同宿主機容器的網絡互通,這也是kubernetes實現網絡互通的方式,要想知道flannel是如何實現網絡互通的,請查看我的下一篇博文:flannel解讀,將會在近期發佈,盡情關注。

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