Docker是近年來新興的虛擬化工具,它能夠和虛擬機同樣實現資源和系統環境的隔離。本文將主要根據IBM發表的研究報告,論述Docker與傳統虛擬化方式的不一樣之處,並比較物理機、Docker容器、虛擬機三者的性能差別及差別產生的原理。 linux
以下圖分別是虛擬機與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架構進行優化,大大減低了計算效率。安全
內存訪問效率的比較相對比較複雜一點,主要是內存訪問有多種場景:
(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還存在着如下幾個缺點:
1.資源隔離方面不如虛擬機,Docker是利用cgroup實現資源限制的,只能限制資源消耗的最大值,而不能隔絕其餘程序佔用本身的資源。
2.安全性問題。Docker目前並不能分辨具體執行指令的用戶,只要一個用戶擁有執行Docker的權限,那麼他就能夠對Docker的容器進行全部操做,無論該容器是不是由該用戶建立。好比A和B都擁有執行Docker的權限,因爲Docker的server端並不會具體判斷Docker cline是由哪一個用戶發起的,A能夠刪除B建立的容器,存在必定的安全風險。
3.Docker目前還在版本的快速更新中,細節功能調整比較大。一些核心模塊依賴於高版本內核,存在版本兼容問題。架構
摘自:http://www.linuxidc.com/Linux/2016-05/130991.htm併發