本文首發於我的公眾號 Linux雲計算網絡(id: cloud_dev),專注於干貨分享,號內有 10T 書籍和視頻資源,后台回復「1024」即可領取,歡迎大家關注,二維碼文末可以掃。
知其然而不知其所以然,不知也。老古人說得多好,學知識不懂得知識背后的原理,等於白學。
通過前面兩篇文章,我們知道了容器的單主機網絡和多主機網絡,對於這么多網絡方案,我們看到對 Docker 的整體網絡結構好像沒有改動,都是水平擴展的,那 Docker 網絡究竟是怎么集成這么多網絡方案而不改變自身原有的結構呢?本文就來一探究竟。
Docker 的總體框架
要回答這個問題,得從 Docker 的總體框架說起。
容器和虛擬機一樣,都是虛擬化的產品,都包括計算虛擬化,存儲虛擬化和 IO 虛擬化。容器作為輕量級的進程,不像虛擬機那般復雜,這三塊分別靠三個 Driver 來完成的,execdriver 負責計算虛擬化,networkdriver 負責網絡虛擬化,graphdriver 負責存儲虛擬化。由此可見,Docker 靠 Driver 這種設計思想來支撐起它的基礎平台,再往深了挖,它的每個子模塊都隨處可見這種設計思想,就網絡這個子模塊來看,也是如此。
Docker 的網絡模型
docker engine + libcontainer
期初的 Docker 網絡子模塊的代碼是分散在 docker daemon 和 libcontainer 中的,libcontainer 是一個獨立的容器管理包,execdriver 和 networkdriver 都是通過 libcontainer 來實現對容器的具體操作。
隨着業務場景越來越復雜,這種內嵌的方式很難針對不同的網絡場景進行擴展。后來,Docker 收購了一個做多主機網絡解決方案的公司 SocketPlane,然后讓那幫人專門來解決這個問題。這就是接下來要介紹的 libnetwork。
libnetwork && CNM
libnetwork 起初的做法很簡單,就是將 docker engine 和 libcontainer 中網絡相關的代碼抽出來,合並成一個單獨的庫,做成網絡抽象層,並對外提供 API。Docker 的願景就是希望 libnetwork 能夠做像 libcontainer 那樣,成為一個多平台的容器網絡基礎包。
后來受一個 GitHub issue ( https://github.com/moby/moby/issues/9983) 的啟發,libnetwork 引入容器網絡模型(Container Network Model,CNM),該模型進一步對 Docker 的網絡結構進行了細分,提出了三個概念:network、sandbox 和 endpoint。
network
network 是一個抽象的概念,你可以把它理解成一個網絡的插件,或者是網絡的 Driver,比如說單主機網絡的 Driver 就有 none、host、bridge,joined container 這四種,多主機網絡就有 overlay、macvlan、flannel 這些。network 可以獨立出去做,只需調用 Docker 對外提供的 API 就可以作為插件集成到 Docker 網絡中使用。
sandbox
sandbox 實現了容器內部的網絡棧,它定義容器的虛擬網卡,路由表和 DNS 等配置,其實就是一個標准的 linux network namespace 實現。
endpoint
network 實現了一個第三方的網絡棧,sandbox 則實現了容器內部的網絡棧,那這兩者怎么聯系起來呢?答案就是通過 endpoint,endpoint 實現了 veth pair,一個 endpoint 就表示一對 veth pair,一端掛在容器中,另一端掛在 network 中。
network、sandbox 和 endpoint 三者之間的關系:
-
一個 network 可以包含多個 endpoint,自然也就包含多個 sandbox。
-
一個 sandbox 可以包含多個 endpoint,可以屬於多個 network。
-
一個 endpoint 只可以屬於一個 network,並且只屬於一個 sandbox。
如上圖顯示三個容器,每個容器一個 sandbox,除了第二個容器有兩個 endpoint 分別接入 network1 和 network2 之外,其余 sandbox 都只有一個 endpoint 分別接入不同的 network。
到此,我們就可以解答文章開篇提到的問題,“不同的網絡方案如何集成到 Docker 網絡模型中而不改變原有結構?”
答案就是基於 libnetwork CNM,將各個網絡模型以插件或 Driver 的形式集成到 Docker 網絡中來,與 docker daemon 協同工作,實現容器網絡。Docker 原生的 Driver 包括單主機的 none、bridge、joined container 和 多主機的 overlay、macvlan,第三方 Driver 就包括多主機的 flannel、weave、calico 等。
總結
-
libnetwork 基於 CNM 模型將 Docker 網絡結構從原生方案中抽離出來,增強了網絡擴展性,以至於現在各種網絡方案層出不窮,都可以輕松集成到 Docker 中。
-
network,sandbox,endpoint 三個概念。
我的公眾號 「Linux雲計算網絡」(id: cloud_dev) ,號內有 10T 書籍和視頻資源,后台回復 「1024」 即可領取,分享的內容包括但不限於 Linux、網絡、雲計算虛擬化、容器Docker、OpenStack、Kubernetes、工具、SDN、OVS、DPDK、Go、Python、C/C++編程技術等內容,歡迎大家關注。