原文地址

譯者:本人翻譯水平有限,目的僅是為了學好Docker,如有錯誤請見諒。

翻譯版本:v1.01(將不斷優化翻譯質量)

本文包含以下內容

Docker容器就是將應用及其所依賴執行環境的完整檔案系統打成一個包:包括所需程式碼,執行庫,系統工具,系統庫等。如此來保證應用和應用的執行環境始終不變,從而保證該應用每次執行的結果都是相同。且Docker預設已為應用提供了一個保護層,使容器和其它基礎架構是相互之間是隔離的。

但當應用需要與外界溝通時,應如何設計網路去實現,使容器易於維護,服務發現,負載均衡,安全,效能和可擴充套件性呢?此文件則是提出解決這些網路設計難題的可用工具列表和一般的部署模式。本文不包含物理網路的設計,但會提供設計Docker網路時對應用物理網路的約束條件。

前提

續閱讀之前,推薦先熟悉Docker慨念和Docker Swarm部分內容。

容器網路和微服務的挑戰

微服務實踐已經增大了應用的規模,使到應用的連線與隔離的變得更加重要了。Docker的連網理念以應用為驅動。目標是為嚮應用開發者提供正確的虛擬層網路操作。

有如其它所有的設計,網路設計是一個追求平衡的藝術。Docker企業版和Docker生態系統已為網路工程師去搭建最平衡的應用及其環境提供了一整套工具。且每個可選的工具都俱有不同的優點和取捨。每個選擇都提供了詳細的指南,使到網路工程師可以很容易地知道那些工具最適合用於他們的環境。

Docker已經開發出新的應用交付方法,並且容器也改變了一些傳統的連網方法。以下是應器化應用的一般性設計主題:

  • 可移植性,如可利用特定網路功能去保證最大的跨網路環境可移植性?
  • 服務發現,如何知道服務的位置及其數量的增加或減少?
  • 負載均衡,如何共享多個位置的服務負載,並可隨時擴大與縮小?
  • 安全,如何分段隔離以防止有問題的容器去訪問其它容器?如何保證容器應用及群集的控制流是安全的?
  • 效能,如何提供高效能的網路服務,最小的延遲和最大的頻寬?
  • 可擴充套件性,如何確保應用擴充套件至多臺主機時不會丟失原有的特性?

容器網路模型

Docker網路架構是基於一套叫做容器網路模型(CNM)的介面。CNM的理念是提供可以跨不同網路基礎架構可實現移植的應用。這個模型平衡了應用的可移植性同時不會損失基礎架構原有的各種特性和功能。.

CNM結構

CNM中的高層架構。他們虛擬了所有作業系統和基礎架構的不可知性,所以應用無論在何種基礎架構上都可以有一樣的體驗。
  • 沙箱(SandBox)--一個沙箱包含了容器的網路配置。這裡包括了容器介面的管理,路由表,和DNS設定。沙箱的實現可以是Linux網路名稱空間,FreeBSD Jail或其它類似的慨念。一個沙箱可以包含多個來自不同網路的端點,即可以同時連線多個網路。
  • 端點(Endpoint)--沙箱通過端點來連線網路。端點結構的存在使到應用與網路的連線實現虛擬化。這樣有助於維護應用的可移值性,因此一個服務可以在無須知道如何去連線網路的情況下使用不同型別的網路驅動。
  • 網路(Network)--CNM並不是OSI模型中說的網路層。而是由Linux橋接,VLan等來實現。網路收集了所有連線在其上的端點,並實現了這些端點的互連。端點如果不連線到其中一個網路,那麼將無法與外界連線。
CNM驅動介面
容器連網模型提供了兩個可拔插且開放的介面供使用者使用,這些介面是用於通訊,利用供應商提供的附加功能,網路可見性,或網路控制等方面。
目前存在以下網路驅動:
  • 網路驅動(Network Drivers)--Docker網路驅動提供了使網路可以工作的具體實現。他們是可拔插的,所以很易於支援不同的使用者使用場景。多個網路驅動可同時用於指定的Docker引擎和群集。有以下兩個廣泛使用的CNM網路驅動:
  1. 內建網路驅動(Native Network Drivers)--內建網路驅動是內置於Docker引擎,並隨Docker提供的驅動。有多個驅動可供選擇,以支援不同的功能,如overlay網路和local bridge網路。
  2. 遠端網路驅動(Remote Network Drivers)--遠端網路驅動是由社群或其它供應商建立的網路驅動。這些驅動可用於與現有的軟體或硬體環境進行整合。使用者也可以建立自己的網路驅動以達成各種特殊需求。
  • IPAM(IP地址管理)驅動--Docker有一個內建的IP地址管理驅動,在沒有特別指定IP的情況下,它會為網路和端點提供了預設的子網或IP地址。IP地址通過網路(docker network create),容器(docker container create)和服務(docker service create)建立指令來人工分配。遠端IPAM驅動也存在和提供了整合到現有IPAM的工具。

Docker內建網路驅動

Docker內建網路驅動是Docker引擎的一部份不需要任何額外模組。他們可以被docker network命令所呼叫。以下是現存的內建網路驅動:
驅動描述
Host沒有名稱空間隔離,主機上的所有介面都可以直接被容器使用。
Bridge受Docker管理的Linux橋接網路。預設在同一個bridge網路的容器都可以相互通迅。
容器的外部訪問也可以使用bridge驅動來設定。
Overlay提供多主機的容器網路互連。同時使用了本地Linux橋接網路和VXLAN技術實現容器之間跨物理網路架構的連線。
MACVLAN使用MACVLAN橋接模式建立容器介面和主機介面之間的連線。實現為容器提供在物理網路中可路由的IP地址。
此外VLAN可以被中繼至macvlan驅動以強制實現容器的2層分段。
None容器具有屬於自己的網路棧和網路名稱空間,但並在容器內新增網路介面。如沒有其它的設定,則容器將完全獨立於其它網路。

網路作用域(scope)

如docker network ls的輸出所示,Docker網路驅動有一個作用域的概念。網路的作用域由驅動的作用域決定,如本地或swarm作用域(scope),本地作用域(scope)驅動僅在主機範圍內提供連線和網路服務(例如DNS和IPAM)。Swarm作用域驅動則提供跨swarm群集內的連線和網路服務。Swarm作用域網路在整個群集中有相同的網路ID,而本地作用域網路則具有各自唯一的網路ID。
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
1475f03fbecb        bridge              bridge              local
e2d8a4bd86cb        docker_gwbridge     bridge              local
407c477060e7        host                host                local
f4zr3zrswlyg        ingress             overlay             swarm
c97909a4b198        none                null                local

Docker遠端網路驅動

以下由社群和供應商建立的遠端網路驅動是與CNM相容。各自向容器提供不一樣的功能和網路服務。
驅動描述
由思科提供的一個開源的網路外掛,為多租戶微服務部署提供基礎設施和安全策略。
同時也為非容器負載和物理網路提供整合,例如ACI,contiv實現了遠端網路和IPAM驅動。
weave提供Docker容器跨多主機或雲訪問的虛擬網路,提供應用的自動發現,能在部分連線的網路上操作,
不需要額外的群集儲存,且操作非常友好。
在雲資料中心上開源的虛擬網路解決方案。針對資料中心的大部份負載(虛擬機器,容器,裸機伺服器),只要求IP連線。
使用標準的IP路由提供連線。通過iptables程式設計來實現對伺服器上的源和目的地工作負載的多租戶隔離和精細化策略。
kuryrOpenStack Kuryr專案的一部份。通過使用Neuton實現了Docker網路(libnetwork)遠端驅動API,OpenStack網路服務。
kuryr還包含了IPAM驅動。

Docker遠端IPAM驅動

社群和供應商建立的IPAM驅動也可用於提供與現有系統和特殊功能的整合。
驅動描述
開源的IPAM外掛,用於與現有的infoblox工具進行整合。

Linux網路基礎知識

Linux核心網路是TCP/IP協議棧的非常成熟的高效能的實現(除此之外還有其它核心特性如DNS和VXLAN)。Docker網路使用原始的核心網路棧建立的高層網路驅動,簡而言之,Docker網路就是Linux網路。
使用Linux核心特性來實現,確保了高效能和強健性。更重要的是它提供了跨多釋出版本,如此加強了應用的可移植性。
有幾個Docker用於現實內建CNM網路驅動的Linux網路塊。這些網路塊包括:Linux bridges, network namespaces, veth pairs和iptables。這些工具的組合實現了Docker網路驅動,並提供轉發規則,網路分段,和複雜網路策略的管理工具

Linux Bridge

Linux Bridge是用於取代Linux核心實現虛擬2層裝置的工具。它是基於MAC地址來轉發流量,通過檢查流量來動態學習。Linux bridge接被廣泛用於很多的Docker網路驅動。不要將Linux Bridge和Docker的bridge相混淆,Docker bridge是Linux Bridge的高層實現。

Network Namespaces

Linux Network Namespace是用於在核心中使用本地主機的介面,路由,和防火牆規則來隔離網路。是容器在Linux上實現安全隔離的一種技術,用於隔離容器。在網路慨念上它們類似於VRF(網路和主機內的資料平面分段)。一般情況下Network Namespace可以確保在同一主機上的容器除非通過Docker network進行連線,否則不能相互通訊。CNM網路驅動實現每個容器的namespace分隔。當然,容器也是可以共享相同的網路名稱空間或同屬於主機的網路空間的一部份。主機網路名稱空間容器、主機介面、主機路由表,這些namespace都被稱為全域性的網路名稱空間。

虛擬乙太網裝置(veth)

veth是Linux網路介面是兩個網路名稱空間之間的有線連線。veth在每個名稱空間裡都有一個介面。流量從一個介面直接傳輸到另一個介面。Docker網路驅動使用veth去提供明確的名稱空間之間的連線。當一個容器被附加到一個Docker網路時,veth的一端就會放到容器的內部(通常顯示為ethX介面),而另一端則連線到Docker網路。

iptables

iptables是內建的包過濾系統,它是自Linux核心2.4版本之後的一部分。它提供豐富的3層/4層防火牆功能,如資料包標記規則鏈,資料包偽裝,資料包丟棄。內建Docker網路驅動廣泛使用iptables去分段網路流量,提供主機埠對映,和為負載均衡而標記流量等功能。

Docker網路控制平面(control plane)

Docker分散式網路控制平面通過附帶傳播控制平面資料來管理Swarm-scoped的狀態。這是內建於Docker Swarm群集的功能無需任何額外的元件,例如關鍵值儲存。控制平面使用Gossip協議基於SWIM跨整個Docker容器群集拓撲去傳播網路狀態資訊。Gossip協議可以保證叢集維護訊息大小恆等不變、並高效一致、失敗檢測時間和跨大規模群集的快速聚合功能。這樣可以確保網路可以無故障地穩定地跨多個節點,有效避免如慢聚合或被動節點故障等問題。

控制平面有很高的安全性,提供透過加密通道來提供機密性,完整性,和可驗證性。也可以有效減少主機收到的更新資料。


控制平面由幾個相互協同工作、能快速跨大規模網路實現快速聚合的元件來組成。控制平面本身的分佈性確保了不會由於群集控制器的故障而影響到網路效能,即管理任務配置完成後,群集不再依賴管理端執行。

Docker網路控制平面由以下元件組成:

  • 訊息散佈元件,負責在一組的節點內點對點地扇形散佈訊息。每次都是在固定的時間間隔和相同的節點數量內進行傳播以保證不會由於過大的群集規模而過度佔用網路流量。指數級的資訊傳播橫跨節點以確保快速的聚合和滿足任意大小的群集執行需求。 
  • 故障檢測,通過直接或間接的Hello訊息避免被動的節點故障,且無懼網路自身的擁塞和特殊路徑。
  • 全狀態同步,週期性的全狀態同步達到快速聚合和解決網路斷層的問題。
  • 拓撲感知,該演算法可以感知節點與節點之間的延時。使用此資料可以使節點組的快速聚合更加高效。
  • 控制平面加密,此保護可免受到中間人攻擊,從而緩解網路安全問題。

注:Docker網路控制平面是Swarm的一個元件,需要在Swarm群集中才能操作。

Docker主機(Host)網路驅動

host網路驅動是最為Docker初學者所知的驅動之一。原因是這與Linux原來的操作完全相同。--net=host實際上就是關閉Docker網路而讓容器直接使用主機作業系統的網路。

與其它網路驅動讓每個容器都被放置在自己的網路空間(或沙箱)提供完全的容器間的網路隔離相比。 host驅動讓所有容器都在同一個主機網路空間上並共用主機的IP地址棧。所有在該主機的容器都可通過主機的介面相互通訊。從網路的觀點來說這就等同於沒有使用容器技術一樣。由於容器們都是使用相同的主機介面,所以沒有兩個節點是可以同時繫結相同的主機TCP埠的。這樣導致在同一主機上的容器在繫結埠時必須要相互協調。


#Create containers on the host network
$ docker run -itd --net host --name C1 alpine sh
$ docker run -itd --net host --name nginx

#Show host eth0
$ ip add | grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    inet 172.31.21.213/20 brd 172.31.31.255 scope global eth0

#Show eth0 from C1
$ docker run -it --net host --name C1 alpine ip add | grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP qlen 1000
    inet 172.31.21.213/20 brd 172.31.31.255 scope global eth0

#Contact the nginx container through localhost on C1
$ curl localhost
!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

在這個例子中,在這臺主機上,c1和nginx容器共用主機的eth0介面。這樣並不適用於多租戶或安全性要求高的應用環境。主機上的容器可以自由訪問該主機上的其它容器。由例子中的,c1容器可以執行curl nginx命令,可見容器之間是有可以使用localhost來相互通迅的。

在host驅動下,Docker並不管理任何容器的網路,例如埠對映和路由規則。這意味著常用的網路引數如-p和-icc都不會起作用。這樣也使host網路和其它網路驅動相比更簡單且延時更低。流量直接從容器到達主機的介面,提供裸機的效能,等同於無容器的處理。

全主機的訪問和無自動的策略管理使host驅動不同於其它一般的網路驅動。然而,host驅動也有一些吸引人的屬性,經常被用於對網路效能或應用排錯需求很高的情況下。

Docker橋接(Bridge)網路驅動

本節只解釋預設的Docker bridge網路,暫不討論使用者自定義的bridge網路。

預設Docker bridge網路

預設情況下,在所有執行Docker引擎的主機都會有一個叫做bridge的Docker網路。這個網路是使用bridge網路驅動建立的,是Linux bridge的例項化。以下說明一些容易混亂的慨念:

  • bridge,是Docker網路的一個名字
  • bridge,是一個網路驅動,或模板,網路是使用這個驅動來建立的。
  • docker0,是Linux bridge的名字,是核心建立的塊用於實現這個網路。

在一臺獨立的Docker主機上,在沒有特別指定的情況下bridge是容器連線的預設網路。在以下的例子中,容器沒有指定其它網路引數。Docker引擎會將容器連線到預設的bridge網路。要注意eth0是由bridge驅動來建立的,並由內建的IPAM驅動來管理IP地址。

#Create a busybox container named "c1" and show its IP addresses
host $ docker run -it --name c1 busybox sh
c1 # ip address
4: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 scope global eth0
...
 注:容器網路介面的MAC地址是動態產生的並內嵌了IP地址從而避免衝突。如此例中的ac:11:00:02就是對應的172.17.0.2。

在主機上使用brctl工具(通過yum install bridge-utils安裝)可以檢視現存的Linux橋網路名稱空間。將會顯示一個叫docker0的橋。docker0有一個介面,名為vetha3788c4,它提供從橋到c1容器內eth0介面的連線。

host $ brctl show
bridge name      bridge id            STP enabled    interfaces
docker0          8000.0242504b5200    no             vethb64e8b8

在容器c1內部,容器的路由表將流量直接傳給eth0介面,再到docker0橋。

c1# ip route
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0  src 172.17.0.2

容器可以繫結多個介面,視乎於有多少個網路連線到該容器。在容器內每一個網路對應一個介面。


從主機的路由表顯示,在全域性網路名稱空間的IP介面中包含了docker0。主機的路由表提供docker0和eth0之間的外部網路連線,從容器內部到外部網路的完整路徑:

host $ ip route
default via 172.31.16.1 dev eth0
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.42.1
172.31.16.0/20 dev eth0  proto kernel  scope link  src 172.31.16.102

預設情況下bridge分配了一個子網,該子網的地址範圍是172.[17-31].0.0/16或192.168.[0-240].0/20,它自動判斷,不會與所在主機介面的網段相沖突。預設bridge網路也可以被配置為使用指定的地址範圍。現存的Linux bridge會使用bridge網路,而不會由Docker重新建立一個。到Docker引擎文件庫中可以獲取更多關於bridge的資訊。

注:預設bridge網路只支援傳統的link。預設的bridge網路不支援基於名稱的服務發現和使用者指定IP地址。

使用者自定義bridge網路

在預設網路的基礎上,使用者可以建立他們自己的網路,叫做使用任意網路驅動建立的使用者自定義網路。在此情況下使用者自定義的bridge網路是安裝在主機上的新Linux橋。不同於預設的bridge網路,使用者自定義網路支援手工指定IP地址和子網分配。如果一個子網已經分配了,IPAM驅會自動分配下一個可用的私網空間子網。


圖中的使用者自定義bridge網路連線了兩個容器。一個是指定子網的叫my_bridge,另一個沒有指定任何IP引數,所以IPAM驅動分配了下個可用的IP子網,其餘的容器都有指定的IP。

$ docker network create -d bridge --subnet 10.0.0.0/24 my_bridge
$ docker run -itd --name c2 --net my_bridge busybox sh
$ docker run -itd --name c3 --net my_bridge --ip 10.0.0.254 busybox sh

brctl(通過yum install bridge-utils安裝)現在顯示了第二個在主機上的Linux bridge,名叫br-4bcc22f5e5b9,匹配my_bridge的網路ID。my_bridge也有兩個veth介面連線到容器c2和c3。

$ brctl show
bridge name      bridge id            STP enabled    interfaces
br-b5db4578d8c9  8000.02428d936bb1    no             vethc9b3282
                                                     vethf3ba8b5
docker0          8000.0242504b5200    no             vethb64e8b8

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
b5db4578d8c9        my_bridge           bridge              local
e1cac9da3116        bridge              bridge              local
...

列出全域性網路名稱空間介面可見Linux網路電路被Docker引擎例項化了。每個veth和Linux bridge代表了一個Linux bridge和容器網路名稱空間的連線。

$ ip link

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 
5: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 
6: br-b5db4578d8c9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 
8: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 
10: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 
...

單個容器的外部訪問

預設情況下所有的容器都在同一個Docker網路上(多主機swarm作用域或local作用域)容器之間的埠都可相互連線。在不同的Docker網路和進入(ingress)容器發起流量都是經過防火牆的。這是一個基本的安全措施,它保護了容器免受外部網路和容器之間的威脅。這個在網路安全中有更詳細的說明。

更多型別的Docker網路(包括bridge和overlay)從外部訪問容器內的應用必須要有明確的授權,這個通過內部埠對映來實現。Docker釋出的埠將容器內部的埠繫結在主機介面上。下圖描述了容器c2流量的進入方式(向下的箭頭)和流出方式(向上的箭頭)。容器的輸出(流出)流量預設是被允許的。容器的流出連線是通一個臨時埠偽裝(masqueraded)/SNATed來實現的(一般的埠範圍是32768到60999)。返回的流量也是被允許的,同時容器會自動使用主機上最佳的可路由IP上的臨時埠。

流入訪問是由特定的釋出埠來提供的。埠釋出可以由Docker引擎、UCP和引擎CLI來完成。一個特定的或隨機選擇的埠會被配置為容器或服務的源埠並繫結在主機上。該埠可以被設定為監聽一個特定的或所有的主機介面以接收返回的流量,所有的流量都被對映到這個埠到容器內部介面的鏈路上。

$ docker run -d --name C2 --net my_bridge -p 5000:80 nginx

外部訪問的配置是在Docker CLI或UCP中使用--publish / -p 引數。執行以上命令後,如圖所示容器c2是連線到my_bridge網路並有一個10.0.0.2的IP地址。該容器在主機介面192.168.0.2上對外發布服務埠為5000。所有的流量經由此埠流向容器公開的10.0.0.2:80。

輸出流量由容器經過偽裝後通過臨時埠32768再經過主機的192.168.0.2介面發出。返回流量則使用以相同的IP和埠為目標同樣經過偽裝後返回到容器的地下:埠10.0.0.2:33920 。當使用埠釋出時,在網路上的外部流量總是使用主機IP和容器釋出的埠,而不會使用容器內部的IP和埠。

更多關於容器對外提供服務埠和Docker引擎群集的資訊請閱讀Swarm服務的對外訪問

Overlay驅動網路架構

內建Docker overlay網路驅動使多主機聯網變得簡單和快速。通過overlay驅動,多主機網路成為了Docker內部的首層網路,且無需額外的準備或元件。overlay使用Swarm分散式控制平面去提供集中化的管理,可以穩定安全地橫跨整個大型群集網路。

VXLAN資料平面(data plane)

overlay驅動使用VXLAN資料平面工業標準,使容器網路脫離對物理網路的依賴。Docker overlay網路將容器流量封裝在VXLAN包頭中,如此就可以穿過2層和3層的物理網路。overlay使到網路不受物理網路拓撲的約束動態分段和易於控制。使用標準的IETF VXLAN包頭捉使可以使用標準的工具去檢查和分析流量。

注:VXLAN已成為Linux核心3.7版本以後的一部份。Docker使用原生的核心VXLAN特性去建立overlay網路。Docker overlay網路路徑全部都在核心名稱空間裡。這樣可以有更少的上下文切換,更少的CPU消耗,流量直接在應用和物理網絡卡之間傳輸。

IETF VXLAN(RFC 7348)是資料層的封裝格式,可實現在3層網路之上進行2層分段。VXLAN的設計滿足可以支援大規模應用的標準的IP網路、在共享物理網路基礎架構上的多租戶環境和基於雲的網路,均可以支援VXLAN的透明傳輸。

VXLAN定義為將MAC封裝在UDP中,將2層幀封裝在IP/UDP包頭中。在IP/UDP包頭幀封下提供主機之間在低層網路傳輸。在每臺主機之間建立overlay無狀態VXLAN通道實現點對多點的連線,由於overlay不依賴低層網路的拓撲,所以使應用變得更加便捷。網路策略和連線不管是在內部部署,還是部署在開發者PC或公有云上都可以無源依賴物理網路,實現透明傳輸。


上圖展示了資料包從容器c1到容器c2時橫跨overlay網路的情況。

  • c1對c2進行了DNS解釋。兩個容器都在同一overlay網路之中,Docker引擎提供了DNS伺服器解釋c2為overlay IP 10.0.0.3。
  • 一個overlay網路就是一個2層網段,因此當出現容器c1到容器c2的通訊時,容器c1會根據容器c2的MAC地址會生成2層幀。
  • 此框架通過overlay網路驅動,並由一個VXLAN包頭所封裝。分散式的overlay控制平面管理每個VXLAN通道端點的位置和狀態,因此它知道c2是位置在實體地址為192.168.0.3的主機host-B,這個地址成為了低層IP包頭中的目標地址。
  • 只要將資料包封裝成VXLAN包,物理網路就可以負責將它路由或橋接到正確的主機上。
  • 資料包到達host-B的eth0介面後,由overlay網路驅動來解封裝。從c1到c2的原始2層幀就會到達c2的eth0介面,並送達監聽此資料包的應用。

overlay驅動的內部架構

Docker Swarm控制平面自動提供overlay網路。無需進行VXLAN配置或Linux網路配置。資料平面加密,是overlay的一個可選特性,由overlay驅動自動完成所有網路配置。只需使用docker network create -d overlay命令建立網路或將現有網路連線到已建好的overlay網路中。


在建立overlay網路的過程中,Docker引擎需要每臺主機上都必須要有overlay。每建立一個overlay就會有一個Linux bridge關聯到一個VXLAN介面上。只有當容器被連線到overlay網路時Docker引擎才會在主機上例項化overlay網路,如此預防了一些不存的容器使到overlay無端擴張。

以下例項建立一個overlay網路並連線一個容器到這個網路上。Docker Swarm/UCP自動建立overlay網路。以下例項要求先將Swarm或UCP配置好。

#Create an overlay named "ovnet" with the overlay driver
$ docker network create -d overlay --subnet 10.1.0.0/24 ovnet

#Create a service from an nginx image and connect it to the "ovnet" overlay network
$ docker service create --network ovnet nginx

當overlay網路建立好之後,注意此時主機內會多出幾個介面和bridge,如下所示:

# Peek into the container of this service to see its internal interfaces
conatiner$ ip address

#docker_gwbridge network     
52: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 
    link/ether 02:42:ac:14:00:06 brd ff:ff:ff:ff:ff:ff
    inet 172.20.0.6/16 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe14:6/64 scope link
       valid_lft forever preferred_lft forever

#overlay network interface
54: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 
    link/ether 02:42:0a:01:00:03 brd ff:ff:ff:ff:ff:ff
    inet 10.1.0.3/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet 10.1.0.2/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:aff:fe01:3/64 scope link
       valid_lft forever preferred_lft forever

兩個在容器內部的介面對應兩個在主機上的bridge。在overlay網路中,每個容器最少有兩個介面分別連線到overlay和docker_gwbridge。

Bridge目的
overlay

為在同一個overlay網路上的容器之間的流入和流出點提供VXLAN封裝和加密。在所有主機上擴充套件overlay。會分配一個子網,並在參與的overlay網路上有相同的名字。

docker_gwbridge流出群集的流出bridge,每臺主機只會有一個docker_gwbridge。容器到容器的流量將無法在此通過。

注:Dockers Overlay驅動自從Docker引擎1.9後就已經存在,但需要一個額外的關鍵值儲存去管理網路的狀態。Docker引擎1.12將控制平面狀態整合到Docker引擎,所以不再需要額外的關鍵值儲存。1.12也引進了幾個新特性,包括加密和服務負載均衡。舊版本的Docker引擎不支援新引進網路特性。

Docker服務的外部訪問

Swarm & UDP提供群集釋出埠的外部訪問。雖然服務的流入和流出並不依賴中央閘道器,但分佈在各主機的服務任務的流入/流出則不同。有兩個服務埠釋出的模式,分別是host模式和ingress模式。

ingress模式的服務釋出

ingress模式的埠釋出使用Swarm Routing Mesh去應用負載均衡服務中的各個任務。 ingress模式在每個UCP/Swarm節點上釋出並繫結埠。到釋出埠的流入流量是通過Routing Mesh和輪詢實現負載均衡,自動將流量從新導向到一個健康服務任務上。即使該主機上沒有執行服務任務,流量也會被自動導向到另一臺有執行該任務的主機上。

$ docker service create --replicas 2 --publish mode=ingress,target=80,published=8080 nginx

注:mode=ingress是服務的預設模式。這條命令也能使用簡短版本-p 80:8080來定義。埠8080是繫結在每臺群集主機上並負載均衡到這個服務的兩個容器。

host模式的服務釋出

host模式埠釋出只在執行服務任務的主機上繫結埠。埠直接對映到該主機上的容器。每臺主機只能執行一個服務任務,否則會出現埠衝突。

$ docker service create --replicas 2 --publish mode=host,target=80,published=8080 nginx

注:host模式需要使用mode=host引數。所釋出的埠8080只會存在於執行那兩個容器的主機上。不會應用負載均衡,因此流量只會直接流向本地容器。如此當同一個主機上執行多個相同的服務任務時會引起埠衝突。

Ingress設計

每種釋出模式都有很多好的使用案例。ingress模式適合於服務有多個複製,並要求這些複製能實現負載均衡。host模式適合於已經由其它工具在外部實現了服務發現功能的場景。另一很好的host模式的案例是所有容器只會在一臺主機上執行,且各容器都有各自特殊的使命(如監控和記錄日誌)而無需負載均衡。


MACVLAN

macvlan驅動是一個新推出的經過考驗的真實網路虛擬化技術的實現。在Linux上的實現是非常輕量級的,因為它使用了Linux bridge來隔離,簡單地關聯一個Linux乙太網介面或子介面以強制實現物理網路之間的隔離。

MACVLAN提供大量唯一的特性和功能。擁有非常簡單和輕量級的架構意味著有積極的效能優勢。MACVLAN驅動更優於埠對映,提供容器和物理網路之間的連線。允許容器可以獲取能在物理網路上路由的IP地址。

MACVLAN使用案例很多,包括:

  • 有非常低網路延遲需求的應用
  • 網路設計要求容器要執行在同一個子網上並使用外部主機的網路

macvlan驅動可以使用父介面的概念。這個介面可以是一個物理介面如eth0。802.1q VLAN子介面如eth0.10(.10代表VLAN10),或者甚至可以結合主機的介面卡將兩個乙太網介面捆綁成一個單一的邏輯介面。

在配置MACVLAN網路時需要一個閘道器。該閘道器必須由主機的外部網路基礎架構來提供。MACVLAN網路允許在同一網路中的容器進行通訊。在同一主機但不同網路的容器在沒有外部路由的情況下是無法通訊的。


以下例項將MACVLAN網路繫結到主機的eth0上。同時還附加了兩個容器到mvnet MACVLAN網路,並展示了它們是可以相互Ping通的。每個容器都有一個在192.168.0.0/24段物理子網的地址,並預設閘道器是物理網路上的閘道器。

#Creation of MACVLAN network "mvnet" bound to eth0 on the host 
$ docker network create -d macvlan --subnet 192.168.0.0/24 --gateway 192.168.0.1 -o parent=eth0 mvnet

#Creation of containers on the "mvnet" network
$ docker run -itd --name c1 --net mvnet --ip 192.168.0.3 busybox sh
$ docker run -it --name c2 --net mvnet --ip 192.168.0.4 busybox sh
/ # ping 192.168.0.3
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.052 ms

如圖所示,c1和c2都是通過主機的eth0附加到一個叫macvlan的MACVLAN網路上。

MACVLAN的VLAN 主幹(trunk)

眾所周知,主幹(Trunking)802.1q的實現對於一臺Linux主機是很困難的。它要求更改配置檔案才能使在重啟後依然生效。如一個bridge參與進來,就需要有一個物理網絡卡要被移入到該bridge中,並且bridge會獲取IP地址。macvlan驅動通過建立,刪除和重啟主機來完全管理子介面和其它MACVLAN網路元件。


當macvlan驅動用子介面被例項化後,將允許在主機上實現VLAN主幹,使容器可以在2層網路上分段。macvlan驅動會自動建立子介面並將這些介面連線到容器的介面上。由此可使每個容器都可以在不同的VLAN中,使它們不能通迅,除非有外部閘道器路由。

#Creation of  macvlan10 network in VLAN 10
$ docker network create -d macvlan --subnet 192.168.10.0/24 --gateway 192.168.10.1 -o parent=eth0.10 macvlan10

#Creation of  macvlan20 network in VLAN 20
$ docker network create -d macvlan --subnet 192.168.20.0/24 --gateway 192.168.20.1 -o parent=eth0.20 macvlan20

#Creation of containers on separate MACVLAN networks
$ docker run -itd --name c1 --net macvlan10 --ip 192.168.10.2 busybox sh
$ docker run -it --name c2 --net macvlan20 --ip 192.168.20.2 busybox sh

上述的配置,我們使用通過配置子介面的macvlan驅動建立了兩個互相分隔的網路。macvlan驅動建立子介面並用以連線主機eth0和容器介面。主機介面和上游交換機必須要設定成主幹模式switchport mode trunk,只有這樣VLAN才可以被標記並通過此介面。一個或更多的容器可以連線到指定的macvlan網路以建立複雜的2層網路策略。

注:因為在一個主機介面上有多個MAC地址,所以可能要開啟埠的雜亂模式,這還取決於網絡卡是否支援MAC過濾功能。

none(孤島)網路驅動

和host網路驅動相似,none網路驅動基本上是一個無管理的網路選項。Docker引擎不會在容器內部建立介面,埠對映或安裝連線路由。容器使用--net=none引數後就會完全與其它容器和主機孤立。網路管理員或外部工具必須要負責提供其它與外界聯絡的管道。使用none網路的容器內部只會有loopback介面。

與host 驅動不同,none驅動會建立一個與其它容器相隔離的名稱空間。這樣保證了容器網路與其它容器和主機的隔離。

注:容器使用--net=none或--net=host引數後將無法與其它Docker網路連線。

物理網路的設計要求

Docker EE和Docker網路是為一般的資料中心網路基礎架構和拓撲而設的。集中的控制器和故障容忍群集保證相容整個大型的網路環境。元件提供的連網功能(如網路提供,MAC地址學習,overlay加密)都是Docker引擎,UCP,或Linux核心自身的一部份。執行內建的網路驅動時無需任何額外的元件或特殊的網路特性。

更準備地說,Docker內建網路驅動沒有以下要求:

  • 多播
  • 外部關鍵值儲存
  • 特殊路由協議
  • 主機之間的2層鄰接
  • 特定的拓撲結構如主幹&枝葉結構(spine&leaf),傳統的3層結構,和PoD設計。任何型別的拓撲都支援。

容器網路模型提升了應用的可移植性,在所有的環境中均能保證效能要求並能達到應用的策略要求。

Swarm內建的服務發現

單一Docker引擎和一個由Docker Swarm部署的服務任務是使用Docker內嵌的DNS去提供服務發現功能。在使用者自定義bridge、overlay網路和MACVLAN網路中Docer引擎有一個內部DNS伺服器,它提供了所有在其上的容器的DNS解釋。每個Docker容器(或Swarm模式下的服務任務)都有一個DNS直譯器負責將DNS請求轉發給Docker引擎,Docker引擎則充當DNS伺服器的角色。Docker引擎會自動檢查這此DNS請求,發現是屬於對網路上容器或服務的請求時就會提供解釋,為請求提供容器,任務或的服務名的IP地址或服務的虛擬IP(VIP),這些IP地址來源於內建的關鍵值儲存。

服務發現是網路作用域(network-scoped),意思是隻有在同一個網路中的容器或任務才能使用內嵌的DNS功能。在不同網路的容器不能相互解釋IP地址。另外,節點只會儲存參與到同一網路的容器或任務的DNS記錄。這樣特性提升了網路的安全性和效能。

對於源容器,如果目標容器或服務不屬於同一個網路那麼Docker引擎就會將DNS請求轉發到配置的預設DNS伺服器。


在此例項中有一個具有兩個容器的服務,名叫myservice。在同一個網路上還有一個叫client的服務。client執行兩個curl操作分別連線docker.com和myservice。有以下要求的動作:

  • 容器內建的直譯器在127.0.0.11:53上攔截DNS請求,並將請求轉發給Docker引擎的DNS伺服器。
  • myservice解釋為內部負載均衡的虛擬IP(VIP),再分發給相應的任務IP。
  • docker.com不存在於mynet網路的服務名池中,所以請求會被轉發到主機配置的預設DNS伺服器。

Docker內建負載均衡

Docker Swarm群集有內建的內部和外部負載均衡功能。內部負載均衡在同一Swarm或UCP群集中提供容器之間的負載均衡。外部負載均衡為流入群集的流量提供負載均衡。

UCP內部負載均衡

內部負載均衡器是在Docker服務建立時自動被例項化的。當Docker Swarm群集建立一個服務時,他們會自動分配一個與服務處的於同一網路的VIP。服務名將會被解釋為此IP。傳輸給VIP的流量會自動轉發給voerlay網路內所有健康的服務任務。此法可以避免任何客戶端的負載均衡由單一IP而返回給客戶端。Docker安排路由並平等分配流量給所有健康的服務任務。


以下命令可以檢視VIP,docker service inspect my_service

# Create an overlay network called mynet
$ docker network create -d overlay mynet
a59umzkdj2r0ua7x8jxd84dhr

# Create myservice with 2 replicas as part of that network
$ docker service create --network mynet --name myservice --replicas 2 busybox ping localhost
8t5r8cr0f0h6k2c3k7ih4l6f5

# See the VIP that was created for that service
$ docker service inspect myservice
...

"VirtualIPs": [
                {
                    "NetworkID": "a59umzkdj2r0ua7x8jxd84dhr",
                    "Addr": "10.0.0.3/24"
                },
]

注:DNS輪替(DNS RR)負載均衡,是另一個服務負載均衡可選項(通過配置--endpoint-mode引數來設定)。在DNS RR模式下並不是每個服務都會建立VIP。Docker DNS伺服器會將服務名會以輪流的方式解釋到各個獨立的容器IP。

UCP外部4層負載均衡(Docker Routing Mesh)

在建立和更新服務時可以使用--publish引數繫結服務的對外埠。在Docker Swarm模式下發布埠就意味著所有節點都會監聽此埠。但當該服務的任務沒有在該節點執行時,它也會監聽嗎?

這是路由網格(routing mesh)發揮作用的地方。Routing mesh是Docker1.12的新功能,組合了ipvs和iptables去建立功能強大的群集級別的4層負載均衡器。它允許所有的Swarm節點去接受服務釋出埠的連線。當任一Swarm節點接收以服務釋出TCP/UDP埠為目標的流量時,它會將流量轉發給預先定義好的叫ingress的overlay網路。該ingress網路行為與其它的overlay網路相似,只是它僅為來自外部客戶端轉輸給群集服務而設。它與上文提及的基於VIP的內部負載均衡相同。

一旦運行了服務,就可以為應用對映到任一Docker Swarm節點,並建立一個統一的外部DNS記錄。在routing mesh路由特性下,無需關心容器執行在哪一臺節點上。

#Create a service with two replicas and export port 8000 on the cluster
$ docker service create --name app --replicas 2 --network appnet -p 8000:80 nginx

上圖展示了Routing Mesh是如何工作的。

  • 一個服務建立了兩個複製,併發布了一個8000的外部埠。
  • routing mesh在群集中的所有主機都綁定了8000埠。
  • 流量的目標app可以進入任一節點。上例中External LB將流量傳送到沒有執行服務複製的節點上。
  • 核心的IPVS負載均衡將流量重定向到overlay網路上的健康服務複製。

UCP外部7層負載均衡器(HTTP Routing Mesh)

UCP通過HTTP Routing Mesh提供7層HTTP/HTTPS負載均衡功能。URLs可負載均衡到服務和服務複製。


點選UCP負載均衡參考架構獲取更多關於UCP 7層LB設計。

Docker網路安全和加密

網路安全是在設計和實現docker容器負載時最應考慮的問題。此節包含Docker網路安全考慮的關鍵內容。

網路分段和資料平面安全

Docker管理分散式的防火牆去分段容器網路並防止對容器資源惡意訪問。預設情況下,Docker網路會分段隔離流量。此方法提供了真正的3層網路隔離。

Docker引擎管理主機的防火牆規則以預防網路和容器釋出的管理埠互相訪問。在一個Swarm&UCP群集中會建立分散式的防火牆以動態保護群集中的應用執行例項。

下表列出了Docker網路的訪問策略。

路徑訪問
在相同Docker網路

在同一Docker網路中的所有介面是被允許訪問的。此規則適用於所有網路型別,如swarm scope, local scope, build-in, 和遠端驅動。

在Docker網路之間在Docker引擎管理的分散式主機防火牆下Docker網路之間的訪問是被拒的。容器可以附加到多個網路以達到和多個Docker網路通迅的目的。Docker網路之間的網路連線也可以管理為通向外部主機。
從Docker網路流出從Docker網路流出是被允許的。返回流量會通過本地防火牆並安全地被自動允許。
流入到Docker網路

流入流量預設被拒絕。埠通過host埠或ingress模式釋出埠提供特定的流入訪問。

一個例外情況是MACVLAN驅動操作與主機相同的IP空間,使容器網路完全開放。其它遠端網路驅動提供與MACVLAN類似的功能也是允許流入流量。

控制平面安全

Docker Swarm集成了PKI。所有在Swarm的管理端和節點都會從一個已簽名證書中得到一個已簽名的加密標識。所有管理端到管理端和管理端到節點的控制通迅都通過開箱即用的TLS安全加密。在Swarm模式中無需在外部生成證書或手動設定任何證書頒發機構去得到端到端的控制平面流量加密。證書會定期自動輪換。

資料平面網路加密

Docker開箱即用的overlay網路支援IPSec加密。Swarm&UCP在流量離開源容器時管理IPSec通道加密碼網路流量,並在流量到達目標容器後解密流量。這樣確保應用流量的高安全性而無需關注低層網路環境。在一個混合的,多租戶的或多雲的環境中,這是確保資料橫跨網路不會超出控制的安全關鍵。

下圖展示了運在一個Docker Swarm中的兩個容器之間如何安全通迅。


這個特性可在每個網路建立時新增--opt encryted=true引數時啟用(如:docker network create -d overlay --opt encrypted=true <NETWORK_NAME>)。網路建立後就可以在網路中建立服務(如:docker service create --network <NETWORK_NAME> <IMAGE> <COMMAND>)。當同一個服務在兩個不同的主機上建立任務時,一個IPsec在之主機之間的通道就會被建立,當流量離開源主機時被加密,進入目標主機後會被解密。

Swarm領導者會定期再生成一個對稱鑰匙並安全地分發到所有群集內的節點。這個鑰匙是由IPsec用於加密和解密資料平面流量。加密是通過IPSec在主機對主機(host-to-host)使用AES-GCM轉輸模式。

管理面安全&UCP中的RBAC

當使用CUP建立網路時,工作組和標籤定義到容器資源的訪問。資源許可權標籤定義了什麼人可以檢視,配置,和使用指定的Docker網路。


這個UCP截圖展示了使用production-team標籤如何雲控制網路只允許團隊的成員訪問。另外,如網路加密選項可以通UCP來套接。

IP地址管理

容器網路模型(CNM)提供了IP地址的靈活管理。有兩種IP地址的管理方法。

CNM有內建的IPAM驅動,簡單的全域性地為群集分配IP地址並預防了重複分配。內建的IPAM驅動是用於沒任何特別的設定下預設配置。

CNM有使用來自其它供應商和社群的遠端IPAM驅動介面。這些驅動使到可以與現有供應商和自建的IPAM工具進行整合。

使用UCP可以進行人工配置容器的IP地址和子網,如CLI或Docker API。這些地址取自於這些決定如何處理請求的驅動。

子網的大小和設計是非常依賴於特定的應用和特殊的網路驅動。IP地址空間在網路部署模型中有更深入的描述。包括埠對映,overlay,和MACVLAN都表達了IP地址是如何組織的。一般情況下容器地址會被分別放置到兩個桶裡。內部容器網路(bridge和overlay)IP地址預設是不能在物理網路上路由的。從而,來自容器介面的流量是可以在物理網路上路由的。這對節點物理網路的子網和內部網路(bridge, overlay)不會發生IP衝突很重要。重複的地址空間會導致流量無法到達目的地。

網路排錯

Docker網路的排錯對於開發者和網路工程師來說都是很難的。通過很好地理解Docker網路是如何工作並正確地設定工具,就可以排錯和解決這些網路問題。一個推薦的方法是使用netshoot容器來排查網路問題。netshoot容器有一套強大的網路排錯工具可以用於排查Docker網路問題。

使用排錯容器如netshoot,這些網路排錯工具非常便捷。netshoot容器可以附加到任一網路,能放在主機網路名稱空間,或在另一個容器的網路名稱空間去檢查主機網路的任一角度。

此容器包含以下工具:

  • iperf
  • tcpdump
  • netstat
  • iftop
  • drill
  • util-linux(nsenter)
  • curl
  • nmap

網路部署模型

以下例項使用了虛構的叫做Docker Pets的app,展示了網路部署模型。在網頁上展出了寵物的圖片,記錄了頁面的點選計數,此計數儲存在後端資料庫。

  • web是前端網頁伺服器,基於chrch/docker-pets:1.0映象
  • db是一個consul後端

chrch/docker-pets依賴一個環境變數DB,來指定如何找到後端db服務。

單一主機的Bridge驅動

這個模型是內建Docker bridge網路驅動的預設行為。這個bridge驅動建立了一個連線到主機的私有網路,並提供一個在主機介面上的外部埠對映以提供對外連線。

$ docker network create -d bridge petsBridge

$ docker run -d --net petsBridge --name db consul

$ docker run -it --env "DB=db" --net petsBridge --name web -p 8000:5000 chrch/docker-pets:1.0
Starting web container e750c649a6b5
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

注:當IP地址沒有指定時,埠對映繫結在主機的所有介面上。在此案例中容器的應用是繫結在0.0.0.0:8000。要提供特定IP地址的宣告就要使用-p IP:host_port:container_port引數。更多的關於埠釋出的可選項可以在Docker文件庫中找到。


此應用在主機上的所有介面綁定了8000埠。也提供Db=db,提供後端容器的名字。Docker引擎的內建DNS解釋這個容器的名字為db的IP地址。由於bridge是本地驅動,DNS決定的作用域只在單臺主機上。

以下命令顯示了我們的容器已經分配了來自petsBridge網路的172.19.0.0/24 IP空間的私有IP。在沒有特別指定IPAM驅動時Docker會使用內建的IPAM驅動去提供一個來自適合子網的IP。

$ docker inspect --format {{.NetworkSettings.Networks.petsBridge.IPAddress}} web
172.19.0.3

$ docker inspect --format {{.NetworkSettings.Networks.petsBridge.IPAddress}} db
172.19.0.2

這些IP地址被用於通往petsBridge網路的內部通迅。這些IP從來不會離開該主機。

帶外部服務發現的多主機bridge驅動

因為bridge驅動是一個本地作用域驅動,所以多主機網路需要一個多主機服務發現(SD)解決方案。外部SD註冊了容器或服務的位置和狀態,並允許其它服務去發現他們的位置。因為bridge驅動通過繫結埠去實現外部訪問,外部SD儲存host-ip:port作為指定容器的位置。

在以下例子中,每個服務的位置都要手動配置,模仿外部服務發現。db服務的位置是通過DB環境變數傳遞給web的。

#Create the backend db service and expose it on port 8500
host-A $ docker run -d -p 8500:8500 --name db consul

#Display the host IP of host-A
host-A $ ip add show eth0 | grep inet
    inet 172.31.21.237/20 brd 172.31.31.255 scope global eth0
    inet6 fe80::4db:c8ff:fea0:b129/64 scope link

#Create the frontend web service and expose it on port 8000 of host-B
host-B $ docker run -d -p 8000:5000 -e 'DB=172.31.21.237:8500' --name web chrch/docker-pets:1.0

web服務在主機host-B IP地址的8000埠提供網頁。


注:在此例項中我們沒有特別指定一個網路,所以預設是自動選擇使用Docker bridge網路。

當我們配置db的位置在172.31.21.237:8500時,我們正在建立一個服務發現的表格。我們為web服務靜態地配置db服務的位置。在單一主機的例項中,這個工作將由Docker引擎提供內建的DNS決定容器名稱來自動完成。在多主機的例項中我們通過手動配置服務發現。

在生產環境不推薦使用硬編碼的應用位置。外部服務發現工具的存在提供了這個對映在群集中可以動態地建立和刪除。例如:Consul和etcd。

下一節將研究overlay驅動方案,它提供了在群集中的內建全域性服務發現特性。相對於使用多個外部工具去提供網路服務,簡單是overlay驅動的一大主要優勢。

帶overlay驅動的多主機

此模型合用了內建overlay驅動去提供開箱即用的多主機連線。overlay驅動的預設設定在一個容器應用之內提供到除內部連線之外的外部連線。overlay驅動架構一節中回顧了overlay驅動的內部,在閱讀此節時請先回顧該節內容。

這個例項再次使用docker-pets應用。在下例中建立了一個Docker swarm。關於如何建立Swarm請參閱Docker文件庫。Swarm建立好之後,使用docker service create命令去建立由Swarm管理的容器和網路。

以下展示瞭如何檢查Swarm,建立一個overlay網路,然後在overlay網路上提供幾個服務。所有這些命令都要在UCP/Swarm控制器上執行。

#Display the nodes participating in this swarm cluster that was already created
$ docker node ls
ID                           HOSTNAME          STATUS  AVAILABILITY  MANAGER STATUS
a8dwuh6gy5898z3yeuvxaetjo    host-B  Ready   Active
elgt0bfuikjrntv3c33hr0752 *  host-A  Ready   Active        Leader

#Create the dognet overlay network
host-A $ docker network create -d overlay petsOverlay

#Create the backend service and place it on the dognet network
host-A $ docker service create --network petsOverlay --name db consul

#Create the frontend service and expose it on port 8000 externally
host-A $ docker service create --network petsOverlay -p 8000:5000 -e 'DB=db' --name web chrch/docker-pets:1.0

host-A $ docker service ls
ID            NAME  MODE        REPLICAS  IMAGE
lxnjfo2dnjxq  db    replicated  1/1       consul:latest
t222cnez6n7h  web   replicated  0/1       chrch/docker-pets:1.0

在此單主機bridge例項中,我們通過DB=db作為環境變數,到web服務。overlay驅動解釋db服務的名字為容器的overlay IP地址。發生在web和db之間的通迅僅僅使用overlay IP子網。

注:overlay和bridge網路內部,所有到容器的TCP和UDP埠是開啟並關聯到所有其它附加到overlay網路的容器。

web服務釋出了8000埠,且routing mesh在所有Swarm群集主機上釋出了8000埠。在瀏覽器中使用<host-A>:8000或<host-B>:8000來測試這個應用是否正在工作。

overlay的優點和使用案例

  • 對於小型和大型的多主機連線部署都非常簡單
  • 無需額外配置或元件就可以提供服務發現和負載均衡
  • overlay加密對於橫向微分段很有用
  • routing mesh可用於在整個群集中宣佈服務

App教程: MACVLAN bridge 模式

在很多情況下,應用或網路環境要求容器有可以在低層物理網路上路由的IP地址。MACVLAN驅動使這成麼現實。在MACVLAN架構章節中有描述。一個MACVLAN網路將自己繫結在主機介面上。這個介面可以是物理介面,邏輯子介面或繫結的組邏輯介面。它可以充當一個虛擬交換機並提供在同一MACVLAN網路上的容器之間的通迅。每個容器接收到唯一的附加節點的物理網路MAC地址和IP地址。


在此例項中,Pets應用被部署在Host-A和Host-B上。

#Creation of local macvlan network on both hosts
host-A $ docker network create -d macvlan --subnet 192.168.0.0/24 --gateway 192.168.0.1 -o parent=eth0 petsMacvlan
host-B $ docker network create -d macvlan --subnet 192.168.0.0/24 --gateway 192.168.0.1 -o parent=eth0 petsMacvlan

#Creation of db container on host-B
host-B $ docker run -d --net petsMacvlan --ip 192.168.0.5 --name db consul

#Creation of web container on host-A
host-A $ docker run -it --net petsMacvlan --ip 192.168.0.4 -e 'DB=192.168.0.5:8500' --name web chrch/docker-pets:1.0

由此可見與多主機bridge例項非常相似,但有以下值得注意的不同點:

  • 從web到db使用db自己的IP相對於主機IP。請記住macvlan容器IP是可以在低層網路路由的。
  • db或web沒有釋出任何埠,因為所有容器中的埠都是開啟的,並可以使用容器的IP立即到達。

當macvlan驅動提供這個唯一特性時,一方面是犧牲了可移植性。低層MACVLAN配置和部署工作量很大,容器地址必須要附著在容器放置的物理位置,另外還要防止地址