Kubernetes中dockershim移除之后应对措施

互联网科技 时间:2022-06-02 发表评论

背景

Kubernetes在v1.20提出Dockershim Removal Kubernetes Enhancement Proposal

kep就有计划将dockershim模块从kubelet中移除,经过几个版本的迭代,在kubernetes 1.24发布的时候彻底移除掉dockershim。 dockershim 模块存在于kubernetes的kubelet中,kubelet通过dockershim来对接docker创建容器。其中的关系图一所示


其工作流为当pod调度到某个节点,该节点的kubelet list-watch到了pod,则会触发pod创建的过程,pod创建的时候会通过CRI来调用dockershim的方法,之后dockershim调用docker提供的api,完成相关容器的创建命令的下发。之后docker通过调用containerd完成最终container的创建任务。


为了更好的推动kubenretes以及CRI的发展,kubernetes提出了移除dockershim的kep。主要是基于以下几点考虑:

历史包袱:早期kubernetes版本,只支持docker engine一种特定的container runtime, docker engine本身并没有支持CRI接口规范,所以kubernetes project中包含了特定的代码来做这种转化,使得dockershim代码变成了kubernetes一部分。


CRI规范推进以及kubernetes自身的发展:随着kubernetes发展,维护dockershim模块变成了一种巨大的负担。未来随着newer CRI runtime中将会引入以及cgroups v2以及user namespaces等新特性的支持,涉及到大量dockershim的兼容工作要做,移除dockershim对于未来推动CRI发展至关重要。



解决方案


Completely remove in-tree dockershim from kubelet by dims · Pull Request #97252 · kubernetes/kubernetes (github.com) 中彻底移除了dockershim的代码,如何需要升级到>1.24v的k8s,则将不能直接将docker作为默认kubelet的engine。移除dockershim之后,我们可以采用的常见的替代方案,通过下图的对比就可以清晰的几种差异



cri-dockerd方案

cri-dockerd由mariadb开源贡献,类似与将kubelet中的dockershim模块由cri-dockerd来承担,实现了通过CRI与kubelet交互,与docker api进行交互,对于仍然想使用docker来创建容器的一个可行的替代方案。但是缺点也很明显,调用链更长,也就意味着整个创建容器的过程并不是很高效,而且故障定位更加的困难。


Containerd方案

作为一个比较推荐的方案,调用链路更加的短和高效,并且containerd也是作为docker的后端广泛的验证,可靠性有一定的保障,社区更加的活跃,对于runc和kata-container容器支持的挺好。



CRI—O方案

CRI—O是Redhat联合IBM, Intel, SUSE 以及其他厂商提出的支持CRI container runtime, openshift默认支持的CRI-0。其是另外一种高层次的container runtime,类似于containerd,同样实现container Runtime interface(CRI)。它支持从仓库拉取容器image,以及启动一个低层次的runtime来运行容器进程。





容器应用改造

采用containerd或者CRI-0方案,彻底脱离了docker,但是对于存量的容器系统应用可能依赖docker,所以社区在废除dockershim给出了很多建议让用户去判断你的容器化应用是否依赖于docker,如果依赖于docker则需要去对应用本身的改造,可以从以下几个方面判断是否依赖于docker。

kubernetes平台中的应用是否存在特权pod,该类型的pod有可能会执行docker的命令、调用docker提供的api、restart docker服务或者修改docker相关配置。

是否配置过docker的配置 /etc/docker/daemon.json,例如配置私有镜像仓库或者image mirror,需要做相应的调整

判断在kubernetes平台之外,运行在物理机上的脚本或者其他运行,是否会去执行docker命令,这些可能包括

ssh 到node上执行的运维命令

node启动脚本

监控或者安全相关的agent,平台组件容器

第三方提供的工具的操作是否涉及到上面提到的特权操作

确保整个平台没有对dockershim行为的间接依赖。例如有些工具可能被配置为对特定的docker行为做出反应,例如,对特定的指标发出警报,或搜索特定的日志消息,作为故障排除说明的一部分。如果您配置了这样的工具,那么在迁移之前在测试集群上测试其行为。

按照上述提示,去评估应用以及kubernetes平台是否依赖于docker,如果依赖则建议对其改造,支持containerd或者CRI-O。


集群升级

实际适配改造的过程中,我们会发现一些应用可能是第三方供应商提供,适配改造需要一定的时间,针对这种情况,则需要在集群中既要支持containerd/CRI-0,也要能够采用cri-docker来部署对于依赖docker的应用,则我们对于原集群进行升级的时候,可以采用如下的流程策略,这里以k8s 1.23升级到k8s 1.24来进行说明,这里的k8s集群是通过kubeadm来构建出来的




当前集群是1.23版本,采用kubelet,dockershim的方式对接docker, 由1个master和3个node组成的k8s集群,3个node分别是node1、node2、node3。

其上部署demo应用,yaml如下

apiVersion: apps/v1

kind: Deployment

metadata:

name: demo

labels:

app: nginx

spec:

replicas: 1

selector:

matchLabels:

app: nginx

template:

metadata:

labels:

app: nginx

spec:

containers:

- name: nginx

image: nginx:1.14.2



需要将该集群升级到1.24版本,采用containerd方案,对于docker依赖的应用采用cri-docker的方案


首先

Step1: 在现有集群中加入两个节点node4/node5,node4、node5采用cri-docker与kubelet对接,其上只承载对于docker有依赖的应用。node4、node5通过label组成一个特殊的资源池,并加上taint,加上taint是为了不允许非依赖的docker的应用部署。

[root@node1 archos]#  kubectl  label node node4 ake.io/container-runtime=cri-dockerd

node/node4 labeled

[root@node1 archos]# kubectl taint node  node4 ake.io/container-runtime=cri-dockerd:NoSchedule

node/node4 tainted

[root@node1 archos]#  kubectl  label node node5 ake.io/container-runtime=cri-dockerd

node/node5 labeled

[root@node1 archos]# kubectl taint node  node5 ake.io/container-runtime=cri-dockerd:NoSchedule

node/node5 tainted



Step2:将依赖docker的应用迁移到cri-dockerd的资源池中,通过在demo应用中增加node亲和性以及tolerations信息,如下所示

apiVersion: apps/v1

kind: Deployment

metadata:

name: demo

labels:

app: nginx

spec:

replicas: 1

selector:

matchLabels:

app: nginx

template:

metadata:

labels:

app: nginx

spec:

affinity:

nodeAffinity:

requiredDuringSchedulingIgnoredDuringExecution:

nodeSelectorTerms:

- matchexpressions:

- key: ake.io/container-runtime

operator: In

values:

- cri-dockerd

tolerations:

- key: "ake.io/container-runtime"

operator: "Equal"

value: "cri-dockerd"

effect: "NoSchedule"

containers:

- name: nginx

image: nginx:1.14.2


下面采用驱逐的方式对k8s集群从1.23版本升级到1.24版本

Step3:首先升级master节点,升级过程中完成cri的切换,使用containerd方案


Step4: 升级原资源池中的node,升级过程中完成对于cri的切换,  升级node过程中首先分批次驱逐node上所有的pod,完成pod驱逐之后,则升级其上的组件,升级到k8s 1.24版本


Step5: 升级cri-docker资源池,升级node过程中首先分批次驱逐node上所有的pod,完成pod驱逐之后,则升级其上的组件,升级到k8s 1.24版本。


至此整个k8s集群已经升级到1.24版本,集群默认采用containerd,对于依赖于docker的容器化应用,通过调度规则调度到cri-dockerd的资源池。

总结

dockershim的移除在k8s 1.24是一个重大的调整,本文详细介绍了当前可选的解决方案以及社区相关的建议,便于更好的应对这个变化。相信dockershim从kubernetes主干代码的移除,能够更加激发CRI领域的创新,并且kubenretes的整体架构以及代码变得更加的优雅。


 
反对 0举报 0 收藏 0 打赏 0评论 0
 
网站首页 关于我们 联系方式 使用协议 网站留言RSS订阅违规举报 友情链接