K8s的安全機制必須倚賴第三方檢測工具協助來得知、修補並鞏固強化資安機制。本文模擬演練,讓輕量化叢集Minikube在其上運行NGINX服務並操作Kube-Hunter檢測工具,讓大家了解K8s的漏洞主要源自於其運行環境的主機設定,只要做好安全檢查就能降低K8s的安全風險。
無可諱言,Docker技術的火熱是讓K8s得以受到重視的一大助力,近年來不少大型科技公司逐漸地擁抱Docker,而Docker技術中真正實現將應用程式虛擬化的容器數量就如指數型地成長。
前景雖好,但同時也衍生出新的問題及挑戰,也就是該如何有效地管理這些大量的容器呢?科技巨擎Google為了解決眼前的現況,開發了一套現今在容器界家喻戶曉的容器管理系統K8s。
本文將導引K8s技術,了解K8s的背景知識、基礎架構和安全需求與趨勢,藉由K8s檢查工具Kube-Hunter,得以模擬演練找出輕量化的K8s叢集Minikube環境中潛在的安全需求。該模擬也可以應用到實際運行中的K8s叢集,讓K8s的應用得以獲得安全上的認證。
認識K8s發展背景
K8s的全名叫做「Kubernetes」,之所以簡稱為K8s是因為它的字母K和s的中間有8個字母而聞名。其實如果將時間推回2014年以前,K8s還不像現今這麼的火紅,直到2014年之後,輕量化虛擬化技術Docker竄起,讓原本只是在小眾市場使用的K8s受到大家的歡迎,因此K8s的成功有一大部分要歸功於輕量化的虛擬化技術Docker,原因是在Docker技術中真正實現虛擬化的技術是容器,它可以快速地在幾秒鐘之內將要運行的服務或應用程式啟動完成。
然而,當越來越多的大型科技公司轉而將內部各種服務或應用程式轉向Docker的懷抱時,可想而知,容器的數量暴增。就以Google為例,每周至少會啟用20億的容器來供應大量的使用量。因此,當有這麼大量的容器應用產生,勢必得開始思考如何對這大量的容器進行有系統性的管理,將使用容器的效益最大化,免得造成使用容器但是卻要花大量時間去做「管理」的窘境。
有鑑於此,Google率先開發了容器管理平台K8s來解決「如何有效管理大量的容器」這個迫切的問題,K8s也從中找到了其存在的價值。此外,Google也將K8s容器管理系統的原始程式碼開源,並將其變成雲端原生運算基金會(Cloud Native Computing Foundation,CNCF)組織底下的一個專案統一管理,在這之後,K8s的聲勢跟著水漲船高,成為現今大部分使用容器應用業者所採用的重要容器管理平台。
K8s基礎架構與相關工具比較
接著,說明K8s基礎架構,並介紹管理容器相關工具。
K8s基礎架構
K8s作為管理容器的工具,會將各個節點集結起來組成一個K8s叢集(K8s Cluster),在一個叢集中至少需要有兩個節點,分別是「主節點」(Master Node)及一至多個「工作節點」(Worker Node),以下分別說明主節點及工作節點上的基礎元件及其功能。圖1是主節點和工作節點的關係圖,從中可以看到主節點上有kube-apiserver、kube-scheduler、kube-controller-manager、etcd等物件,工作節點上則包含kubelet、kube-proxy、Container Runtime Engine、Ingress、Service、Pod等物件。
依序介紹kube-apiserver、etcd、kube-scheduler及kube-controller-manager等物件。
‧kube-apiserver:可在主節點上提供一個介面給Kubectl或kubeadm等K8s工具從內部及外部呼叫請求,可以說是主節點和工作節點能夠溝通的橋樑。
‧etcd:這是一個主節點上的資料庫,儲存內容為叢集的狀態和設定檔資訊。
‧kube-scheduler:其工作是負責自動化,或透過使用者自定義的設定去調配工作節點上Pod的資源與優先順序等等。
‧kube-controller-manager:它的用途是監視整個叢集的狀態。
在工作節點中,包含kubelet、kube-proxy、Container Runtime Engine、Pod、Service、Ingress等基本物件,工作節點上的物件關係說明如下,關係圖則如圖2所示。
‧Kubelet:每一個工作節點上都會有一個kubelet物件,工作節點可以透過它與主節點上的kube-apiserver溝通,負責管理Pod的生命週期。
‧Kube-proxy:kube-proxy物件,它負責管理叢集中的網路服務。
‧Container Runtime Engine(容器執行環境引擎):K8s作為容器管理工具,它需要有一個容器可以執行的環境,這個環境被稱為「容器執行環境」,負責管理容器執行環境的稱之為「容器執行環境引擎」,如圖2中的數字所示。
‧Pod:這是K8s中最小的物件,一個Pod裡面可以有一個至多個的容器,圖2中標示C的方框即代表容器,且同一個Pod中的容器共享同一份儲存空間和網路,Pod內要執行的應用程式可以被定義在一個yaml檔中。
‧Service:Service物件的功能是定義Pod要如何被連線及存取,其會收到來自Ingress物件的請求並將它轉到對應的Pod,此時外部連線進來的使用者便可以使用Pod中容器運行的服務,Service物件的內容跟Pod一樣可以被定義在yaml檔中。
‧Ingress:Ingress通常與Service會是一組的,原因在於,倘若今天全部的外部連線皆仰賴Service物件,每一個從外部進來的請求都要有一個連接埠與Service上的連接埠做對應,在這個情況下,光靠Service物件的話,管理會變得困難,需要在工作節點上開啟多個連接埠。因此,可以在Service物件前面增加Ingress物件,在許多個Service物件前建立類似「反向代理伺服器」的功能,只需要在節點上保留一個連接埠,並透過主機名稱或路徑名稱決定要將請求導向哪一個Service物件,如圖2中的框選(/路徑1~3)是以路徑名稱為範例,Ingress的內容也可以被定義在一個yaml檔中。
管理容器相關工具比較
除了當紅炸子雞K8s外,其實還有其他與K8s相似功能的工具,在此整理成表1做說明。
Google開發的K8s是目前最多人使用的容器管理平台,第一個初始化版本出現在2014年,其開源的特性提供許多人使用,也有大量的K8s社群,提供K8s的使用者遇到問題時可以發問及討論的空間。
Docker Swarm是Docker原生的容器管理平台,雖說Google開發的K8s是最多數人使用的容器管理平台,但是Docker Swarm畢竟與Docker師出同門,因此在組態設定上占有優勢,相容性也較好,所以同樣受到不少使用者的支持。
OpenShift是Red Hat公司推出的雲端運算平台,也有提供管理容器的工具,它與K8s的不同點在於,K8s作為最多人使用的容器管理平台,但是當需要完善的處理網路、儲存、監控、日誌記錄等功能時,K8s往往需要再結合其他各種工具,而OpenShift作為雲端運算平台,已經將上述提到的幾項工具都整合在一起,使用者只要使用OpenShift提供的介面便可以管理容器,達到與使用K8s相同的效果且過程較為淺顯易懂。
K8s安全與相關檢測工具介紹
以下介紹三款K8s環境中常用的檢測工具,分別為Kube-Hunter、Kube-Bench及Checkov。
Kube-Hunter
Kube-Hunter(GitHub網址為https://github.com/aquasecurity/kube-hunter)是容器新創公司Aqua開源釋出的容器資安工具,它主要鎖定的目標是K8s的容器基礎架構環境,可以對K8s進行「滲透測試」,該工具也可以與網頁串接,讓用戶使用網頁與其他人分享執行滲透任務的結果,不過要特別注意的是,因Kube-Hunter會對指定的K8s叢集進行滲透測試,因此需要經過叢集管理員的同意才可進行,否則可能被視為入侵行為。
Kube-Bench
Kube-Bench(GitHub網址為https://github.com/aquasecurity/kube-bench)是由Go語言寫成,與Kube-Hunter同為容器新創公司Aqua開源釋出,主要是針對「K8s執行環境」進行檢查,這套工具是可以檢查K8s是否根據網路安全中心(Center of Internet Security,CIS)規定的CIS K8s基準。CIS K8s Benchmark主要檢測的目標種類包含主節點、主節點設定、etcd資料庫、工作節點以及K8s相關安全設定等,網址為「https://www.cisecurity.org/benchmark/kubernetes」。
Checkov
Checkov(GitHub網址為https://github.com/bridgecrewio/checkov)是由Bridgecrew公司所開發,它是一套靜態程式碼分析工具,支援透過自動掃描或是750種以上的可自定義安全政策找出K8s中常見的錯誤設定問題,其特色是掃描基礎架構即代碼(Infrastructure as Code,IaC),意思是Checkov可以針對K8s設定檔中的程式碼進行檢查,找出可能發生安全性問題的錯誤設定。
K8s的安全問題主要來自於運行叢集主機的設定是否存在不當的設定,Kube-Hunter皆可針對叢集主機進行相對應的檢查,因此接下來的操作將使用Kube-Hunter作為範例,藉此了解如何透過工具檢查自身的K8s叢集可能存在的安全問題。
安裝並操作Kube-Hunter
本次操作步驟使用VirtualBox安裝Ubuntu Linux虛擬機為範例,並以輕量化K8s叢集Minikube搭配Kube-Hunter作為檢測工具。使用Minikube之前必須安裝的工具有Docker、Kubectl、Minikube等。
安裝Docker、Kubectl以及Minikube
Docker、Kubectl、Minikube安裝方式皆可參照其官網教學,網址分別為:
https://docs.docker.com/engine/install/ubuntu/
https://K8s.io/docs/tasks/tools/install-kubectl-linux/#install-kubectl-binary-with-curl-on-linux
https://minikube.sigs.K8s.io/docs/start/
啟動Minikube叢集
首先設定Minikube啟動的驅動為none,執行指令「sudo minikube config set driver none」,如圖3所示。
接著執行「sudo minikube start --driver=none --kubernetes-version=1.23.3」指令,啟動Minikube叢集並指定K8s版本為1.23.3,如圖4所示。
再執行「sudo minikube status」指令,檢查Minikube叢集是否已成功啟動。若成功啟動叢集,則會顯示狀態為「Running」,如圖5左方框選所示。
安裝Kube-Hunter
Kube-Hunter的GitHub網址為「https://github.com/aquasecurity/kube-hunter」。Kube-Hunter是用來檢查執行中K8s是否有被安全地部署,其測試程式皆被寫成一個yaml格式的檔案,使用的方法步驟如下:
先將Kube-Hunter的程式碼從GitHub上抓取下來,請在虛擬機中執行指令「sudo git clone https://github.com/aquasecurity/kube-hunter」,如圖6所示。
取得抓取下來的專案後,執行「cd kube-hunter」指令進入該專案,如圖7所示,之後建立執行檢查的Pod,指令為「kubectl create -f job.yaml」。若成功建立,就會顯示「created」。
接著執行「sudo kubectl get pods」指令,取得Pod的ID,本例為「kube-hunter-82c1c」,如圖8所示。
然後,取得執行Pod後的Log紀錄以得到Pod中的容器執行的結果,指令格式為「kubectl logs 」,這邊的pod_id是「kube-hunter-82c1c」,因此,正確指令為「kubectl logs kube-hunter-82c1c」,如圖9所示。
最後查看執行的結果,若Kube-Hunter有發現相關的漏洞,會將結果整理成列表,如圖10所示,且可以至Aqua公司的漏洞資料庫(https://avd.aquasec.com)查詢漏洞詳細資訊。
情境模擬說明
北央公司為較早期成立的軟體公司,當時所有的系統服務皆採取傳統的方式部署,然而,隨著容器與K8s的盛行,公司資訊部門的高層決議要將既有的系統轉為容器化,並選擇時下正夯的K8s作為容器管理平台。
然而,既有的系統數量之大,並非朝夕之間可以完成,且公司內部較少人有相關背景。為此,公司找來了雲端虛擬化資安專家于冠,他不僅懂K8s,也對資安領域頗有研究。
來到北央公司,于冠決定一步一腳印,分兩階段進行。第一階段先讓部門的工程師熟悉K8s,為此,于冠請資訊部門的同仁先自行安裝Minikube叢集並在上面運行應用程式,並且要對外開放服務一個星期來模擬真正的使用情境。
阿飛是資訊部門的實習生,他接到跟大家一樣的任務,在這之後,他制定了進度,先從安裝Minikube開始,在被建立出來的叢集上建立一個Pod上面運行NGINX網頁伺服器的容器。
阿飛先安裝Minikube所需要的相關工具,之後再啟動Minikube叢集,如圖3至圖5所示的指令。接著,阿飛要在叢集上建立NGINX網頁伺服器的Pod,而如果要手動建立一個Pod,可以將Pod的內容都定義在一個yaml檔中,因此先執行指令「vim my-first-pod.yaml」建立一個空的yaml檔(圖11)。再來將圖12中的內容寫入「my-first-pod.yaml」檔中,完成後,下指令「sudo kubectl create -f my-first-pod.yaml」建立Pod(圖13),最後執行「sudo kubectl get pods」指令,檢查Pod是否成功建立(圖14)。
建立完Pod之後,還要建立Service物件,才能在本機上存取Pod上的NGINX服務,跟建立Pod一樣,先建立yaml檔,指令為「sudo vim my-first-service.yaml」,如圖15所示,並將圖16所示中的資料寫入「my-first-service.yaml」檔中。
完成後,使用「sudo kubectl create -f my-first-service.yaml」指令來建立Service(圖17),最後執行「sudo kubectl get service」指令,檢查Service是否成功建立(圖18)。
建立完Service物件後,便可以從虛擬機中直接連線到Pod上的NGINX服務,先打開FireFox瀏覽器,輸入「10.0.2.15:30390」,其中「10.0.2.15」為虛擬機IP,可以利用指令「ip addr」檢查,「30390」為在Service物件中nodePort定義的通訊埠號,如圖16中的框選所示,成功連線到NGINX的畫面如圖19所示。
很快地,時間過了一個禮拜,于冠檢查Minikube叢集時看大家都表現得不錯,都成功地將對應的服務執行在Minikube叢集上。因此,于冠決定要踏入下一個階段,而下一階段要處理的是資安,也就是說,K8s不僅僅是讓它成功執行就好,還要考慮到其安全得以穩定系統操作,而K8s本身最大的安全議題是運行叢集主機的設定是否具有不當設定。也可以使用相關的檢測工具來檢查叢集的安全,因此小飛決定使用Kube-Hunter檢測工具來檢查Minikube叢集是否符合安全狀態。
小飛使用Kube-Hunter工具對運行環境進行滲透測試,他照著圖6至圖8的指令成功啟動執行Kube-Hunter的Pod後,並以圖9中的指令取得執行的紀錄,執行結果如圖20所示。
從圖20的Kube-Hunter檢查結果中阿飛發現三個漏洞,編號分別為KHV002、KHV005及KHV050,這些漏洞為Aqua漏洞資料庫所記錄,阿飛決定到Aqua漏洞資料庫查詢這三個漏洞的嚴重程度及描述,網址為「https://avd.aquasec.com」。阿飛發現KHV002和KHV050這兩個的漏洞程度皆為Medium以下,而KHV005的漏洞程度則為High,如圖21右方框選所示,因此特別針對該漏洞去深入瞭解。經過了解,該漏洞的原因是因為Kubernetes API可以不用經過驗證被任何使用者存取,說明如圖21左上框選所示,這是非常危險的,因此Aqua提供的解決方法為應指定特定的服務帳號,也就是特定帳號才可以存取該叢集開啟的API服務,方法說明如圖21左下框選所示。
經過Kube-Hunter工具的檢查,小飛意外發現自己的Minikube叢集上竟然含有等級為High的漏洞,為此,立馬照著圖21說明將該漏洞進行修補,因及時修補得以保障資安而使得系統更具信任性。經過于冠安排的兩階段訓練,阿飛已經漸漸地越來越了解K8s在做的事情以及知道除了讓叢集上的系統服務可以執行外,也需要考量到更深入的資安危機處理,就像KVH005漏洞,其看似平凡無奇,但是當漏洞被有心人士發現,就有可能成為被入侵的進入點,進而影響到整個叢集的運作。
今天阿飛只是在自己的模擬環境中執行,且叢集上運行的服務並不多,工作節點也僅有一個,但倘若今日叢集中含有多個正式上線的服務或是多個工作節點同時在運作,當被發現有漏洞時,將可能造成嚴重的安全風險。
經過幾個月的時間,終於將公司現有的系統服務全數轉移完成,小飛在這過程當中不僅學到了完整的K8s實務訓練,也因為成就感讓他對於容器化與K8s產生興趣,並得練就武藝,在系統安全上大幅提升操作與實戰經驗。
結語
本文說明了K8s的安全機制,必須倚靠第三方檢測工具的幫助來協助使用者得知並進行修補並得鞏固強化資安機制。在模擬演練中,透過輕量化叢集Minikube在其上運行NGINX服務並透過操作Kube-Hunter檢測工具,讓大家了解其實K8s的漏洞主要源自於其運行環境的主機設定,若能在每一次使用K8s時都做好安全上的檢查,不僅K8s上的系統服務可以正常運作,也能降低K8s的安全風險,並確保K8s的維護人員或使用K8s上執行服務的使用者都能享有安全的環境,確實維護系統運作的穩定度。
<本文作者:社團法人台灣E化資安分析管理協會(ESAM, https://www.esam.io/)國立中央大學平行與分散計算實驗室(簡稱PaDiC實驗室)創立於2006年,由王尉任教授率領成員致力於雲端運算之研究,其領域包含分散式程式技術、邊緣運算、虛擬機器容錯與高可用性技術、網路應用程式和科學計算。>