雲計算時代,計算資源如同小馬哥當年所言,已經成為了互聯網上的水和電。
虛擬主機、web服務器、數據庫、對象存儲等等各種服務我們都可以通過各種各樣的雲平台來完成。
而在雲計算欣欣向榮的背後,有一個重要的功臣,那就是虛擬化技術。可以毫不客氣的説,沒有了虛擬化技術,雲計算無從談起。
説起虛擬化你會想到什麼?從我們常用的虛擬機三件套VMware、VirtualPC、VirutalBox到如今大火的KVM和容器技術Docker?
這些技術是什麼關係,背後的技術原理是怎樣的,又有什麼樣的區別,各自應用的場景又是什麼樣的?
看完這篇文章,相信大家都能回答上面問題。
歷史背景
什麼是虛擬化技術?
維基百科中的解釋是這樣的:
虛擬化(技術)是一種資源管理技術,是將計算機的各種實體資源(CPU、內存、磁盤空間、網絡適配器等),予以抽象、轉換後呈現出來並可供分割、組合為一個或多個電腦配置環境。
對於一台計算機,我們可以簡單的劃分為三層:從下到上依次是物理硬件層,操作系統層、應用程序層
1974年,兩位計算機科學家Gerald Popek 和 Robert Goldberg發表了一篇重要的論文《虛擬化第三代體系結構的正式要求》,在這篇論文中提出了虛擬化的三個基本條件:
- 等價性:程序在本地計算機執行和在虛擬機中執行應該表現出一樣的結果(不包括執行時間的差異)
- 安全性:虛擬機彼此隔離,與宿主計算機隔離
- 性能:絕大多數情況下虛擬機中的代碼指令應該直接在物理CPU中執行,少部分特殊指令可由VMM參與。
那如何實現對計算機底層的物理資源的虛擬化分割呢?在計算機技術的發展歷史上,出現了兩種著名的方案,分別是I型虛擬化和II型虛擬化
圖中的VMM意為Virtual Machine Monitor,虛擬機監控程序,或者用另一個更專業的名詞:HyperVisor
從圖中可以清楚的看到兩種虛擬化方案的區別:
Type I: 直接凌駕於硬件之上,構建出多個隔離的操作系統環境
Type II: 依賴於宿主操作系統,在其上構建出多個隔離的操作系統環境
我們熟知的VMware事實上有兩個產品線,一個是VMware ESXi,直接安裝在裸金屬之上,不需要額外的操作系統,屬於第一類虛擬化。另一個是我們普通用户更加熟知的VMware WorkStation,屬於第二類虛擬化。
如何實現上述的虛擬化方案呢?
一個典型的做法是——陷阱 & 模擬技術
什麼意思?簡單來説就是正常情況下直接把虛擬機中的代碼指令放到物理的CPU上去執行,一旦執行到一些敏感指令,就觸發異常,控制流程交給VMM,由VMM來進行對應的處理,以此來營造出一個虛擬的計算機環境。
不過這一經典的虛擬化方案在Intel x86架構上卻遇到了問題。
全虛擬化:VMware 二進制翻譯技術
不同於8086時代16位實地址工作模式,x86架構進入32位時代後,引入了保護模式、虛擬內存等一系列新的技術。同時為了安全性隔離了應用程序代碼和操作系統代碼,其實現方式依賴於x86處理器的工作狀態。
這就是眾所周知的x86處理器的Ring0-Ring3四個“環”。
操作系統內核代碼運行在最高權限的Ring0狀態,應用程序工作於最外圍權限最低的Ring3狀態,剩下的Ring1和Ring2主流的操作系統都基本上沒有使用。
這裏所説的權限,有兩個層面的約束:
- 能訪問的內存空間
- 能執行的特權指令
來關注一下第二點,特權指令。
CPU指令集中有一些特殊的指令,用於進行硬件I/O通信、內存管理、中斷管理等等功能,這一些指令只能在Ring0狀態下執行,被稱為特權指令。這些操作顯然是不能讓應用程序隨便執行的。處於Ring3工作狀態的應用程序如果嘗試執行這些指令,CPU將自動檢測到並拋出異常。
回到我們的主題虛擬化技術上面來,如同前面的定義所言,虛擬化是將計算資源進行邏輯或物理層面的切割劃分,構建出一個個獨立的執行環境。
按照我們前面所説的陷阱 & 模擬手段,可以讓虛擬機中包含操作系統在內的程序統一運行在低權限的Ring3狀態下,一旦虛擬機中的操作系統進行內存管理、I/O通信、中斷等操作時,執行特權指令,從而觸發異常,物理機將異常派遣給VMM,由VMM進行對應的模擬執行。
這本來是一個實現虛擬化很理想的模式,不過x86架構的CPU在這裏遇到了一個跨不過去的坎。
到底是什麼問題呢?
回顧一下前面描繪的理想模式,要這種模式能夠實現的前提是執行敏感指令的時候能夠觸發異常,讓VMM有機會介入,去模擬一個虛擬的環境出來。
但現實是,x86架構的CPU指令集中有那麼一部分指令,它不是特權指令,Ring3狀態下也能夠執行,但這些指令對於虛擬機來説卻是敏感的,不能讓它們直接執行。一旦執行,沒法觸發異常,VMM也就無法介入,虛擬機就露餡兒了!
這結果將導致虛擬機中的代碼指令出現無法預知的錯誤,更嚴重的是影響到真實物理計算機的運行,虛擬化所謂的安全隔離、等價性也就無從談起。
怎麼解決這個問題,讓x86架構CPU也能支持虛擬化呢?
VMware和QEMU走出了兩條不同的路。
VMware創造性的提出了一個二進制翻譯技術。VMM在虛擬機操作系統和宿主計算機之間扮演一個橋樑的角色,將虛擬機中的要執行的指令“翻譯”成恰當的指令在宿主物理計算機上執行,以此來模擬執行虛擬機中的程序。你可以簡單理解成Java虛擬機執行Java字節碼的過程,不同的是Java虛擬機執行的是字節碼,而VMM模擬執行的就是CPU指令。
另外值得一提的是,為了提高性能,也並非所有的指令都是模擬執行的,VMware在這裏做了不少的優化,對一些“安全”的指令,就讓它直接執行也未嘗不可。所以VMware的二進制翻譯技術也融合了部分的直接執行。
對於虛擬機中的操作系統,VMM需要完整模擬底層的硬件設備,包括處理器、內存、時鐘、I/O設備、中斷等等,換句話説,VMM用純軟件的形式“模擬”出一台計算機供虛擬機中的操作系統使用。
這種完全模擬一台計算機的技術也稱為全虛擬化,這樣做的好處顯而易見,虛擬機中的操作系統感知不到自己是在虛擬機中,代碼無需任何改動,直接可以安裝。而缺點也是可以想象:完全用軟件模擬,轉換翻譯執行,性能堪憂!
而QEMU則是完全軟件層面的“模擬”,乍一看和VMware好像差不多,不過實際本質是完全不同的。VMware是將原始CPU指令序列翻譯成經過處理後的CPU指令序列來執行。而QEMU則是完全模擬執行整個CPU指令集,更像是“解釋執行”,兩者的性能不可同日而語。
半虛擬化:Xen 內核定製修改
既然有全虛擬化,那與之相對的也就有半虛擬化,前面説了,由於敏感指令的關係,全虛擬化的VMM需要捕獲到這些指令並完整模擬執行這個過程,實現既滿足虛擬機操作系統的需要,又不至於影響到物理計算機。
但説來簡單,這個模擬過程實際上相當的複雜,涉及到大量底層技術,並且如此模擬費時費力。
而試想一下,如果把操作系統中所有執行敏感指令的地方都改掉,改成一個接口調用(HyperCall),接口的提供方VMM實現對應處理,省去了捕獲和模擬硬件流程等一大段工作,性能將獲得大幅度提升。
這就是半虛擬化,這項技術的代表就是Xen,一個誕生於2003年的開源項目。
這項技術一個最大的問題是:需要修改操作系統源碼,做相應的適配工作。這對於像Linux這樣的開源軟件還能接受,充其量多了些工作量罷了。但對於Windows這樣閉源的商業操作系統,修改它的代碼,無異於痴人説夢。
硬件輔助虛擬化 VT / AMD-v
折騰來折騰去,全都是因為x86架構的CPU天然不支持經典虛擬化模式,軟件廠商不得不想出其他各種辦法來在x86上實現虛擬化。
如果進一步講,CPU本身增加對虛擬化的支持,那又會是一番怎樣的情況呢?
在軟件廠商使出渾身解數來實現x86平台的虛擬化後的不久,各家處理器廠商也看到了虛擬化技術的廣闊市場,紛紛推出了硬件層面上的虛擬化支持,正式助推了虛擬化技術的迅猛發展。
這其中為代表的就是Intel的VT系列技術和AMD的AMD-v系列技術。
硬件輔助虛擬化細節較為複雜,簡單來説,新一代CPU在原先的Ring0-Ring3四種工作狀態之下,再引入了一個叫工作模式的概念,有VMX root operation 和 VMX non-root operation 兩種模式,每種模式都具有完整的Ring0-Ring3四種工作狀態,前者是VMM運行的模式,後者是虛擬機中的OS運行的模式。
VMM運行的層次,有些地方將其稱為Ring -1,VMM可以通過CPU提供的編程接口,配置對哪些指令的劫持和捕獲,從而實現對虛擬機操作系統的掌控。
換句話説,原先的VMM為了能夠掌控虛擬機中代碼的執行,不得已採用“中間人”來進行翻譯執行,現在新的CPU告訴VMM:不用那麼麻煩了,你提前告訴我你對哪些指令哪些事件感興趣,我在執行這些指令和發生這些事件的時候就通知你,你就可以實現掌控了。完全由硬件層面提供支持,性能自然高了不少。
上面只是硬件輔助虛擬化技術的一個簡單理解,實際上還包含更多的要素,提供了更多的便利給VMM,包括內存的虛擬、I/O的虛擬等等,讓VMM的設計開發工作大大的簡化,VMM不再需要付出昂貴的模擬執行成本,整體虛擬化的性能也有了大幅度的提升。
VMware從5.5版本開始引入對硬件輔助虛擬化的支持,隨後在2011年的8.0版本中正式全面支持。於是乎,我們在創建虛擬機的時候,可以選擇要使用哪一種虛擬化引擎技術,是用原先的二進制翻譯執行,還是基於硬件輔助虛擬化的新型技術。
同一時期的XEN從3.0版本也加入對硬件輔助虛擬化的支持,從此基於XEN的虛擬機中也能夠運行Windows系統了。
KVM-QEMU
有了硬件輔助虛擬化的加持,虛擬化技術開始呈現井噴之勢。VirtualBox、Hyper-V、KVM等技術如雨後春筍般接連面世。這其中在雲計算領域聲名鵲起的當屬開源的KVM技術了。
KVM全稱for Kernel-based Virtual Machine,意為基於內核的虛擬機。
在虛擬化底層技術上,KVM和VMware後續版本一樣,都是基於硬件輔助虛擬化實現。不同的是VMware作為獨立的第三方軟件可以安裝在Linux、Windows、MacOS等多種不同的操作系統之上,而KVM作為一項虛擬化技術已經集成到Linux內核之中,可以認為Linux內核本身就是一個HyperVisor,這也是KVM名字的含義,因此該技術只能在Linux服務器上使用。
KVM技術常常搭配QEMU一起使用,稱為KVM-QEMU架構。前面提到,在x86架構CPU的硬件輔助虛擬化技術誕生之前,QEMU就已經採用全套軟件模擬的辦法來實現虛擬化,只不過這種方案下的執行性能非常低下。
KVM本身基於硬件輔助虛擬化,僅僅實現CPU和內存的虛擬化,但一台計算機不僅僅有CPU和內存,還需要各種各樣的I/O設備,不過KVM不負責這些。這個時候,QEMU就和KVM搭上了線,經過改造後的QEMU,負責外部設備的虛擬,KVM負責底層執行引擎和內存的虛擬,兩者彼此互補,成為新一代雲計算虛擬化方案的寵兒。
容器技術-LXC & Docker
前面談到的無論是基於翻譯和模擬的全虛擬化技術、半虛擬化技術,還是有了CPU硬件加持下的全虛擬化技術,其虛擬化的目標都是一台完整的計算機,擁有底層的物理硬件、操作系統和應用程序執行的完整環境。
為了讓虛擬機中的程序實現像在真實物理機器上運行“近似”的效果,背後的HyperVisor做了大量的工作,付出了“沉重”的代價。
雖然HyperVisor做了這麼多,但你有沒有問過虛擬機中的程序,這是它想要的嗎?或許HyperVisor給的太多,而目標程序卻説了一句:你其實可以不用這樣辛苦。
確實存在這樣的情況,虛擬機中的程序説:我只是想要一個單獨的執行執行環境,不需要你費那麼大勁去虛擬出一個完整的計算機來。
這樣做的好處是什麼?
虛擬出一台計算機的成本高還是隻虛擬出一個隔離的程序運行環境的成本高?答案很明顯是前者。一台物理機可能同時虛擬出10台虛擬機就已經開始感到乏力了,但同時虛擬出100個虛擬的執行環境卻還是能夠從容應對,這對於資源的充分利用可是有巨大的好處。
近幾年大火的容器技術正是在這樣的指導思想下誕生的。
不同於虛擬化技術要完整虛擬化一台計算機,容器技術更像是操作系統層面的虛擬化,它只需要虛擬出一個操作系統環境。
LXC技術就是這種方案的一個典型代表,全稱是LinuX Container,通過Linux內核的Cgroups技術和namespace技術的支撐,隔離操作系統文件、網絡等資源,在原生操作系統上隔離出一個單獨的空間,將應用程序置於其中運行,這個空間的形態上類似於一個容器將應用程序包含在其中,故取名容器技術。
舉個不是太恰當的比喻,一套原來是三居室的房子,被二房東拿來改造成三個一居室的套間,每個一居室套間裏面都配備了衞生間和廚房,對於住在裏面的人來説就是一套完整的住房。
如今各個大廠火爆的Docker技術底層原理與LXC並不本質區別,甚至在早期Docker就是直接基於LXC的高層次封裝。Docker在LXC的基礎上更進一步,將執行執行環境中的各個組件和依賴打包封裝成獨立的對象,更便於移植和部署。
容器技術的好處是輕量,所有隔離空間的程序代碼指令不需要翻譯轉換,就可以直接在CPU上執行,大家底層都是同一個操作系統,通過軟件層面上的邏輯隔離形成一個個單獨的空間。
容器技術的缺點是安全性不如虛擬化技術高,畢竟軟件層面的隔離比起硬件層面的隔離要弱得多。隔離環境系統和外面的主機共用的是同一個操作系統內核,一旦利用內核漏洞發起攻擊,程序突破容器限制,實現逃逸,危及宿主計算機,安全也就不復存在。
超輕虛擬化 firecracker
虛擬完整的計算機隔離性好但太過笨重,簡單的容器技術又因為太過輕量純粹靠軟件隔離不夠安全,有沒有一個折中的方案同時兼具兩者的優點,實現既輕量又安全呢?
近年來,一種超輕虛擬化的思想開始流行開來,亞馬遜推出的firecracker就是一個典型的代表。
firecracker將虛擬化技術的強隔離性和容器技術的輕量性進行融合,提出了一個microVM的概念,底層通過KVM虛擬化技術實現各個microVM的強隔離,而隔離的虛擬機中運行的是一個個精簡版的微型操作系統,砍掉了大量無用的功能,專為容器設計的微型OS。
超輕虛擬化如今成為一個新的浪潮,除了AWS的firecracker,谷歌的gVisor, Intel主導的NEMU也在向這個領域開始發力。
總結
本文簡單介紹了虛擬化技術的基本概念和基本要求。隨後引出由於早期的x86架構不支持經典的虛擬化方案,各家軟件廠商只能通過軟件模擬的形式來實現虛擬化,其代表是早期的VMware WorkStation和Xen。
不過純粹依靠軟件的方式畢竟有性能的瓶頸,好在Intel和AMD及時推出了CPU硬件層面的虛擬化支持,軟件廠商迅速跟進適配,極大的改善了虛擬化的性能體驗。這一時期的代表有新版本的VMware WorkStation、Hyper-V、KVM等。
近年來,隨着雲計算和微服務的縱深發展,對虛擬化技術的虛擬粒度逐漸從粗到細。從最早的虛擬化完整的計算機,到後來只需虛擬出一個操作系統,再到後來虛擬出一個微服務需要的環境即可,以Docker為代表的容器技術在這個時期大放異彩。