隨著 IT 技術(shù)的發(fā)展,AI、區(qū)塊鏈和大數(shù)據(jù)等技術(shù)提升了對(duì)應(yīng)用毫秒級(jí)擴(kuò)展的需求,開發(fā)人員也面臨著的功能快速推出的壓力?;旌显剖切鲁B(tài),數(shù)字化轉(zhuǎn)型是保持競(jìng)爭(zhēng)力的必要條件,虛擬化成為這些挑戰(zhàn)的基本技術(shù)。
在虛擬化的世界,有兩個(gè)詞耳熟能詳:虛擬機(jī)和容器。前者是對(duì)硬件的虛擬化,后者則更像是操作系統(tǒng)的虛擬化。兩者都提供了沙箱的能力:虛擬機(jī)通過(guò)硬件級(jí)抽象提供,而容器則使用公共內(nèi)核提供進(jìn)程級(jí)的隔離。有很多人將容器看成是“輕量化的虛擬機(jī)”,通常情況下我們認(rèn)為容器是安全的,那到底是不是跟我們想象的一樣?
容器:輕量化的虛擬機(jī)?
容器是打包、共享和部署應(yīng)用的現(xiàn)代化方式,幫助企業(yè)實(shí)現(xiàn)快速、標(biāo)準(zhǔn)、靈活地完成服務(wù)交互。容器化是建立在 Linux 的命名空間(namespace)和控制組(cgroup) 的設(shè)計(jì)之上。
命名空間創(chuàng)建一個(gè)幾乎隔離的用戶空間,并為應(yīng)用提供專用的系統(tǒng)資源,如文件系統(tǒng)、網(wǎng)絡(luò)堆棧、進(jìn)程ID和用戶ID。隨著用戶命名空間的引入,內(nèi)核版本 3.8 提供了對(duì)容器功能的支持:Mount(mnt)、進(jìn)程 ID(pid)、Network(net)、進(jìn)程間通信(ipc)、UTS、用戶 ID(user)6 個(gè)命名空間(如今已達(dá) 8 個(gè),后續(xù)加入了 cgroup 和 time 命名空間)。
cgroup 則實(shí)施對(duì)應(yīng)用的資源限制、優(yōu)先級(jí)、記賬和控制。cgroup可以控制 CPU、內(nèi)存、設(shè)備和網(wǎng)絡(luò)等資源。
同時(shí)使用 namespace 和 cgroup 使得我們可以在一臺(tái)主機(jī)上安全地運(yùn)行多個(gè)應(yīng)用,并且每個(gè)應(yīng)用都位于隔離的環(huán)境中。
虛擬機(jī)提供更強(qiáng)大的隔離
雖然容器很棒,足夠輕量級(jí)。但通過(guò)上面的描述,同一個(gè)主機(jī)上的多個(gè)容器其實(shí)是共享同一個(gè)操作系統(tǒng)內(nèi)核,只是做到了操作系統(tǒng)級(jí)的虛擬化。雖然命名空間提供了高度的隔離,但仍然有容器可以訪問(wèn)的資源,這些資源并沒(méi)有提供命名空間。這些資源是主機(jī)上所有容器共有的,比如內(nèi)核 Keyring、/proc、系統(tǒng)時(shí)間、內(nèi)核模塊、硬件。
我們都知道沒(méi)有 100% 安全的軟件,容器化的應(yīng)用也一樣,從應(yīng)用源碼到依賴庫(kù)到容器 base 鏡像,甚至容器引擎本身都可能存在安全漏洞。發(fā)生容器逃逸的風(fēng)險(xiǎn)遠(yuǎn)高于虛擬機(jī),黑客可以利用這些逃逸漏洞,操作容器的外部資源也就是宿主機(jī)上的資源。除了漏洞,有時(shí)使用的不當(dāng)也會(huì)帶來(lái)安全風(fēng)險(xiǎn),比如為容器分配了過(guò)高的權(quán)限(CAP_SYS_ADMIN 功能、特權(quán)權(quán)限),都可能導(dǎo)致容器逃逸。
而虛擬機(jī)依靠硬件級(jí)的虛擬化,實(shí)現(xiàn)的硬件隔離比命名空間隔離提供了更強(qiáng)大的安全邊界。與容器相比,虛擬機(jī)提供了更高程度的隔離,只因其有自己的內(nèi)核。
由此可見(jiàn),容器并不是真正的“沙盒”,也并不是輕量化的虛擬機(jī)。有沒(méi)有可能為容器增加一個(gè)更安全的邊界,盡可能的與主機(jī)操作系統(tǒng)隔離,做到類似虛擬機(jī)的強(qiáng)隔離,使其成為真正的“沙盒”?
沙盒化容器
答案是有,就是沙盒容器。這種容器就像虛擬機(jī)一樣有自己的內(nèi)核,這層內(nèi)核成為用戶空間內(nèi)核。這層內(nèi)核要保持容器的輕量級(jí),使用現(xiàn)代編程技術(shù)編寫,本身非常輕,僅用于作為容器和主機(jī)之間的強(qiáng)隔離層。
并且還要支持 OCI 和 CRI 規(guī)范,可以與 Docker 和 Kubernetes 等容器工具很好的集成。
這里簡(jiǎn)單介紹下 gVisor 和 Kata Containers。
gVisor
gVisor 是使用 Go 編寫的應(yīng)用內(nèi)核,實(shí)現(xiàn)了 Linux 操作系統(tǒng)的大部分接口。其包含了一個(gè)叫做 runsc 的 OCI 運(yùn)行時(shí),提供了應(yīng)用和宿主機(jī)內(nèi)核間的隔離層。runsc 也實(shí)現(xiàn)了與 Docker 和 Kubernetes 的集成,可以很容易的運(yùn)行沙盒容器。
gVisor 為每個(gè)容器提供了獨(dú)立的操作系統(tǒng)內(nèi)核。應(yīng)用與 gVisor 內(nèi)核提供的虛擬環(huán)境進(jìn)行交互,不是直接訪問(wèn)宿主機(jī)的內(nèi)核。gVisor 還限制和管理文件和網(wǎng)絡(luò)操作,確保容器化應(yīng)用和主機(jī)操作系統(tǒng)之間有兩個(gè)隔離層。通過(guò)減少和限制應(yīng)用與主機(jī)內(nèi)核的交互,盡可能減小攻擊者繞過(guò)容器隔離機(jī)制的攻擊面。
與大部分內(nèi)核不同,gVisor 不需要固定的物理資源;相反,其利用現(xiàn)有的主機(jī)內(nèi)核功能,并作為一個(gè)正常進(jìn)程運(yùn)行。換句話說(shuō),gVisor 以 Linux 的方式實(shí)現(xiàn)了 Linux。
gVisor 沙盒由多個(gè)進(jìn)程組成,這些進(jìn)程共同構(gòu)成了可以運(yùn)行一個(gè)或多個(gè)容器的環(huán)境。
每個(gè)沙盒都有其獨(dú)立的實(shí)例:
Sentry:運(yùn)行容器的內(nèi)核,攔截并響應(yīng)應(yīng)用的系統(tǒng)調(diào)用。
沙盒中的每個(gè)容器都有其獨(dú)立的實(shí)例:
Gofer:提供容器文件系統(tǒng)的訪問(wèn)。
Kata Containers
Kata Containers 與容器一樣輕量級(jí)且快,并與容器管理層集成-- 包括 Docker 和 Kubernetes 等流行的容器編排工具 -- 同時(shí)還提供了與虛擬機(jī)一樣的安全。
Kata Containers 與 OCI、容器運(yùn)行時(shí)接口(CRI)和容器網(wǎng)絡(luò)接口(CNI)完全集成。它支持各種類型的網(wǎng)絡(luò)模型(例如,passthrough、MacVTap、橋接、tc 鏡像)和可配置的訪客內(nèi)核,以便需要特殊網(wǎng)絡(luò)模型或內(nèi)核版本的應(yīng)用都可以在上面運(yùn)行。上圖顯示了 Kata VM 中的容器如何與現(xiàn)有編排平臺(tái)交互。
Kata 在主機(jī)上有一個(gè) kata 運(yùn)行時(shí)來(lái)啟動(dòng)和配置新容器。對(duì)于 Kata VM 中的每個(gè)容器,主機(jī)上都有一個(gè)相應(yīng)的 Kata Shim。Kata Shim 接收來(lái)自客戶端(例如 docker 或 kubectl)的 API 請(qǐng)求,并通過(guò) VSock 將請(qǐng)求轉(zhuǎn)發(fā)給 Kata VM 內(nèi)的代理。Kata 容器進(jìn)一步進(jìn)行了幾項(xiàng)優(yōu)化,以減少 VM 啟動(dòng)時(shí)間。
Kata Containers 由兩個(gè)開源項(xiàng)目合并而來(lái):Intel 的 Clear containers 和 Hyper runV。前者注重性能(引導(dǎo)時(shí)間小于 100ms)和安全;而后者通過(guò)支持不同的 CPU 架構(gòu)和管理系統(tǒng),將技術(shù)無(wú)關(guān)放在首位。Kata Containers 可以說(shuō)集二者之大成。
與傳統(tǒng)的容器相比,Kata Container 做到了虛擬機(jī)的隔離,集虛擬機(jī)的安全性和容器的性能于一身。
總結(jié)
與普通容器相比,沙盒容器提供了更強(qiáng)的隔離性,這種強(qiáng)隔離提供了更高的安全性。同時(shí)這類容器技術(shù)支持 OCI 和 CRI 規(guī)范,可以與現(xiàn)有的容器工具以及 Kubernetes 很好的集成。