歡迎光臨
每天分享高質量文章

gVisor:Google開源的新型沙箱容器運行時環境

容器技術徹底改變了我們對應用程式進行開發、打包與部署的具體方式。然而,系統在與容器對接時仍會暴露出大量攻擊面,因此相當一部分安全專家不建議在容器當中運行不受信任或潛在的惡意應用程式[1]。
隨著用戶越來越多地希望在容器當中運行異構及低信任度工作負載,沙箱化容器也就應運而生——此類容器能夠在主機操作系統與容器內應用程式之間提供安全的隔離邊界。
為此,我們將介紹gVisor[2]——一款新型沙箱解決方案,其能夠為容器提供安全的隔離措施,同時繼續保持遠優於虛擬機的輕量化特性。gVisor能夠與Docker及Kubernetes實現集成,從而在生產環境中更輕鬆地建立起沙箱化容器系統。


傳統Linux容器並不屬於沙箱環境

傳統Linux容器當中運行的應用程式採用等同於常規(非容器化)應用程式的系統資源訪問方式:即直接對主機內核進行系統呼叫。內核以高權限樣式運行,允許其與必要硬體交互並將結果傳回給應用程式。

對於傳統容器,我們可以立足內核對應用程式所能訪問的資源作出一些限制。這些限制通過Linux cgroups與命名空間來實現。然而,並非所有資源皆可通過這種方式加以控制。此外,即使存在這些限制,內核仍然在很大程度上暴露在惡意應用程式的攻擊範圍之內。
像seccomp過濾器這類內核功能可以在應用程式與主機內核之間建立更好的隔離機制,但其要求用戶創建預定義的系統呼叫白名單。在實踐當中,我們往往很難預先確定哪些應用程式需要哪些系統呼叫。如果應用程式所需要的系統呼叫當中存在安全漏洞,過濾器功能更是表現得無能為力。


現有基於虛擬機的容器技術

改進容器隔離能力的一種方法,是在其自有虛擬機中運行各套容器。這能夠為每個容器提供屬於自己的“機器”,包括對應內核與虛擬化設備,且與主機完全分離。在這種情況下,即使訪客虛擬機當中存在漏洞,管理程式也仍能將其與主機以及同樣運行在主機上的其它應用程式/容器隔離開來。

不同的虛擬機往往能夠提供良好的隔離性、兼容性與性能表現,但其同樣需要占用可觀的資源與空間。
Kata容器是一個開源專案,其利用精簡化虛擬機以盡可能減少資源占用量,同時最大限度提高容器隔離能力。與gVisor一樣,Kata也包含與Docker及Kubernetes相兼容的開放容器倡議(簡稱OCI)運行時。


利用gVisor建立沙箱化容器

gVisor能夠在保證輕量化優勢的同時,提供與虛擬機類似的隔離效果。gVisor的核心為一套運行非特權普通行程的內核,且支持大多數Linux系統呼叫。該內核使用Go編寫,這主要是考慮到Go語言擁有良好的記憶體管理機制與型別安全性。與在虛擬機當中一樣,gVisor沙箱中運行的應用程式也將獲得自己的內核與一組虛擬設備——這一點與主機及其它沙箱方案有所區別。

gVisor通過在用戶空間內攔截應用程式系統呼叫並充當訪客內核,gVisor能夠提供強大的隔離邊界。而與需要一組固定資源的虛擬機不同,gVisor能夠隨時適應不斷變化的資源條件,這一點更像是普通Linux行程。gVisor很像是一種超虛擬化操作系統,其與完整虛擬機相比擁有更靈活的資源利用方式與更低的固定成本,但這種靈活性的代價是其系統呼叫成本更高且應用程式兼容性略差。
保護工作負載已經成為目前業界的首要任務,我們很高興地看到gVisor這類創新方案的出現,並期待著能夠在規範方面開展合作,共同對聯合技術組件加以改進,從而為生態系統帶來更可靠的安全保障能力。”
——Samuel Ortiz,Kata技術指導委員會成員、英特爾公司首席工程師
“Hyper公司鼓勵我們瞭解gVisor採用的全新容器隔離方法,業界需要一套強大的安全容器技術生態系統,我們期待著與gVisor合作以將安全容器推向主流市場。”
——Xu Wang,Kata技術指導委員會成員、Hyper.sh公司CTO


與Docker及Kubernetes相集成

gVisor運行時能夠與Docker及Kubernetes實現無縫化集成,這一集成效果通過匹配OCI運行時API的runsc(即‘run Sandboxed Container’的縮寫)實現。
runsc運行時可與Docker的預設容器運行時runc進行互換。其安裝非常簡單; 在安裝完成後,只需要一個額外標記即可在Docker內運行沙箱化容器:

$ docker run --runtime=runsc hello-world
$ docker run --runtime=runsc -p 3306:3306 mysql
在Kubenetes當中,大多數資源隔離在pod層面實現,而這意味著pod能夠天然充當gVisor的沙箱邊界。Kubernetes社區目前正在對沙箱pod API進行標準化調整,但目前已經開放實驗性支持供用戶體驗。
runsc運行時能夠在Kubernetes集群當中通過cri-o或cri-containerd等專案運行沙箱化pod——此類專案負責將Kubelet中的訊息轉換為OCI運行時命令。
gVisor能夠實現大部分Linux系統API(總計200項系統呼叫與計數),但仍有一部分無法支持。部分系統呼叫與引數目前尚無法使用,/proc與/sys檔案系統中的某些特定部分同樣如此。因此,還有少數應用程式不能在gVisor當中運行。但除此之外,包括Node.js、Java 8、MySQL、Jenkins、Apache、Redis以及MongoDB等在內的大多數應用程式皆可順利運作。
馬上開始

作為開發者,我們希望能夠讓容器的易用性與可移植性同虛擬機的資源隔離能力結合起來。而gVisor無疑是我們朝著這一方向邁出的重要一步。您可以查看我們在GitHub上的repo[2]以瞭解如何使用gVisor以及更多背後技術細節。同樣歡迎大家加入我們的Google群組[3]參與討論!
最後,請參閱gVisor PM的採訪內容以瞭解更多信息。