【獻禮DockerCon】Docker 1.7.0 深度解析
6月16日,Docker 1.7.0 發(fā)布,重磅炸彈在Docker圈引起巨大轟動,同時也為6月22日在舊金山舉辦的DockerCon大會獻禮。在本文中,DaoCloud團隊成員孫宏亮帶領(lǐng)您深度解析Docker 1.7.0。
早在Docker 1.6.0之際,Docker官方的工程師即宣稱:1.7.0版本將會帶來很大的變化,包括:Docker的bug修改以及功能添加;并且還體現(xiàn)在Docker的架構(gòu)上,如網(wǎng)絡(luò)模塊等。
話不多說,趕緊讓我們進入Docker 1.7.0的深度解析。從Docker的版本變更日志來看,Docker 1.7.0在四個方面會有或多或少的變動,分別是:Docker運行時(Runtime),Docker的代碼變化,Docker的builder模塊,以及Docker的bug修復(fù)。
本文主要涉及Docker 1.7.0的runtime。
1. 增添了一個仍然處于試驗階段的特性:支持out of process的數(shù)據(jù)卷插件。
何為試驗性質(zhì)的特性,換言之Docker的這部分特性還不支持在生產(chǎn)環(huán)境中采用,這些特性更多的希望用戶僅僅在測試環(huán)境,以及沙箱環(huán)境中采用。試驗性特性完全是Docker 1.7.0的一大亮點。
在以上的基礎(chǔ)上理解out-of-process,就容易很多,插件本身與Docker Daemon無耦合,即插即用,在Docker Daemon范疇之外發(fā)揮作用。
目前Docker的試驗性特性可以從兩個方面來描述,首先Docker目前已經(jīng)支持用戶自定義第三方插件的使用;另外在這基礎(chǔ)上,Docker自身支持了容器數(shù)據(jù)卷volume插件。此外,Docker還定義了一整套與插件相關(guān)的API,方便用戶使用。當(dāng)然,相信后續(xù)在該領(lǐng)域,不論是Docker 官方,還是整個社區(qū),都會不斷有新的插件誕生。值得一提的,在數(shù)據(jù)卷volume插件方面,出現(xiàn)了Flocker的身影,這也意味著容器的數(shù)據(jù)存儲問題,真正被提上臺面,并由相應(yīng)合理的解決方案。
2.從docker daemon的角度,添加了userland-proxy的起停開關(guān)。
首先介紹userland- proxy一直以來的作用。眾所周知,在Docker的橋接bridge網(wǎng)絡(luò)模式下,Docker容器時是通過宿主機上的NAT模式,建立與宿主機之外世界的通信。然而在宿主機上,一般情況下,進程可以通過三種方式訪問容器,分別為::, :,以及<0.0.0.0>:。實際上,最后一種方式的成功訪問完全得益于userland-proxy,即 Docker Daemon在啟動一個Docker容器時,每為容器在宿主機上映射一個端口,都會啟動一個docker-proxy進程,實現(xiàn)宿主機上0.0.0.0地址上對容器的訪問代理。
當(dāng)時引入userland-proxy時,也許是因為設(shè)計者意識到了0.0.0.0地址對容器訪問上的功能缺陷。然而,在docker- proxy加入Docker之后相當(dāng)長的一段時間內(nèi)。Docker愛好者普遍感受到,很多場景下,docker-proxy并非必需,甚至?xí)硪恍┢渌谋锥恕?/p>
影響較大的場景主要有兩種。
第一,單個容器需要和宿主機有多個端口的映射。此場景下,若容器需要映射1000個端口甚至更多,那么宿主機上就會創(chuàng)建1000個甚至更多的 docker-proxy進程。據(jù)不完全測試,每一個docker-proxy占用的內(nèi)存是4-10MB不等。如此一來,直接消耗至少4-10GB內(nèi)存,以及至少1000個進程,無論是從系統(tǒng)內(nèi)存,還是從系統(tǒng)CPU資源來分析,這都會是很大的負擔(dān)。
第二,眾多容器同時存在于宿主機的情況,單個容器映射端口極少。這種場景下,關(guān)于宿主機資源的消耗并沒有如第一種場景下那樣暴力,而且一種較為慢性的方式侵噬資源。
如今,Docker Daemon引入- -userland-proxy這個flag,將以上場景的控制權(quán)完全交給了用戶,由用戶決定是否開啟,也為用戶的場景的proxy代理提供了靈活性。
3. docker exec命令增加- -user參數(shù),用戶控制docker exec在容器中執(zhí)行命令時所處的用戶。
自從docker 1.3.0引入docker exec之后,用戶對容器的操縱能力被大大釋放,容器對用戶而言不再是一個運行的黑盒。然而,docker exec帶來巨大好處的同時,我們也能看到這其中的一些瑕疵,當(dāng)然Docker社區(qū)也在不斷地完善docker exec。
首先,docker exec在容器中運行的進程會以root權(quán)限運行,在權(quán)限方面缺乏靈活性的同時,容器的安全很有可能失控。參數(shù)- -user恰好彌補了這方面的不足。其次,docker exec的存在打破了容器內(nèi)進程呈現(xiàn)樹狀關(guān)系的現(xiàn)狀,而設(shè)計初期Docker容器的很多概念均以樹的思想從init process入手,因此目前docker exec的進程并不能和原生態(tài)容器進程完全一樣地被Docker Daemon管理。
#p#
4. 增強Docker容器網(wǎng)關(guān)地址的配置廣度。
Docker 1.7.0發(fā)布之前,在bridge橋接模式下,Docker容器的網(wǎng)關(guān)地址是默認生成的,一般為Docker環(huán)境中的docker0網(wǎng)橋地址。從容器通信的角度而言,默認的方式已經(jīng)可以滿足需要。但是,我們依然可以發(fā)現(xiàn),這種模式存在一些弊端,比如網(wǎng)絡(luò)配置的靈活性以及網(wǎng)絡(luò)安全性。
Docker容器的網(wǎng)絡(luò)一直廣受關(guān)注,缺乏可配置的特性,在如今的軟件發(fā)展中,幾乎就意味著封閉。 --default-gateway 以及--default-gateway-v6 這兩個參數(shù),很大程度上提高了用戶自定義容器網(wǎng)絡(luò)的靈活性,用戶更多場景的覆蓋,似乎從Docker的發(fā)展中若影若現(xiàn)。結(jié)合最近幾次新版本,功能的增強與豐富,不難猜測,Docker的企業(yè)化以及生產(chǎn)化,已經(jīng)更上一層樓。
默認網(wǎng)關(guān)的設(shè)置,為什么說會和容器的網(wǎng)絡(luò)安全相關(guān)呢?過去很長一段時間內(nèi),docker0作為容器的網(wǎng)關(guān)地址,這種方式將容器與宿主機的耦合關(guān)系體現(xiàn)的很徹底。docker0作為宿主機上的網(wǎng)絡(luò)接口,充當(dāng)容器與宿主機的橋梁。然而,也正是橋梁的存在,使得容器內(nèi)部進程很容易穿過網(wǎng)關(guān),到達宿主機,此過程并非對用戶透明。
5. 容器CFS quota的支持
完善Docker對內(nèi)核cgoups的支持,指的是對于一個組內(nèi)的進程組在一個周期內(nèi)被內(nèi)核CFS調(diào)度算法調(diào)度的時間限額,單位為微秒。該配置項在cgroups中相應(yīng)的文件為/sys/fs/cgroup/cpu/cpu.cfs_quota_us。
6. 容器磁盤IO限制的支持
眾所周知,容器將會為用戶提供一個隔離的運行環(huán)境,容器內(nèi)部的進程或者進程組使用資源時將受到限制,這樣的資源,包括:內(nèi)存資源(物理內(nèi)存以及swap),CPU資源(CPU時間片以及CPU核等),磁盤空間資源等,以上這部分內(nèi)容或多或少,Docker的新版本之前或多或少都可以實現(xiàn),然而隔離維度依舊不夠完美,這次Docker添加了—blkio-weight參數(shù),實現(xiàn)對容器磁盤 IO限制的支持。隔離更加完備,用戶也不再需要擔(dān)心容器間磁盤IO資源的競爭。
7. ZFS支持
Docker 1.7.0 正式宣布支持ZFS文件系統(tǒng)。此舉也意味著Docker容器文件系統(tǒng)的支持從原先的5種增加到6種。此前,Docker支持 aufs,devmapper,btrfs,ovelayfs,vfs(用于支持volume),如今添加對ZFS的支持。ZFS的支持,不禁讓人聯(lián)想到與Docker的數(shù)據(jù)卷volume插件的Flocker。錯進錯出,似乎關(guān)系較為微妙。
值得一提的是,除了支持ZFS之外,筆者發(fā)現(xiàn)在負責(zé)容器文件系統(tǒng)的graph模塊中,添加了driver_windows.go,雖然內(nèi)容極其簡易,并非完全實現(xiàn)對windows的全盤支持,但是至少讓大家看到Docker支持windows的步伐在不斷邁進。
8. docker logs的功能擴展
查看容器日志,相信很多Docker愛好者都體驗過,這也是用戶查看容器運行狀態(tài)的重要依據(jù)。
可以簡單了解Docker容器日志的原理:對于每一個創(chuàng)建的Docker容器,Docker Daemon均會在內(nèi)部創(chuàng)建一個goroutine來監(jiān)聽容器內(nèi)部進程的標(biāo)準輸出stdout以及標(biāo)準錯誤stderr,并將內(nèi)容傳遞至日志文件中。每當(dāng)用戶發(fā)通過Docker Client發(fā)起查看容器日志的請求docker logs之后,Docker Daemon會將日志文件的內(nèi)容傳遞至Docker Client顯示。
docker logs的發(fā)展,幾乎可以分為4個階段:Docker誕生初期的原生態(tài)日志打印;允許用戶follow容器的日志;開啟容器容器的tail功能,以及容器日志的since功能,打印從某一個時間戳開始之后的容器日志。
雖然容器日志的功能在逐漸增強,但是不可否認的是,容器日志是容器本身與Docker Daemon耦合最大的模塊之一,而這涉及Docker設(shè)計之初的計劃,絕非完美,但的確是短時間內(nèi)最易用的方案。
9. 容器與宿主機共享UTS命名空間的支持
不同的場景下,容器與宿主機可以完全隔離,容器也可能與宿主機存在共享信息的情況,Docker網(wǎng)絡(luò)的host模式就是一個很好的例子,該模式下的容器共享宿主機的網(wǎng)絡(luò)命名空間。
共享UTS命名空間的支持,意味著容器與宿主機的關(guān)系越來越微妙。也許目前很多Docker愛好者已經(jīng)習(xí)慣容器與宿主機完全隔離的運行,當(dāng)然也會有一些用戶曾經(jīng)抱怨完全隔離的運行環(huán)境并不能平滑的將傳統(tǒng)遺留業(yè)務(wù)容器化。那么,目前Docker在兼顧兩者的情況下,更多地在滿足后者的需求,不久的將來,Docker容器的運用場景必將更加豐富,這也是Docker走向企業(yè)化以及生產(chǎn)化必須要趟的路。
總體而言,Docker 1.7.0給筆者的感受是:功能上逐漸向企業(yè)需求靠攏,在production-ready的路上不斷優(yōu)化,另外在安全方面在不涉及內(nèi)核基礎(chǔ)上也不斷完善。