Docker是近年來新興的虛擬化工具,它可以和虛擬機(jī)一樣實(shí)現(xiàn)資源和系統(tǒng)環(huán)境的隔離。本文將主要根據(jù)IBM發(fā)表的研究報(bào)告,論述docker與傳統(tǒng)虛擬化方式的不同之處,并比較物理機(jī)、docker容器、虛擬機(jī)三者的性能差異及差異產(chǎn)生的原理。
docker與虛擬機(jī)實(shí)現(xiàn)原理比較
如下圖分別是虛擬機(jī)與docker的實(shí)現(xiàn)框架。
比較兩圖的差異,左圖虛擬機(jī)的Guest OS層和Hypervisor層在docker中被Docker Engine層所替代。虛擬機(jī)的Guest OS即為虛擬機(jī)安裝的操作系統(tǒng),它是一個完整操作系統(tǒng)內(nèi)核;虛擬機(jī)的Hypervisor層可以簡單理解為一個硬件虛擬化平臺,它在Host OS是以內(nèi)核態(tài)的驅(qū)動存在的。
虛擬機(jī)實(shí)現(xiàn)資源隔離的方法是利用獨(dú)立的OS,并利用Hypervisor虛擬化CPU、內(nèi)存、IO設(shè)備等實(shí)現(xiàn)的。例如,為了虛擬CPU,Hypervisor會為每個虛擬的CPU創(chuàng)建一個數(shù)據(jù)結(jié)構(gòu),模擬CPU的全部寄存器的值,在適當(dāng)?shù)臅r候跟蹤并修改這些值。需要指出的是在大多數(shù)情況下,虛擬機(jī)軟件代碼是直接跑在硬件上的,而不需要Hypervisor介入。只有在一些權(quán)限高的請求下,Guest OS需要運(yùn)行內(nèi)核態(tài)修改CPU的寄存器數(shù)據(jù),Hypervisor會介入,修改并維護(hù)虛擬的CPU狀態(tài)。
Hypervisor虛擬化內(nèi)存的方法是創(chuàng)建一個shadow page table。正常的情況下,一個page table可以用來實(shí)現(xiàn)從虛擬內(nèi)存到物理內(nèi)存的翻譯。在虛擬化的情況下,由于所謂的物理內(nèi)存仍然是虛擬的,因此shadow page table就要做到:虛擬內(nèi)存->虛擬的物理內(nèi)存->真正的物理內(nèi)存。
對于IO設(shè)備虛擬化,當(dāng)Hypervisor接到page fault,并發(fā)現(xiàn)實(shí)際上虛擬的物理內(nèi)存地址對應(yīng)的是一個I/O設(shè)備,Hypervisor就用軟件模擬這個設(shè)備的工作情況,并返回。比如當(dāng)CPU想要寫磁盤時,Hypervisor就把相應(yīng)的數(shù)據(jù)寫到一個host OS的文件上,這個文件實(shí)際上就模擬了虛擬的磁盤。
對比虛擬機(jī)實(shí)現(xiàn)資源和環(huán)境隔離的方案,docker就顯得簡練很多。docker Engine可以簡單看成對Linux的NameSpace、Cgroup、鏡像管理文件系統(tǒng)操作的封裝。docker并沒有和虛擬機(jī)一樣利用一個完全獨(dú)立的Guest OS實(shí)現(xiàn)環(huán)境隔離,它利用的是目前linux內(nèi)核本身支持的容器方式實(shí)現(xiàn)資源和環(huán)境隔離。簡單的說,docker利用namespace實(shí)現(xiàn)系統(tǒng)環(huán)境的隔離;利用Cgroup實(shí)現(xiàn)資源限制;利用鏡像實(shí)現(xiàn)根目錄環(huán)境的隔離。
通過docker和虛擬機(jī)實(shí)現(xiàn)原理的比較,我們大致可以得出一些結(jié)論:
(1)docker有著比虛擬機(jī)更少的抽象層。由于docker不需要Hypervisor實(shí)現(xiàn)硬件資源虛擬化,運(yùn)行在docker容器上的程序直接使用的都是實(shí)際物理機(jī)的硬件資源。因此在CPU、內(nèi)存利用率上docker將會在效率上有優(yōu)勢,具體的效率對比在下幾個小節(jié)里給出。在IO設(shè)備虛擬化上,docker的鏡像管理有多種方案,比如利用Aufs文件系統(tǒng)或者Device Mapper實(shí)現(xiàn)docker的文件管理,各種實(shí)現(xiàn)方案的效率略有不同。
(2)docker利用的是宿主機(jī)的內(nèi)核,而不需要Guest OS。因此,當(dāng)新建一個容器時,docker不需要和虛擬機(jī)一樣重新加載一個操作系統(tǒng)內(nèi)核。我們知道,引導(dǎo)、加載操作系統(tǒng)內(nèi)核是一個比較費(fèi)時費(fèi)資源的過程,當(dāng)新建一個虛擬機(jī)時,虛擬機(jī)軟件需要加載Guest OS,這個新建過程是分鐘級別的。而docker由于直接利用宿主機(jī)的操作系統(tǒng),則省略了這個過程,因此新建一個docker容器只需要幾秒鐘。另外,現(xiàn)代操作系統(tǒng)是復(fù)雜的系統(tǒng),在一臺物理機(jī)上新增加一個操作系統(tǒng)的資源開銷是比較大的,因此,docker對比虛擬機(jī)在資源消耗上也占有比較大的優(yōu)勢。事實(shí)上,在一臺物理機(jī)上我們可以很容易建立成百上千的容器,而只能建立幾個虛擬機(jī)。
docker與虛擬機(jī)計(jì)算效率比較
在上一節(jié)我們從原理的角度推測docker應(yīng)當(dāng)在CPU和內(nèi)存的利用效率上比虛擬機(jī)高。在這一節(jié)我們將根據(jù)IBM發(fā)表的論文給出的數(shù)據(jù)進(jìn)行分析。以下的數(shù)據(jù)均是在IBM x3650 M4服務(wù)器測得,其主要的硬件參數(shù)是:
(1)2顆英特爾xeon E5-2655 處理器,主頻2.4-3.0 GHz。每顆處理器有8個核,因此總共有16個核。
(2)256 GB RAM.
在測試中是通過運(yùn)算Linpack程序來獲得計(jì)算能力數(shù)據(jù)的。結(jié)果如下圖所示:
圖中從左往右分別是物理機(jī)、docker和虛擬機(jī)的計(jì)算能力數(shù)據(jù)??梢奷ocker相對于物理機(jī)其計(jì)算能力幾乎沒有損耗,而虛擬機(jī)對比物理機(jī)則有著非常明顯的損耗。虛擬機(jī)的計(jì)算能力損耗在50%左右。
為什么會有這么大的性能損耗呢?一方面是因?yàn)樘摂M機(jī)增加了一層虛擬硬件層,運(yùn)行在虛擬機(jī)上的應(yīng)用程序在進(jìn)行數(shù)值計(jì)算時是運(yùn)行在Hypervisor虛擬的CPU上的;另外一方面是由于計(jì)算程序本身的特性導(dǎo)致的差異。虛擬機(jī)虛擬的cpu架構(gòu)不同于實(shí)際cpu架構(gòu),數(shù)值計(jì)算程序一般針對特定的cpu架構(gòu)有一定的優(yōu)化措施,虛擬化使這些措施作廢,甚至起到反效果。比如對于本次實(shí)驗(yàn)的平臺,實(shí)際的CPU架構(gòu)是2塊物理CPU,每塊CPU擁有16個核,共32個核,采用的是NUMA架構(gòu);而虛擬機(jī)則將CPU虛擬化成一塊擁有32個核的CPU。這就導(dǎo)致了計(jì)算程序在進(jìn)行計(jì)算時無法根據(jù)實(shí)際的CPU架構(gòu)進(jìn)行優(yōu)化,大大減低了計(jì)算效率。
docker與虛擬機(jī)內(nèi)存訪問效率比較
內(nèi)存訪問效率的比較相對比較復(fù)雜一點(diǎn),主要是內(nèi)存訪問有多種場景:
(1)大批量的,連續(xù)地址塊的內(nèi)存數(shù)據(jù)讀寫。這種測試環(huán)境下得到的性能數(shù)據(jù)是內(nèi)存帶寬,性能瓶頸主要在內(nèi)存芯片的性能上;
(2)隨機(jī)內(nèi)存訪問性能。這種測試環(huán)境下的性能數(shù)據(jù)主要與內(nèi)存帶寬、cache的命中率和虛擬地址與物理地址轉(zhuǎn)換的效率等因素有關(guān)。
以下將主要針對這兩種內(nèi)存訪問場景進(jìn)行分析。在分析之前我們先概要說明一下docker和虛擬機(jī)的內(nèi)存訪問模型差異。下圖是docker與虛擬機(jī)內(nèi)存訪問模型:
可見在應(yīng)用程序內(nèi)存訪問上,虛擬機(jī)的應(yīng)用程序要進(jìn)行2次的虛擬內(nèi)存到物理內(nèi)存的映射,讀寫內(nèi)存的代價比docker的應(yīng)用程序高。
下圖是場景(1)的測試數(shù)據(jù),即內(nèi)存帶寬數(shù)據(jù)。左圖是程序運(yùn)行在一塊CPU(即8核)上的數(shù)據(jù),右圖是程序運(yùn)行在2塊CPU(即16核)上的數(shù)據(jù)。單位均為GB/s。
從圖中數(shù)據(jù)可以看出,在內(nèi)存帶寬性能上docker與虛擬機(jī)的性能差異并不大。這是因?yàn)樵趦?nèi)存帶寬測試中,讀寫的內(nèi)存地址是連續(xù)的,大批量的,內(nèi)核對這種操作會進(jìn)行優(yōu)化(數(shù)據(jù)預(yù)存取)。因此虛擬內(nèi)存到物理內(nèi)存的映射次數(shù)比較少,性能瓶頸主要在物理內(nèi)存的讀寫速度上,因此這種情況docker和虛擬機(jī)的測試性能差別不大;
內(nèi)存帶寬測試中docker與虛擬機(jī)內(nèi)存訪問性能差異不大的原因是由于內(nèi)存帶寬測試中需要進(jìn)行虛擬地址到物理地址的映射次數(shù)比較少。根據(jù)這個假設(shè),我們推測,當(dāng)進(jìn)行隨機(jī)內(nèi)存訪問測試時這兩者的性能差距將會變大,因?yàn)殡S機(jī)內(nèi)存訪問測試中需要進(jìn)行虛擬內(nèi)存地址到物理內(nèi)存地址的映射次數(shù)將會變多。結(jié)果如下圖所示。
左圖是程序運(yùn)行在一個CPU上的數(shù)據(jù),右圖是程序運(yùn)行在2塊CPU上的數(shù)據(jù)。從左圖可以看出,確實(shí)如我們所預(yù)測的,在隨機(jī)內(nèi)存訪問性能上容器與虛擬機(jī)的性能差距變得比較明顯,容器的內(nèi)存訪問性能明顯比虛擬機(jī)優(yōu)秀;但出乎我們意料的是在2塊CPU上運(yùn)行測試程序時容器與虛擬機(jī)的隨機(jī)內(nèi)存訪問性能的差距卻又變的不明顯。
針對這個現(xiàn)象,IBM的論文給出了一個合理解釋。這是因?yàn)楫?dāng)有2塊CPU同時對內(nèi)存進(jìn)行訪問時,內(nèi)存讀寫的控制將會變得比較復(fù)雜,因?yàn)閮蓧KCPU可能同時讀寫同一個地址的數(shù)據(jù),需要對內(nèi)存數(shù)據(jù)進(jìn)行一些同步操作,從而導(dǎo)致內(nèi)存讀寫性能的損耗。這種損耗即使對于物理機(jī)也是存在的,可以看出右圖的內(nèi)存訪問性能數(shù)據(jù)是低于左圖的。2塊CPU對內(nèi)存讀寫性能的損耗影響是非常大的,這個損耗占據(jù)的比例遠(yuǎn)大于虛擬機(jī)和docker由于內(nèi)存訪問模型的不同產(chǎn)生的差異,因此在右圖中docker與虛擬機(jī)的隨機(jī)內(nèi)存訪問性能上我們看不出明顯差異。
docker與虛擬機(jī)啟動時間及資源耗費(fèi)比較
上面兩個小節(jié)主要從運(yùn)行在docker里的程序和運(yùn)行在虛擬機(jī)里的程序進(jìn)行性能比較。事實(shí)上,docker之所以如此受到開發(fā)者關(guān)注的另外一個重要原因是啟動docker的系統(tǒng)代價比啟動一臺虛擬機(jī)的代價要低得多:無論從啟動時間還是從啟動資源耗費(fèi)角度來說。docker直接利用宿主機(jī)的系統(tǒng)內(nèi)核,避免了虛擬機(jī)啟動時所需的系統(tǒng)引導(dǎo)時間和操作系統(tǒng)運(yùn)行的資源消耗。利用docker能在幾秒鐘之內(nèi)啟動大量的容器,這是虛擬機(jī)無法辦到的??焖賳印⒌拖到y(tǒng)資源消耗的優(yōu)點(diǎn)使docker在彈性云平臺和自動運(yùn)維系統(tǒng)方面有著很好的應(yīng)用前景。
docker的劣勢
前面的內(nèi)容主要論述docker相對于虛擬機(jī)的優(yōu)勢,但docker也不是完美的系統(tǒng)。相對于虛擬機(jī),docker還存在著以下幾個缺點(diǎn):
1.資源隔離方面不如虛擬機(jī),docker是利用cgroup實(shí)現(xiàn)資源限制的,只能限制資源消耗的最大值,而不能隔絕其他程序占用自己的資源。
2.安全性問題。docker目前并不能分辨具體執(zhí)行指令的用戶,只要一個用戶擁有執(zhí)行docker的權(quán)限,那么他就可以對docker的容器進(jìn)行所有操作,不管該容器是否是由該用戶創(chuàng)建。比如A和B都擁有執(zhí)行docker的權(quán)限,由于docker的server端并不會具體判斷docker cline是由哪個用戶發(fā)起的,A可以刪除B創(chuàng)建的容器,存在一定的安全風(fēng)險(xiǎn)。
3.docker目前還在版本的快速更新中,細(xì)節(jié)功能調(diào)整比較大。一些核心模塊依賴于高版本內(nèi)核,存在版本兼容問題
留言反饋