作者 | 王旭 螞蟻金服資深技術(shù)專家 本文整理自《CNCF x Alibaba 云原生技術(shù)公開(kāi)課》第 28 講,,點(diǎn)擊直達(dá)課程頁(yè)面,。 關(guān)注“阿里巴巴云原生”公眾號(hào),回復(fù)關(guān)鍵詞**“入門(mén)”**,,即可下載從零入門(mén) K8s 系列文章 PPT,。 一、緣起:安全容器的命名Phil Karlton 有一句名言:“計(jì)算機(jī)科學(xué)界只有兩個(gè)真正的難題——緩存失效和命名,?!?/p> 對(duì)我們?nèi)萜魅Χ?,我相信「命名」絕對(duì)配得上這句話,。這毫無(wú)疑問(wèn)是一件讓老開(kāi)發(fā)者沉默、讓新人落淚的事情,。僅就系統(tǒng)軟件而言,,我們當(dāng)今比較通行地稱為**「Linux 容器技術(shù)」**這個(gè)概念,它曾經(jīng)用過(guò)的名字還有 Jail, Zone, Virtual Server, Sandbox 等,。同樣,,在早期虛擬化的技術(shù)棧里也把一類虛擬機(jī)叫做容器,畢竟這個(gè)詞本身就指代那些用來(lái)包容,、封裝和隔離的器物,。它實(shí)在太過(guò)常見(jiàn)了,以至于以嚴(yán)謹(jǐn)著稱的 Wikipedia,它的詞條叫做「OS-Level Virtualization」(系統(tǒng)級(jí)虛擬化) ,,從而回避了「什么是容器」這個(gè)問(wèn)題,。 在 2013 年,Docker 問(wèn)世之后,,容器這個(gè)概念伴隨著不可變基礎(chǔ)設(shè)施,、云原生這一系列概念在隨后的幾年間以摧枯拉朽之勢(shì)顛覆了基于“軟件包 配置”這種細(xì)粒度組合的應(yīng)用部署,用簡(jiǎn)單的聲明式策略和不可變的容器就清爽地定義了軟件棧,。應(yīng)用怎么部署,,在這兒似乎有點(diǎn)離題了,我在這里想要強(qiáng)調(diào)的是: “云原生語(yǔ)境下的容器,,實(shí)質(zhì)是「應(yīng)用容器」——是以標(biāo)準(zhǔn)格式封裝的,,運(yùn)行于標(biāo)準(zhǔn)操作系統(tǒng)環(huán)境(常常是 Linux ABI)上的應(yīng)用打包——或運(yùn)行這一應(yīng)用打包的程序/技術(shù)?!?/p> 這個(gè)定義是我下的,,但它并不是我的個(gè)人意志,是基于 OCI 規(guī)范這一共識(shí)寫(xiě)出來(lái)的,。這個(gè)規(guī)范規(guī)定了容器之中應(yīng)用被放到什么樣的環(huán)境下,、如何運(yùn)行,比如說(shuō)容器的根文件系統(tǒng)上哪個(gè)可執(zhí)行文件會(huì)被執(zhí)行,,是用什么用戶執(zhí)行,,需要什么樣的 CPU,有什么樣的內(nèi)存資源,、外置存儲(chǔ),,還有什么樣的共享需求等等。 所以說(shuō),,標(biāo)準(zhǔn)格式的封裝,、標(biāo)準(zhǔn)的操作系統(tǒng)環(huán)境在一起以應(yīng)用為中心就構(gòu)成了應(yīng)用容器的打包。 以這個(gè)共識(shí)為基礎(chǔ),,就可以來(lái)說(shuō)說(shuō)安全容器了,。當(dāng)年,我和我的聯(lián)合創(chuàng)始人趙鵬使用「虛擬化容器」這個(gè)名字來(lái)命名我們的技術(shù)的,,不過(guò)為了博人眼球,,我們用了「Secure as VM, Fast as Container」這樣的 Slogan,于是,,被容器安全性問(wèn)題戳中心坎的人們立刻用「Secure Container」或者說(shuō)「安全容器」來(lái)稱呼這種東西了,,一發(fā)而不可收。雖然在我們的內(nèi)心里,,這個(gè)技術(shù)是一層額外的隔離,,它只是安全中的一環(huán),,但是呢,用戶還是愿意用安全容器這個(gè)名字來(lái)稱呼它,。我們給安全容器下的定義就是: 安全容器是一種運(yùn)行時(shí)技術(shù),,為容器應(yīng)用提供一個(gè)完整的操作系統(tǒng)執(zhí)行環(huán)境(常常是 Linux ABI),但將應(yīng)用的執(zhí)行與宿主機(jī)操作系統(tǒng)隔離開(kāi),,避免應(yīng)用直接訪問(wèn)主機(jī)資源,,從而可以在容器主機(jī)之間或容器之間提供額外的保護(hù)。 這就是我們的安全容器,。 二,、間接層:安全容器的精髓說(shuō)安全容器的時(shí)候,就要提到「間接層」這個(gè)詞,。它出自于 Linus Torvalds 在 2015 年的 LinuxCon 上提出的: “安全問(wèn)題的唯一正解在于允許那些(導(dǎo)致安全問(wèn)題的)Bug 發(fā)生,,但通過(guò)額外的隔離層來(lái)阻擋住它們?!?/p> 為了安全,,為什么要引入隔離層呢?其實(shí) Linux 本身這樣的規(guī)模是非常大的,,無(wú)法從理論上來(lái)驗(yàn)證程序是沒(méi)有 Bug 的,,于是,一旦合適的 Bug 被利用,,安全性風(fēng)險(xiǎn)就變成安全性問(wèn)題了,。安全性的框架和修補(bǔ)并不能確保安全,所以我們需要進(jìn)行一些額外的隔離來(lái)減少漏洞以及因?yàn)檫@些漏洞造成的被徹底攻破的風(fēng)險(xiǎn),。 這就是安全容器的由來(lái),。 三、Kata Containers:云原生化的虛擬化2017 年 12 月,,我們?cè)?KubeCon 上對(duì)外發(fā)布了 Kata Containers 的安全容器項(xiàng)目,,這個(gè)項(xiàng)目有兩個(gè)前身:由我們之前開(kāi)始的 runV 以及 Intel 的 Clear Container 項(xiàng)目。這兩個(gè)項(xiàng)目都是 2015 年 5 月開(kāi)始開(kāi)展的,,實(shí)際上是早于 Linus 在 KubeCon 2015 說(shuō)的那番話的,。 它們的思路都很簡(jiǎn)單:
現(xiàn)在的問(wèn)題是虛機(jī)不太夠快,,阻礙了它在容器環(huán)境中的應(yīng)用,如果能擁有「speed of container」的話,,那我們就可能可以有一個(gè)用虛擬機(jī)來(lái)做隔離的安全容器技術(shù)了,。這個(gè)也就是 Kata Containers 本身的一個(gè)思路,就是用虛擬機(jī)來(lái)做 Kubernetes 的 PodSandbox,。在 Kata 里面被拿來(lái)做 VM 的先后有 qemu, firecracker, ACRN, cloud-hypervisor 等,。 下圖就是 Kata Containers 怎么去和 Kubernetes 集成的,這里的例子用的是 containerd,,當(dāng)然 CRI-O 也是一樣的,。 目前,Kata Containers 通常是在 Kubernetes 中使用,。首先 Kubelet 通過(guò) CRI 接口找到 containerd 或者 CRI-O,,這個(gè)時(shí)候比如鏡像這樣的操作一般也是由 containerd 或者 CRI-O 來(lái)執(zhí)行的。根據(jù)請(qǐng)求,,它會(huì)把 runtime 部分的需求變成一個(gè) OCI spec,,并交給 OCI runtime 執(zhí)行。比如說(shuō)上圖上半部分中的 kata-runtime,,或者說(shuō)下半部分精簡(jiǎn)過(guò)后的 containerd-shim-kata-v2,。具體的過(guò)程是這樣的:
可以看到,,在我們的 PodSandbox 里面,實(shí)際上只有一個(gè) Guest Kernel 跑著一些容器本身的打包和容器應(yīng)用,,并不包含一個(gè)完整的操作系統(tǒng),。就是說(shuō),這個(gè)過(guò)程,,它用起來(lái)并不像是傳統(tǒng)的虛擬機(jī),,對(duì)于容器來(lái)說(shuō),它只有容器的引擎,,并且通過(guò)少用不必要的內(nèi)存,、共享能共享的內(nèi)存來(lái)進(jìn)一步地降低內(nèi)存的開(kāi)銷。 與傳統(tǒng)的虛擬機(jī)比起來(lái),,開(kāi)銷更小,、啟動(dòng)更輕快,對(duì)于大部分的場(chǎng)景來(lái)說(shuō),,它可以做到「secure as VM」,、「fast as container」。同時(shí),,在安全性技術(shù)以外,,相比傳統(tǒng)的虛機(jī),它有更多的彈性,,更少了機(jī)器的那種物理操作的手感,,比如說(shuō)這里面說(shuō)過(guò)的包括動(dòng)態(tài)資源的插拔以及使用 virtio-fs 這樣的技術(shù)等。它是一個(gè)專門(mén)為我們這種場(chǎng)景、為像 kata 這樣的場(chǎng)景來(lái)做的一個(gè)把 host 的基本文件系統(tǒng)的內(nèi)容(比如說(shuō)容器的 rootfs )共享給虛擬機(jī)的這樣一個(gè)技術(shù),。 通過(guò)其中一些之前為非易失存儲(chǔ),、非易失內(nèi)存來(lái)做的 DAX 的技術(shù),,能夠在不同的 PodSandbox 之間,,也就是不同的 Pod 之間、不同的容器之間,,共享一些可以共享的只讀的內(nèi)存部分,。這樣可以在不同的 PodSandbox 之間去節(jié)省很多的內(nèi)存。同時(shí)所有的 Pod 的管理都是通過(guò) Kubernetes 從外部進(jìn)行的容器管理,,并且從外部來(lái)獲取 metrics 和 debug 信息,,并沒(méi)有登陸虛擬機(jī)這樣一種手感。所以它看起來(lái)是一種非常容器化的操作,,雖然從底層來(lái)看,,它還是一個(gè)虛擬機(jī),但是實(shí)際上它是一個(gè)面向云原生的虛擬化,。 四,、gVisor:進(jìn)程級(jí)虛擬化gVisor,我們又把它叫做進(jìn)程級(jí)的虛擬化,,它是和 kata 不一樣的另外一種方式,。 在 2018 年的 5 月份,哥本哈根的 KubeCon 上,,Google 開(kāi)源了他們內(nèi)部開(kāi)發(fā)了 5 年的 gVisor 安全容器作為對(duì) kata containers 的回應(yīng),,表明了他們有一種不同的安全容器的解決方案。 如果說(shuō) Kata Containers 是通過(guò)對(duì)現(xiàn)有的隔離技術(shù)進(jìn)行組合和改造來(lái)構(gòu)建容器間的隔離層的話,,那么 gVisor 的設(shè)計(jì)顯然是更加簡(jiǎn)潔的,。 如上圖右側(cè)所示,它是一個(gè)用 Go 語(yǔ)言重寫(xiě)的運(yùn)行在用戶態(tài)的操作系統(tǒng)內(nèi)核,,這個(gè)內(nèi)核的名字叫做 sentry,,它并不依賴于虛擬化和虛擬機(jī)技術(shù),相反,,它是借助一個(gè)它們內(nèi)部叫做一個(gè) Platform(平臺(tái))的能力,,讓宿主機(jī)的操作系統(tǒng)做一個(gè)操作,把應(yīng)用所有的期望對(duì)操作系統(tǒng)的操作都轉(zhuǎn)交給 sentry 來(lái)進(jìn)行,,sentry 做處理之后會(huì)把其中的一部分交給操作系統(tǒng)來(lái)幫它完成,,大部分則由自己來(lái)完成。 gVisor 是一個(gè)純粹的面向應(yīng)用的隔離層,,從一開(kāi)始就不是一個(gè)完全等同于虛擬機(jī)的東西,,它就是用來(lái)在 Linux 上面跑一個(gè) Linux 程序的。作為一個(gè)隔離層,,它的安全性依據(jù)在于:
Linux 大概有 300 多個(gè) Syscall,實(shí)際上 sentry 最后向操作系統(tǒng)發(fā)起的調(diào)用只會(huì)集中在 60 多個(gè) Syscall 上,。這個(gè)是源于 gVisor 的開(kāi)發(fā)者們對(duì)操作系統(tǒng)的安全做了一些研究,,他們發(fā)現(xiàn),大多數(shù)對(duì)操作系統(tǒng)的成功的攻擊都是來(lái)自于不常用的系統(tǒng)調(diào)用的,。 這個(gè)很容易理解,,因?yàn)椴怀S玫南到y(tǒng)調(diào)用,它的實(shí)現(xiàn)路徑一般都是比較老的路徑,,也就是說(shuō)這些部分的開(kāi)發(fā)一般不是太積極,,只有很少的開(kāi)發(fā)者來(lái)維護(hù),那些熱門(mén)路徑上的代碼要更安全一些,,因?yàn)槟切┐a被 review 的次數(shù)比較多,。所以 gVisor 的設(shè)計(jì)就是讓?xiě)?yīng)用對(duì)那些并不常用的 Syscall 的訪問(wèn)根本就到不了操作系統(tǒng)層面,而只在 sentry 里就把它處理掉,。 從 sentry 訪問(wèn)宿主機(jī)的,,只使用那些被驗(yàn)證過(guò)的、比較成熟,、比較熱的路徑上的系統(tǒng)調(diào)用,,這樣的話,安全性就會(huì)比原來(lái)看起來(lái)好很多,。我們現(xiàn)在 Syscall 是原來(lái)的 1/5,,但是被攻擊的可能性是并不到 1/5 的。
在 Unix 系統(tǒng)里面,大部分東西都是一些文件,,所以 open 可以做太多的事情了,,大部分的攻擊都是通過(guò) open 來(lái)進(jìn)行的。gVisor 的開(kāi)發(fā)者就單獨(dú)地把 open 放到了一個(gè)獨(dú)立的進(jìn)程里面去實(shí)現(xiàn),,這個(gè)進(jìn)程叫做 Gofer,。一個(gè)獨(dú)立的進(jìn)程實(shí)際上是更容器被 seccomp、被一些系統(tǒng)的限制,、一些 'capbility drop' 來(lái)保護(hù),。Gofer 可以做更少的事情,可以用非 root 去執(zhí)行,如此一來(lái)整個(gè)系統(tǒng)的安全性就被進(jìn)一步地被提高了,。
Go 語(yǔ)言本身是一個(gè)內(nèi)存更安全的一個(gè)實(shí)現(xiàn),,因此整個(gè) gVisor 就更不容易被攻擊,更不容易發(fā)生一些內(nèi)存上的問(wèn)題,。當(dāng)然,,Go 語(yǔ)言在有些地方還是不夠太系統(tǒng)級(jí)的,,gVisor 的開(kāi)發(fā)者也坦言,,他們?yōu)榱俗鲞@件事情,也對(duì) Go Runtime 做了很多調(diào)整,,并把這些東西也反饋回給了 Go 語(yǔ)言的社區(qū),。 可以說(shuō) gVisor 的架構(gòu)很漂亮,有很多開(kāi)發(fā)者跟我坦誠(chéng),,他們其實(shí)很喜歡 gVisor 的架構(gòu),,覺(jué)得這個(gè)更簡(jiǎn)單、更純粹,、更干凈,。當(dāng)然了,雖然它的架構(gòu)很漂亮,,但重新實(shí)現(xiàn)一個(gè)內(nèi)核這件事情也只有 Google 這樣的巨頭能做得出來(lái),,類似的可能還有微軟的 WSL 1。而且這個(gè)設(shè)計(jì)是比較超前的,,它其實(shí)存在一些問(wèn)題:
所以短時(shí)間之內(nèi),gVisor 這樣的解決方案并不能成為一個(gè)終極的解決方案,,不過(guò)它可以適應(yīng)一些特定的場(chǎng)景,,并且它也帶來(lái)一些啟示性。我覺(jué)得這個(gè)啟示性對(duì)未來(lái)的操作系統(tǒng),、CPU 指令集的發(fā)展都可能會(huì)有一些作用,。而且我相信,在未來(lái),,不管是 kata 還是 gVisor,,都會(huì)有一個(gè)演進(jìn),我們期待著最后會(huì)有一個(gè)公共的解決方案來(lái)統(tǒng)一地解決應(yīng)用的執(zhí)行問(wèn)題,。 五,、安全容器:不止于安全安全容器的名字雖叫安全,但是它提供的是一個(gè)隔離性,。它的作用是不止于安全的,。 安全容器通過(guò)隔離層讓?xiě)?yīng)用的問(wèn)題——不管是來(lái)自于外部的惡意攻擊還是說(shuō)意外的錯(cuò)誤,都不至于影響主機(jī),,也不會(huì)在不同的 Pod 之間相互影響,,所以實(shí)際上,這個(gè)額外的隔離層,,它所帶來(lái)的影響不只是安全,,還有其它的方面。它對(duì)于系統(tǒng)的調(diào)度,、服務(wù)質(zhì)量,,還有應(yīng)用信息的保護(hù)都是有好處的。 我們說(shuō)傳統(tǒng)的操作系統(tǒng)容器技術(shù)是內(nèi)核進(jìn)程管理的一個(gè)延伸,,容器進(jìn)程本身是一組相關(guān)聯(lián)的進(jìn)程,,對(duì)于宿主機(jī)的調(diào)度系統(tǒng)來(lái)說(shuō),它是完全可見(jiàn)的,,一個(gè) Pod 里的所有容器或進(jìn)程,,同時(shí)也都被宿主機(jī)調(diào)度和管理。這就意味著,,如果你有一個(gè)大量容器的環(huán)境,,宿主機(jī)本身內(nèi)核的負(fù)擔(dān)就會(huì)很重,在很多實(shí)際環(huán)境中已經(jīng)可以觀察到這個(gè)負(fù)擔(dān)帶來(lái)的開(kāi)銷了,。 尤其是現(xiàn)在計(jì)算機(jī)技術(shù)的不斷發(fā)展,,一個(gè)操作系統(tǒng)會(huì)有大量的內(nèi)存,,大量的 CPU,幾百 G 的內(nèi)存都是可以見(jiàn)到的,。在這個(gè)情況下,,如果分配的容器數(shù)量很多,調(diào)度系統(tǒng)就會(huì)有非常沉重的開(kāi)銷,。在采納安全容器之后,,在宿主機(jī)上就看不到這些完整的信息了,這個(gè)隔離層同時(shí)承擔(dān)了一些對(duì)隔離層上面應(yīng)用的調(diào)度,,于是在主機(jī)上面就只需要調(diào)度這些沙箱本身,,降低了宿主機(jī)的調(diào)度開(kāi)銷,這也就是它為什么會(huì)提高調(diào)度效率的原因,。 提高調(diào)度效率的同時(shí),,它會(huì)把所有的應(yīng)用彼此隔離起來(lái),這樣就避免了容器之間,、容器和主機(jī)之間的干擾,,提高了服務(wù)質(zhì)量,。從另外一個(gè)方向來(lái)看,,我們做安全容器的初衷是為了保護(hù)宿主機(jī)不受到容器內(nèi)惡意或者有問(wèn)題的應(yīng)用的影響,反過(guò)來(lái),,作為一個(gè)云來(lái)說(shuō),,我們有可能會(huì)面對(duì)有惡意的攻擊,所以也是保護(hù)我們自己,。 同時(shí)用戶也不愿意讓我們過(guò)多地去訪問(wèn)用戶的資源,,用戶需要使用資源,但它并不需要我們看到它的數(shù)據(jù),。安全容器可以把用戶運(yùn)行的東西完全封裝在容器里,,這樣的話可以讓主機(jī)的運(yùn)維管理操作并不能訪問(wèn)到應(yīng)用的數(shù)據(jù),從而把應(yīng)用的數(shù)據(jù)保護(hù)在沙箱里,,不需要去碰到用戶數(shù)據(jù),。如果我們要訪問(wèn)用戶數(shù)據(jù),作為一個(gè)云的話,,那就必須得讓用戶給你授權(quán),,這個(gè)時(shí)候,用戶不確定你是不是有什么惡意的操作,,如果我們的沙箱封裝得很好的話,,那也就不需要額外的對(duì)用戶授權(quán)的要求,這對(duì)于保護(hù)用戶的私密性是更好的,。 當(dāng)我們把目光看向未來(lái)的時(shí)候,,可以看到,,安全容器不僅僅是在做安全隔離,安全容器隔離層的內(nèi)核相對(duì)于宿主機(jī)的內(nèi)核是獨(dú)立的,,專門(mén)對(duì)應(yīng)用服務(wù),,從這個(gè)角度來(lái)說(shuō),主機(jī)和應(yīng)用的功能之間實(shí)際上是一個(gè)合理的功能分配與優(yōu)化,。它可以展現(xiàn)出很多的潛力,,未來(lái)的安全容器,可能不僅僅是隔離性能開(kāi)銷的降低,,同時(shí)也是在提高應(yīng)用的性能,。隔離技術(shù)會(huì)讓云原生基礎(chǔ)設(shè)施更加完美。 六,、本文總結(jié)本文的主要內(nèi)容就到此為止了,,這里為大家簡(jiǎn)單總結(jié)一下:
|
|
來(lái)自: Earlycl6i7o9ek > 《技術(shù)》