這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
【編者的話】11月4日,Docker 1.9 正式發布。其中Docker Swarm 和多跨主機網路正式可在生產環境使用,Docker Engine 提供了全新的儲存卷管理系統,Docker Compose 對更多環境提供了更好的支援。所有的這些都為大規模部署生產環境下的分布式應用打下了堅實的基礎。本文詳細分析了Docker 1.9的種種新特性。
@Container大會,專為一線開發人員和營運工程師設計的頂級容器技術會議。
1. 新特性簡介
十一月四號,Docker對1.9進行了發布,新的發行版中添加了很多有趣的特性,下面我就對新的發行版中的新特性做一個簡單的介紹。
- 跨主機網路:新的網路裝置可以支援使用者建立基於多個主機的虛擬網路,使容器間可以跨網路通訊。
- 持久化儲存:Docker 1.9 包含一個重新設計的完整儲存卷管理系統,這使得使用者可以更加容易的從前端來管理這些資料卷。
- Docker Swarm 1.0:修複bug並對其進行大量最佳化。Docker公司在1000個節點上測試了30000個容器,swarm可以如絲般潤滑的運行。
- Docker Engine 1.9:新的Docker Engine中加入了如下新特性:Dockerfile 的構建時參數、並行鏡像 pull、自訂 stop 訊號、AWS CloudWatch logging driver和磁碟 I/O metrics。
- Docker Compose 1.5:Docker Compose 是一個定義並運行多容器應用的工具,它有如下更新:支援 Windows、Compose 檔案中的環境變數、對多環境更好的支援、和 networking 整合和Compose file 校正。
- Docker Toolbox:這個工具可以使Mac和Windows支援這些新特性。
- Docker Registry 2.2:主要做了以下更新:支援 Google Cloud Storage、唯讀模式、支援可配置主機名稱、基於檔案的存在配置、可配置的 HTTP 健全狀態檢查和可配置的 HTTP 響應 headers。
詳細的更新說明可以參照《Docker 1.9 發布:Swarm 和跨主機網路進入 production-ready 階段》和Announcing Docker 1.9: Production-ready Swarm and Multi-host Networking。
2. 新特性原理解讀
下面就對我比較感興趣的幾點,做一下詳細的介紹。
首先,此次發行版最令人信服的就是Docker的跨主機網路了。早在六月的DockerCon大會上Docker公司就宣布已經開始進行對Docker Network的實驗性工作。在1.9中docker network命令脫離了實驗分支,正式進入了發行版中。有了新的Networking我們可以建立虛擬網路,然後將container加入到虛擬網路中,以獲得最適合所部署應用的網路拓撲結構。
和傳統的links模式相比,新的Networking有如下三點改進:
- 可以跨越不同的物理和虛擬機器主機,串連不同的容器。
- 使用者可以輕鬆的停止,開啟和重啟容器,而不用擔心破壞容器之間的相互串連。
- 使用者可以以任何順序建立容器。
在清楚了新的Networking的特性之後,我們來看一下這部分的實現原理。
Networking的跨主機部分使用的時ovs(Open vSwitch)和VXLAN隧道進行實現。關於容器之間的隔離,則使用了iptables。
要清楚Networking的執行流,首先要清楚如下三個概念:
- Sandbox:一個Sandbox包含了一個容器的網路棧。其中包括容器的管理介面,路由表和DNS設定。主要是通過namespace和cgroup進行實現。一個Sandbox可以包括多個Endpoint。
- Endpoint:一個Endpoint通過加入一個Sandbox來加入一個Network。Endpoint就相當於一個網卡。
- Network:一個Network是一組直接互聯的Endpoint組成的。它相當於一個二級網路。
清楚了以上三個基本概念之後我們來看看Network的執行流。
- 指定network的驅動和各項相關參數之後調用 libnetwork.New()建立一個NetWorkController執行個體。這個執行個體提供了各種介面,Docker可以通過它建立新的NetWork和Sandbox等。
- 通過controller.NewNetwork(networkType, "network1")來建立指定類型和名稱的Network。
- 通過network.CreateEndpoint("Endpoint1")來建立一個Endpoint。在這個函數中Docker為這個Endpoint分配了ip和介面,而對應的network執行個體中的各項配置資訊則會被使用到Endpoint中,其中包括iptables的配置規則和連接埠資訊等。
- 通過調用controller.NewSandbox()來建立Sandbox。這個函數主要調用了namespace和cgroup等來建立一個相對獨立的沙箱空間。
- 調用ep.Join(sbx)將Endpoint加入指定的Sandbox中,則這個Sandbox也會加入建立Endpoint對應的Network中。
總的來說,Endpoint是由Network建立的,隸屬於這個建立它的Network,當Endpoint加入Sandbox的時候,就相當於這個Sandbox加入到了這個Network中來。下面的圖可以簡要說明三者的關係。
然後是關於Volumes,即持久化儲存這一塊,Docker也做了比較大的改動。首先最明顯的就是--volume不再僅僅作為docker run的一個flag,也作為一個單獨的子命令出現在Docker中。底層也為volume添加了諸如ls、create、inspect和rm等volume子命令的api。新的volume子命令可以允許使用者先建立volume,然後在啟動的container的時候進行掛載,此舉也更加方便了volume的管理。
一個簡單的例子方便大家快速上手新特性:
$ docker volume create --name hello
hello
$ docker run -d -v hello:/world busybox ls /world
通過這個例子可以建立一個名為hello的volume,然後將其掛載到容器內的/world目錄下。
在Docker Engine 1.9中也有一些有趣實用的特性。
前面提到的磁碟 I/O metrics就是一個很實用的特性。這個新特性通過抓取系統內blkio IoServiceBytesRecursive中的資訊對磁碟的I/O進行計算,並通過docker state命令列印出來。所以現在通過docker state獲得的容器資訊就變成了如下的形式:
並行鏡像 pull也是一個有趣的新特性。現在可以做到如果使用者pull的鏡像正在被其他進程 pull,進度條會顯示這個資訊並正確退出。上一個版本的Docker Engine在處理使用者pull的鏡像正在被其他進程 pull這個問題中,用的是管道,這樣的話就很容易出現管道堵塞,就會卡死在“Layer already being pulled by another client”。
新的版本中使用了名為progressreader的工具包,如果遇到上述問題的話,Docker Engine可以調用這個工具包,通過共用的Broadcaster讀取其他進程pull使用者所指定鏡像的進度,顯示這個進度,並做出正確的返回。
最後來講講Docker Engine 1.9中的自訂 stop 訊號。這個特性可以在Dockerfile 指令中新增 STOPSIGNAL,通過使用這個指令Docker允許使用者自訂應用在收到docker stop所收到的訊號。這個新特性主要通過重寫Docker中signal庫內的stopsignal來支援自訂訊號的傳遞,在上層調用時則將使用者自訂的訊號傳入底層函數即可。
Q&A
Q:請問ovs和vxlan在吞吐和延遲方面有效能損失嗎,有無測試單位?
A:損失肯定是有的,但是具體的指標,Docker方面沒有給出測試結果。
Q:本地化建立images咋樣了,ovs是本地化嗎,物理網卡需要多少頻寬?
A:這個本次更新沒有提到。ovs的配置會本地化,具體物理網卡多大Docker官方沒有給出說明。
Q:1.9之後容器的網路棧是在容器啟動之前就配置好了還是啟動之後,之前版本的Docker,網路初始化是在容器啟動前還是啟動後?
A:網路棧啟動之前就會配置,啟動時候進行載入。之前的Docker也是這樣。
Q:docker daemon為跨主機網路增加了哪些配置項,跨主機網路的資訊存放在哪裡?
A:這個問題太具體了,需要仔細看看代碼才知道,我只是大概看了一下,畢竟網路這部分更新太多了。
Q:請問從1.9開始Docker就支援ovs了麼,ovs還是需要自行安裝吧?
A:1.9開始使用ovs實現networking部分,底層還是調用的ovs。ovs需要自己安裝。
Q:也就是說從1.9以後ovs就是直接通過隧道使用,而不是通過route來實現,對嗎?
A:可以這樣理解。
Q:請問volume特性現在有類似kubernetes persist volume的功能嗎,對接第三方儲存?
A:現在的volume還是對接本地檔案夾的,擁有了子命令,更多的是方便使用和管理。
Q:1.9版本特性,是不是更容易建立固定IP類虛擬機器的容器?
是的。
Q:跨主機的容器網路是由Docker daemon來維護的嗎?
A:是通過daemon維護的。
Q:Docker1.9的CRIU方案相對前幾個版本有哪些改進,新版本使用熱遷移有哪些坑?
A:Docker還是不能熱遷移,runC才可以。
Q:跨主機網路功能是全部在docker engine實現的麼,還是需要依賴安裝好的ovs相關環境?
A:底層還是調用ovs。
Q:如果容器重啟或重建對已經構建的虛擬網路有影響嗎?
A:沒有影響。
Q:D能不能給個1.9網路新特性的實際使用的例子?
A:我上面給的那個執行流大概就和實際使用的例子類似,就是建立Network,然後建立ep,建立沙箱,將ep裝入沙箱中。實際使用的例子可以參考Docker官方文檔。
Q:多個容器共用一個儲存如何解決同時寫的問題?
A:其實本質上Docker的資料卷就是一個bindmount,其工作原理和Linux主機上的共用卷原理一致。
===========================
以上內容根據2015年11月5日晚群分享內容整理。分享人
高相林,浙江大學SEL實驗室碩士研究生,目前在雲平台團隊從事科研和開發工作。浙大團隊對PaaS、Docker、大資料和主流開源雲端運算技術有深入的研究和二次開發經驗,團隊現聯合社區將部分技術文章貢獻出來,希望能對讀者有所協助。 DockOne每周都會組織定向的技術分享,歡迎感興趣的同學加:liyingjiesx,進群參與,您有想聽的話題可以給我們留言。