Docker 網路基礎介紹

OneAPM官方技術部落格發表於2016-05-12

【編者按】本文作者為 Mesosphere 開發大使 Michael Hausenblas,主要介紹配置 Docker 單主機網路的基本知識。文章系國內 ITOM 管理平臺 OneAPM 編譯呈現。

Docker 網路基礎介紹

想要了解有關 Docker 網路的更多資訊,包括多主機網路介紹,請檢視本文作者 Michael Hausenblas 撰寫的報告——《Docker 網路與服務探索》,點此下載該報告

當你開始擴大 Docker 的應用範圍時,忽然發現,你需要了解很多關於網路的知識。作為 Docker 網路的入門介紹,本文將從小處著手,首先你要考慮如何管理容器之間的連線。Docker 容器需要有個主機才能執行,該主機既可以是實體機器(例如:企業資料中心的裸機伺服器),也可以是 on-prem 或雲中的虛擬機器。如圖一所示,主機上會執行 Docker 後臺程式與 Docker 客戶端。一方面,你可以與 Docker 登錄檔互動(pull 或 push Docker 圖片);另一方面,也可以啟動、停止或監視容器。

Docker 網路基礎介紹 圖片1. 簡化版 Docker 架構(單主機)

主機與容器之間的關係為 1:N。也就是說,一個主機上通常會執行著多個容器。例如,Facebook 報告稱,取決於機器的規模,每個主機上平均執行著10到40個容器。此外,Mesosphere 對裸機進行的多項負載測試結果顯示,在每個主機上執行250以內的容器是可能的。

不過,無論是單主機部署模式,還是採用了機器叢集,你都不可避免地需要面對網路:

  • 對大多數單主機部署而言,問題可以歸結為通過共享卷組(shared volume)進行資料交換還是通過網路(基於 HTTP 或其他協議)進行資料交換。儘管 Docker 資料卷組簡單易用,但也會導致緊密耦合,這意味著更難將單主機部署轉變為多主機部署。通常,共享卷組的優勢在於資料處理速度。
  • 在多主機部署中,你需要考慮兩個方面:單個主機內的容器如何相互交流?不同主機之間的容器又如何交流?效能考慮與安全要素都將影響你的設計決定。當單主機的容量無法滿足需求(請參考前文關於單主機承載的平均容器數及最大容器數的討論),或打算使用諸如 Apache Spark, HDFS 或 Cassandra 之類的分散式系統時,多主機部署就變得必不可少了。

分散式系統與資料區域性性

使用分散式系統(進行計算或儲存)的主要好處通常來自併發處理,後者常常伴隨資料區域性性。此處,資料區域性性是指將程式碼釋出至資料所處位置的原則,而不是傳統的那樣倒過來。試思考以下情況:如果你的資料集大小以 TB 計,而程式碼量以 MB 計,在叢集中移動程式碼其實比將多個 TB 的資料移至中央處理區更加高效。除了獲得併發處理的優勢,分散式系統還具備更好的容錯性,因為系統的一些部分仍或多或少保留了獨立運轉的能力。

簡而言之,Docker 網路是 Docker 提供的原生容器 SDN 解決方法。概括來說,Docker 網路提供了四種可選模式:橋接模式、主機模式、容器模式以及無網路模式。本文將逐一討論這四種模式與單主機配置相關的內容,並在文末總結時提及諸如安全之類的一般話題。

橋接模式網路

在此模式下(參考圖片2),Docker 後臺程式會建立 docker0,一個虛擬的乙太網橋,用於自動轉發與之連線的任意網路介面間的資料包。預設情況下,該後臺程式會建立一對對等介面(peer interface),分派其一為容器的 eth0 介面,另一個則分派在主機的名稱空間下,同時從私有 IP 地址範圍中為該橋接分配一個 IP 地址或子網路,由此,同一主機上的所有容器都連線到此內網中。

示例1. 執行中的 Docker 橋接模式網路

$ docker run -d -P --net=bridge nginx:1.9.1$ docker ps
CONTAINER ID   IMAGE                  COMMAND    CREATED
STATUS         PORTS                  NAMES17d447b7425d   nginx:1.9.1            nginx -g   19 seconds ago
Up 18 seconds  0.0.0.0:49153->443/tcp,               0.0.0.0:49154->80/tcp  trusting_feynman

注意

由於橋接模式是 Docker 預設的連線模式,在示例1中,你也可以使用docker run -d -P nginx:1.9.1。如果你沒有使用 -P 引數(用於釋出容器的所有公開埠),也沒有使用 -p host_port:container_port(用於釋出特定的埠),IP 資料包在主機之外就無法路由至容器。

Docker 網路基礎介紹 圖片2. 橋接模式網路設定

主機模式網路

該模式能有效禁止 Docker 容器的網路隔離。因為容器共享了主機的網路名稱空間,它會直接暴露於公網。因此,你需要通過埠對映(port mapping)開展協調工作。

例項2. 執行中的 Docker 主機模式網路

$ docker run -d --net=host ubuntu:14.04 tail -f /dev/null$ ip addr | grep -A 2 eth0:2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000    link/ether 06:58:2b:07:d5:f3 brd ff:ff:ff:ff:ff:ff
    inet **10.0.7.197**/22 brd 10.0.7.255 scope global dynamic eth0

$ docker ps
CONTAINER ID  IMAGE         COMMAND  CREATED
STATUS        PORTS         NAMES
b44d7d5d3903  ubuntu:14.04  tail -f  2 seconds ago
Up 2 seconds                jovial_blackwell
$ docker exec -it b44d7d5d3903 ip addr2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000    link/ether 06:58:2b:07:d5:f3 brd ff:ff:ff:ff:ff:ff
    inet **10.0.7.197**/22 brd 10.0.7.255 scope global dynamic eth0

正如示例2所示,容器與主機的 IP 地址是一致的,同為 10.0.7.197

在圖片3中,在使用主機模式時,容器直接繼承了其所在主機的 IP 地址。該模式相比橋接模式運轉更迅速(因為不存在路由的開銷),但是它直接將容器暴露於公網中,而後者包含了諸多安全隱患。

Docker 網路基礎介紹 圖片3. Docker 主機模式網路設定

容器模式網路

在此模式下,Docker 會重用其他容器的網路名稱空間。通常,如果你想提供客製化的網路堆疊,該模式最為有用。該模式也為 Kubernetes 網路所採用。

示例3. 執行中的 Docker 容器模式網路

$ docker run -d -P --net=bridge nginx:1.9.1$ docker ps
CONTAINER ID  IMAGE        COMMAND   CREATED         STATUS
PORTS                      NAMES
eb19088be8a0  nginx:1.9.1  nginx -g  3 minutes ago   Up 3 minutes0.0.0.0:32769->80/tcp,0.0.0.0:32768->443/tcp     admiring_engelbart
$ docker exec -it admiring_engelbart ip addr8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet **172.17.0.3**/16 scope global eth0

$ docker run -it --net=container:admiring_engelbart ubuntu:14.04 ip addr...8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet **172.17.0.3**/16 scope global eth0

結果(如例項3所示)正如我們所想:通過 --net=container 啟動的第二個容器與第一個容器擁有相同的 IP 地址,即自動分配的 admiring_engelbart,也即 172.17.0.3

無網路模式

該模式將容器置於其網路堆疊之內,但並不進行配置。由此,斷絕了網路連線,主要適用於以下兩種情況:不需要網路的容器(例如:向磁碟卷組進行寫入的批量作業),以及當你想配置自定義網路時。

示例4. 執行中的 Docker 無網模式

$ docker run -d -P --net=none nginx:1.9.1$ docker ps
CONTAINER ID  IMAGE          COMMAND   CREATED
STATUS        PORTS          NAMES
d8c26d68037c  nginx:1.9.1    nginx -g  2 minutes ago
Up 2 minutes                 grave_perlman
$  docker inspect d8c26d68037c | grep IPAddress    "IPAddress": "",    "SecondaryIPAddresses": null,

正如示例4所見,並未配置網路連線——這正是我們所期望的。

你可以在此 Docker 文件中瞭解有關網路以及配置選項的更多知識。

注意 本文提及的所有 Docker 指令都在 CoreOS 環境中實踐過,Docker 客戶度與主機端的版本號均為 1.7.1。

總結

除了上文提及的四種 Docker 單主機網路模式,你還應瞭解以下幾個方面的內容(這些內容也都與多主機部署密切相關)。

分配 IP 地址

當容器數量變化頻繁且涉及的數量較多時,手動分配 IP 地址是不可行的。橋接模式在一定程度上能解決該問題。為了避免本地網路中的 ARP (Address Resolution Protocol,地址解析協議)衝突,Docker 後臺程式會根據分配的 IP 地址隨機生成 MAC 地址。

分配埠

你會發現自己不是處於固定埠分配陣營,就是動態埠分配陣營。這可以是隨服務或應用而變的策略,也可以是全域性策略,但是,你必須下定決心。記住,在橋接模式下,Docker 能自動分配可路由的(UDP 或 TCP)埠。

網路安全

預設情況下,Docker 啟用了容器間通訊(這意味著預設設定為 --icc=true),也就是說,同一主機上的容器可以毫無限制地相互交流,這有可能導致拒絕服務(DOS)攻擊。此外,Docker 通過 --ip_forward--iptables 標記控制容器與外部世界的交流。你應該學習這些標記的預設值,並讓公司安全團隊也有所瞭解,同時在 Docker 後臺程式的設定中體現你的認知。對了,由 StackEngine 的 Boyd Hemphill 完成的 Docker 安全分析也是很好的學習材料。

另一個需要考慮的網路安全問題是線上加密。然而,在撰寫本文時,針對這一問題的解決方案非常有限。只有兩個系統提供了開箱即用的解決方案:使用 NaCl 的 Weave 以及包含基於 TLS 設定的 OpenVPN。據筆者從 Docker 安全主管 Diogo Mónica 處得到的訊息,線上加密可能從 1.9版本後開始提供。

最後,建議閱讀 Adrian Mouat 撰寫的《Docker 使用入門》,該文件詳細介紹了有關網路安全的方方面面。

小貼士 自動 Docker 安全檢查 若要在生產環境中自動檢查部署 Docker 容器的常見安全問題,筆者強烈推薦使用 The Docker Bench for Security

OneAPM Cloud Insight 產品集監控、管理、計算、協作、視覺化於一身,幫助所有 IT 公司,減少在系統監控上的人力和時間成本投入,讓運維工作更加高效、簡單。想閱讀更多技術文章,請訪問 OneAPM 官方技術部落格

本文轉自 OneAPM 官方部落格

原文地址:https://www.oreilly.com/learning/what-is-docker-networking

相關文章