转载自:https://www.51cto.com/article/710688.html

前段时间,kubernetes推出了1.24版本,曾经轰动一时的docker弃用也正式实装了,这意味着1.24版本之后,docker将不能作为k8s的容器运行时。docker作为云原生的基础技术底座,如果kubernetes不再支持docker,这在互联网IT业界都会引发不大不小的恐慌,这到底该怎么办?

作者 | 刘启伟,广东公司网络管理中心网管系统室平台团队核心专家。近年来,网管系统室一方面大力推进OSS应用建设,为“三零三自”的自智网络赋能;另一方面,积极推动微服务、容器化、PaaS、DevOps等云原生技术的实践落地。在团队中负责DevOps平台和容器云的建设运营工作,拥有丰富的Kubernetes、Istio、DevOps工具链落地实践经验,致力于克服技术落地难题,用云原生技术赋能应用。

导读

​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完成容器创建和管理,调用链比较简洁。

将容器运行时从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设置。

怎么将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运行时在node annotations中定义,需要单独修改,否则下次使用kubeadm时会出错,比如升级k8s版本的时候。

# 查看当前节点的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的方案经过多年发展已经成熟,被广泛地应用,短期内地位仍然不可撼动。开发、测试环境可以按照需求折腾,迁移容器运行时,积累实践经验。生产环境的话建议保持稳定,等时机成熟再迁移。

kubernetes弃用dockershim的更多相关文章

  1. Kubernetes弃用Docker后怎么办?

    本文转自Rancher Labs 近期,Kubernetes在其最新的Changelog中宣布,自Kubernetes 1.20之后将弃用Docker作为容器运行时.这一消息在云原生领域激起了不小的水 ...

  2. 系列好文 | Kubernetes 弃用 Docker,我们该何去何从?

    作者 | 张攀(豫哲) 来源 | 尔达 Erda 公众号 导读:Erda 作为一站式云原生 PaaS 平台,现已面向广大开发者完成 70w+ 核心代码全部开源!**在 Erda 开源的同时,我们计划编 ...

  3. 实操|如何将 Containerd 用作 Kubernetes runtime

    日前专为开发者提供技术分享的又拍云 OpenTalk 公开课邀请了网易有道资深运维开发工程师张晋涛,直播分享<Containerd 上手实践 >,详细介绍 Containerd 的发展历程 ...

  4. kind:Kubernetes in Docker,单机测试 Kubernetes 群集的最佳方案

    请访问原文发布链接:https://sysin.org/article/kind/,查看最新版. 作者:gc(at)sysin.org,主页:www.sysin.org 2021.04.28 更新,k ...

  5. runc hang 导致 Kubernetes 节点 NotReady

    Kubernetes 1.19.3 OS: CentOS 7.9.2009 Kernel: 5.4.94-1.el7.elrepo.x86_64 Docker: 20.10.6 先说结论,runc v ...

  6. 将 Docker Engine 节点从 dockershim 迁移到 cri-dockerd

    官网地址:https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-doc ...

  7. K8s 终将废弃 docker,TKE 早已支持 containerd

    近日 K8s 官方称最早将在 1.23版本弃用 docker 作为容器运行时,并在博客中强调可以使用如 containerd 等 CRI 运行时来代替 docker.本文会做详细解读,并介绍 dock ...

  8. 基于containerd二进制部署k8s-v1.23.3

    文章目录 前言 k8s 组件 环境准备 创建目录 关闭防火墙 关闭selinux 关闭swap 开启内核模块 分发到所有节点 启用systemd自动加载模块服务 配置系统参数 分发到所有节点 加载系统 ...

  9. 如何使用 Kind 快速创建 K8s 集群?

    作者|段超 来源|尔达 Erda 公众号 ​ 导读:Erda 作为一站式云原生 PaaS 平台,现已面向广大开发者完成 70w+ 核心代码全部开源!在 Erda 开源的同时,我们计划编写<基于 ...

  10. 无需依赖Docker环境制作镜像

    随着高版本的Kubernetes弃用Docker,企业也可以不依赖Docker环境了,但是DevOps通过Kubernetes部署的话,仍然需要制作镜像,那么在没有Docker环境的情况下如何制作呢? ...

随机推荐

  1. FAS2720 配置

    FAS 2720配置操作 第1章 初始化 1.1设备物理安装 1.1.1组件介绍 机头FAS 2720 (2U)   前面板 后面 1.1.2准备工作 (1)工具准备 螺丝刀.网线.Console线. ...

  2. Tesseract图片文字识别

    如何进行图文识别? 百度api收费的,自己训练模型集费时费力,有没有训练好的库,我们拿过来直接用的呢? 有,那就是tesseract. 安装 pipenv install pytesseract pi ...

  3. SX【2020.01.09】NOIP提高组模拟赛(day1)

    [2020.01.09]NOIP提高组模拟赛(day1) 这次考得不理想,只做了前两题,后两题没时间做,说明做题速度偏慢. source : 100 + 20 + 0 + 0 = 120 rank7 ...

  4. Yapi安装配置(CentOs)

    环境要求 nodejs(7.6+) mongodb(2.6+) git 准备工作 清除yum命令缓存 sudo yum clean all 卸载低版本nodejs yum remove nodejs ...

  5. LeetCode-1994 好子集的数目

    来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/the-number-of-good-subsets 题目描述 给你一个整数数组 nums .如果 ...

  6. 四种语言刷算法之 组合总和 II

    力扣40. 组合总和 II 1.C void back(int* candidates, int candidatesSize, int target,int start,int *path,int ...

  7. Android studio学习笔记3

    Android studio学习笔记3 RelativeLayout常见属性 相对于父元素给控件布局 android:layout_centerHrizontal 若为ture水平居中 android ...

  8. FPGA MIG调试bug(二)

    目标器件:复旦微FPGA:JFM7K325T8FCBGA676(对标Xilinx Kintex-7系的XC7K325T) 工程背景:送入FPGA的外部时钟为差分时钟,时钟送入FPGA后,经过PLL输出 ...

  9. LinkedList的线程安全解决办法

    方法一:List<String> list = Collections.synchronizedList(new LinkedList<String>()); 方法二:将Lin ...

  10. [后端-python实战总结]-chapter1-python基础01

    1.1 week 1 > 密码秘文: import getpass username = input('username:') passwd = getpass.getpass('passwd: ...