官方说明:

kubernetes/CHANGELOG-1.20.md at master · kubernetes/kubernetes · GitHub

  • Docker support in the kubelet is now deprecated and will be removed in a future release. The kubelet uses a module called "dockershim" which implements CRI support for Docker and it has seen maintenance issues in the Kubernetes community. We encourage you to evaluate moving to a container runtime that is a full-fledged implementation of CRI (v1alpha1 or v1 compliant) as they become available.

翻译版:

kubelet中的Docker支持现在已弃用,并将在未来的版本中删除。kubelet使用了一个名为“dockershim”的模块,它实现了对Docker的CRI支持,但Kubernetes社区中出现了维护问题。当容器运行时可用时,我们鼓励您考虑迁移到一个完全实现CRI (v1alpha1或v1兼容)的容器运行时。

首先我们先了解一下docker

Docker overview | Docker Documentation

简单来讲,docker是基于内核的namespace做资源隔离,通过controlgroup做了资源控制,最终实现了隔离进程的虚拟环境。

不同的内核的namespace它们的网络是独立管理的包括它们的些用户包括存储都是独立管理的不同的内核的namespace它们的网络是独立管理的。

由于在宿主机中像cpu内存些资源总量是不变的,那你分配给namespace多少就是靠的cgroup。

整个docker是一个CS架构

C:docker client(docker cli)

docker客户端(docker)是用户与docker交互的主要方式。例如使用docker run,客户端会将这些命令发送到dockerd,从而执行它们。

S:docker daemon(dockerd)

docker守护进程(dockerd),监听docker API请求并管理docker对象,例如镜像,容器,网络和存储卷。守护进程还可以与其他守护进程通信以管理docker服务。

container runtime

容器运行时,分为高层容器运行时和低层容器运行时。

高层容器运行时主要工作是拉取解压镜像。

低层运行时应满足OCI运行时规范。

OCI运行时规范定义了容器配置,运行时和生命周期标准。其主要负责读取配置信息和启动容器的进程。

OCI运行时规范制定了运行时和生命周期管理规范,生命周期定义了容器创建,删除和启动三个过程,同事需额外支持两个命令分别为state和kill命令。

runC

runC是OCI运行时的规范的规范实现,即为规范的底层运行时。通过runC可以对容器生命周期进行管理。但是特别注意的是,runC并不支持镜像管理功能。

containerd

containerd是高层运行时,主要负责拉取和解压镜像,但是上传和制作镜像并不是contained负责的,这个是dockerd来负责的。

docker整个流程图如下:

接下来就进入到k8s的概念中了

首先我们了解一个重要的组件,kubelet

kubelet是k8s部署在每个节点上的代理,用于处理master下发的任务,管理pod以及定期向kuber-apiserver汇报所在节点的pod信息,并通过cadvisor监控容器和节点资源。

我们知道pod里面跑了一堆容器,我们的kubelet管理pod,其实就是管理pod中的容器服务,这个也就是k8s管理容器服务的实质。那么接下来的重点就是kubelet是怎么跟container容器进行交互的呢?

根据官方说明,kubernetes从1.5版本开始引入CRI规范。

由于kubelet的任务是管理其所在节点的工作负载,需要有镜像管理和运行容器的能力,因此只有高层运行时才适合接入CRI。

CRI与容器运行时之间需要一个接口层,称之为shim,即shim为CRI接口的实现,shim分为RuntimeService和ImageService。

RuntimeService负责pod和容器生命周期管理。

lmageService负责仓库拉取查看移除镜像。

Docker运行时的CRI被称为dockershim于1.6被内置为kubelet默认启动。

kubelet本身不能直接访问到dockerd(即docker服务端),在k8s1.5版本中引入了CRI规范,1.6版本中默认启动了一个CRI的实现,即dockershim。此时kubelet可以通过dockershim访问dockerd。那么为啥要抽离dockershim,官方的说法是维护 dockershim 已经成为 Kubernetes 维护者肩头一个沉重的负担。

k8s 1.20版本之后的就把dockershim这个实现从kubelet中抽离出来了,shim实现CRI接口规范,通过gRPC的client去调用gRPC的server,这个gRPC其实就是RuntimeService和lmageService的实现。

在CNCF官网中,已经毕业的容器运行时项目有containerd。

dockerd本身是一个单体引擎,后拆分为三个部分,分别为:

runC,containerd与dockerd

runC为低层运行时捐献给了OCI

containerd为高层运行时捐献给了CNCF

dockerd作为docker公司维护的运行时

在最新版本的containerd,已经继承shim模块,并改名叫做CRI plugin,1.1版本之后的containerd集成了CRI plugin。下面是网上的一张经典kubelet从docker到containerd转变流程图。

对docker进行过移植的同学可能发现在docker-ce18.06版本之前,containerd是作为插件集成在docker源码里面的,但是到了18.09版本,被抽离出来了,单独成为一个组件,叫做containerd.io。

那么containerd能干什么呢,为什么它比docker更加轻量化?

  • 管理容器的生命周期(从创建容器到销毁容器)
  • 拉取/推送容器镜像
  • 存储管理(管理镜像及容器数据的存储)
  • 调用 runC 运行容器(与 runC 等容器运行时交互)
  • 管理容器网络接口及网络

官方文档更加详细的介绍

弃用 Dockershim 的常见问题 | Kubernetes

Logo

开源、云原生的融合云平台

更多推荐