Kubernetes 弃用 Docker 后如何切换到 Containerd
共 6392字,需浏览 13分钟
·
2021-05-28 12:35
Kubernetes 从 v1.20 开始弃用 Docker[1],并推荐用户切换到基于容器运行时接口(CRI)[2]的容器引擎,如 containerd、cri-o 等。如果你使用了云服务商提供的托管 Kubernetes 服务,那你不用担心,像 GKE、AKS 等云服务商都已经在新版集群中把默认的运行时切换到 containerd 。
那对于那些自管的集群,又如何把容器运行时从 Docker 切换到 Containerd 呢?
切换容器运行时的方法
首先,标记节点为维护模式,并驱逐其上正在运行的 Pod,避免切换过程中影响应用的正常运行:
kubectl cordon <node-name>
kubectl drain <node-name> --ignore-daemonsets
然后以 root 用户登录到 Node 上面,停止 docker 和 kubelet,并删除 docker:
systemctl stop kubelet
systemctl stop docker
apt purge docker-ce docker-ce-cli
接下来,生成 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"
...
接下来,打开 /etc/default/kubelet
,修改 kubelet 启动选项,配置容器运行时为 containerd:
KUBELET_FLAGS=... --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock
修改完成后, 重启 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。
镜像构建的方法
除了以上的步骤,切换到 containerd 之后,还需要注意 docker.sock 不再可用,也就意味着不能再在容器里面执行 docker 命令来构建镜像了。这里,我推荐几种不需要 docker.sock 也可以构建镜像的方法。
第一个是 Docker Buildx[3],这也是 Kubernetes 社区用于构建多体系结构镜像的方法。比如,你可以执行下面的命令来构建镜像:
docker buildx create --driver kubernetes --driver-opt replicas=3 --use
docker buildx build -t example.com/foo --push .
第二个是 Redhat 开源的 Buildah[4]。Buildah 是 Openshift 默认的镜像构建工具,同时支持 OCI 和 Docker 镜像格式。Buildah 的使用方法类似于 docker build,如:
# 构建镜像
buildah bud -t example.com/foo:latest .
# 查询镜像列表
buildah images
第三个是 Google 开源的 kaniko[5]。Kaniko 不需要 docker daemon 就可以从 Dockerfile 构建镜像。在使用 Kaniko 时要注意,它在构建镜像时需要把构建上下文(context)传入到 kaniko 命令行中,构建上下文可以放到标准输入中,也可以放到 AWS S3、Azure Blob Storage、GCS Bucket 等云存储中。
如下是一个 Kaniko 的使用示例:
echo -e 'FROM alpine \nRUN echo "created from standard input"' > Dockerfile | tar -cf - Dockerfile | gzip -9 | kubectl run kaniko \
--rm --stdin=true \
--image=gcr.io/kaniko-project/executor:latest --restart=Never \
--overrides='{
"apiVersion": "v1",
"spec": {
"containers": [
{
"name": "kaniko",
"image": "gcr.io/kaniko-project/executor:latest",
"stdin": true,
"stdinOnce": true,
"args": [
"--dockerfile=Dockerfile",
"--context=tar://stdin",
"--destination=gcr.io/my-repo/my-image"
],
"volumeMounts": [
{
"name": "cabundle",
"mountPath": "/kaniko/ssl/certs/"
},
{
"name": "docker-config",
"mountPath": "/kaniko/.docker/"
}
]
}
],
"volumes": [
{
"name": "cabundle",
"configMap": {
"name": "cabundle"
}
},
{
"name": "docker-config",
"configMap": {
"name": "docker-config"
}
}
]
}
}'
总结
Docker 弃用后,可以把 Kubernetes 容器运行时切换到社区维护并支持 CRI 的容器引擎,如 containerd、cri-o 等。切换之后,也需要注意,原来使用 docker build 构建镜像的应用需要切换到无需 Dockerd 就可以构建镜像的工具,如 docker buildx、buildah、kaniko 等。
参考资料
Kubernetes 弃用 Docker: https://kubernetes.io/blog/2020/12/02/dont-panic-kubernetes-and-docker/
[2]容器运行时接口(CRI): https://kubernetes.io/blog/2016/12/container-runtime-interface-cri-in-kubernetes/
[3]Docker Buildx: https://docs.docker.com/buildx/working-with-buildx/
[4]Buildah: https://github.com/containers/buildah
[5]kaniko: https://github.com/GoogleContainerTools/kaniko