近一段時(shí)間來,“云原生”已成為企業(yè)應(yīng)用開發(fā)和IT運(yùn)維領(lǐng)域妥妥的“網(wǎng)紅級(jí)”概念。借助靈活的微服務(wù)架構(gòu)和容器化運(yùn)維方式,以及持續(xù)的自動(dòng)化構(gòu)建與發(fā)布能力、聲明式API還有服務(wù)網(wǎng)格等技術(shù)的加持,云原生應(yīng)用已經(jīng)在很多方面徹底改變了企業(yè)設(shè)計(jì)、開發(fā)、發(fā)布和運(yùn)維應(yīng)用程序的方式,讓上云的企業(yè)在靈活性、彈性、成本等諸多方面獲得了顯著收益。
其實(shí)“云原生”這個(gè)概念依然還比較新,并且隨著技術(shù)和需求的演化,其相關(guān)定義依然在不斷迭代更新。之前我們?cè)鴮?duì)微服務(wù)進(jìn)行過簡單的介紹,錯(cuò)過的童鞋可以點(diǎn)擊這里回看 。本文,我們會(huì)一起看看容器的安全與保護(hù)問題,并通過分享安全設(shè)計(jì)實(shí)踐,告訴大家如何加固容器本身的安全性,為云原生應(yīng)用打造一個(gè)堅(jiān)實(shí)、可靠的基礎(chǔ)。
容器 | 使用和安全現(xiàn)狀
首先來看看早前的一次統(tǒng)計(jì)結(jié)果:
彼時(shí),Docker還占據(jù)主要份額。但不容忽視的是,容器化的Containerd份額在當(dāng)時(shí)已經(jīng)出現(xiàn)了大幅增加。目前,Kubernetes社區(qū)版本已經(jīng)在1.20版之后,將對(duì)Docker的支持改成了“Deprecated”,并將從1.23版之后徹底移除對(duì)Docker的支持。
不過Azure Kubernetes Service的動(dòng)作更快。早在1.19版本就開始使用Containerd取代Docker了。對(duì)用戶來說,我們不可避免需要經(jīng)歷遷移過程,包括用criCtl工具替換Docker,以及日志位置和形式的變化等。
總結(jié)來說:RKT、LXC、Mesos等容器運(yùn)行時(shí)已經(jīng)很少見,Docker和Containerd基本成為容器運(yùn)行時(shí)的主流實(shí)現(xiàn)。
另外,在編排工具方面,毫無懸念Kubernetes已占據(jù)榜首。如下圖所示,可見加上OpenShift以及Rancher,其占有比例高達(dá)89%,Swarm則從2018年的11%下降到了5%。
從上述統(tǒng)計(jì)數(shù)據(jù)可以看出,容器和容器編排等主導(dǎo)技術(shù)棧的發(fā)展趨勢(shì)已經(jīng)很明顯了,但容器安全方面并沒有那么樂觀。有一些非常觸目驚心的數(shù)據(jù)值得我們每個(gè)人警醒:
60%的受訪者所在組織在過去一年內(nèi)碰到過安全事件
93%的受訪者不是非常清楚問題的狀況
82%的受訪者認(rèn)為,由于采用了容器,需要重新思考安全職責(zé)問題
那么對(duì)于容器技術(shù)來說,到底為我們?cè)斐闪四男┌踩魬?zhàn)?我們?cè)摬扇≡鯓拥膽?yīng)對(duì)措施?
容器帶來的安全挑戰(zhàn)和應(yīng)對(duì)策略
容器還是虛擬機(jī),這是個(gè)問題:
容器是一種“軟件包”,其中包含了能在任何環(huán)境中運(yùn)行應(yīng)用所需的全部元素。容器可以通過虛擬化操作系統(tǒng)在任何地方(私有數(shù)據(jù)中心、公有云、開發(fā)者的個(gè)人計(jì)算機(jī))。但是它的虛擬化程度與虛擬機(jī)還有很大區(qū)別。
通過下圖的對(duì)比可以看出:傳統(tǒng)虛擬機(jī)會(huì)占用大量磁盤空間,除了虛擬機(jī)托管的應(yīng)用程序外,還包含完整的操作系統(tǒng)和相關(guān)工具;容器則相對(duì)較輕,僅包含運(yùn)行容器化應(yīng)用程序所需的庫和工具,因此比虛擬機(jī)更緊湊,并且啟動(dòng)速度更快。
虛擬機(jī) 容器
容器的主要技術(shù)實(shí)現(xiàn):
以Docker容器為例,主要使用這三大特性來實(shí)現(xiàn)虛擬化與隔離:cgroup + namespace + docker image:
cgroup (資源限制):
驅(qū)動(dòng) :
cgroupfs:
要限制內(nèi)存, CPU等資源限制寫入pid對(duì)應(yīng)的一個(gè)cgroup文件
systemd :
提供一個(gè)cgroup管理方式,所有的寫cgroup操作都必須通過systemd的接口來完成,不能手動(dòng)更改cgroup的文件。
常用顯示項(xiàng)目:
CPU:計(jì)算
Memory:內(nèi)存
Device:設(shè)備
Freezer:批任務(wù)凍結(jié)(為了安全)
Blkio:磁盤訪問
Pid:創(chuàng)建進(jìn)程數(shù)量
namespace (隔離):
mount : 文件系統(tǒng)的視圖,是容器鏡像提供的一個(gè)文件系統(tǒng)。
uts : 隔離hostname和domain。
pid namespace : 保證容器的init進(jìn)程是以1號(hào)進(jìn)程來啟動(dòng)。
network namespace : 除host網(wǎng)絡(luò)這種模式,其他所有的網(wǎng)絡(luò)模式都有一個(gè)networknamespace的文件。
user namespace : 控制用戶UID和GID在容器內(nèi)部和宿主機(jī)上的一個(gè)映射。
IPC namespace : 控制了進(jìn)程兼通信的一些東西,比方說信號(hào)量。
docker image
基于聯(lián)合文件系統(tǒng)
不同層可以被其他鏡像復(fù)用
容器讀寫層作為最新的鏡像最新一層
容器化所采用的主要安全技術(shù):
容器在帶來輕量與便利的同時(shí),也帶來一些安全問題。主要原因包括:
多個(gè)容器間使用的還是同一宿主機(jī)的操作系統(tǒng)內(nèi)核;
Linux內(nèi)核中很多資源和對(duì)象不能被Namespace化;
系統(tǒng)調(diào)用甄別變得復(fù)雜(雖然可以通過Seccomp等技術(shù)過濾和甄別容器內(nèi)部發(fā)起的所有系統(tǒng)調(diào)用來進(jìn)行安全加固,但多了一層對(duì)系統(tǒng)調(diào)用的過濾,會(huì)拖累容器性能。此外,默認(rèn)情況下我們也很難知道到底該開啟哪些系統(tǒng)調(diào)用,禁止哪些系統(tǒng)調(diào)用)。
隨著大家對(duì)安全越來越重視,容器安全技術(shù)本身也在不斷的加強(qiáng)和演進(jìn)。具有代表性的技術(shù)包括:
默認(rèn)利用Capability限制容器Root用戶的能力。Docker默認(rèn)容器的Capability包括(Docker的默認(rèn)Secomp可參閱
https://github.com/moby/moby/blob/master/profiles/seccomp/default.json):
Seccomp系統(tǒng)調(diào)用過濾:
結(jié)合seLinux或Apparmor實(shí)現(xiàn)MAC訪問控制:
打造安全的容器:
容器安全問題的本質(zhì)是共享內(nèi)核。為了解決該問題,逐漸發(fā)展出“安全容器”這一概念,其主要代表技術(shù)有Kata Containers和Gvisor。
Kata Containers的本質(zhì)是一個(gè)輕量化虛擬機(jī)。當(dāng)我們啟動(dòng)一個(gè)Kata Containers后,會(huì)看到一個(gè)正常的虛擬機(jī)在運(yùn)行。這也就意味著:標(biāo)準(zhǔn)的虛擬機(jī)管理程序(Virtual Machine Manager, VMM)是運(yùn)行Kata Containers的必備組件。
2018年,Google發(fā)布了gVisor項(xiàng)目。gVisor項(xiàng)目給容器進(jìn)程配置了一個(gè)用Go語言實(shí)現(xiàn),運(yùn)行在用戶態(tài)的極小“獨(dú)立內(nèi)核”。這個(gè)內(nèi)核對(duì)容器進(jìn)程暴露Linux內(nèi)核,扮演“Guest Kernel”的角色,從而達(dá)到了將容器與宿主機(jī)隔離的目的。兩者大致架構(gòu)對(duì)比如下:
容器docker-bench-security:
在具體的生產(chǎn)運(yùn)行環(huán)境中,我們可執(zhí)行腳本得到最佳實(shí)踐校驗(yàn)結(jié)果。運(yùn)維人員可結(jié)合這些建議作出修改和備注。詳細(xì)地址如下:https://github.com/docker/docker-bench-security
下圖是執(zhí)行結(jié)果,從中可以看到各個(gè)級(jí)別的條目:
鏡像安全掃描:
容器的執(zhí)行程序和文件系統(tǒng)是鏡像,要保障容器安全,鏡像的安全掃描也非常重要。開源的鏡像掃描產(chǎn)品可選擇Clair。
在Azure上,容器注冊(cè)的Azure Defender包含一個(gè)漏洞掃描程序,可掃描基于Azure資源管理器的Azure Container Registry注冊(cè)表中的鏡像。該技術(shù)由業(yè)界領(lǐng)先的漏洞掃描供應(yīng)商Qualys提供支持。
Kubernetes的安全問題
Kubernetes的安全問題可從幾個(gè)不同層面展開。
首先,Kubernetes本身是一個(gè)資源對(duì)象管理平臺(tái),通過把不同對(duì)象進(jìn)行抽象,形成平臺(tái)能夠識(shí)別的資源對(duì)象,例如Pod、Namespace、ReplicaSet等。訪問這些對(duì)象需要統(tǒng)一的API,在API層面主要有三種安全機(jī)制:認(rèn)證、授權(quán),以及準(zhǔn)入控制。
Kubernetes API訪問控制:
其中準(zhǔn)入控制又分成兩種Hook:
Mutating admission webhook:對(duì)資源的定義聲明作出相應(yīng)修改;
Validating admission webhook:判斷資源是否可以創(chuàng)建或更新。
在API認(rèn)證方面,使用最普遍的是X509和ServiceAccount方式。
X509是通過指定相應(yīng)Name和Group屬性實(shí)現(xiàn)的:
Pod的ServiceAccount認(rèn)證方式如下圖所示:
在授權(quán)方面,則主要采取了基于角色的訪問控制機(jī)制。Kubernetes中的角色可根據(jù)是否需要跨名稱空間訪問而分成Role和ClusterRole,同時(shí)綁定關(guān)系也可分成RoleBinding和ClusterRoleBinding,它們之間的關(guān)系如下圖所示:
此外還要注意Kubernetes的安全上下文問題。由于Kubernetes底層還是通過調(diào)用容器運(yùn)行時(shí)來對(duì)容器進(jìn)行生命周期管理和安全限制,所以上述有關(guān)Docker的安全思路也適用于Kubernetes,借此可實(shí)現(xiàn)對(duì)運(yùn)行時(shí)的控制。詳細(xì)內(nèi)容可參閱下圖:
除了通過上述securityContext對(duì)運(yùn)行時(shí)加以控制外,Kubernetes還引入了資源安全規(guī)則對(duì)象PodSecurityPolicy,借此實(shí)現(xiàn)對(duì)名稱空間內(nèi)Pod的統(tǒng)一安全控制。主要控制內(nèi)容如下:
其工作流程如下圖所示:
在流量訪問控制方面,Kubernetes中進(jìn)出站流量可通過NetworkPolicy加以定義。具體來說,我們可以定義如下的內(nèi)容:
ServiceMesh:
如果需要多租戶或企業(yè)級(jí)別的流量和安全管控,僅使用NetworkPolicy是不夠的。此時(shí)需要引入ServiceMesh。各個(gè)ServiceMesh在Kubernetes這個(gè)基座之上都能很好地運(yùn)行。
當(dāng)前流行的ServiceMesh主要有Istio和Linkerd。下圖展示了以Istio為代表地ServiceMesh整體架構(gòu)圖和組件構(gòu)成。因?yàn)樗旧硪灿幸欢ǖ呐渲煤凸芾韽?fù)雜性,對(duì)性能損耗也不能忽略,因此對(duì)于技術(shù)團(tuán)隊(duì)不完整的公司,很多還處于觀望狀態(tài)。
OpenAgentPolicy
由于PodSecurityPolicy本身只能定義Pod的規(guī)則,而在云原生應(yīng)用中,包括在各個(gè)公有云或私有云中,還會(huì)引入更多資源類型,如Service、Node等。
開源社區(qū)也逐步開始廢棄PodSecurityPolicy,轉(zhuǎn)為推薦通過OpenAgentPolicy框架實(shí)現(xiàn)對(duì)各種資源的約束。因?yàn)樾枰s束各種資源,因而有必要提供更大靈活性,進(jìn)而引入了一種新的,表達(dá)能力更豐富的規(guī)則語言:Rego。實(shí)例請(qǐng)參照下圖:
具體到Kubernetes平臺(tái),我們需要使用GateKeeper這個(gè)組件。
在Azure云平臺(tái)中,則是通過Azure Policy來實(shí)現(xiàn)和替代這個(gè)功能的:
存儲(chǔ)安全
Kubernetes可將密鑰等機(jī)密信息存儲(chǔ)在Secret資源之中,但查看etcd中的內(nèi)容會(huì)發(fā)現(xiàn)一切都以明文方式實(shí)現(xiàn),這就會(huì)導(dǎo)致一些安全問題,例如:
在Azure上提供專門保護(hù)加密密鑰、證書(以及與證書關(guān)聯(lián)的私鑰)和機(jī)密(例如連接字符串和密碼)等存儲(chǔ)敏感數(shù)據(jù)和關(guān)鍵業(yè)務(wù)數(shù)據(jù)的服務(wù)--Azure Key Vault。它可以與Azure Kubernetes Service無縫集成,最大限度提高這些敏感信息的訪問和存儲(chǔ)安全性。
Azure Kubernetes Service安全
AKS中主要包含下圖所示的Kubernetes功能模塊,大致可分為控制平面和數(shù)據(jù)平面兩部分:
Azure Kubernetes Service是基于Azure云平臺(tái)的托管Kubernetes服務(wù)。它把控制平面變成了一種托管的平臺(tái)服務(wù),客戶無需管理API Servers、Etcd等組件,只需要為自己的Agent node付費(fèi)。同時(shí)在安全方面,Azure平臺(tái)提供了Application Gateway、Azure Firewall、Azure Key Vault等服務(wù)來保證系統(tǒng)安全。
下圖是一個(gè)比較常見的,以Azure Kubernetes Service為基礎(chǔ)的整體架構(gòu)圖:
整個(gè)架構(gòu)分為四大部分:
1.容器和鏡像安全:
通過AAD認(rèn)證保證容器認(rèn)證安全
通過ACR鏡像掃描保證鏡像安全
2.節(jié)點(diǎn)和集群安全:
節(jié)點(diǎn)自動(dòng)補(bǔ)丁更新
節(jié)點(diǎn)可以發(fā)布到私有網(wǎng)絡(luò)中
3.Pod安全:
通過Azure Policy提供豐富的安全定義
4.流量安全:
通過存儲(chǔ)加密
通過Key Vault保證秘鑰等安全
通過Azure Application Gateway等保證訪問安全
關(guān)于AKS的詳細(xì)信息請(qǐng)參閱相關(guān)文檔。同時(shí)這方面還有一些動(dòng)手實(shí)驗(yàn),詳情可參閱https://github.com/sme-csu/aks-security-design-practice。
容器的安全性是一個(gè)很龐大的話題,限于篇幅,本文不可能一一進(jìn)行詳細(xì)介紹。希望上述內(nèi)容能起到拋磚引玉的作用,幫助大家更好地了解相關(guān)技術(shù),設(shè)計(jì)出更安全的容器環(huán)境。
如果希望進(jìn)一步了解本文涵蓋的相關(guān)話題,可前往https://github.com/sme-csu/App-Mod查看相關(guān)演示文檔和視頻教程。
如果有任何意見或建議,也歡迎通過留言進(jìn)行交流。