網絡已經無處不在。每當基礎設施出現問題時,被抱怨的通常是網絡,很大一部分原因是,網絡負責連接一切——無網絡,無 APP!
在 Docker 早期階段,網絡設計確實非常復雜,那時候配置網絡幾乎是一種樂趣。
Docker 在容器內部運行應用,這些應用之間的交互依賴于大量不同的網絡,這意味著 Docker 需要強大的網絡功能。幸運的是,Docker 對于容器之間、容器與外部網絡和 VLAN 之間的連接均有相應的解決方案。
后者對于那些需要跟外部系統(如虛擬機和物理機)的服務打交道的容器化應用來說至關重要。
Docker 網絡架構源自一種叫作容器網絡模型(CNM)的方案,該方案是開源的并且支持插接式連接。
Libnetwork 是 Docker 對 CNM 的一種實現,提供了 Docker 核心網絡架構的全部功能。不同的驅動可以通過插拔的方式接入 Libnetwork 來提供定制化的網絡拓撲。
為了實現開箱即用的效果,Docker 封裝了一系列本地驅動,覆蓋了大部分常見的網絡需求。其中包括單機橋接網絡(Single-Host Bridge Network)、多機覆蓋網絡(Multi-Host Overlay),并且支持接入現有 VLAN。
Docker 生態系統中的合作伙伴通過提供驅動的方式,進一步拓展了 Docker 的網絡功能。Libnetwork 提供了本地服務發現和基礎的容器負載均衡解決方案。
在頂層設計中,Docker 網絡架構由 3 個主要部分構成:CNM、Libnetwork 和驅動。
? CNM 是設計標準。在 CNM 中,規定了 Docker 網絡架構的基礎組成要素。
? Libnetwork 是 CNM 的具體實現,并且被 Docker 采用,Libnetwork 通過 Go 語言編寫,并實現了 CNM 中列舉的核心組件。
? 驅動通過實現特定網絡拓撲的方式來拓展該模型的能力。
下圖展示了頂層設計中的每個部分是如何組裝在一起的。
一切都始于設計!
Docker 網絡架構的設計規范是 CNM。CNM 中規定了 Docker 網絡的基礎組成要素,完整內容見 GitHub 的 docker/libnetwork 庫。
抽象來講,CNM 定義了 3 個基本要素:沙盒(Sandbox)、終端(Endpoint)和網絡(Network)。
? 沙盒是一個獨立的網絡棧。其中包括以太網接口、端口、路由表以及 DNS 配置。
? 終端就是虛擬網絡接口。就像普通網絡接口一樣,終端主要職責是負責創建連接。在 CNM 中,終端負責將沙盒連接到網絡。
? 網絡是 802.1d 網橋(類似大家熟知的交換機)的軟件實現。因此,網絡就是需要交互的終端的集合,并且終端之間相互獨立。
下圖展示了 3 個組件是如何連接的。
Docker 環境中最小的調度單位就是容器,而 CNM 也恰如其名,負責為容器提供網絡功能。
下圖展示了 CNM 組件是如何與容器進行關聯的——沙盒被放置在容器內部,為容器提供網絡連接。
容器 A 只有一個接口(終端)并連接到了網絡 A。容器 B 有兩個接口(終端)并且分別接入了網絡 A 和網絡 B。容器 A 與 B 之間是可以相互通信的,因為都接入了網絡 A。但是,如果沒有三層路由器的支持,容器 B 的兩個終端之間是不能進行通信的。
需要重點理解的是,終端與常見的網絡適配器類似,這意味著終端只能接入某一個網絡。因此,如果容器需要接入到多個網絡,就需要多個終端。
下圖對前面的內容進行拓展,加上了 Docker 主機。雖然容器 A 和容器 B 運行在同一個主機上,但其網絡堆棧在操作系統層面是互相獨立的,這一點由沙盒機制保證。
CNM 是設計規范文檔,Libnetwork 是標準的實現。Libnetwork 是開源的,采用 Go 語言編寫,它跨平臺(Linux 以及 Windows),并且被 Docker 所使用。
在 Docker 早期階段,網絡部分代碼都存在于 daemon 當中。daemon 變得臃腫,并且不符合 UNIX 工具模塊化設計原則,即既能獨立工作,又易于集成到其他項目。
所以,Docker 將該網絡部分從 daemon 中拆分,并重構為一個叫作 Libnetwork 的外部類庫。
現在,Docker 核心網絡架構代碼都在 Libnetwork 當中。Libnetwork 實現了 CNM 中定義的全部 3 個組件。此外它還實現了本地服務發現(Service Discovery)、基于 Ingress 的容器負載均衡,以及網絡控制層和管理層功能。
如果說 Libnetwork 實現了控制層和管理層功能,那么驅動就負責實現數據層。比如,網絡連通性和隔離性是由驅動來處理的,驅動層實際創建網絡對象也是如此,其關系如下圖所示。
Docker 封裝了若干內置驅動,通常被稱作原生驅動或者本地驅動。
在 Linux 上包括 Bridge、Overlay 以及 Macvlan,在 Windows 上包括 NAT、Overlay、Transport 以及 L2 Bridge。
第三方也可以編寫 Docker 網絡驅動。這些驅動叫作遠程驅動,例如 Calico、Contiv、Kuryr 以及 Weave。
每個驅動都負責其上所有網絡資源的創建和管理。舉例說明,一個叫作“prod-fe-cuda”的覆蓋網絡由 Overlay 驅動所有并管理。這意味著 Overlay 驅動會在創建、管理和刪除其上網絡資源的時候被調用。
為了滿足復雜且不固定的環境需求,Libnetwork 支持同時激活多個網絡驅動。這意味著 Docker 環境可以支持一個龐大的異構網絡。