淺談虛擬化技術:虛擬機(VM)與容器(Container)之技術價值與比較分析

容器化技術是否能取代傳統的虛擬化技術?

James Shieh
技術保鮮盒

--

Photo by Lewis Ngugi on Unsplash

技術的類比能加速理解,但應以技術價值為出發點

早幾年接觸虛擬化技術的讀者,應該還記得從前的虛擬化技術強調的是把實體電腦虛擬化,那個時代背景下有幾個趨勢:(1)雲端運算正普及、(2)企業開始把放在私有伺服器的服務移動到雲端去、(3)企業開始選擇建構自己的私有雲或使用各大科技巨頭的公有雲。此時的虛擬化技術可以很簡單的理解成:把作業系統虛擬化。不過後來隨著容器化技術出現,許多人也用舊的虛擬化技術概念去類比容器化技術,這樣的類比確實能加速理解新技術但卻衍生出許多誤解甚至不夠客觀的優劣勢分析。技術團隊在衡量是否導入容器化技術時,要尤其小心判斷。

為了避免落入科技圈鄙視鏈的思考誤區,最簡單的判斷方式應該由其技術價值為出發點,什麼是技術價值?簡言之就是它為何而生?

C是為了取代組合語言,以便用更高階的撰寫方式設計程式;Java是為了降低機器依賴性、跨平台而誕生的;PHP是作為HTML動態生成的樣板引擎而誕生的。每種技術的誕生都是為了解決當時軟體工程遇到的種種問題,以解決核心問題為中心擴散而成的解決方案。換言之,當你的開發項目離核心問題愈遠,導入這個技術對你的實質效益通常是愈低的。

言歸正傳,我們先來談談傳統的作業系統虛擬化技術是要解決什麼問題吧。

作業系統虛擬化技術——處理如何分享硬體資源的技術

想像一下,如果你有一堆CPU、RAM和Disk Storage,如何有效地管理與分配硬體資源?當你只有10台電腦時你根本不用煩惱這個問題,但如果你有1000台電腦時鐵定會衍生出很多問題。這是虛擬化技術想解決的核心問題之一 。

而作為此類虛擬化技術的主角就是所謂的虛擬機(Virutal Machine,VM),虛擬機操作起來就跟一般電腦一樣,如下圖所示,以作業系統為單位的虛擬化技術強調將硬體資源抽象化後可自由分配給上層的虛擬機使用,使用者可以自由決定虛擬機要使用那種作業系統?分多少的CPU與RAM?而作業系統上運行各種應用程式(App) 。

而這種作業系統虛擬化技術會有一個Hypervisor的角色,負責管理與分配硬體資源,我們根據管理硬體資源的規模可以概分成:

雲級別的Hypervisor:硬體通常是由機架式伺服器組成,其管理的硬體資源包含處理器、記憶體、存儲設備與網路卡等各種硬體,Hypervisor負責將其抽象化或邏輯化供上層的VM使用。一般科技公司由於研發與業務需求,需要大量的硬體資源,於是便可以建構一台私有雲,以便管理與分配這些硬體資源,而全球性的科技巨頭其規模更大,像是Amazon的AWS、Google的GCP、Microsoft的Azure除了把硬體資源分給自己員工使用之外,還可以將其分享給其他人使用,也就成為了所謂的公有雲了。

作業系統級別的Hypervisor:例如VirtualBox,有些Hypervisor可以在host OS級別的機器上運行,不需要大量的CPU或RAM即可運行,這種解決方案通常是給有特殊需求的使用者,例如:

  1. 開發人員同時需要測試多個版本的Android系統。
  2. MacOS可以用Parallels Desktop灌Windows系統,以便使用PowerPoint之類的Windows應用程式。
  3. 電玩遊戲的Youtuber會用Genymotion之類的Android模擬器,邊玩遊戲邊錄製視頻(Genymotion背後也是使用VirtualBox來模擬Linux環境)。

虛擬化技術可以說是雲端運算的基礎,因為其解決了怎麼把硬體資源分享出去的問題,因此才有辦法做到所謂的「按需付費」(Pay-as-you-go),我們使用AWS、GCP或Azure時,可以發現我們付費的方式不外乎是使用了多少儲存空間、多少CPU或RAM、多少頻寬等等。

容器虛擬化技術——處理軟體系統的環境建置

容器虛擬化技術想解決的核心問題簡言之是環境建置的問題,這個問題說起來要比作業系統虛擬化技術難理解得多了。

從前,開發團隊在建置一套系統時得為這套系統準備正確的執行環境,從前的執行環境很單純,我們可能只關心要準備哪一種作業系統以及其版本(比如說Windows Server 2019或CentOS 7.5)。講究一點,我們會討論一個系統使用什麼樣的解決方案堆疊(solution stack)或軟體棧(software stack),例如LAMP(Linux、Apache、MySQL、PHP)。

但近幾年新技術如雨春筍般冒出,工程師可以善用每一種語言或其生態系提供的優勢,以便更快速地實現各種功能,我們可能使用Matlab或Python來開發機器學習或人工智慧演算法,再用C#或Golang或Node.js去實作後端的API與邏輯,資料庫可能是Mongo、MySQL、Oracle或Reids。

正所謂一沙一世界,每個技術雖然在整個專案裡只扮演一部分的角色,卻都有其生態性與版本相容性問題,貿然地升級版本都可能導致系統出錯,就像大多數的問題一樣,很多時候分開處理都好好的,合再一起就壞掉了,工程師們戒慎慌恐地處理這些交互影響的執行環境建置問題,直到容器化技術的出現才讓他們解脫。

許多主管可能還停留在用技術堆疊來看待執行環境的年代裡,所以低估了容器化技術帶來的效益,接著我們就來看看容器化技術如何解決這個問題吧。

讓整個軟體系統的執行環境可以搬遷

「與其為每一個軟體系統建置執行環境,倒不如讓整個軟體系統的執行環境是可以搬遷與重複利用的」這是容器化技術解決問題的方式。因此容器(Container)就是一種可以搬遷與重複利用的執行環境。下圖為一個以Docker作為容器虛擬化技術的示意圖:

容器(Container):以應用程式(App)為單位的虛擬化技術,應用程式與其相依性資源(Dependency)會被封裝在容器(Container)中,使其可以重複利用與搬遷,容器間彼此獨立運行,互不干擾。

相依性資源(Dependency):官方是以bins/libs稱之,也就是二進位執行檔(binaries)與函數庫(libraries),它們可能是MySQL、Nodejs、.Net Framework、程式庫、DLL、編譯器等運行App所需要的執行環境,相依性資源大抵上可以說是我們前面提到的解決方案堆疊(solution stack)或軟體棧(software stack)

Docker Engine:類比Hypervisor在硬體的上層建置一個可以運行虛擬機的環境,Docker也同樣需要在Host OS上建置一個可以運行容器的環境,Docker Engine就是這樣的角色,其可將Docker Image轉換成Container。Docker Image就如同傳統虛擬化技術將OS封裝成*.iso 映像檔(image),Docker也將Dependency封裝成Docker Image,使其可重複利用與移植。

值得一提的是,Docker允許將這些Docker Image公開在網路上存取,就如同Github之於code一樣,Docker Hub之於Image也是一樣的概念,Docker Hub讓這些Image可以被分享、重複利用、下載與更新。我們也可以建置自己的Image管理庫,以便存放不便公開在網路上的Image。透過這樣的生態系與核心技術可以有效解決軟體搬遷的問題。

總結

我們應該要明白,容器化技術並不是用來取代傳統作業系統虛擬化技術。下圖將上述涉及的虛擬化技術整合在一起:

原則上,愈上層的虛擬化技術所需要的硬體資源愈低且分配到的硬體資源愈少,且Container和VM是互補而共生的。

兩種虛擬化技術的差異

  1. 以代表性服務為例:Docker是以App為單位的虛擬化技術;VMWare是以作業系統為單位的虛擬化技術。
  2. 容器虛擬化技術不是用來取代作業系統虛擬化技術的新技術:作業系統虛擬化技術可以很容易地部署好一台VM,但仍需安裝各種執行環境所需要的程式並設定正確的環境參數才能執行App,也就是說,在安裝作業系統之後與執行App之前,仍有需多環境建置工作,Docker的主要優勢在於透過Image和Container大幅簡化並自動化這些工作。
  3. 容器並不是VM:容器是一個封裝了相依性資源與App的執行環境;VM則是一個配置好CPU、RAM與Storage的作業系統。
  4. 容器虛擬化技術以共享Host OS Kernel的方式來執行App:容器依賴Host OS的核心(kernel)來運行容器,因此Windows容器必須在Windows OS上運行;Linux容器必須在Linux-base OS上運行。
  5. 容器(container)是執行環境的實例(instance);VM是作業系統的實例(instance)
  6. 容器化技術更面向DevOps的需求,容器化技術通常會與Kubernetes或Docker Swarm之類的容器調度技術整合,再配合Drone、Jenkins之類的CI/CD工具,使其可以將系統的部署工作完全自動化處理,有效降低後端維運的成本。而傳統的作業系統虛擬化技術並不是處理這種議題的主要技術,雖然像VMware這類的工具也會有附載平衡、故障轉移、復電重啟之類的自動化維運機制,但其保障的是作業系統層級的維運需求。
  7. 硬體資源的分配:Container因為是以App為單位,需要的硬體資源更少,可以更細緻地使用硬體資源,在沒有Docker之前,我們可能為了部署一個App而為其配置了一台VM,其作業系統又佔用了過多的CPU、Storage與RAM;有了Docker之後,我們只要為一個App配置一個Container即可
  8. 應用程式的獨立性:Container間是彼此隔離的,所以我們可以在一台VM下同時執行Nodejs 5,Nodejs 6, Nodejs 7等各種版本的Nodejs container,卻不會產生衝突,在沒有Docker之前,我們會為了避免衝突,為不同版本的Nodejs建置一台獨立的VM,這會造成不少浪費。
  9. VM簡化了硬體資源配置與作業系統安裝的工作,但既使如此還有許多執行環境建置的工作要處理,才能順利部署與執行應用程式(App),Container幫我們自動化地走完這最後一哩路。也就是說,Container簡化了介於作業系統與應用程式(App)之間的環境建置工作。

本篇同步刊登於我的Wordpress:

--

--

James Shieh
技術保鮮盒

Find something more important than you are and dedicate your life to it.