一文搞懂Kubernetes容器運(yùn)行原理
1.Kubernetes容器概述
容器能夠有效地虛擬化主機(jī)操作系統(tǒng)(或內(nèi)核)并將應(yīng)用程序的依賴項(xiàng)與同一臺(tái)機(jī)器上運(yùn)行的其他容器隔離開。在容器出現(xiàn)之前,在同一個(gè)虛擬機(jī) (VM) 上部署了多個(gè)應(yīng)用程序,共享依賴項(xiàng)的任何更改都可能導(dǎo)致奇怪的事情發(fā)生,從而導(dǎo)致排障較為困難。
容器主要通過兩個(gè)部分解決這個(gè)問題:容器引擎和容器鏡像,容器鏡像是應(yīng)用程序及其依賴項(xiàng)的包。容器引擎在容器中運(yùn)行應(yīng)用程序,將其與主機(jī)上運(yùn)行的其他應(yīng)用程序隔離開來。這樣就無需為每個(gè)應(yīng)用程序運(yùn)行單獨(dú)的操作系統(tǒng),從而提高資源利用率并降低成本。
當(dāng)我們開始學(xué)習(xí) Kubernetes 時(shí),我們并不完全清楚每個(gè) Pod 是如何分配 IP 地址以及微服務(wù)容器化后是如何正常工作?;蛟S,我們可能或多或少了解各個(gè)組件的概念以及它們是如何獨(dú)立工作。但是,在特定的環(huán)境下可能不清楚這些組件是如何關(guān)聯(lián)起來。例如,我們知道什么是 CNI 插件,然而,卻不理解 Kubernetes 所涉獵的組件之間是如何相互調(diào)用。因此,基于對(duì)各種核心組件的了解,以及它們?nèi)绾卧?Kubernetes 集群中拼接在一起,以便使得每個(gè) Container 能夠基于其所設(shè)定的環(huán)境變量正確運(yùn)行,在實(shí)際的業(yè)務(wù)環(huán)境中進(jìn)行有效維護(hù)便顯得尤為重要。
在當(dāng)前的 Kubernetes 生態(tài)體系中有多種網(wǎng)絡(luò)解決方案以及容器運(yùn)行時(shí)環(huán)境的各種選項(xiàng)。在本文中,筆者將試圖從整個(gè) Kubernetes 編排架構(gòu)角度來闡述 Container 容器運(yùn)行的基本原理,以使得大家能夠更深入理解容器生態(tài)體系相關(guān)知識(shí)。
2.CRI(容器運(yùn)行時(shí)接口) 架構(gòu)
CRI(Container Runtime Interface)是一個(gè)插件接口,允許 Kubelet 使用不同的容器運(yùn)行時(shí)。各種容器運(yùn)行時(shí)實(shí)現(xiàn)了 CRI API,這允許用戶在他們的 Kubernetes 安裝中使用他們選擇的容器運(yùn)行時(shí)。
我們先簡要了解一下 Containerd 的 CRI 插件架構(gòu)。
CRI 插件是 Kubernetes 容器運(yùn)行時(shí)接口 (CRI) 的實(shí)現(xiàn)。Containerd 與 Kubelet 在同一節(jié)點(diǎn)上運(yùn)行,Containerd 內(nèi)部的 CRI 插件處理來自 Kubelet 的所有 CRI 服務(wù)請(qǐng)求,并使用 Containerd 內(nèi)部結(jié)構(gòu)來管理容器和容器鏡像。
CRI 插件使用 Containerd 來管理整個(gè)容器生命周期和所有容器鏡像。如下所示,CRI 通過 CNI(容器網(wǎng)絡(luò)接口)管理 Pod 網(wǎng)絡(luò)。
基于上述結(jié)構(gòu)圖,讓我們梳理下 CRI 插件如何基于 Kubelet 創(chuàng)建容器并運(yùn)行 Pod 過程:
1、Kubelet 通過 CRI 運(yùn)行時(shí)服務(wù) API 調(diào)用 CRI 插件來創(chuàng)建 Pod。
2、CRI 使用 Containerd Internal 來創(chuàng)建和啟動(dòng)一個(gè)特殊的沙箱容器,并將該容器放在 Pod 的 Cgroups 和 NameSpace 命名空間中。
3、CRI 使用 CNI 配置 Pod 的網(wǎng)絡(luò)命名空間。
4、Kubelet 隨后通過 CRI 鏡像服務(wù) API 調(diào)用 CRI 插件來拉取應(yīng)用容器鏡像。若鏡像不存在于節(jié)點(diǎn)上,CRI 便進(jìn)一步使用 Containerd 來拉取鏡像。
5、Kubelet 然后通過 CRI 運(yùn)行時(shí)服務(wù) API 調(diào)用 CRI,使用拉取的容器鏡像在 Pod 內(nèi)創(chuàng)建和啟動(dòng)應(yīng)用程序容器。
6、CRI 使用 Containerd Internal 創(chuàng)建應(yīng)用容器,將其放入 Pod 的 Cgroups 和 NameSpace 中,然后啟動(dòng) Pod 的新應(yīng)用容器。在這些步驟之后,一個(gè) Pod 及其相應(yīng)的應(yīng)用程序容器被創(chuàng)建并運(yùn)行。
3.CNI(容器網(wǎng)絡(luò)接口)架構(gòu)
作為另一個(gè) CNCF 項(xiàng)目,CNI(容器網(wǎng)絡(luò)接口)也是一個(gè)云原生計(jì)算基金會(huì)項(xiàng)目,由用在 Linux 容器中配置網(wǎng)絡(luò)接口的規(guī)范和庫以及許多受支持的插件組成。CNI 只關(guān)心容器的網(wǎng)絡(luò)連接和刪除容器時(shí)刪除分配的資源。正因?yàn)槿绱?,CNI 的支持范圍很廣,規(guī)范也很容易實(shí)現(xiàn),為 Linux 容器提供基于插件的通用網(wǎng)絡(luò)解決方案。
通常來講,CNI 被容器運(yùn)行時(shí) CR 使用,例如 Kubernetes、Podman、CRI-O 、rkt 、Openshift、Cloud Foundry、Amazon ECS、Singularity、OpenSVC 以及 Mesos 等等。Container 或 Pod 本身最初并不具備網(wǎng)絡(luò)接口,容器運(yùn)行時(shí)使用 ADD、DEL、CHECK 等操作命令調(diào)用 CNI 插件。例如,ADD 為容器創(chuàng)建一個(gè)新的網(wǎng)絡(luò)接口,并將要添加的內(nèi)容的詳細(xì)信息通過 JSON 有效地傳遞給 CNI。
那么,通常如何在 Kubernetes 中使用 CNI ?一般來講,主要根據(jù) CNI 配置文件以確定選用哪種 CNI 插件,具體如下所示:
1、在每個(gè)節(jié)點(diǎn)上配置 CNI 文件(/etc/cni/net.d/xxnet.conf),其中 xxnet.conf表示網(wǎng)絡(luò)配置文件的名稱。
2、基于 CNI 配置文件中進(jìn)行二進(jìn)制插件的安裝部署。
3、在節(jié)點(diǎn)上創(chuàng)建 Pod 后,Kubelet 會(huì)根據(jù) CNI 配置文件運(yùn)行前兩步安裝的 CNI 插件。
4、基于上述進(jìn)行 Pod 網(wǎng)絡(luò)配置。
4.CRI 與 CNI 交互模型
每個(gè)網(wǎng)絡(luò)提供者都有一個(gè) CNI 插件,容器運(yùn)行時(shí)會(huì)調(diào)用其來為 Pod 啟動(dòng)時(shí)配置網(wǎng)絡(luò)。若基于 Containerd 作為容器運(yùn)行時(shí),Containerd CRI 插件調(diào)用 CNI 插件。每個(gè)網(wǎng)絡(luò)提供商也有一個(gè)安裝在每個(gè) Kubernetes 節(jié)點(diǎn)上的代理,用于配置 Pod 網(wǎng)絡(luò)。安裝網(wǎng)絡(luò)提供程序代理后,它要么隨 CNI 配置一起提供,要么在節(jié)點(diǎn)上創(chuàng)建一個(gè),然后 CRI 插件使用該代理來確定要調(diào)用哪個(gè) CNI 插件。
CNI 配置文件的位置是可配置的,默認(rèn)值為 /etc/cni/net.d/<config-file>。集群管理員需要在每個(gè)節(jié)點(diǎn)上提供 CNI 插件。CNI 插件的位置也是可配置的,默認(rèn)值為 /opt/cni/bin。
如果將 Containerd 作為容器運(yùn)行時(shí),可以在 Containerd 配置的 [plugins."io.containerd.grpc.v1.cri".cni] 部分下指定 CNI 配置和 CNI 插件二進(jìn)制文件的路徑。我們以 Flannel 網(wǎng)絡(luò)方案為例,F(xiàn)lanneld 是 Flannel 守護(hù)進(jìn)程,通常作為守護(hù)進(jìn)程安裝在 kubernetes 集群上,使用 install-cni 作為初始化容器。install-cni 容器在每個(gè)節(jié)點(diǎn)上創(chuàng)建 CNI 配置文件 - /etc/cni/net.d/10-flannel.conflist。 Flanneld 創(chuàng)建一個(gè) Vxlan 設(shè)備,從 Api Server 獲取網(wǎng)絡(luò)元數(shù)據(jù)并監(jiān)視 Pod 上的更新。創(chuàng)建 Pod 時(shí),它會(huì)為整個(gè)集群中的所有 Pod 分配路由,這些路由允許 Pod 通過其 IP 地址相互連接。
Containerd CRI Plugin 和 CNI Plugin 之間的交互模型,如下圖所示:
基于上所述,Kubelet 調(diào)用 Containerd CRI 插件以創(chuàng)建 Pod,Containerd CRI 插件調(diào)用 CNI 插件為 Pod 配置網(wǎng)絡(luò)。網(wǎng)絡(luò)提供者 CNI 插件調(diào)用其他基礎(chǔ) CNI 插件來配置網(wǎng)絡(luò)。
5.容器運(yùn)行流程圖
接下來,我們來看一下 Kubelet、Container Runtime 和 CNI 插件等它們是如何拼接在一起的,如何進(jìn)行相互協(xié)作。當(dāng)一個(gè) Pod 被調(diào)度到一個(gè)節(jié)點(diǎn)上時(shí),會(huì)觸發(fā)不同的事件操作來啟動(dòng)一個(gè) Pod。 在節(jié)點(diǎn)上調(diào)度 Pod 后,以下交互將進(jìn)行網(wǎng)絡(luò)配置并啟動(dòng)應(yīng)用程序容器。具體如下所示:
最后,我們來看一個(gè)完整的 Container 運(yùn)行示意圖,具體如下所示:
以上為本文關(guān)于 Container 如何在 Kubernetes 中運(yùn)行的相關(guān)原理解析