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