containerd 是一个高级容器运行时,又名 容器管理器。简单来说,它是一个守护进程,在单个主机上管理完整的容器生命周期:创建、启动、停止容器、拉取和存储镜像、配置挂载、网络等。
containerd 旨在轻松嵌入到更大的系统中。Docker 在底层使用 containerd 来运行容器Kubernetes 可以通过 CRI 使用 containerd 来管理单个节点上的容器。
Kubernetes 从 v1.20 开始弃用 Docker,并推荐用户切换到基于容器运行时接口(CRI)的容器引擎,如 containerd、cri-o 等。
ctr 是作为 containerd 项目的一部分提供的命令行客户端。如果您在机器上运行了 containerd,则 ctr 二进制文件很可能也在那里。
如果你使用了云服务商提供的托管 Kubernetes 服务,那你不用担心,像 GKE、AKS 等云服务商都已经在新版集群中把默认的运行时切换到 containerd 。
那对于那些自管的集群,又如何把容器运行时从 Docker 切换到 Containerd 呢?
切换容器运行时的方法:
首先,标记节点为维护模式,并驱逐其上正在运行的 Pod,避免切换过程中影响应用的正常运行:
kubectl cordon <node-name>
kubectl drain <node-name> --ignore-daemonsets
然后以 root 用户登录到 Node 上面,停止 docker 和 kubelet:
因为我们安装的 Docker 默认安装使用了 containerd 作为后端的容器运行时,所以不需要单独安装 containerd 了,当然你也可以将 Docker 和 containerd 完全卸载掉,然后重新安装,这里我们选择直接使用之前安装的 containerd。
systemctl stop kubelet
systemctl disable docker.service
因为 containerd 中默认已经实现了 CRI,但是是以 plugin 的形式配置的,以前 Docker 中自带的 containerd 默认是将 CRI 这个插件禁用掉了的(使用配置 disabled_plugins = ["cri"]
),所以这里我们重新生成默认的配置文件来覆盖掉。
接下来,生成 containerd 配置文件:
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
由于国内环境无法访问 GCR,需要修改默认 pause 镜像为国内可以访问的地址,比如替换为 MCR:
...
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "mcr.microsoft.com/oss/kubernetes/pause:1.3.1"
...sandbox_image = "registry.aliyuncs.com/k8sxio/pause:3.5"
接下来,打开 /etc/default/kubelet
,修改 kubelet 启动选项,配置容器运行时为 containerd:
接下来修改 kubelet 配置,将容器运行时配置为 containerd,打开 /etc/sysconfig/kubelet
文件,在该文件中可以添加一些额外的 kubelet 启动参数,配置如下所示:
KUBELET_FLAGS=... --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock
上面的配置中我们增加了两个参数,--container-runtime
参数是用来指定使用的容器运行时的,可选值为 docker
或者 remote
,默认是 docker
,由于我们这里使用的是 containerd 这种容器运行时,所以配置为 remote
值(也就是除 docker
之外的容器运行时都应该指定为 remote
)。
然后第二个参数 --container-runtime-endpoint
是用来指定远程的运行时服务的 endpiont 地址的,在 Linux 系统中一般都是使用 unix 套接字的形式,比如这里我们就是指定连接 containerd 的套接字地址 unix:///run/containerd/containerd.sock
。
其实还应该配置一个
--image-service-endpoint
参数用来指定远程 CRI 的镜像服务地址,如果没有指定则默认使用--container-runtime-endpoint
的值了,因为 CRI 都会实现容器和镜像服务的。
配置完成后重启 containerd 和 kubelet 即可:
systemctl daemon-reload
systemctl restart containerd
systemctl restart kubelet
最后,退出 Node,使用 kubectl 命令验证节点的容器运行时:
# kubectl get node <node-name> -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
<node-name> Ready agent 13d v1.18.2 10.241.0.21 <none> Ubuntu 18.04.5 LTS 5.4.0-1039 containerd://1.4.3
可以发现,容器运行时已经切换到了 containerd,其版本为 1.4.3。最后,把节点重新加回集群中:
kubectl uncordon <node-name>
对其他的节点重复以上步骤,就可以把集群的 docker 替换成 containerd。