進程是準虛擬化的虛擬機—容器虛擬化的原理

<!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } H1 { margin-bottom: 0.21cm } H1.western { font-family: "DejaVu Sans", sans-serif; font-size: 16pt } H1.cjk { font-family: "DejaVu Sans"; font-size: 16pt } H1.ctl { font-family: "Lohit Hindi"; font-size: 16pt } H2 { margin-bottom: 0.21cm } H2.western { font-family: "DejaVu Sans", sans-serif; font-size: 14pt; font-style: italic } H2.cjk { font-size: 14pt; font-style: italic } H2.ctl { font-family: "Lohit Hindi"; font-size: 14pt; font-style: italic } A:link { so-language: zxx } --> <!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } H1 { margin-bottom: 0.21cm } H1.western { font-family: "DejaVu Sans", sans-serif; font-size: 16pt } H1.cjk { font-family: "DejaVu Sans"; font-size: 16pt } H1.ctl { font-family: "Lohit Hindi"; font-size: 16pt } H2 { margin-bottom: 0.21cm } H2.western { font-family: "DejaVu Sans", sans-serif; font-size: 14pt; font-style: italic } H2.cjk { font-size: 14pt; font-style: italic } H2.ctl { font-family: "Lohit Hindi"; font-size: 14pt; font-style: italic } A:link { so-language: zxx } -->

                           進程是準虛擬化的虛擬機—容器虛擬化的原理

                                                                                                                                                                       by 沈東良(良少)http://blog.csdn.net/shendl

 

       首先聲明,我對容器虛擬化並不精通,雖然我們公司也從事Linux Container這個容器虛擬化的研究,但是那是另外一個team的工作。

       我這裏從原理性的角度分析一下容器虛擬化的原理,可能和實際的容器虛擬化技術並不相同,還請見諒和指正。我只談原理不談風月。

進程是準虛擬化的虛擬機

      虛擬化技術最早是IBM在上世紀60年代的System/360操作系統中開發的。一般操作系統是用進程來劃分資源,而System/360把虛擬計算機當作資源劃分的單位。

       System/360和後來的vmware,kvm等都是完全虛擬化。

 

      讓我們看一下虛擬化的定義,維基百科中這樣定義:

虛擬化Virtualization)是一個表現邏輯羣組或電腦資源的子集的進程,用戶可以用比原本的組態更好的方式來存取這些進程。這些資源的新虛擬部份是不受現有資源的架設方式,地域或物理組態所限制。一般所指的虛擬化資源包括計算能力和資料儲存。

 

         我的理解是,虛擬化就是虛擬硬件資源,包括CPU,內存,硬盤,外設等等。


         完全虛擬化完全虛擬了計算機的所有硬件。運行於其上的操作系統意識不到它運行在虛擬的計算機上。這樣的效果當然是我們所理解的虛擬化。

         那麼,如果僅僅虛擬化一部分資源呢?算虛擬化嗎?

         如果虛擬機上的操作系統能夠意識到自己運行在虛擬機中呢?算虛擬化嗎?
         如果虛擬機中不能運行操作系統,但依然虛擬化了若干硬件資源呢?算虛擬化嗎?

 

         我的答案是上述種種情況都是虛化化!

 

          Xen的虛擬機中的操作系統意識到自己是運行在虛擬機上,而不是真正的硬件上,它需要通過hypercall調用物理計算機上運行的操作系統提供的API才能完成運行。

         Xen是虛擬機管理器嗎?是的,它是準虛擬化類型的虛擬機。

         KVM使用的virtio,是在虛擬機操作系統中安全了一個驅動。這個驅動知道自己運行在虛擬機中而不是物理機中。它通過hypercall調用物理機操作系統提供的服務,實現了對外設的虛擬化。Virtio屬於外設的類虛擬化。

 

        虛擬內存技術,把一小塊物理內存虛擬爲多塊獨立的非常非常大的虛擬內存。內存管理模塊算不算是hypervisor呢?當然算。


       多進程操作系統,分時調度多個進程,每一個進程都認爲自己獨佔CPU。進程調度算不算是hypervisor呢?當然算。


       現代操作系統同時支持多進程和虛擬內存技術,進程可以使用虛擬CPU,虛擬內存,共享外部設備,使用的都是虛擬的資源。所以多進程就更是虛擬化技術了。進程就是虛擬機。

       進程和xen的虛擬機操作系統一樣,它知道自己運行在虛擬資源之上,需要使用hypercall才能完成自己的正常運行。

       進程的hypercall就是系統調用!

        xen虛擬機通過hypercall要求Host爲它提供特權和外部設備。進程也是通過系統調用,要求內核提供特權服務和外部設備。

        因此,我們說內核是準虛擬化的hypervisor,進程就是準虛擬化的虛擬機。

 

容器虛擬化的原理

        讀者可能對我上面的結論並不信服。可能會說,xen的虛擬機可以跑操作系統,雖然是修改過的操作系統,但也是操作系統。進程這個“虛擬機”可以嗎?


【其實也可以啦。qemu/bochs就是在一個進程中模擬一臺計算機。計算機甚至可以是異構的。而且它們不用內核提供任何特別的服務。 qemu/bochs是硬件模擬器。

        現代語言,如java,.net,Python,javascript都使用進程虛擬機,虛擬了CPU。它們的源碼會被編譯成一種虛擬的CPU使用的虛擬的彙編語言。這樣,只要在各個平臺上實現虛擬CPU的進程虛擬機就可以實現跨平臺了。而且,進程虛擬機執行僞彙編代碼要比直接解釋源代碼高效的多!

       不過,上述這些技術都是在進程中又玩了一些花樣,因此不在本文的談論範圍之內,我就不說了。

 

      進程是不可以直接運行操作系統,但虛擬化的定義應該是虛擬硬件資源,沒規定一定要運行操作系統啊!

 

       計算機執行的大部分業務任務都是用戶空間的進程實現的。內核僅僅是爲進程提供服務的。進程虛擬機直接使用內核提供的服務,當然比在虛擬機內部再運行一個操作系統高效的多。不管你XEN的準虛擬化操作系統內核多麼牛逼,我根本沒這個對於的內核,總比你高效吧!

       使用相同內核的虛擬機,聽起來是不是和容器虛擬化(又叫:操作系統級虛化化)一樣?

       容器虛擬化,我的映像是SunSolaris操作系統首先提出和實現的。一臺計算機上,可以提供上百個獨立的進程組。這些進程組的資源是隔絕的。進程組叫做容器。

       容器中的進程無法看到容器外的資源。每個容器也不能使用超出限額的資源。

 

       容器虛擬化技術在虛擬主機領域應用非常廣泛。使用容器虛擬化,可以嚴格控制硬盤空間,網絡流量等。它比傳統的虛擬主機更加靈活。用戶想裝什麼軟件就裝什麼軟件。而且對資源的控制更強。很難出現佔用他人資源的情況。

 

       知道誰對雲計算/虛擬化最起勁嗎?就是虛擬主機廠商。rackspace公司就是國際領先的虛擬主機廠商。有了雲計算和虛擬化,它運營虛擬主機的成本就更省了!

 

進程虛擬機和容器虛擬化

       其實,容器虛擬化就是基於進程虛擬機實現的。上面已經說了,進程是共用內核的虛擬機,共用了硬件資源。

       實現容器虛擬化,關鍵的就是容器的實現。容器隔離了物理資源。有些資源別人用不了,有些資源用的比我少。


      現在我就說說我猜測的實現原理。我就以我最熟悉的Linux爲例來說明。

 

        Linux的每一個進程都有一個namespace對象。它保存的就是從root開始的文件系統。子進程會繼承父進程的這個對象。因此,一般情況下,整個linux操作系統只有一個namespace對象。看到的都是相同的文件系統。

 

      但是,進程也可以創建自己獨立的namespace對象。它創建的子進程就會繼承這個namespace對象。

 

      chroot命令可以切換到另一個linux根文件系統執行,容器虛擬化使用的就是這個原理。

 

      容器虛擬化也使用了這個原理。這樣,每一個容器中的進程看到的文件系統就是不同的,看到的設備文件也是不同的。因此可以使用不同的硬件資源和文件。

        linuxqutoa模塊可以實現對文件夾等的大小限制。這樣就不能使用超過限制的硬盤資源。

         Linux支持tap/tun等機制實現的虛擬網卡。每一個容器可以使用自己獨有的虛擬網卡。內核可以對虛擬網卡進行帶寬和流浪的限制和統計。

        Linux的進程組也可以設置時間片,規定進程只能運行在哪一個或者哪幾個CPU上。這樣就可以限制容器虛擬機對CPU的使用率。

        Linux內核還可以對不同進程組/用戶的內存的使用進行限制。

 

       總之,Linux內核可以根據進程組或者用戶對資源進行種種限制。而namespace可以設置對文件系統和設備的使用限制。目前LXC等容器虛擬化軟件都向Linux內核增加了模塊,用於實現更加複雜的容器虛擬化。

 

      據說,LXCoverload只有1%-3%。這應該比任何完全虛擬化技術都要少很多。

 

      當然,容器虛擬化也不是萬能的。容器虛擬化不提供操作系統虛擬化。一個容器只是一些進程的集合而已。如果用戶需要和Host的內核不同的以內核安裝一些驅動,甚至需要不同的操作系統,如在LXC上要跑Windows,那麼就需要完全虛擬化技術了。如果使用虛擬主機提供商的產品,那就意味着需要花比容器虛擬化更多的錢。因爲虛擬主機提供商的成本更高了。

 

      不過,即使是需要完全虛擬化的場合,我依然不推薦XEN。如果沒有支持硬件虛擬化的CPU,那麼它不能跑Windows等軟件。因爲XEN無法修改Windows內核源碼。


       XEN需要定製版本的HostLinux內核和定製版本的VMLinux內核。這些版本的數量是很少的,而且定製版本的Linux內核,會使很多驅動無法運行。如,我的電腦如果運行XEN內核,那麼顯卡驅動就無法運行了。對內核限制太多,那還不如使用容器虛擬化呢!至少不用改內核,不會導致驅動無法運行。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發佈了185 篇原創文章 · 獲贊 136 · 訪問量 214萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章