在前面的文章中,我们已经简要介绍了 Kubernetes 核心组件的相关内容,有兴趣的话,可以移步至如下文章:
在当前的 Kubernetes 生态体系中有多种网络解决方案以及容器运行时环境的各种选项。在本文中,笔者将试图从整个 Kubernetes 编排架构角度来阐述 Container 容器运行的基本原理,以使得大家能够更深入理解容器生态体系相关知识。
CRI 架构
CRI(Container Runtime Interface)是一个插件接口,允许 Kubelet 使用不同的容器运行时。各种容器运行时实现了 CRI API,这允许用户在他们的 Kubernetes 安装中使用他们选择的容器运行时。
我们先简要了解一下 Containerd 的 CRI 插件架构。
CRI 插件是 Kubernetes 容器运行时接口 (CRI) 的实现。Containerd 与 Kubelet 在同一节点上运行,Containerd 内部的 CRI 插件处理来自 Kubelet 的所有 CRI 服务请求,并使用 Containerd 内部结构来管理容器和容器镜像。
CRI 插件使用 Containerd 来管理整个容器生命周期和所有容器镜像。如下所示,CRI 通过 CNI(容器网络接口)管理 Pod 网络。
基于上述结构图,让我们梳理下 CRI 插件如何基于 Kubelet 创建容器并运行 Pod 过程:
1、Kubelet 通过 CRI 运行时服务 API 调用 CRI 插件来创建 Pod。
2、CRI 使用 Containerd Internal 来创建和启动一个特殊的沙箱容器,并将该容器放在 Pod 的 Cgroups 和 NameSpace 命名空间中。
3、CRI 使用 CNI 配置 Pod 的网络命名空间。
4、Kubelet 随后通过 CRI 镜像服务 API 调用 CRI 插件来拉取应用容器镜像。若镜像不存在于节点上,CRI 便进一步使用 Containerd 来拉取镜像。
5、Kubelet 然后通过 CRI 运行时服务 API 调用 CRI,使用拉取的容器镜像在 Pod 内创建和启动应用程序容器。
6、CRI 使用 Containerd Internal 创建应用容器,将其放入 Pod 的 Cgroups 和 NameSpace 中,然后启动 Pod 的新应用容器。在这些步骤之后,一个 Pod 及其相应的应用程序容器被创建并运行。
CNI 架构
作为另一个 CNCF 项目,CNI(容器网络接口)也是一个云原生计算基金会项目,由用在 Linux 容器中配置网络接口的规范和库以及许多受支持的插件组成。CNI 只关心容器的网络连接和删除容器时删除分配的资源。正因为如此,CNI 的支持范围很广,规范也很容易实现,为 Linux 容器提供基于插件的通用网络解决方案。
通常来讲,CNI 被容器运行时 CR 使用,例如 Kubernetes、Podman、CRI-O 、rkt 、Openshift、Cloud Foundry、Amazon ECS、Singularity、OpenSVC 以及 Mesos 等等。Container 或 Pod 本身最初并不具备网络接口,容器运行时使用 ADD、DEL、CHECK 等操作命令调用 CNI 插件。例如,ADD 为容器创建一个新的网络接口,并将要添加的内容的详细信息通过 JSON 有效地传递给 CNI。
那么,通常如何在 Kubernetes 中使用 CNI ?一般来讲,主要根据 CNI 配置文件以确定选用哪种 CNI 插件,具体如下所示:
1、在每个节点上配置 CNI 文件(/etc/cni/net.d/xxnet.conf),其中 xxnet.conf表示网络配置文件的名称。
2、基于 CNI 配置文件中进行二进制插件的安装部署。
3、在节点上创建 Pod 后,Kubelet 会根据 CNI 配置文件运行前两步安装的 CNI 插件。
4、基于上述进行 Pod 网络配置。
CRI 与 CNI 交互模型
每个网络提供者都有一个 CNI 插件,容器运行时会调用其来为 Pod 启动时配置网络。若基于 Containerd 作为容器运行时,Containerd CRI 插件调用 CNI 插件。每个网络提供商也有一个安装在每个 Kubernetes 节点上的代理,用于配置 Pod 网络。安装网络提供程序代理后,它要么随 CNI 配置一起提供,要么在节点上创建一个,然后 CRI 插件使用该代理来确定要调用哪个 CNI 插件。
CNI 配置文件的位置是可配置的,默认值为 /etc/cni/net.d/<config-file>。集群管理员需要在每个节点上提供 CNI 插件。CNI 插件的位置也是可配置的,默认值为 /opt/cni/bin。
如果将 Containerd 作为容器运行时,可以在 Containerd 配置的 [plugins."io.containerd.grpc.v1.cri".cni] 部分下指定 CNI 配置和 CNI 插件二进制文件的路径。我们以 Flannel 网络方案为例,Flanneld 是 Flannel 守护进程,通常作为守护进程安装在 kubernetes 集群上,使用 install-cni 作为初始化容器。install-cni 容器在每个节点上创建 CNI 配置文件 - /etc/cni/net.d/10-flannel.conflist。 Flanneld 创建一个 Vxlan 设备,从 Api Server 获取网络元数据并监视 Pod 上的更新。创建 Pod 时,它会为整个集群中的所有 Pod 分配路由,这些路由允许 Pod 通过其 IP 地址相互连接。
Containerd CRI Plugin 和 CNI Plugin 之间的交互模型,如下图所示:
基于上所述,Kubelet 调用 Containerd CRI 插件以创建 Pod,Containerd CRI 插件调用 CNI 插件为 Pod 配置网络。网络提供者 CNI 插件调用其他基础 CNI 插件来配置网络。
Pod(Container)配置网络交互
接下来,我们来看一下 Kubelet、Container Runtime 和 CNI 插件等它们是如何拼接在一起的,如何进行相互协作。当一个 Pod 被调度到一个节点上时,会触发不同的事件操作来启动一个 Pod。 在节点上调度 Pod 后,以下交互将进行网络配置并启动应用程序容器。具体如下所示:
最后,我们来看一个完整的 Container 运行示意图,具体如下所示:
以上为本文关于 Container 如何在 Kubernetes 中运行的相关原理解析,若文中相关术语及内容表达有误,欢迎大家随时沟通,交流。
- EOF -