新聞中心
Kubernetes 已經(jīng)成為容器編排調(diào)度領(lǐng)域的事實標準,其優(yōu)良的架構(gòu)不僅保證了豐富的容器編排調(diào)度功能,同時也提供了各個層次的擴展接口以滿足用戶的定制化需求。其中,容器運行時作為 Kubernetes 管理和運行容器的關(guān)鍵組件,當然也提供了簡便易用的擴展接口,也就是 CRI(Container Runtime Interface)。

成都創(chuàng)新互聯(lián)服務(wù)項目包括南川網(wǎng)站建設(shè)、南川網(wǎng)站制作、南川網(wǎng)頁制作以及南川網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,南川網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到南川省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
本文將介紹 CRI 的由來、演進以及未來展望,主要內(nèi)容分為四個部分:Kubernetes架構(gòu)簡介、容器運行時接口的基本原理、容器運行時的演進以及未來的展望。
Kubernetes 簡介
我們知道,Kubernetes是一個開源的容器集群管理系統(tǒng),它的發(fā)展非常迅速,已經(jīng)成為***和最活躍的容器編排系統(tǒng)。
從架構(gòu)上來說,Kubernetes 的組件可以分為 Master 和 Node 兩部分,其中 Master 是整個集群的大腦,所有的編排、調(diào)度、API 訪問等都由 Master 來負責。
具體的來說,Master 包括以下幾個組件:
- etcd 保存了整個集群的狀態(tài)。
- kube-apiserver 提供了資源操作的唯一入口,并提供認證、授權(quán)、訪問控制、API 注冊和發(fā)現(xiàn)等機制。
- kube-controller-manager 負責維護集群的狀態(tài),包括很多資源的控制器,是保證 Kubernetes 聲明式 API 工作的大腦。
- kube-scheduler 負責資源的調(diào)度,按照預定的調(diào)度策略將 Pod 調(diào)度到相應的 Node 上;
而 Node 則是負責運行具體的容器,并為容器提供存儲、網(wǎng)絡(luò)等必要的功能:
- kubelet 負責維持容器的生命周期,同時也負責 Volume(CSI)和網(wǎng)絡(luò)(CNI)的管理;
- Container runtime 負責鏡像管理以及 Pod 和容器的真正運行。Kubelet 默認的容器運行時為 Docker;
- kube-proxy 負責為 Service 提供 cluster 內(nèi)部的服務(wù)發(fā)現(xiàn)和負載均衡
- Network plugin 也就基于 CNI(Container Network Internface)負責為容器配置網(wǎng)絡(luò)。
除了這些核心的組件以外,Kubernetes 當然還包含了很多豐富的功能,這些都是通過擴展(Addon)的方式來部署的。比如 kube-dns 和 metrics-server 等,都是以容器的方式部署在集群里面,并提供 API 給其他組件調(diào)用。
提示:在 Kubernetes 中,通常你可以聽到兩種不同類型的擴展 Kubernetes 功能的方式:1) ***種是擴展(Addon),比如 dashboard、EFK、Prometheus、各種 Operator 等,這些擴展不需要 Kubernetes 提供標準的接口,但是都為 Kubernetes 增加了新的功能特性;2) 還有一種方式則是插件(Plugin),比如 CNI、CRI、CSI、Device Plugin 等,這些都是 Kubernetes 各個核心組件提供了標準的內(nèi)置接口,而外部插件則是實現(xiàn)這些接口,從而將 Kubernetes 擴展到更多的用例場景中。
Kubelet 架構(gòu)
剛才提到,Kubelet 負責維持容器的生命周期。除此之外,它也配合 kube-controller-manager 管理容器的存儲卷,并配合 CNI 管理容器的網(wǎng)絡(luò)。下面就是 Kubelet 的簡單架構(gòu)示意圖:
你可以發(fā)現(xiàn),Kubelet 也是有很多組件構(gòu)成,包括
- Kubelet Server 對外提供 API,供 kube-apiserver、metrics-server 等服務(wù)調(diào)用。比如 kubectl exec 需要通過 Kubelet API /exec/{token} 與容器進行交互。
- Container Manager 管理容器的各種資源,比如 cgroups、QoS、cpuset、device 等。
- Volume Manager 管理容器的存儲卷,比如格式化磁盤、掛載到 Node 本地、***再將掛載路徑傳給容器。
- Eviction 負責容器的驅(qū)逐,比如在資源不足時驅(qū)逐優(yōu)先級低的容器,保證高優(yōu)先級容器的運行。
- cAdvisor 負責為容器提供 metrics 數(shù)據(jù)源。
- Metrics 和 stats 提供容器和節(jié)點的度量數(shù)據(jù),比如 metrics-server 通過 /stats/summary 提取的度量數(shù)據(jù)是 HPA 自動擴展的依據(jù)。
- 再向下就是 Generic Runtime Manager,這是容器運行時的管理者,負責跟 CRI 交互,完成容器和鏡像的管理。
- 在 CRI 之下,包括兩種容器運行時的實現(xiàn)
- 一個是內(nèi)置的 dockershim,實現(xiàn)了 docker 容器引擎的支持以及 CNI 網(wǎng)絡(luò)插件(包括 kubenet)的支持
- 另一個就是外部的容器運行時,用來支持 runc、containerd、gvisor 等外部容器運行時。
Kubelet 通過 CRI 接口跟外部容器運行時交互,而上圖右側(cè)就是 CRI 容器運行時的架構(gòu)。它通常包括以下幾個組件:
- CRI Server,這是 CRI gRPC server,監(jiān)聽在 unix socket 上面。在討論容器運行時的時候,這個 Server 也通常成為 CRI shim(夾在容器引擎和Kubelet之間的一層)。
- Streaming Server,提供 streaming API,用在 Exec、Attach、Port Forward 等流式接口上。
- 容器和鏡像的管理,比如拉取鏡像、創(chuàng)建和啟動容器等。
- CNI 網(wǎng)絡(luò)插件的支持,用于給容器配置網(wǎng)絡(luò)。
- ***是容器引擎(Container Engine)的管理,比如支持 runc 、containerd 或者支持多個容器引擎。
這樣,Kubernetes 中的容器運行時按照不同的功能就可以分為三個部分:
- ***個是 Kubelet 中容器運行時的管理模塊 Generic Runtime Manager,它通過 CRI 來管理容器和鏡像。
- 第二個是容器運行時接口,是 Kubelet 與外部容器運行時的通信接口。
- 第三個是具體的容器運行時實現(xiàn),包括 Kubelet 內(nèi)置的 dockershim 以及外部的容器運行時(如 cri-o、cri-containerd 等)。
容器運行時接口(CRI)
容器運行時接口(CRI),顧名思義,用來在 Kubernetes 擴展容器運行時,從而用戶可以選擇自己喜歡的容器引擎。
CRI 是基于 gPRC 的,用戶不需要關(guān)心內(nèi)部通信邏輯,而只需要實現(xiàn)定義的接口就可以,包括 RuntimeService 和 ImageService: RuntimeService負責管理Pod和容器的生命周期,而ImageService負責鏡像的生命周期管理。
除了 gRPC API,CRI 還包括用于實現(xiàn) streaming server 的庫(用于 Exec、Attach、PortForward 等接口)和 CRI Tools。這兩個稍后再作詳細介紹。
基于 CRI 接口的容器運行時通常稱為 CRI shim, 這是一個 gRPC Server,監(jiān)聽在本地的unix socket上;而kubelet作為gRPC的客戶端來調(diào)用CRI接口。
另外,外部容器運行時需要自己負責管理容器的網(wǎng)絡(luò),推薦使用CNI,這樣跟Kubernetes的網(wǎng)絡(luò)模型保持一致。
CRI 的推出為容器社區(qū)帶來了新的繁榮,cri-o、frakti、cri-containerd 等一些列的容器運行時為不同場景而生:
- cri-containerd——基于 containerd 的容器運行時
- cri-o——基于 OCI 的容器運行時
- frakti——基于虛擬化的容器運行時
而基于這些容器運行時,還可以輕易聯(lián)結(jié)新型的容器引擎,比如可以通過 clear container、gVisor 等新的容器引擎配合 cri-o 或 cri-containerd 等輕易接入 Kubernetes,將 Kubernetes 的應用場景擴展到了傳統(tǒng) IaaS 才能實現(xiàn)的強隔離和多租戶場景。
當使用CRI運行時,需要配置kubelet的--container-runtime參數(shù)為remote,并設(shè)置--container-runtime-endpoint為監(jiān)聽的unix socket位置(Windows上面為 tcp 或 npipe)。
CRI 接口
那么,CRI 接口到底長的什么樣呢?
CRI 接口包括 RuntimeService 和 ImageService 兩個服務(wù),這兩個服務(wù)可以在一個 gRPC server 里面實現(xiàn),當然也可以分開成兩個獨立服務(wù)。目前社區(qū)的很多運行時都是將其在一個 gRPC server 里面實現(xiàn)。
管理鏡像的 ImageService 提供了 5 個接口,分別是查詢鏡像列表、拉取鏡像到本地、查詢鏡像狀態(tài)、刪除本地鏡像以及查詢鏡像占用空間等。這些都很容易映射到 docker API 或者 CLI 上面。
而 RuntimeService 則提供了更多的接口,按照功能可以劃分為四組:
- PodSandbox 的管理接口:PodSandbox 是對 Kubernete Pod 的抽象,用來給容器提供一個隔離的環(huán)境(比如掛載到相同的 cgroup 下面),并提供網(wǎng)絡(luò)等共享的命名空間。PodSandbox 通常對應到一個 Pause 容器或者一臺虛擬機。
- Container 的管理接口:在指定的 PodSandbox 中創(chuàng)建、啟動、停止和刪除容器。
- Streaming API 接口:包括 Exec、Attach 和 PortForward 等三個和容器進行數(shù)據(jù)交互的接口,這三個接口返回的是運行時 Streaming Server 的 URL,而不是直接跟容器交互。
- 狀態(tài)接口,包括查詢 API 版本和查詢運行時狀態(tài)。
Streaming API
Streaming API 用于客戶端與容器需要交互的場景,所以采用的是流式接口,包括 Exec、PortForward 和 Attach 等。Kubelet 內(nèi)置的 docker 通過 nsenter、socat 等方法來支持這些特性,但它們不一定適用于其他的運行時。因而,CRI 也顯式定義了這些 API,并且要求容器運行時返回一個 streaming server 的 URL 以便 Kubelet 重定向 API Server 發(fā)送過來的流式請求。
這樣一個完整的 Exec 流程就是
- 客戶端 kubectl exec -i -t ...
- kube-apiserver 向 Kubelet 發(fā)送流式請求 /exec/
- Kubelet 通過 CRI 接口向 CRI Shim 請求 Exec 的 URL
- CRI Shim 向 Kubelet 返回 Exec URL
- Kubelet 向 kube-apiserver 返回重定向的響應
- kube-apiserver 重定向流式請求到 Exec URL,接著就是 CRI Shim 內(nèi)部的 Streaming Server 跟 kube-apiserver 進行數(shù)據(jù)交互,完成 Exec 的請求和響應
在 v1.10 及更早版本中,容器運行時必需返回一個 API Server 可直接訪問的 URL(通常跟 Kubelet 使用相同的監(jiān)聽地址);而從 v1.11 開始,Kubelet 新增了 --redirect-container-streaming(默認為 false),默認不再轉(zhuǎn)發(fā)而是代理 Streaming 請求,這樣運行時可以返回一個 localhost 的 URL。通過 Kubelet 代理的好處是由 Kubelet 處理與 API server 通信之間的請求認證。
實際上,各個運行時 streaming server 的處理框架都是類似的,因而 Kubelet 也提供來一個 steaming server 庫,方便容器運行時的開發(fā)者引用。
容器運行時演進過程
了解了容器運行時接口的基本原理之后,接下來,我們再來看一下容器運行時的演進過程。
容器運行時的演進可以分為三個階段:
首先,在 Kubernetes v1.5 之前,Kubelet 內(nèi)置了 Docker 和 rkt 的支持,并且通過 CNI 網(wǎng)絡(luò)插件給它們配置容器網(wǎng)絡(luò)。這個階段的用戶如果需要自定義運行時的功能是比較痛苦的,需要修改 Kubelet 的代碼,并且很有可能這些修改無法推到上游社區(qū)。這樣,還需要維護一個自己的 fork 倉庫,維護和升級都非常麻煩。
不同用戶實現(xiàn)的容器運行時各有所長,許多用戶都希望Kubernetes支持自定義的運行時。于是,從v1.5 開始增加了 CRI 接口,通過容器運行時的抽象層消除了這些障礙,使得無需修改 Kubelet 就可以支持運行多種容器運行時。CRI 接口包括了一組 Protocol Buffer、gRPC API 、用于 streaming 接口的庫以及用于調(diào)試和驗證的一系列工具等。在此階段,內(nèi)置的 Docker 實現(xiàn)也逐步遷移到了 CRI 的接口之下。但此時 rkt 還未完全遷移,這是因為 rkt 遷移 CRI 的過程將在獨立的 repository 完成,方便其維護和管理。
第三階段,從 v1.11 開始,Kubelet 內(nèi)置的 rkt 代碼刪除,CNI 的實現(xiàn)遷移到 dockershim 之內(nèi)。這樣,除了 docker 之外,其他的容器運行時都通過 CRI 接入。外部的容器運行時除了實現(xiàn) CRI 接口外,也要負責為容器配置網(wǎng)絡(luò)。一般推薦使用 CNI,因為這樣可以支持社區(qū)內(nèi)的眾多網(wǎng)絡(luò)插件,不過這不是必需的,網(wǎng)絡(luò)插件只需要滿足 Kubernetes 網(wǎng)絡(luò)的基本假設(shè)即可,即 IP-per-Pod、所有 Pod 和 Node 都可以直接通過 IP 相互訪問。
CRI 容器運行時
CRI 的推出為容器社區(qū)帶來了新的繁榮,適用于各種不同場景的運行時也應運而生。比如:
這里也注意區(qū)分 CRI 容器運行時與容器引擎的區(qū)別:
- CRI 容器運行時是指實現(xiàn)了 Kubelet CRI 接口的運行時,這樣就可以無縫集成到 Kubernetes 之中。
- 容器引擎只是負責管理容器鏡像和容器運行的一個服務(wù),它也有一個標準是 OCI(Open Container Initiative)。
比如 CNCF 的 Container Runtime Landscape 中包括了一些列的“Container Runtime”,這其中有一些是實現(xiàn)了 CRI 的,比如 cri-o;而更多的則只是一個容器引擎,需要通過 cri-o、cri-containerd 等才可以應用到 Kubernetes 之中。
CRI Tools
CRI Tools 對 Kubernetes 容器運行時和容器應用的排錯來說是一個非常有用的工具。它是一個 SIG Node 所屬的子項目,可以應用到所有實現(xiàn)了 CRI 接口的容器運行時中。CRI Tools 包括兩個組件,crictl 用于排錯和調(diào)試,而 critest 用于容器運行時實現(xiàn)進行一致性驗證。
crictl
先來看 crictl。crictl 提供了一個類似了 docker 命令的命令行工具。在排錯或者調(diào)試容器應用時,有時候系統(tǒng)管理員需要登錄到節(jié)點上去查看容器或鏡像的狀態(tài),以便收集系統(tǒng)和容器應用的信息。這時候,推薦使用 crictl 來完成這些工作,因為 crictl 為所有不同的容器引擎都提供了一個一致的使用體驗。
從使用上來說,crictl 的使用非常類似于 docker 命令行工具,比如你可以使用 crictl pods 來查詢 PodSandbox 的列表、使用 crictl ps 來查詢?nèi)萜鞯牧斜?、使?crictl images 查詢鏡像列表。
需要注意的是,crictl 的設(shè)計目標是排錯,而并非 docker 或者 kubectl 等的替代品。比如,由于 CRI 并沒有定義鏡像構(gòu)建的接口,crictl 并不提供 docker build 這種構(gòu)建鏡像的功能。但由于 crictl 提供了一個面向 Kubernetes 的接口,相對于 docker 來說,crictl 可以提供一個對容器和 Pod 更清晰的視圖。
critest
critest 是一個容器運行時的一致性驗證工具,用于驗證容器運行時是否符合 Kubelet CRI 的要求。它是 CRI TOOLS 工具的一部分。除了驗證測試,critest 還提供了 CRI 接口的性能測試,比如 critest -benchmark。
推薦將 critest 集成到 CRI 容器運行時的 Devops 流程中,保證每個變更都不會破壞 CRI 的基本功能。
另外,還可以選擇將 critest 與 Kubernetes Node E2E 的測試結(jié)果提交到 Sig-node 的 TestGrid,向社區(qū)和用戶展示。
未來展望
Docker 運行時拆分
目前 Docker 是內(nèi)置在 Kubelet 中的一個運行時,也是默認的容器運行時。這樣,實際上 Kubelet 就會依賴于 Docker,從而為 Kubelet 本身帶來一定的維護負擔。
比如,Kubelet 內(nèi)部有些功能可能只是適用于 Docker 運行時。當 Docker 或者 Docker 依賴的其他組件(比如 containerd、runc)發(fā)現(xiàn)嚴重缺陷時,修復這些缺陷就需要重現(xiàn)編譯和發(fā)布 Kubelet。
此外,當用戶想要在 Docker 運行時中新增功能時,這些新增的功能可能并不容易引入到 Kubelet 中,特別是三個月的發(fā)布周期中,新的特性通常不會引入到現(xiàn)有的穩(wěn)定分支中。從 Docker 運行時的角度來說,新特性的引入通常也會比較緩慢。
所以,拆分 Docker 容器引擎,將其獨立出去成為一個 cri-docker 就可以解決上述的所有問題。
由于 Docker 作為默認的容器引擎,在生產(chǎn)環(huán)境中已經(jīng)得到廣泛應用,拆分和遷移會應用絕大部分用戶,因為具體的遷移方法還需要社區(qū)的詳細討論。
強隔離容器引擎
雖然 Kubernetes 提供了基本的多租戶功能,可以不同應用放到不同 namespace 中進行隔離,也可以使用 RBAC 控制不同用戶對各類資源的訪問,但由于 Docker 共享內(nèi)核的特性,在 Kubernetes 中運行不可信應用時還是有很大的安全隱患。為了消除這個問題,強隔離容器引擎應運而生。
最早的強隔離容器引擎就是 Kata containers 的前身 hyperd 和 clear container,它將 Kubernetes Pod 作為一個虛擬機來運行,這樣就可以通過虛擬化的方式對容器應用進行強隔離。虛擬化是整個云計算中 IaaS 的基礎(chǔ),它的安全性已經(jīng)得到了廣泛驗證,因而其安全性也就得到了保證。這兩個項目目前已經(jīng)合并成為 Kata containers。
除了 Kata containers 之外,Google 和 AWS 也在推進強隔離的容器引擎,也就是 gVisor 和 Firecraker。
跟 Kata containers 不同,gVisor 并不會去創(chuàng)建一個完整的 VM,而是實現(xiàn)了一個自己的沙箱(文檔成為用戶態(tài)內(nèi)核),攔截和過濾容器的 syscall,從而達到安全隔離的目的。雖然 gVisor 相對于 VM 來說更輕量化,但攔截過濾也會帶來很高的成本,對最終容器應用的性能會造成一定損失。
同樣的,F(xiàn)irecraker 基于 KVM 實現(xiàn)了一個輕量級的 VM,稱為 microVM。跟 Kata 不同的是,它沒有使用 QEMU,而是用 Rust 構(gòu)建了一套精簡的設(shè)備模型,從而讓每個 microVM 只占用大約 5MB 的內(nèi)存。
多容器運行時
有了強隔離的容器引擎后,不可避免的就出現(xiàn)了一些新的問題。比如,很多 Kubernetes 自身的服務(wù)或者擴展由于需要 HostNetwork 或特權(quán)模式,無法運行在強隔離的環(huán)境中。所以,多容器運行時也就應運而生了。
這樣,就可以使用 runc/docker 等運行特權(quán)應用,而使用強隔離容器引擎運行普通應用。比如,典型的組合為:
- runc + kata
- runc + gVisor
- Windows server containers + Hyper-V containers
以前,很多容器運行時都是在 CRI Shim 中支持多個容器引擎,并通過 Annotations 的形式選擇。而借助于新的 RuntimeClass 資源,就可以直接通過 Pod Spec 來選擇不同的 runtime。
- apiVersion: node.k8s.io/v1beta1
- kind: RuntimeClass
- metadata:
- name: myclas
- # RuntimeClass is non-namespaced
- handler: myconfiguration
- ---
- apiVersion: v1
- kind: Pod
- metadata:
- name: mypod
- spec:
- runtimeClassName: myclass
- # ...
RuntimeClass 本身還處在比較早期的階段,未來還會繼續(xù)在調(diào)度等方面進一步增強。
網(wǎng)頁名稱:解析Kubernetes容器運行時
本文地址:http://www.5511xx.com/article/cosejdo.html


咨詢
建站咨詢
