天天看點

Kubernetes【容器運作時】Kata Containers 與 gVisor

文章目錄

  • ​​1. 容器發展​​
  • ​​2. KataContainers原理​​
  • ​​3. gVisor原理​​
  • ​​4. 對比​​

1. 容器發展

使用虛拟化技術來做一個像 Docker 一樣的容器項目,并不是一個新鮮的主意。早在 Docker 項目釋出之後,Google 公司就開源了一個實驗性的項目,叫作 ​

​novm​

​​。這,可以算是試圖使用正常的虛拟化技術來運作 Docker 鏡像的第一次嘗試。不過,​

​novm​

​ 在開源後不久,就被放棄了,這對于 Google 公司來說或許不算是什麼新鮮事,但是 novm 的昙花一現,還是激發出了很多核心開發者的靈感。

是以在 2015 年,幾乎在同一個星期,​

​Intel OTC (Open Source Technology Center)​

​​ 和國内的 HyperHQ 團隊同時開源了兩個基于虛拟化技術的容器實作,分别叫做 ​

​Intel Clear Container​

​​ 和 ​

​runV​

​ 項目。

而在 2017 年,借着 Kubernetes 的東風,這兩個相似的容器運作時項目在中立基金會的撮合下最終合并,就成了現在大家耳熟能詳的 ​

​Kata Containers​

​ 項目。 由于 Kata Containers 的本質就是一個精簡後的輕量級虛拟機,是以它的特點,就是“像虛拟機一樣安全,像容器一樣靈活”。

而在 2018 年,Google 公司則釋出了一個名叫 ​

​gVisor​

​ 的項目。gVisor 項目給容器程序配置一個用 Go 語言實作的、運作在使用者态的、極小的“獨立核心”。這個核心對容器程序暴露 Linux 核心 ABI,扮演着“Guest Kernel”的角色,進而達到了将容器和主控端隔離開的目的。

難看到,無論是 Kata Containers,還是 gVisor,它們實作安全容器的方法其實是殊途同歸的。這兩種容器實作的本質,都是給程序配置設定了一個獨立的作業系統核心,進而避免了讓容器共享主控端的核心。這樣,容器程序能夠看到的攻擊面,就從整個主控端核心變成了一個極小的、獨立的、以容器為機關的核心,進而有效解決了容器程序發生“逃逸”或者奪取整個主控端的控制權的問題。這個原理,可以用如下所示的示意圖來表示清楚。

Kubernetes【容器運作時】Kata Containers 與 gVisor

而它們的差別在于,​​

​Kata Containers​

​ 使用的是傳統的虛拟化技術,通過虛拟硬體模拟出了一台“小虛拟機”,然後在這個小虛拟機裡安裝了一個裁剪後的 Linux 核心來實作強隔離。

而 gVisor 的做法則更加激進,Google 的工程師直接用 Go 語言“模拟”出了一個運作在使用者态的作業系統核心,然後通過這個模拟的核心來代替容器程序向主控端發起有限的、可控的系統調用。接下來,我就來為你詳細解讀一下 ​

​KataContainers​

​​ 和 ​

​gVisor​

​ 具體的設計原理。

2. KataContainers原理

Kubernetes【容器運作時】Kata Containers 與 gVisor

我們前面說過,Kata Containers 的本質,就是一個輕量化虛拟機。是以當你啟動一個 Kata Containers 之後,你其實就會看到一個正常的虛拟機在運作。這也就意味着,一個标準的虛拟機管理程式(​

​Virtual Machine Manager, VMM​

​​)是運作 ​

​Kata Containers​

​​ 必備的一個元件。在我們上面圖中,使用的 VMM 就是 ​

​Qemu​

​。

而使用了虛拟機作為程序的隔離環境之後,​

​Kata Containers​

​ 原生就帶有了 Pod 的概念。即:這個 Kata Containers 啟動的虛拟機,就是一個 Pod;而使用者定義的容器,就是運作在這個輕量級虛拟機裡的程序。在具體實作上,Kata Containers 的虛拟機裡會有一個特殊的 Init 程序負責管理虛拟機裡面的使用者容器,并且隻為這些容器開啟 Mount Namespace。是以,這些使用者容器之間,原生就是共享 Network 以及其他 Namespace 的。

此外,為了跟上層編排架構比如 Kubernetes 進行對接,Kata Containers 項目會啟動一系列跟使用者容器對應的 shim 程序,來負責操作這些使用者容器的生命周期。當然,這些操作,實際上還是要靠虛拟機裡的 Init 程序來幫你做到。而在具體的架構上,Kata Containers 的實作方式同一個正常的虛拟機其實也非常類似。這裡的原理,可以用如下所示的一幅示意圖來表示。

Kubernetes【容器運作時】Kata Containers 與 gVisor

可以看到,當 Kata Containers 運作起來之後,虛拟機裡的使用者程序(容器),實際上隻能看到虛拟機裡的、被裁減過的 ​​

​Guest Kernel​

​​,以及通過 ​

​Hypervisor​

​ 虛拟出來的硬體裝置。

而為了能夠對這個虛拟機的 I/O 性能進行優化,​

​Kata Containers​

​​ 也會通過 vhost 技術(比如:​

​vhost-user​

​​)來實作 ​

​Guest​

​​ 與 ​

​Host​

​​ 之間的高效的網絡通信,并且使用 ​

​PCI Passthrough​

​ (PCI 穿透)技術來讓 Guest 裡的程序直接通路到主控端上的實體裝置。這些架構設計與實作,其實跟正常虛拟機的優化手段是基本一緻的。

3. gVisor原理

相比之下,gVisor 的設計其實要更加“激進”一些。它的原理,可以用如下所示的示意圖來表示清楚。

Kubernetes【容器運作時】Kata Containers 與 gVisor

​​

​gVisor​

​​ 工作的核心,在于它為應用程序、也就是使用者容器,啟動了一個名叫 ​

​Sentry​

​ 的程序。 而 Sentry 程序的主要職責,就是提供一個傳統的作業系統核心的能力,即:**運作使用者程式,執行系統調用。**是以說,Sentry 并不是使用 Go 語言重新實作了一個完整的 Linux 核心,而隻是一個對應用程序“冒充”核心的系統元件。

在這種設計思想下,我們就不難了解,Sentry 其實需要自己實作一個完整的 Linux 核心網絡棧,以便處理應用程序的通信請求。然後,把封裝好的二層幀直接發送給 Kubernetes 設定的 Pod 的 ​

​Network Namespace​

​ 即可。

此外,​

​Sentry​

​​ 對于 ​

​Volume​

​​ 的操作,則需要通過 ​

​9p​

​​ 協定交給一個叫做 ​

​Gofer​

​​ 的代理程序來完成。Gofer 會代替應用程序直接操作主控端上的檔案,并依靠 ​

​seccomp​

​ 機制将自己的能力限制在最小集,進而防止惡意應用程序通過 Gofer 來從容器中“逃逸”出去。

而在具體的實作上,​

​gVisor​

​​ 的 ​

​Sentry​

​​ 程序,其實還分為兩種不同的實作方式。這裡的工作原理,可以用下面的示意圖來描述清楚。

Kubernetes【容器運作時】Kata Containers 與 gVisor

第一種實作方式,是使用 Ptrace 機制來攔截使用者應用的系統調用(System Call),然後把這些系統調用交給 Sentry 來進行處理。這個過程,對于應用程序來說,是完全透明的。而 Sentry 接下來,則會扮演作業系統的角色,在使用者态執行使用者程式,然後僅在需要的時候,才向主控端發起 Sentry 自己所需要執行的系統調用。這,就是 gVisor 對使用者應用程序進行強隔離的主要手段。不過, Ptrace 進行系統調用攔截的性能實在是太差,僅能供 Demo 時使用。

而第二種實作方式,則更加具有普适性。它的工作原理如下圖所示。

Kubernetes【容器運作時】Kata Containers 與 gVisor

在這種實作裡,​

​Sentry​

​​ 會使用 KVM 來進行系統調用的攔截,這個性能比 Ptrace 就要好很多了。當然,為了能夠做到這一點,Sentry 程序就必須扮演一個 ​

​Guest Kernel​

​​ 的角色,負責執行使用者程式,發起系統調用。而這些系統調用被 KVM 攔截下來,還是繼續交給 Sentry 進行處理。隻不過在這時候,​

​Sentry​

​ 就切換成了一個普通的主控端程序的角色,來向主控端發起它所需要的系統調用。

可以看到,在這種實作裡,Sentry 并不會真的像虛拟機那樣去虛拟出硬體裝置、安裝 Guest 作業系統。它隻是借助 KVM 進行系統調用的攔截,以及處理位址空間切換等細節。值得一提的是,在 Google 内部,他們也是使用的第二種基于 ​

​Hypervisor​

​​ 的 ​

​gVisor​

​​ 實作。隻不過 Google 内部有自己研發的 ​

​Hypervisor​

​,是以要比 KVM 實作的性能還要好。

4. 對比

通過以上的講述,相信你對 Kata Containers 和 gVisor 的實作原理,已經有一個感性的認識了。需要指出的是,到目前為止,gVisor 的實作依然不是非常完善,有很多 Linux 系統調用它還不支援;有很多應用,在 gVisor 裡還沒辦法運作起來。 此外,​

​gVisor​

​ 也暫時沒有實作一個 Pod 多個容器的支援。當然,在後面的發展中,這些工程問題一定會逐漸解決掉的。

另外,你可能還聽說過 AWS 在 2018 年末釋出的一個叫做 ​

​Firecracker​

​​ 的安全容器項目。這個項目的核心,其實是一個用 Rust 語言重新編寫的 VMM(即:虛拟機管理器)。這就意味着, ​

​Firecracker​

​​ 和 ​

​Kata Containers​

​ 的本質原理,其實是一樣的。隻不過, Kata Containers 預設使用的 VMM 是 Qemu,而 Firecracker,則使用自己編寫的 VMM。是以,理論上,Kata Containers 也可以使用 Firecracker 運作起來。

繼續閱讀