編者按:Docker是現(xiàn)在炙手可熱的技術(shù),特別是剛剛過去的DockerCon著實(shí)讓Docker火了一把,如何開始Docker的學(xué)習(xí)呢?本文轉(zhuǎn)載自@fe-rest在GitHub上的博客,作者從以下幾點(diǎn)內(nèi)容帶你入門:
Docker存在的問題和現(xiàn)有的解決思路
Docker is an open-source engine that automates the deployment of any application as a lightweight, portable, self-sufficient container that will run virtually anywhere.
Docker 是 PaaS 提供商dotCloud開源的一個(gè)基于 LXC 的高級容器引擎,源代碼托管在 Github 上, 基于go語言并遵從Apache2.0協(xié)議開源。 Docker近期非常火熱,無論是從 github 上的代碼活躍度,還是Redhat在RHEL6.5中集成對Docker的支持, 就連 Google 家的 Compute Engine 也支持 docker 在其之上運(yùn)行, 最近百度也用 Docker 作為其PaaS的基礎(chǔ)(不知道規(guī)模多大)。
一款開源軟件能否在商業(yè)上成功,很大程度上依賴三件事 - 成功的 user case, 活躍的社區(qū)和一個(gè)好故事。 dotCloud 自家的 PaaS 產(chǎn)品建立在docker之上,長期維護(hù) 且有大量的用戶,社區(qū)也十分活躍,接下來我們看看docker的故事。
環(huán)境管理復(fù)雜 - 從各種OS到各種中間件到各種app, 一款產(chǎn)品能夠成功作為開發(fā)者需要關(guān)心的東西太多,且難于管理,這個(gè)問題幾乎在所有現(xiàn)代IT相關(guān)行業(yè)都需要面對。
云計(jì)算時(shí)代的到來 - AWS的成功, 引導(dǎo)開發(fā)者將應(yīng)用轉(zhuǎn)移到 cloud 上, 解決了硬件管理的問題,然而中間件相關(guān)的問題依然存在 (所以openstack HEAT和 AWS cloudformation 都著力解決這個(gè)問題)。開發(fā)者思路變化提供了可能性。
虛擬化手段的變化 - cloud 時(shí)代采用標(biāo)配硬件來降低成本,采用虛擬化手段來滿足用戶按需使用的需求以及保證可用性和隔離性。然而無論是KVM還是Xen在 docker 看來, 都在浪費(fèi)資源,因?yàn)橛脩粜枰氖歉咝н\(yùn)行環(huán)境而非OS, GuestOS既浪費(fèi)資源又難于管理, 更加輕量級的LXC更加靈活和快速。
LXC的移動(dòng)性 - LXC在 linux 2.6 的 kernel 里就已經(jīng)存在了,但是其設(shè)計(jì)之初并非為云計(jì)算考慮的,缺少標(biāo)準(zhǔn)化的描述手段和容器的可遷移性,決定其構(gòu)建出的環(huán)境難于 遷移和標(biāo)準(zhǔn)化管理(相對于KVM之類image和snapshot的概念)。docker 就在這個(gè)問題上做出實(shí)質(zhì)性的革新。這正式筆者第一次聽說docker時(shí)覺得最獨(dú)特的地方。
面對上述幾個(gè)問題,docker設(shè)想是交付運(yùn)行環(huán)境如同海運(yùn),OS如同一個(gè)貨輪,每一個(gè)在OS基礎(chǔ)上的軟件都如同一個(gè)集裝箱,用戶可以通過標(biāo)準(zhǔn)化手段自由組裝運(yùn)行環(huán)境, 同時(shí)集裝箱的內(nèi)容可以由用戶自定義,也可以由專業(yè)人員制造。這樣,交付一個(gè)軟件,就是一系列標(biāo)準(zhǔn)化組件的集合的交付,如同樂高積木,用戶只需要選擇合適的積木組合, 并且在最頂端署上自己的名字(最后個(gè)標(biāo)準(zhǔn)化組件是用戶的app)。這也就是基于docker的PaaS產(chǎn)品的原型。
在docker的網(wǎng)站上提到了docker的典型場景:
由于其基于LXC的輕量級虛擬化的特點(diǎn),docker相比KVM之類最明顯的特點(diǎn)就是啟動(dòng)快,資源占用小。因此對于構(gòu)建隔離的標(biāo)準(zhǔn)化的運(yùn)行環(huán)境,輕量級的PaaS(如dokku), 構(gòu)建自動(dòng)化測試和持續(xù)集成環(huán)境,以及一切可以橫向擴(kuò)展的應(yīng)用(尤其是需要快速啟停來應(yīng)對峰谷的web應(yīng)用)。
PaaS環(huán)境是不言而喻的,其設(shè)計(jì)之初和dotcloud的案例都是將其作為PaaS產(chǎn)品的環(huán)境基礎(chǔ)
因?yàn)槠錁?biāo)準(zhǔn)化構(gòu)建方法(buildfile)和良好的REST API,自動(dòng)測試和持續(xù)集成/部署能夠很好的集成進(jìn)來
因?yàn)長XC輕量級的特點(diǎn),其啟動(dòng)快,而且docker能夠只加載每個(gè)container變化的部分,這樣資源占用小,能夠在單機(jī)環(huán)境下與KVM之類的虛擬化方案相比能夠更加快速和占用更少資源
What Docker Can NOT Do
Docker并不是全能的,設(shè)計(jì)之初也不是KVM之類虛擬化手段的替代品,個(gè)人簡單總結(jié)了幾點(diǎn)
針對1-2,有windows base應(yīng)用的需求的基本可以pass了; 3-5主要是看用戶的需求,到底是需要一個(gè)container還是一個(gè)VM, 同時(shí)也決定了docker作為 IaaS 不太可行。 針對6,7雖然是docker本身不支持的功能,但是可以通過其他手段解決(disk quota, mount --bind
)。總之,選用container還是vm, 就是在隔離性和資源復(fù)用性上做tradeoff
另外即便docker 0.7能夠支持非AUFS的文件系統(tǒng),但是由于其功能還不穩(wěn)定,商業(yè)應(yīng)用或許會(huì)存在問題,而AUFS的穩(wěn)定版需要kernel 3.8, 所以如果想復(fù)制dotcloud的 成功案例,可能需要考慮升級kernel或者換用ubuntu的server版本(后者提供deb更新)。我想這也是為什么開源界更傾向于支持ubuntu的原因(kernel版本)
由于篇幅所限,這里就不再展開翻譯,可參見鏈接 - http://docs.docker.io/en/latest/use/
由于篇幅所限,這里就不再展開翻譯,可參見鏈接 - http://docs.docker.io/en/latest/use/builder/
Docker核心解決的問題是利用LXC來實(shí)現(xiàn)類似VM的功能,從而利用更加節(jié)省的硬件資源提供給用戶更多的計(jì)算資源。同VM的方式不同, LXC 其并不是一套硬件虛擬化方法 - 無法歸屬到全虛擬化、部分虛擬化和半虛擬化中的任意一個(gè),而是一個(gè)操作系統(tǒng)級虛擬化方法, 理解起來可能并不像VM那樣直觀。所以我們從虛擬化要docker要解決的問題出發(fā),看看他是怎么滿足用戶虛擬化需求的。
用戶需要考慮虛擬化方法,尤其是硬件虛擬化方法,需要借助其解決的主要是以下4個(gè)問題:
lxc-start
進(jìn)程的子進(jìn)程, 只是在Kernel的namespace中隔離的, 因此需要一些kernel的patch來保證用戶的運(yùn)行環(huán)境不會(huì)受到來自host主機(jī)的惡意入侵, dotcloud(主要是)利用kernel grsec
patch解決的.LXC所實(shí)現(xiàn)的隔離性主要是來自kernel的namespace, 其中pid
, net
, ipc
, mnt
, uts
等namespace將container的進(jìn)程, 網(wǎng)絡(luò), 消息, 文件系統(tǒng)和hostname 隔離開。
pid namespace
之前提到用戶的進(jìn)程是lxc-start
進(jìn)程的子進(jìn)程, 不同用戶的進(jìn)程就是通過pid
namespace隔離開的,且不同 namespace 中可以有相同PID。具有以下特征:
/sbin/init
進(jìn)程)pseudo-filesystem
的/proc目錄只能看到自己namespace中的進(jìn)程正是因?yàn)橐陨系奶卣鳎械腖XC進(jìn)程在docker中的父進(jìn)程為docker進(jìn)程,每個(gè)lxc進(jìn)程具有不同的namespace。同時(shí)由于允許嵌套,因此可以很方便的實(shí)現(xiàn)LXC in LXC
net namespace
有了 pid
namespace, 每個(gè)namespace中的pid能夠相互隔離,但是網(wǎng)絡(luò)端口還是共享host的端口。網(wǎng)絡(luò)隔離是通過net
namespace實(shí)現(xiàn)的, 每個(gè)net
namespace有獨(dú)立的 network devices, IP addresses, IP routing tables,/proc/net
目錄。這樣每個(gè)container的網(wǎng)絡(luò)就能隔離開來。 LXC在此基礎(chǔ)上有5種網(wǎng)絡(luò)類型,docker默認(rèn)采用veth的方式將container中的虛擬網(wǎng)卡同host上的一個(gè)docker bridge連接在一起。
ipc namespace
container中進(jìn)程交互還是采用linux常見的進(jìn)程間交互方法(interprocess communication - IPC), 包括常見的信號(hào)量、消息隊(duì)列和共享內(nèi)存。然而同VM不同,container 的進(jìn)程間交互實(shí)際上還是host上具有相同pid namespace中的進(jìn)程間交互,因此需要在IPC資源申請時(shí)加入namespace信息 - 每個(gè)IPC資源有一個(gè)唯一的 32bit ID。
mnt namespace
類似chroot
,將一個(gè)進(jìn)程放到一個(gè)特定的目錄執(zhí)行。mnt
namespace允許不同namespace的進(jìn)程看到的文件結(jié)構(gòu)不同,這樣每個(gè) namespace 中的進(jìn)程所看到的文件目錄就被隔離開了。同chroot
不同,每個(gè)namespace中的container在/proc/mounts
的信息只包含所在namespace的mount point。
uts namespace
UTS("UNIX Time-sharing System") namespace允許每個(gè)container擁有獨(dú)立的hostname和domain name, 使其在網(wǎng)絡(luò)上可以被視作一個(gè)獨(dú)立的節(jié)點(diǎn)而非Host上的一個(gè)進(jìn)程。
user namespace
每個(gè)container可以有不同的 user 和 group id, 也就是說可以以container內(nèi)部的用戶在container內(nèi)部執(zhí)行程序而非Host上的用戶。
有了以上6種namespace從進(jìn)程、網(wǎng)絡(luò)、IPC、文件系統(tǒng)、UTS和用戶角度的隔離,一個(gè)container就可以對外展現(xiàn)出一個(gè)獨(dú)立計(jì)算機(jī)的能力,并且不同container從OS層面實(shí)現(xiàn)了隔離。 然而不同namespace之間資源還是相互競爭的,仍然需要類似ulimit
來管理每個(gè)container所能使用的資源 - LXC 采用的是cgroup
。
參考文獻(xiàn)
[1]http://blog.dotcloud.com/under-the-hood-linux-kernels-on-dotcloud-part
[2]http://lwn.net/Articles/531114/
cgroups
實(shí)現(xiàn)了對資源的配額和度量。 cgroups
的使用非常簡單,提供類似文件的接口,在 /cgroup
目錄下新建一個(gè)文件夾即可新建一個(gè)group,在此文件夾中新建task
文件,并將pid寫入該文件,即可實(shí)現(xiàn)對該進(jìn)程的資源控制。具體的資源配置選項(xiàng)可以在該文件夾中新建子 subsystem ,{子系統(tǒng)前綴}.{資源項(xiàng)}
是典型的配置方法, 如memory.usage_in_bytes
就定義了該group 在subsystem memory
中的一個(gè)內(nèi)存限制選項(xiàng)。 另外,cgroups
中的 subsystem可以隨意組合,一個(gè)subsystem可以在不同的group中,也可以一個(gè)group包含多個(gè)subsystem - 也就是說一個(gè) subsystem
關(guān)于術(shù)語定義
<code>A *cgroup* associates a set of tasks with a set of parameters for one or more subsystems. A *subsystem* is a module that makes use of the task grouping facilities provided by cgroups to treat groups of tasks in particular ways. A subsystem is typically a "resource controller" that schedules a resource or applies per-cgroup limits, but it may be anything that wants to act <span>on</span> a group of processes, e.g. a virtualization subsystem. </code>
我們主要關(guān)心cgroups可以限制哪些資源,即有哪些subsystem是我們關(guān)心。
cpu : 在cgroup中,并不能像硬件虛擬化方案一樣能夠定義CPU能力,但是能夠定義CPU輪轉(zhuǎn)的優(yōu)先級,因此具有較高CPU優(yōu)先級的進(jìn)程會(huì)更可能得到CPU運(yùn)算。 通過將參數(shù)寫入cpu.shares
,即可定義改cgroup的CPU優(yōu)先級 - 這里是一個(gè)相對權(quán)重,而非絕對值。當(dāng)然在cpu
這個(gè)subsystem中還有其他可配置項(xiàng),手冊中有詳細(xì)說明。
cpusets : cpusets 定義了有幾個(gè)CPU可以被這個(gè)group使用,或者哪幾個(gè)CPU可以供這個(gè)group使用。在某些場景下,單CPU綁定可以防止多核間緩存切換,從而提高效率
memory : 內(nèi)存相關(guān)的限制
blkio : block IO相關(guān)的統(tǒng)計(jì)和限制,byte/operation統(tǒng)計(jì)和限制(IOPS等),讀寫速度限制等,但是這里主要統(tǒng)計(jì)的都是同步IO
net_cls, cpuacct , devices , freezer 等其他可管理項(xiàng)。
參考文獻(xiàn)
http://blog.dotcloud.com/kernel-secrets-from-the-paas-garage-part-24-c
http://en.wikipedia.org/wiki/Cgroups
https://www.kernel.org/doc/Documentation/cgroups/cgroups.txt
借助于namespace的隔離機(jī)制和cgroup限額功能,LXC提供了一套統(tǒng)一的API和工具來建立和管理container, LXC利用了如下 kernel 的features:
LXC 向用戶屏蔽了以上 kernel 接口的細(xì)節(jié), 提供了如下的組件大大簡化了用戶的開發(fā)和使用工作:
LXC 旨在提供一個(gè)共享kernel的 OS 級虛擬化方法,在執(zhí)行時(shí)不用重復(fù)加載Kernel, 且container的kernel與host共享,因此可以大大加快container的 啟動(dòng)過程,并顯著減少內(nèi)存消耗。在實(shí)際測試中,基于LXC的虛擬化方法的IO和CPU性能幾乎接近 baremetal 的性能(論據(jù)參見文獻(xiàn)[3]), 大多數(shù)數(shù)據(jù)有相比 Xen具有優(yōu)勢。當(dāng)然對于KVM這種也是通過Kernel進(jìn)行隔離的方式, 性能優(yōu)勢或許不是那么明顯, 主要還是內(nèi)存消耗和啟動(dòng)時(shí)間上的差異。在參考文獻(xiàn)[4]中提到了利用iozone進(jìn)行 Disk IO吞吐量測試KVM反而比LXC要快,而且筆者在device mapping driver下重現(xiàn)同樣case的實(shí)驗(yàn)中也確實(shí)能得到如此結(jié)論。參考文獻(xiàn)[5]從網(wǎng)絡(luò)虛擬化中虛擬路由的場景(個(gè)人理解是網(wǎng)絡(luò)IO和CPU角度)比較了KVM和LXC, 得到結(jié)論是KVM在性能和隔離性的平衡上比LXC更優(yōu)秀 - KVM在吞吐量上略差于LXC, 但CPU的隔離可管理項(xiàng)比LXC更明確。
關(guān)于CPU, DiskIO, network IO 和 memory 在KVM和LXC中的比較還是需要更多的實(shí)驗(yàn)才能得出可信服的結(jié)論。
參考文獻(xiàn)
[1]http://linuxcontainers.org/
[2]http://en.wikipedia.org/wiki/LXC
[3]http://marceloneves.org/papers/pdp2013-containers.pdf (性能測試)
[4]http://www.spinics.net/lists/linux-containers/msg25750.html (與KVM IO比較)
[5]http://article.sciencepublishinggroup.com/pdf/10.11648.j.ajnc.20130204.11.pdf
Docker對container的使用基本是建立唉LXC基礎(chǔ)之上的,然而LXC存在的問題是難以移動(dòng) - 難以通過標(biāo)準(zhǔn)化的模板制作、重建、復(fù)制和移動(dòng) container。 在以VM為基礎(chǔ)的虛擬化手段中,有image和snapshot可以用于VM的復(fù)制、重建以及移動(dòng)的功能。想要通過container來實(shí)現(xiàn)快速的大規(guī)模部署和更新, 這些功能不可或缺。 Docker正是利用AUFS來實(shí)現(xiàn)對container的快速更新 - 在docker0.7中引入了storage driver, 支持AUFS, VFS, device mapper, 也為BTRFS以及ZFS引入提供了可能。 但除了AUFS都未經(jīng)過dotcloud的線上使用,因此我們還是從AUFS的角度介紹。
AUFS (AnotherUnionFS) 是一種 Union FS, 簡單來說就是支持將不同目錄掛載到同一個(gè)虛擬文件系統(tǒng)下(unite several directories into a single virtual filesystem)的文件系統(tǒng), 更進(jìn)一步地, AUFS支持為每一個(gè)成員目錄(AKA branch)設(shè)定'readonly', 'readwrite' 和 'whiteout-able' 權(quán)限, 同時(shí)AUFS里有一個(gè)類似 分層的概念, 對 readonly 權(quán)限的branch可以邏輯上進(jìn)行修改(增量地, 不影響readonly部分的)。通常 Union FS有兩個(gè)用途, 一方面可以實(shí)現(xiàn)不借助 LVM, RAID 將多個(gè)disk和掛在到一個(gè)目錄下, 另一個(gè)更常用的就是將一個(gè)readonly的branch和一個(gè)writeable的branch聯(lián)合在一起,Live CD正是基于此可以允許在 OS image 不變的基礎(chǔ)上允許用戶在其上進(jìn)行一些寫操作。Docker在AUFS上構(gòu)建的container image也正是如此,接下來我們從啟動(dòng)container中的linux為例介紹docker在AUFS特性的運(yùn)用。
典型的Linux啟動(dòng)到運(yùn)行需要兩個(gè)FS - bootfs + rootfs (從功能角度而非文件系統(tǒng)角度)
bootfs (boot file system) 主要包含 bootloader 和 kernel, bootloader主要是引導(dǎo)加載kernel, 當(dāng)boot成功后 kernel 被加載到內(nèi)存中后 bootfs就被umount了. rootfs (root file system) 包含的就是典型 Linux 系統(tǒng)中的 /dev
, /proc
,/bin
, /etc
等標(biāo)準(zhǔn)目錄和文件。
由此可見對于不同的linux發(fā)行版, bootfs基本是一致的, rootfs會(huì)有差別, 因此不同的發(fā)行版可以公用bootfs 如下圖:
典型的Linux在啟動(dòng)后,首先將 rootfs 置為 readonly, 進(jìn)行一系列檢查, 然后將其切換為 "readwrite" 供用戶使用。在docker中,起初也是將 rootfs 以readonly方式加載并檢查,然而接下來利用 union mount 的將一個(gè) readwrite 文件系統(tǒng)掛載在 readonly 的rootfs之上,并且允許再次將下層的 file system設(shè)定為readonly 并且向上疊加, 這樣一組readonly和一個(gè)writeable的結(jié)構(gòu)構(gòu)成一個(gè)container的運(yùn)行目錄, 每一個(gè)被稱作一個(gè)Layer。如下圖:
得益于AUFS的特性, 每一個(gè)對readonly層文件/目錄的修改都只會(huì)存在于上層的writeable層中。這樣由于不存在競爭, 多個(gè)container可以共享readonly的layer。 所以docker將readonly的層稱作 "image" - 對于container而言整個(gè)rootfs都是read-write的,但事實(shí)上所有的修改都寫入最上層的writeable層中, image不保存用戶狀態(tài),可以用于模板、重建和復(fù)制。
上層的image依賴下層的image,因此docker中把下層的image稱作父image,沒有父image的image稱作base image
因此想要從一個(gè)image啟動(dòng)一個(gè)container,docker會(huì)先加載其父image直到base image,用戶的進(jìn)程運(yùn)行在writeable的layer中。所有parent image中的數(shù)據(jù)信息以及 ID、網(wǎng)絡(luò)和lxc管理的資源限制等具體container的配置,構(gòu)成一個(gè)docker概念上的container。如下圖:
由此可見,采用AUFS作為docker的container的文件系統(tǒng),能夠提供如下好處:
節(jié)省存儲(chǔ)空間 - 多個(gè)container可以共享base image存儲(chǔ)
快速部署 - 如果要部署多個(gè)container,base image可以避免多次拷貝
內(nèi)存更省 - 因?yàn)槎鄠€(gè)container共享base image, 以及OS的disk緩存機(jī)制,多個(gè)container中的進(jìn)程命中緩存內(nèi)容的幾率大大增加
升級更方便 - 相比于 copy-on-write 類型的FS,base-image也是可以掛載為可writeable的,可以通過更新base image而一次性更新其之上的container
允許在不更改base-image的同時(shí)修改其目錄中的文件 - 所有寫操作都發(fā)生在最上層的writeable層中,這樣可以大大增加base image能共享的文件內(nèi)容。
以上5條 1-3 條可以通過 copy-on-write 的FS實(shí)現(xiàn), 4可以利用其他的union mount方式實(shí)現(xiàn), 5只有AUFS實(shí)現(xiàn)的很好。這也是為什么Docker一開始就建立在AUFS之上。
由于AUFS并不會(huì)進(jìn)入linux主干 (According to Christoph Hellwig, linux rejects all union-type filesystems but UnionMount.), 同時(shí)要求kernel版本3.0以上(docker推薦3.8及以上),因此在RedHat工程師的幫助下在docker0.7版本中實(shí)現(xiàn)了driver機(jī)制, AUFS只是其中的一個(gè)driver, 在RHEL中采用的則是Device Mapper的方式實(shí)現(xiàn)的container文件系統(tǒng),相關(guān)內(nèi)容在下文會(huì)介紹。
參考文獻(xiàn)
[1]https://groups.google.com/forum/#!topic/docker-dev/KcCT0bACksY
[2]http://blog.docker.io/2013/11/docker-0-7-docker-now-runs-on-any-linux-distribution/
[3]http://blog.dotcloud.com/kernel-secrets-from-the-paas-garage-part-34-a
[4]http://aufs.sourceforge.net/aufs.html
[5]http://aufs.sourceforge.net/
[6]http://en.wikipedia.org/wiki/Aufs
[7]http://docs.docker.io/en/latest/terms/filesystem/
[8]http://docs.docker.io/en/latest/terms/layer/
[9]http://docs.docker.io/en/latest/terms/image/
[10]http://docs.docker.io/en/latest/terms/container/
grsec
是linux kernel安全相關(guān)的patch, 用于保護(hù)host防止非法入侵。由于其并不是docker的一部分,我們只進(jìn)行簡單的介紹。 grsec
可以主要從4個(gè)方面保護(hù)進(jìn)程不被非法入侵:
安全永遠(yuǎn)是相對的,這些方法只是告訴我們可以從這些角度考慮container類型的安全問題可以關(guān)注的方面。
參考文獻(xiàn)
[1] http://blog.dotcloud.com/kernel-secrets-from-the-paas-garage-part-44-g
[2] http://grsecurity.net/
看似docker主要的OS級虛擬化操作是借助LXC, AUFS只是錦上添花。那么肯定會(huì)有人好奇docker到底比LXC多了些什么。無意中發(fā)現(xiàn) stackoverflow 上正好有人問這個(gè)問題, 回答者是Dotcloud的創(chuàng)始人,感興趣的可以去看下。
http://stackoverflow.com/questions/17989306/what-does-docker-add-to-just-plain-lxc
作為sandbox大概是container的最基本想法了 - 輕量級的隔離機(jī)制, 快速重建和銷毀, 占用資源少。用docker在開發(fā)者的單機(jī)環(huán)境下模擬分布式軟件部署和調(diào)試,可謂又快又好。 同時(shí)docker提供的版本控制和image機(jī)制以及遠(yuǎn)程image管理,可以構(gòu)建類似git的分布式開發(fā)環(huán)境。可以看到用于構(gòu)建多平臺(tái)image的packer以及同一作者的vagrant已經(jīng)在這方面有所嘗試了,筆者會(huì)后續(xù)的blog中介紹這兩款來自同一geek的精致小巧的工具。
dotcloud、heroku以及cloudfoundry都試圖通過container來隔離提供給用戶的runtime和service,只不過dotcloud采用docker, heroku采用LXC, cloudfoundry采用 自己開發(fā)的基于cgroup的warden。基于輕量級的隔離機(jī)制提供給用戶PaaS服務(wù)是比較常見的做法 - PaaS 提供給用戶的并不是OS而是runtime+service, 因此OS級別的隔離機(jī)制 向用戶屏蔽的細(xì)節(jié)已經(jīng)足夠。而docker的很多分析文章提到『能夠運(yùn)行任何應(yīng)用的“PaaS”云』只是從image的角度說明docker可以從通過構(gòu)建image實(shí)現(xiàn)用戶app的打包以及標(biāo)準(zhǔn)服務(wù)service image的復(fù)用, 而非常見的buildpack的方式。
由于對Cloud Foundry和docker的了解, 接下來談?wù)劰P者對PaaS的認(rèn)識(shí)。PaaS號(hào)稱的platform一直以來都被當(dāng)做一組多語言的runtime和一組常用的middleware,提供這兩樣?xùn)|西 即可被認(rèn)為是一個(gè)滿足需求的PaaS。然而PaaS對能部署在其上的應(yīng)用要求很高:
綜上所述部署在PaaS上的應(yīng)用幾乎不具有從老平臺(tái)遷移到之上的可能,新應(yīng)用也難以進(jìn)入?yún)?shù)調(diào)優(yōu)這種深入的工作。個(gè)人理解還是適合快速原型的展現(xiàn),和短期應(yīng)用的嘗試。
然而docker確實(shí)從另一個(gè)角度(類似IaaS+orchestration tools)實(shí)現(xiàn)了用戶運(yùn)行環(huán)境的控制和管理,然而又基于輕量級的LXC機(jī)制,確實(shí)是一個(gè)了不起的嘗試。 筆者也認(rèn)為IaaS + 靈活的orchestration tools(深入到app層面的管理 如bosh)是交付用戶環(huán)境最好的方式。
前文也提到docker存在disk/network不便限額和在較低版本kernel中(如RHEL的2.6.32)AUFS不支持的問題。本節(jié)嘗試給出解答。
雖然cgroup提供IOPS之類的限制機(jī)制,但是從限制用戶能使用的磁盤大小和網(wǎng)絡(luò)帶寬上還是非常有限的。
Disk/network的quota現(xiàn)在有兩種思路:
通過docker run -v命令將外部存儲(chǔ)mount到container的目錄下,quota從Host方向限制,在device mapper driver中更采用實(shí)際的device因此更好控制。 參考[1]
通過使用disk quota來限制AUFS的可操作文件大小。類似cloud foundry warden的方法, 維護(hù)一個(gè)UID池,每次創(chuàng)建container都從中取一個(gè)user name, 在container里和Host上用這個(gè)username創(chuàng)建用戶,在Host上用setquota限制該username的UID的disk. 網(wǎng)絡(luò)上由于docker采用veth的方式,可以采用tc
來控制host上的veth的設(shè)備。參考[2]
參考文獻(xiàn):
[1]https://github.com/dotcloud/docker/issues/111
[2]https://github.com/dotcloud/docker/issues/471
這里簡單介紹下device mapper driver的思路,參考文獻(xiàn)[2]中的討論非常有價(jià)值。 docker的dirver要利用snapshot機(jī)制,起初的fs是一個(gè)空的ext4的目錄,然后寫入每個(gè)layer。每次創(chuàng)建image其實(shí)就是對其父image/base image進(jìn)行snapshot, 然后在此snapshot上的操作都會(huì)被記錄在fs的metadata中和AUFS layer(沒讀代碼不是很理解?),docker commit
將 diff信息在parent image上執(zhí)行一遍. 這樣創(chuàng)建出來的image就可以同當(dāng)前container的運(yùn)行環(huán)境分離開獨(dú)立保存了。
這里僅僅查看材料理解不是很透徹,還是需要深入代碼去了解詳情。如果有理解的請不吝賜教。目前已知存在的問題是刪除的image的 block 文件沒有被刪除,見https://github.com/dotcloud/docker/issues/3182, 筆者發(fā)現(xiàn)此問題前4個(gè)小時(shí)作者給出了原因,看起來是kernel的issue,在討論中包含work around的方法。
參考文獻(xiàn):
[1]http://blog.docker.io/2013/11/docker-0-7-docker-now-runs-on-any-linux-distribution/
[2]https://groups.google.com/forum/#!topic/docker-dev/KcCT0bACksY
原文鏈接:Docker Getting Start: Related Knowledge(責(zé)編:周小璐)
如您需要了解更多Docker相關(guān)的資訊或是技術(shù)文檔可訪問Docker技術(shù)社區(qū);如您有更多的疑問請?jiān)贒coker技術(shù)論壇提出,稍后會(huì)有專家進(jìn)行答疑。