Kubernetes弃用Docker,别慌!这里有一套实战方法告诉你~
导读
Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。Kubernetes 拥有一个庞大且快速增长的生态系统,其服务、支持和工具的使用范围广泛。
作者简介
1、前言
前段时间,Kubernetes 推出了 1.24 版本,曾经轰动一时的 Docker 弃用也正式实装了,这意味着 1.24 版本之后,Docker 将不能作为 k8s 的容器运行时。
Docker 作为云原生的基础技术底座,如果 Kubernetes 不再支持 Docker,这在互联网 IT 业界都会引发不大不小的恐慌,这到底该怎么办?是不是 Docker 完全不能使用了?
2、技术的真相
其实 Kubernetes 只是弃用了 dockershim,并不是弃用了 Docker 的全部。Docker 体系中的 containerd 是符合 CRI 标准的,可以继续作为 Kubernetes 的容器运行时。而 OCI标准的实现者 runC 也是 Docker 体系的。
另一方面,Docker 构建的镜像符合 OCI 标准,可以运行在 Kubernetes 集群中,所以仍然可以在本地使用 Docker 进行开发和测试。
2.1 OCI 和 CRI 标准分别是什么?
OCI(Open Container Initiative)是一组围绕容器技术的开放标准和规范,主要定义了容器的生命周期管理规范。
OCI 的实现者通常被称为“低级容器运行时”,例如 runC。低级运行时的主要功能是按照给定的容器文件系统和 JSON 配置文件,创建容器,并管理容器的生命周期。
CRI(Container Runtime Interface)是一组插件接口,定义了 Kubernetes(kubelet)与容器运行时的接口规范,实现两者之间的解耦。
通过 CRI 与 Kubernetes 交互的运行时通常被称为“容器运行时”。运行时的功能是为容器准备必要的运行环境,比如拉取镜像、解压镜像并创建容器文件系统、创建容器网络等,然后调用低级容器运行时,创建和运行容器。
2.2 Kubernetes支持哪些容器运行时?
Kubernetes 支持任何符合 CRI 标准的容器运行时。在 1.23 版本之前,常用的容器运行时有三种:docker、containerd、cri-o。
Docker
Docker 守护进程是不符合 CRI 标准的。为了支持 Docker 作为容器运行时,kubelet 内置了一个 dockershim 模块,kubelet 通过 CRI 调用 dockershim,再由它转换请求,调用 Docker 守护进程,而 1.24 版本将要移除的就是这个模块。此模式下创建容器时的调用过程如下:
Kubelet 通过 CRI 调用 dockershim
dockershim 转换请求,调用 docker 守护进程
docker 调用 containerd
containerd 创建 containerd-shim 进程,再由 containerd-shim 调用 runC 完成容器创建。终容器由 containerd-shim 管理,容器内所有进程都是 containerd-shim 的子进程。
containerd
containerd 是从 docker 守护进程中独立出来的容器运行时,终也要通过 runC 运行容器。
在 CRI 标准被提出后,为了兼容 CRI,减少调用开销,containerd 开发了一个守护进程,叫 CRI-containerd。原先调用链 kubelet -> dockershim -> dockerd -> containerd 被简化成为 kubelet -> CRI-containerd -> containerd。后来,containerd 干脆将 CRI-containerd 以 CRI 插件形式内建在项目中,直接通过方法调用,进一步将调用链简化为 kubelet -> containerd。
cri-o
CRI 标准被提出后,红帽按照 CRI 开发的一个轻量级容器运行时,是 CRI 标准的小实现。此模式下kubelet直接调用 cri-o,再由 cri-o 调用 runC 完成容器创建和管理,调用链比较简洁。
广东公司网络管理中心网管系统室负责建设和维护O域容器云,近期刚好启动Kubernetes 版本升级工作,借此机会,我们决定在测试环境上将容器运行时从 docker迁移至 cri-o,并验证下 Kubernetes 1.23 -> 1.24 版本升级方案,以下是迁移的部分注意事项及详细步骤。
3、迁移注意事项和详细步骤
❖注意事项:
1、对于使用 docker in docker 的 pod,如果是挂载宿主机的 docker.sock 守护进程,迁移后将不能运行,如果是在容器中安装独立的 docker 守护进程,迁移后仍然可以正常运行。
2、/etc/docker/daemon.json 中的配置需要同步到新的运行时,比如仓库的镜像站点。
3、检查各种运维脚本,如果包含 docker 命令需要修改。
4、容器 stdout/stderr 日志形式变更,如果使用 Fluentd 或者 Filebeat 收集日志,需要修改配置。
①日志目录:使用 docker 时,日志通过 /var/log/containers 链接到 /var/log/pods/ 目录,后链接到 /var/lib/docker/containers/xxx/ 目录,如果使用其他运行时,一般是通过 /var/log/containers 链接到 /var/log/pods/ 目录,由 kubelet 管理。
②日志格式:使用 docker 时,很多人习惯设置 json 格式,而切换到其他运行时,默认格式是 text,格式为 “time stream log-info”。日志解析配置需要修改。
③日志回滚:使用 docker 时,在 daemon.json 配置,切换运行时后,通过 kubelet 的配置项 containerLogMaxSize、containerLogMaxFiles 设置。
5、其他注意点参考官网FAQ文档:
https://kubernetes.io/zh/blog/2022/02/17/dockershim-faq/
怎么将 Kubernetes 的容器运行时从 docker 迁移至 cri-o?
操作系统:centOS 7.9
内核版本:5.4.178
kubernetes版本:1.23.3
cri-o:1.22.3
1、迁移按节点进行,先驱逐 pod 并隔离节点
kubectl drain --delete-emptydir-data --force --ignore-daemonsets <NODE_NAME>
2、卸载 docker
systemctl stop kubelet
systemctl stop docker
systemctl disable docker
yum remove -y docker-ce
# docker数据目录先保留一段时间,运行没异常再删除
rm -rf /var/lib/docker
3、内核设置
这些设置一般在k8s安装前都会设置,这里再确认一次,已经设置好的忽略这一步。
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sysctl --system
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
4、安装 cri-o
# 设置yum源
export OS=CentOS_7
export VERSION=1.22
curl -L -o
/etc/yum.repos.d/devel:kubic:libcontainers:stable.repo https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/devel:kubic:libcontainers:stable.repo
curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo
# 安装cri-o
yum install -y cri-o
5、修改 cri-o 配置
# 查看conmon路径
which conmon
# 修改cri-o配置文件
vi /etc/crio/crio.conf
# 修改crio.runtime表,加上conmon路径配置
[crio.runtime]
conmon = "/usr/bin/conmon"
# 修改crio.image表,加上pause镜像设置。xxx需要换成你的私有镜像库
[crio.image]
insecure_registries = ["xxx"]
pause_image = "xxx/k8s/pause:3.6"
# 修改registry配置
vi /etc/containers/registries.conf
# 添加私有镜像库,xxx需要替换成你的私有镜像库,这里设置了insecure,可按实现情况修改
# 因为我用的是私有仓库,不需要设置镜像站点
[[registry]]
prefix = "xxx"
insecure = true
blocked = false
location = "xxx"
6、启动 cri-o 服务
systemctl enable crio
systemctl start crio
systemctl status crio
7、修改 kubelet 配置
设置 kubelet 命令行启动参数,指定使用 cri-o 运行时。
vi /etc/sysconfig/kubelet
# 修改内容,加上以下两个参数
KUBELET_EXTRA_ARGS=--container-runtime=remote --container-runtime-endpoint='unix:///var/run/crio/crio.sock'
修改 /var/lib/kubelet/kubeadm-flags.env 文件,文件中如果有以下3个参数,请删除。
-- cgroup-driver k8s 建议在配置文件设置,不要在命令行。
-- cni-plugin 1.24 版本后会和 docker-shim 一起被移除。
-- pod-infra-container-image 当使用 cri-o 运行时,kubelet 忽略这个参数,需要在 cri-o 配置中指定。
修改 kubelet 的配置文件 /var/lib/kubelet/config.yaml,修改以下4个参数,如果参数不存在则添加上去。
设置 kubelet 的 cgroup 驱动为 systemd,因为 cri-o 默认驱动是 systemd,必须保持一致。旧版本 kubelet 默认驱动是 cgroupfs,1.22以上才是默认systemd。
cgroupDriver: systemd
设置运行时请求超时:
runtimeRequestTimeout: 5m
容器 stdout/stderr 日志文件的回滚设置,按实际需求修改。
containerLogMaxSize: 100Mi
containerLogMaxFiles: 3
修改了 /var/lib/kubelet/config.yaml 文件后,建议同步修改内容到 kubelet-config-1.xx configmap,1.xx 是 kubernetes 的版本。因为集群扩容时,新节点使用这个 configmap 生成配置文件,这样可以保证新旧节点配置文件一致。
kubectl edit cm -n kube-system kubelet-config-1.23
8、启动 kubelet,查看 kubelet 状态、节点状态、pod 状态是否正常
systemctl start kubelet
systemctl status kubelet
9、更新 kubeadm 使用的 cri 运行时
# 查看当前节点的kubeadm使用的cri运行时
kubectl get node <NODE_NAME> -o jsonpath='{.metadata.annotations.kubeadm\.alpha\.kubernetes\.io/cri-socket}'
# 将dokcershim修改为cri-o
kubectl annotate node <NODE_NAME> --overwrite kubeadm.alpha.kubernetes.io/cri-socket=/var/run/crio/crio.sock
10、安装 podman
podman 是一个开源的容器管理工具,命令几乎与 Docker 一致,可以用于替换 docker。相较于 Docker,它不存在守护进程,因此 podman 避免了 docker daemon 引入的问题。另一方面,cri-o 专注于 CRI 实现,没有提供 build、tag 镜像等功能,而 podman 和 cri-o 的镜像是共享的,可以为 cri-o 补充镜像管理功能。
yum install -y podman
podman info
11、重启服务器
Docker 卸载后可能还有一些配置遗留,例如 iptables 规则,建议重启服务器,防止被影响。
12、将节点重新加入集群调度
kubectl uncordon <NODE_NAME>
到这里,个节点的容器运行时迁移就完成了,可以按照相同的方法再迁移其他节点。
迁移完成后就能愉快地把 K8s 版本升到 1.24.0 了。
4 后记
虽然 k8s 已经正式移除了 dockershim,但是 docker+kubernetes 的方案经过多年发展已经成熟,被广泛地应用,短期内地位仍然不可撼动。开发、测试环境可以按照需求折腾,迁移容器运行时,积累实践经验。生产环境的话建议保持稳定,等时机成熟再迁移。
来源:本文转自公众号移动Labs,作者刘启伟
相关文章