1. 程式人生 > >docker與虛擬機器效能比較

docker與虛擬機器效能比較

概要

docker是近年來新興的虛擬化工具,它可以和虛擬機器一樣實現資源和系統環境的隔離。本文將主要根據IBM發表的研究報告,論述docker與傳統虛擬化方式的不同之處,並比較物理機、docker容器、虛擬機器三者的效能差異及差異產生的原理。

docker與虛擬機器實現原理比較

如下圖分別是虛擬機器與docker的實現框架。
虛擬機器實現框架 docker實現框架
比較兩圖的差異,左圖虛擬機器的Guest OS層和Hypervisor層在docker中被Docker Engine層所替代。虛擬機器的Guest OS即為虛擬機器安裝的作業系統,它是一個完整作業系統核心;虛擬機器的Hypervisor層可以簡單理解為一個硬體虛擬化平臺,它在Host OS是以核心態的驅動存在的。
虛擬機器實現資源隔離的方法是利用獨立的OS,並利用Hypervisor虛擬化CPU、記憶體、IO裝置等實現的。例如,為了虛擬CPU,Hypervisor會為每個虛擬的CPU建立一個數據結構,模擬CPU的全部暫存器的值,在適當的時候跟蹤並修改這些值。需要指出的是在大多數情況下,虛擬機器軟體程式碼是直接跑在硬體上的,而不需要Hypervisor介入。只有在一些許可權高的請求下,Guest OS需要執行核心態修改CPU的暫存器資料,Hypervisor會介入,修改並維護虛擬的CPU狀態。
Hypervisor虛擬化記憶體的方法是建立一個shadow page table。正常的情況下,一個page table可以用來實現從虛擬記憶體到實體記憶體的翻譯。在虛擬化的情況下,由於所謂的實體記憶體仍然是虛擬的,因此shadow page table就要做到:虛擬記憶體->虛擬的實體記憶體->真正的實體記憶體。
對於IO裝置虛擬化,當Hypervisor接到page fault,並發現實際上虛擬的實體記憶體地址對應的是一個I/O裝置,Hypervisor就用軟體模擬這個裝置的工作情況,並返回。比如當CPU想要寫磁碟時,Hypervisor就把相應的資料寫到一個host OS的檔案上,這個檔案實際上就模擬了虛擬的磁碟。
對比虛擬機器實現資源和環境隔離的方案,docker就顯得簡練很多。docker Engine可以簡單看成對Linux的NameSpace、Cgroup、映象管理檔案系統操作的封裝。docker並沒有和虛擬機器一樣利用一個完全獨立的Guest OS實現環境隔離,它利用的是目前Linux核心本身支援的容器方式實現資源和環境隔離。簡單的說,docker利用namespace實現系統環境的隔離;利用Cgroup實現資源限制;利用映象實現根目錄環境的隔離。
通過docker和虛擬機器實現原理的比較,我們大致可以得出一些結論:
(1)docker有著比虛擬機器更少的抽象層。由於docker不需要Hypervisor實現硬體資源虛擬化,執行在docker容器上的程式直接使用的都是實際物理機的硬體資源。因此在CPU、記憶體利用率上docker將會在效率上有優勢,具體的效率對比在下幾個小節裡給出。在IO裝置虛擬化上,docker的映象管理有多種方案,比如利用Aufs檔案系統或者Device Mapper實現docker的檔案管理,各種實現方案的效率略有不同。
(2)docker利用的是宿主機的核心,而不需要Guest OS。因此,當新建一個容器時,docker不需要和虛擬機器一樣重新載入一個作業系統核心。我們知道,引導、載入作業系統核心是一個比較費時費資源的過程,當新建一個虛擬機器時,虛擬機器軟體需要載入Guest OS,這個新建過程是分鐘級別的。而docker由於直接利用宿主機的作業系統,則省略了這個過程,因此新建一個docker容器只需要幾秒鐘。另外,現代作業系統是複雜的系統,在一臺物理機上新增加一個作業系統的資源開銷是比較大的,因此,docker對比虛擬機器在資源消耗上也佔有比較大的優勢。事實上,在一臺物理機上我們可以很容易建立成百上千的容器,而只能建立幾個虛擬機器。

docker與虛擬機器計算效率比較

在上一節我們從原理的角度推測docker應當在CPU和記憶體的利用效率上比虛擬機器高。在這一節我們將根據IBM發表的論文給出的資料進行分析。以下的資料均是在IBM x3650 M4伺服器測得,其主要的硬體引數是:
(1)2顆英特爾xeon E5-2655 處理器,主頻2.4-3.0 GHz。每顆處理器有8個核,因此總共有16個核。
(2)256 GB RAM.
在測試中是通過運算Linpack程式來獲得計算能力資料的。結果如下圖所示:
此處輸入圖片的描述
圖中從左往右分別是物理機、docker和虛擬機器的計算能力資料。可見docker相對於物理機其計算能力幾乎沒有損耗,而虛擬機器對比物理機則有著非常明顯的損耗。虛擬機器的計算能力損耗在50%左右。
為什麼會有這麼大的效能損耗呢?一方面是因為虛擬機器增加了一層虛擬硬體層,執行在虛擬機器上的應用程式在進行數值計算時是執行在Hypervisor虛擬的CPU上的;另外一方面是由於計算程式本身的特性導致的差異。虛擬機器虛擬的cpu架構不同於實際cpu架構,數值計算程式一般針對特定的cpu架構有一定的優化措施,虛擬化使這些措施作廢,甚至起到反效果。比如對於本次實驗的平臺,實際的CPU架構是2塊物理CPU,每塊CPU擁有16個核,共32個核,採用的是NUMA架構;而虛擬機器則將CPU虛擬化成一塊擁有32個核的CPU。這就導致了計算程式在進行計算時無法根據實際的CPU架構進行優化,大大減低了計算效率。

docker與虛擬機器記憶體訪問效率比較

記憶體訪問效率的比較相對比較複雜一點,主要是記憶體訪問有多種場景:
(1)大批量的,連續地址塊的記憶體資料讀寫。這種測試環境下得到的效能資料是記憶體頻寬,效能瓶頸主要在記憶體晶片的效能上;
(2)隨機記憶體訪問效能。這種測試環境下的效能資料主要與記憶體頻寬、cache的命中率和虛擬地址與實體地址轉換的效率等因素有關。
以下將主要針對這兩種記憶體訪問場景進行分析。在分析之前我們先概要說明一下docker和虛擬機器的記憶體訪問模型差異。下圖是docker與虛擬機器記憶體訪問模型:
此處輸入圖片的描述
可見在應用程式記憶體訪問上,虛擬機器的應用程式要進行2次的虛擬記憶體到實體記憶體的對映,讀寫記憶體的代價比docker的應用程式高。
下圖是場景(1)的測試資料,即記憶體頻寬資料。左圖是程式執行在一塊CPU(即8核)上的資料,右圖是程式執行在2塊CPU(即16核)上的資料。單位均為GB/s。
此處輸入圖片的描述

此處輸入圖片的描述
從圖中資料可以看出,在記憶體頻寬效能上docker與虛擬機器的效能差異並不大。這是因為在記憶體頻寬測試中,讀寫的記憶體地址是連續的,大批量的,核心對這種操作會進行優化(資料預存取)。因此虛擬記憶體到實體記憶體的對映次數比較少,效能瓶頸主要在實體記憶體的讀寫速度上,因此這種情況docker和虛擬機器的測試效能差別不大;
記憶體頻寬測試中docker與虛擬機器記憶體訪問效能差異不大的原因是由於記憶體頻寬測試中需要進行虛擬地址到實體地址的對映次數比較少。根據這個假設,我們推測,當進行隨機記憶體訪問測試時這兩者的效能差距將會變大,因為隨機記憶體訪問測試中需要進行虛擬記憶體地址到實體記憶體地址的對映次數將會變多。結果如下圖所示。
此處輸入圖片的描述此處輸入圖片的描述
左圖是程式執行在一個CPU上的資料,右圖是程式執行在2塊CPU上的資料。從左圖可以看出,確實如我們所預測的,在隨機記憶體訪問效能上容器與虛擬機器的效能差距變得比較明顯,容器的記憶體訪問效能明顯比虛擬機器優秀;但出乎我們意料的是在2塊CPU上執行測試程式時容器與虛擬機器的隨機記憶體訪問效能的差距卻又變的不明顯。
針對這個現象,IBM的論文給出了一個合理解釋。這是因為當有2塊CPU同時對記憶體進行訪問時,記憶體讀寫的控制將會變得比較複雜,因為兩塊CPU可能同時讀寫同一個地址的資料,需要對記憶體資料進行一些同步操作,從而導致記憶體讀寫效能的損耗。這種損耗即使對於物理機也是存在的,可以看出右圖的記憶體訪問效能資料是低於左圖的。2塊CPU對記憶體讀寫效能的損耗影響是非常大的,這個損耗佔據的比例遠大於虛擬機器和docker由於記憶體訪問模型的不同產生的差異,因此在右圖中docker與虛擬機器的隨機記憶體訪問效能上我們看不出明顯差異。

docker與虛擬機器啟動時間及資源耗費比較

上面兩個小節主要從執行在docker裡的程式和執行在虛擬機器裡的程式進行效能比較。事實上,docker之所以如此受到開發者關注的另外一個重要原因是啟動docker的系統代價比啟動一臺虛擬機器的代價要低得多:無論從啟動時間還是從啟動資源耗費角度來說。docker直接利用宿主機的系統核心,避免了虛擬機器啟動時所需的系統引導時間和作業系統執行的資源消耗。利用docker能在幾秒鐘之內啟動大量的容器,這是虛擬機器無法辦到的。快速啟動、低系統資源消耗的優點使docker在彈性雲平臺和自動運維繫統方面有著很好的應用前景。

docker的劣勢

前面的內容主要論述docker相對於虛擬機器的優勢,但docker也不是完美的系統。相對於虛擬機器,docker還存在著以下幾個缺點:
1.資源隔離方面不如虛擬機器,docker是利用cgroup實現資源限制的,只能限制資源消耗的最大值,而不能隔絕其他程式佔用自己的資源。
2.安全性問題。docker目前並不能分辨具體執行指令的使用者,只要一個使用者擁有執行docker的許可權,那麼他就可以對docker的容器進行所有操作,不管該容器是否是由該使用者建立。比如A和B都擁有執行docker的許可權,由於docker的server端並不會具體判斷docker cline是由哪個使用者發起的,A可以刪除B建立的容器,存在一定的安全風險。
3.docker目前還在版本的快速更新中,細節功能調整比較大。一些核心模組依賴於高版本核心,存在版本相容問題

參考文獻

  1. Felter W, Ferreira A, Rajamony R, et al. An Updated Performance Comparison of Virtual Machines and Linux Containers[J]. technology, 2014, 28: 32.