目录
前言
在 v1.24 版本之前的 k8s 直接集成了 Docker Engine
组件,但从 v1.24 版本起,Kubernetes
项目正式移除了 Dockershim
,也就是说 K8s 不再唯一支持以 Docker 作为 K8s 容器运行时。尽管移除了 Dockershim,但这并不代表 Docker 不可用,我们依然可通过容器运行时接口(CRI)
来将 Docker 作为 K8s 的容器运行时。
容器运行时部署于 K8s 集群的 work 节点上,以使得 Pod 可以正常运行。
常见容器运行时:
- Containerd
- CRI-O
- Docker Engine
- Mirantis Container Runtime
一、CGroup
1.1 基本概念
CGroup
相信大家并不陌生,只要接触过 Docker 容器技术的应该都用过。CGroup 是 Linux 的一个底层技术,用于限制分配给系统进程的资源。
在我前面的 K8s 集群部署文档中,我们知道 kubelet
和底层容器运行时需要对控制组实现 Pod 和容器资源管理和限制(如 CPU、内存等资源设置请求和限制)。因此,想要对接 K8s 控制组,关键点就在于 kubelet 和容器运行时需要使用同一个 cgroup
驱动。
CGroup 驱动有一下两种:
- cgroupfs
- systemd
1.2 cgroupfs 驱动
1.2.1 基本概念
cgroupfs 驱动
是 kubelet 中默认的 cgroup 驱动,当使用 cgroupfs
驱动时, kubelet 和容器运行时将直接对接 cgroup 文件系统来配置 cgroup。
当你的系统是以 systemd 作为初始化时,不推荐使用 cgroupfs
驱动,因为 systemd 期望系统上只有一个 cgroup 管理器。 此外,如果你的系统使用的 cgroup v2
版本,则应用 systemd
cgroup 驱动取代 cgroupfs
。
1.2.2 什么是 cgroup v2
Linux 中有两个 cgroup 版本:cgroup v1 和 cgroup v2。cgroup v2 是新一代的 cgroup
API,cgroup v2 提供了一个具有增强资源管理能力的统一控制系统。一些 Kubernetes 特性专门使用 cgroup v2 来增强资源管理和隔离,因此,推荐使用 systemd 来作为 cgroup 驱动,从而可提升更好的资源管理效果。
如何查看 Linux 节点上的 cgroup 版本?
stat -fc %T /sys/fs/cgroup/
# 对于 cgroup v2,输出为 cgroup2fs
# 对于 cgroup v1,输出为 tmpfs
下图的 cgroup 版本为 v1
1.2.3 cgroup v2 使用要求
- 操作系统发行版启用 cgroup v2
- Linux 内核为 5.8 或更高版本
- 容器运行时支持 cgroup v2
- kubelet 和容器运行时被配置为使用 systemd cgroup 驱动
1.3 systemd cgroup 驱动
1.3.1 基本概念
当某个 Linux 系统发行版使用 systemd 作为其初始化系统时,初始化进程会生成并使用一个 root 控制组(cgroup
),并充当 cgroup 管理器。
systemd 与 cgroup 集成紧密,并将为每个 systemd 单元分配一个 cgroup。 因此,如果你 systemd
用作初始化系统,同时使用 cgroupfs
驱动,则系统中会存在两个不同的 cgroup 管理器。
同时存在两个 cgroup 管理器将造成系统中针对可用的资源和使用中的资源出现两个视图。某些情况下, 将 kubelet 和容器运行时配置为使用 cgroupfs
、但为剩余的进程使用 systemd
的那些节点将在资源压力增大时变得不稳定。
当 systemd 是选定的初始化系统时,缓解这个不稳定问题的方法是针对 kubelet 和容器运行时将 systemd
用作 cgroup 驱动。
1.3.2 kubelet 设置 cgroup 驱动
如:将
systemd
设置为 cgroup 驱动编辑
KubeletConfiguration
的cgroupDriver
选项,并将其设置为systemd
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
...
cgroupDriver: systemd
下图为我博客截图:
注意:更改已加入集群的节点的 cgroup 驱动是一项敏感的操作。 如果 kubelet 已经使用某 cgroup 驱动的语义创建了 Pod,此时更改运行时以使用别的 cgroup 驱动,当为现有的 Pod 重新创建 PodSandbox 时会产生错误,该错误重启 kubelet 也可能无法解决此类问题,只能重新部署 K8s 集群,因此对于一个正在正常运行的 K8s 集群,我们就最好不要动其 cgroup 驱动了。
二、CRI
这里我以 Kubernetes 1.24 举例,因为我部署的就是该版本的 k8s 集群。
各位小伙伴也可以尝试以二进制方式部署一下 K8s 集群,会有很大收获。
什么是 CRI?其实 CRI 就是我们的容器运行时接口,可以通过 CRI 来实现 K8s 来集成不同的容器组件。
首先,对于 Kubernetes 1.24 集群,你的容器运行时必须至少支持 v1alpha2
版本的容器运行时接口。因为 Kubernetes 1.24 默认使用 v1 版本的 CRI API。如果容器运行时不支持 v1 版本的 API, 则 kubelet 会回退到使用(已弃用的)v1alpha2
版本的 API。
2.1 Containerd
2.1.1 基本概念
什么是 Containerd ?这里不过多解释,简单的说:Containerd 不需要经过 dockershim,是一个工业级标准的容器运行时,它强调简单性、健壮性和可移植性。在 Linux 上,containerd 的默认 CRI 套接字是 /run/containerd/containerd.sock
。
2.1.2 配置 CGroup 驱动
以 systemd 驱动为例
1、安装 Containerd
2、生成配置文件
mkdir -p /etc/containerd && containerd config default > /etc/containerd/config.toml
3、修改配置文件
vim /etc/containerd/config.toml
...
SystemdCgroup = true
# 将 SystemdCgroup = false 改为 SystemdCgroup = true
...
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.7"
# 将 sandbox_image = "k8s.gcr.io/pause:3.6" 改为:sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.7"
4、启动 Containerd
systemctl enable containerd && systemctl start containerd
2.2 CRI-O
2.2.1 基本概念
对 CRI-O 没有过多的研究,CRI-O 是一个由 redhat 发起并开源且由社区驱动的 container-runtime,专为 K8s 而生。这里就不过多介绍,感兴趣的化可以深入研究。
CRI-O 默认使用 systemd cgroup 驱动程序,可编辑 /etc/crio/crio.conf
或在 /etc/crio/crio.conf.d/02-cgroup-manager.conf
中放置一个插入式配置,具体操作如下。
2.2.2 配置 CGroup 驱动
[crio.runtime]
conmon_cgroup = "pod"
cgroup_manager = "cgroupfs"
...
[crio.image]
pause_image="registry.aliyuncs.com/google_containers/pause:3.7"
...
# 将 pause_image="registry.k8s.io/pause:3.6" 改为 pause_image="registry.aliyuncs.com/google_containers/pause:3.7"
当使用 CRI-O 时,并且 CRI-O 的 cgroup 设置为 cgroupfs
时,必须将 conmon_cgroup
设置为值 pod
。
2.3 Docker Engine
2.3.1 基本概念
Docker 就不用多说,各位想必再熟悉不过了。想要使用 docker 作为 k8s 的编排对象,那需要安装 cri-docker 来作为 dockershim。对于 cri-dockerd
,默认情况下,CRI 套接字是 /run/cri-dockerd.sock
。
cri-docker 源码安装地址:https://github.com/Mirantis/cri-dockerd
2.3.2 配置 CGroup 驱动
修改 CGroup 为 systemd
修改沙箱镜像为国内源
...
[Service]
Type=notify
ExecStart=/usr/local/bin/cri-dockerd --container-runtime-endpoint fd:// --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.7
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
...
# 在 ExecStart= 部分添加即可
修改完成后重启 Docker 即可
systemctl restart docker.service
2.4 Mirantis
Mirantis Container Runtime (MCR)
是一种商用容器运行时,以前称为 Docker 企业版,可以使用 MCR 中包含的开源 cri-dockerd
组件将 Mirantis Container Runtime 与 Kubernetes 一起使用。
更多 Mirantis 相关知识,可阅读其官方文档。
看了这么多容器运行时,没有谁好谁坏,适合自己公司业务的就是最好的