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