从Docker和Kubernetes看Containerd

news2024/12/24 8:42:49

导读:

在学习Containerd之前,我们需要去了解Docker与Kubernetes这两个使用Containerd最多的技术,也需要明白什么是容器,什么是容器运行时,以及里面涉及的组件,这些组件是用来干什么的,及容器领域的概念,如libcontainer、runc、OCI、CRI、shim等。

什么是容器?

在 Linux 内核中,容器不是一类对象。容器本质上由几个底层的内核原语组成:namespace(允许你跟谁交谈),cgroup(允许使用的资源量),和 LSM(Linux 安全模块 —— 允许你做的事情)。这些凑在一起能够为我们的进程设置安全、隔离和可计量的执行环境。

每次创建隔离进程时,都不需要手动隔离、自定义命名空间等,把这些组件捆绑在一起,我们称之为容器。但是每次手动执行所有的操作将很麻烦,因此出现了容器运行时工具,它能将这些部分组合成一个隔离的、安全的执行环境变得很容易,让我们能以重复的方式部署。

什么是容器运行时?

容器运行时是掌控容器运行的整个生命周期,以docker为例,其主要提供功能如下:

  • 制定容器镜像格式

  • 构建容器镜像

  • 管理容器镜像

  • 管理容器实例

  • 运行容器

  • 实现容器镜像共享

这些功能均可由小的组件单独实现,因此容器运行时是运行和管理容器运行所需要的组件。

随着容器运行时的发展,Docker公司与CoreOS和Google共同创建了OCI(开放容器标准),并提供了两种规范:

  • 运行时规范:该规范目标是定义容器的配置、执行环境和生命周期

  • 镜像规范:该规范的目标创建可互操作的工具,用于构建、传输和准备要运行的容器镜像

在runc作为了OCI的一种实现参考之后,各种运行时工具和库也慢慢出现。而根据这些运行时的功能不同,比如有的只运行容器(runc,lxc),有的还可以对镜像进行管理(Containerd,cri-o),因此通俗的分为高级运行时(high-level)和低级运行时(low-level)。

低级运行时:侧重于运行容器,为容器设置namespace和cgroup

  • lxc

  • rkt

  • runc

  • kata

  • gVisor

高级运行时:包含更多上层功能,如为开发人员提供API,镜像存储管理等

  • Containerd

  • cri-o

  • docker

Docker

Docker是第一个流行的容器技术,最初Docker使用的是LXC(0.7版本之前)但是隔离的层次不完善,后来Docker开发了libcontainer(0.7~1.10版本),最后演变为runc和Containerd(Docker被逼无奈将libcontainer捐献出来改名为runc)。

从1.11版本之后,Docker容器运行开始通过集成Containerd和runc等多个组件完成。现在的架构中,Containerd负责容器的生命周期管理,提供了在一个节点上执行容器和管理镜像的最小功能集,并向上为Docker Daemon提供grpc接口。

当请求创建一个容器时,Docker Daemon并不会直接去创建,而且请求containerd创建容器,containerd在收到请求后,也不会去直接操作容器,而是创建containerd-shim的进程去操作容器(因为需要一个父进程去做状态收集、维持stdin、stdout、stderr打开等工作,如果父进程是contaienrd,当containerd挂掉时,整个宿主机的容器都会退出),而containerd-shim会去调用runc来启动容器,runc在启动完容器后会直接退出,此时containerd-shim成为容器的父进程,负责收集容器进程的状态上报给containerd,并在容器中 pid 为 1 的进程退出后接管容器中的子进程进行清,确保不会出现僵尸进程。

runc创建容器则是根据上述的OCI去做操作,例如namespaces、cgroups的配置,以及挂载root文件系统等操作。

Docker 将容器操作都迁移到 containerd 中去是因为当时做 Swarm,想要进军 PaaS 市场,做了这个架构切分,让 Docker Daemon 专门去负责上层的封装编排,当然后面的结果我们知道 Swarm 在 Kubernetes 面前是惨败,然后 Docker 公司就把 containerd 项目捐献给了 CNCF 基金会,这个也是现在的 Docker 架构。

Kubernetes

2014年Kubernetes诞生,由于当时Docker很流行,因此很自然的选择了Docker,在CRI出现之前,Kubelet通过内嵌的dockershim操作Docker API来操作容器,进而达到一个面向终态的效果。

而随着Docker将Containerd开源出以及更多的容器运行时出来,Kubernetes为了精简和支持更多的容器运行时,Google和Redhat推出了CRI标准,用于Kubernetes平台和容器运行时解耦CRI(容器运行时接口)。

CRI本质上是Kubernetes定义的一组与容器运行时进行交互的接口,因此容器运行时只要实现了CRI,就可以对接到Kubernetes平台中。但是当时Kubernetes的地位不高,所以一些容器运行时不会去实现CRI接口,于是就出现了shim,shim的职责是作为适配器将各种容器运行时本身的接口适配到 Kubernetes 的 CRI 接口上,上图的dockershim就是Kubernetes对接Docker到CRI接口的实现。

在引入CRI后,Kubelet的架构如图所示:

通过观察分析能够发现,Kubernetes使用Docker的调用链比较长,而Docker的一些功能对于Kubernetes来说又不需要,所以自然的将容器运行时切换到Containerd。切换到Containerd后取消掉了中间环节,但操作体验和以前一样,在Containerd1.0时,对CRI的适配是通过一个单独的CRI-Containerd实现(因为最开始containerd还会去适配其他系统,所以没有直接实现CRI)。到了Containerd1.1版本后就去掉了CRI-Containerd,直接把适配逻辑作为插件集成到Containerd主进程中,变得更加简洁。

CRI的接口主要分为两类:

  • ImageService:镜像相关的操作

  • RuntimeService:容器和Sandbox运行时管理

RuntimeService 中 CRI 设计的一个重要原则,就是确保这个接口本身,只关注容器,不关注 Pod,这么做是因为:

  • Pod 是 Kubernetes 的编排概念,而不是容器运行时的概念。所以,我们就不能假设所有下层容器项目,都能够暴露出可以直接映射为 Pod 的 API;

  • 如果 CRI 里引入了关于 Pod 的概念,那么接下来只要 Pod API 对象的字段发生变化,那么 CRI 就很有可能需要变更。而在 Kubernetes 开发的前期,Pod 对象的变化还是比较频繁的,但对于 CRI 这样的标准接口来说,这个变更频率就有点麻烦了。

虽然 CRI 里还是有一组叫做 RunPodSandbox 的接口。但是,这个 PodSandbox,对应的并不是 Kubernetes 里的 Pod API 对象,而只是抽取了 Pod 里的一部分与容器运行时相关的字段,比如 HostName、DnsConfig、CgroupParent 等。所以说,PodSandbox 这个接口描述的其实是 Kubernetes 将 Pod 这个概念映射到容器运行时层面所需要的字段,或者说是一个 Pod 对象的子集。而创建、管理 Pod 的逻辑则放置在 kubernetes 中,而不是 CRI 要实现的接口中。

随着 CRI 方案的发展,以及其他容器运行时对 CRI 的支持越来越完善,Kubernetes 社区在2020年7月份就开始着手移除 dockershim 方案了,现在的移除计划是在 1.20 版本中将 kubelet 中内置的 dockershim 代码分离,将内置的 dockershim 标记为维护模式,当然这个时候仍然还可以使用 dockershim,目标是在 1.24 版本发布没有 dockershim 的版本(代码还在,但是要默认支持开箱即用的 docker 需要自己构建 kubelet,会在某个宽限期过后从 kubelet 中删除内置的 dockershim 代码)。

CRI的实现

目前,CRI领域有两个主要的参与者,一个是Docker的高级运行时Containerd,一个是RedHat专门为Kubernetes设计的运行时CRI-O。

CRI-O

当容器运行时的标准被提出以后,RedHat的一些人开始想他们可以构建一个更简单的运行时,而且这个运行时仅仅为Kubernetes所用。这样就有了skunkworks项目,最后定名为 CRI-O, 它实现了一个最小的CRI接口,旨在充当CRI和支持的OCI运行时的轻量级桥梁。

CONTAINERD

Containerd 是一个工业级标准的容器运行时,它强调简单性、健壮性和可移植性,可以在宿主机中管理完整的容器生命周期:容器镜像的传输和存储、容器的执行和管理、存储和网络等,主要有以下功能:

  • 管理容器的生命周期(从创建容器到销毁容器)

  • 拉取/推送容器镜像

  • 存储管理(管理镜像及容器数据的存储)

  • 调用 runc 运行容器(与 runc 等容器运行时交互)

  • 管理容器网络接口及网络(CNI)

Containerd在Docker或者Kunernetes中都是使用最多的运行时,同时也是我们环境中接触最多的,因此后续着重学习Containerd。

Containerd

Containerd 可用作 Linux 和 Windows 的守护程序,它管理其主机系统完整的容器生命周期,从镜像传输和存储到容器执行和监测,再到底层存储到网络附件等等。

为了解耦,Containerd 将系统划分成了不同的组件,每个组件都由一个或多个模块协作完成(Core 部分),每一种类型的模块都以插件的形式集成到 Containerd 中,而且插件之间是相互依赖的,例如,上图中的每一个长虚线的方框都表示一种类型的插件,包括 Service Plugin、Metadata Plugin、GC Plugin、Runtime Plugin 等,其中 Service Plugin 又会依赖 Metadata Plugin、GC Plugin 和 Runtime Plugin。每一个小方框都表示一个细分的插件,例如 Metadata Plugin 依赖 Containers Plugin、Content Plugin 等。比如:

  • Content Plugin: 提供对镜像中可寻址内容的访问,所有不可变的内容都被存储在这里

  • Snapshot Plugin: 用来管理容器镜像的文件系统快照,镜像中的每一层都会被解压成文件系统快照,类似于 Docker 中的 graphdriver

总体来看 Containerd 可以分为三个大块:

  • Storage 管理镜像文件的存储

  • Metadata 管理镜像和容器的元数据

  • Runtime 由Task触发的运行时

Containerd被设计成可以很容易的嵌入到更大的系统中,例如Docker使用containerd运行容器,Kubernetes通过CRI使用containerd管理单个 节点上的容器 除了编程方式使用外,它还可以通过命令行使用,但不像docker全面,主要用于调试和学习目的,主要有:

  • ctr Containerd依据自身开发的命令行工具

  • nerdctl 与docker命令行风格兼容的命令行工具

  • crictl K8S根据CRI规范定义的命令行工具

GRPC API

Containerd通过暴露的gRPC API给外部管理容器,而Containerd中主要提供的API有:

其他还包括events、diffs等,具体见containerd的gRPC API

创建容器流程

Docker、ctr、nerdctl都是通过Containerd提供的API进行容器的管理,Kubernetes、crictl则是通过CRI接口实现。

使用gRPC API创建容器

  • 分配一个新的读写快照(snapshot),使得容器可以存储持久化数据(为容器创建新快照时,需要提供快照ID以及容器使用的镜像)

  • 创建一个Container对象,用于分配数据

  • 创建一个Task,用于实际的运行容器(当Task已创建时,意味着命名空间、根文件系统和各种容器级别的设置已被初始化,但容器定义的进程尚未启动)

  • 在启动Task之前需要等待Task创建成功,然后再调用Start去启动Task

Kubelet创建Pod流程

  • 调用CRI插件,通过RuntimeService创建Pod

  • CRI调用CNI接口创建和配置Pod的网络命令空间

  • CRI调用Containerd内部接口创建特殊的pause容器,并将该容器放入Pod的cgroups和namespace中(使用不同的容器运行时,PodSandbox的实现方式也不一样,比如使用kata作为runtime,PodSandbox被实现为一个虚拟机;而使用runc作为runtime,PodSandbox就是一个独立的namespace和cgroups)

  • 调用CRI插件,通过ImageServie拉取应用容器镜像

  • 如果节点上不存在镜像,则使用Contianerd拉取镜像

  • 调用CRI插件,使用RuntimeService创建和启动应用容器

  • CRI调用Containerd内部接口创建容器,放到Pod的cgroups和namespace中

Containerd创建任务流程

上述说的创建容器流程和创建Pod流程都是调用Containerd内部接口的逻辑,实际的过程由Containerd启动Containerd-shim进程调用runc创建容器,具体步骤如下:

  • Containerd调用Containerd-shim start 启动用于创建runc的Containerd-shim,这样Containerd-shim就与Containerd脱离了关系,重启Containerd也不会影响Containerd-shim进程

  • 通过ttrpc调用Containerd-shim的Newtask方法,之后调用runc create

  • 再通过ttrpc调用Containerd-shim的Start方法,之后调用runc start启动pause容器

  • 以同样的方式启动Pod中定义的container

1.   Containerd 被设计成嵌入到一个更大的系统中,而不是直接由开发人员或终端用户使用

2.   Docker有网络功能模块,比如它会创建 docker0 网桥,所以在使用 docker 时可以直接实现端口映射等功能,而这些网络能力都是 Docker Daemon 实现的。但是Containerd 中不包含相应的网络功能,想要启动的容器有网络能力,需要额外安装 CNI 相关的工具和插件(bridge、flannel 等)

*Containerd一切皆插件

总结

本文通过引入Docker和Kubernetes的发展介绍容器、容器运行时,将容器领域c常见的概念OCI、CRI、shim、runc,containerd串联起来,能够帮组我们进一步理解Docker和Kubernetes背后是怎么创建容器的,以及Containerd的实际运行原理。

参考

  • https://github.com/containerd/containerd

  • https://github.com/kubernetes

  • https://github.com/moby/moby

  • https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2221-remove-dockershim

  • 一文搞懂容器运行时

  • containerd shim原理深入解读

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/615184.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Zabbix Httpd漏洞修复2

一、背景 漏洞库升级的真是快啊,绿盟扫描的zabbix服务器又有新的漏洞了,经一番折腾,搞定,记录如下。 二、漏洞内容 漏洞主要还是集中在php和http漏洞 三、修复过程 思路还是升级httpd版本解决。 1、查看下zabbix版本&#xff…

【JVM】垃圾回收机制

垃圾回收三大步骤:判断是不是垃圾(垃圾判断算法) -> 标记需要回收的垃圾(三色标记) -> 回收垃圾(垃圾回收算法)。 一、如何判断是不是垃圾(垃圾判断算法)? (1)引用计数器算法:对象中记录…

基于STM32F103C8T6的超声波测距——串口输出

文章目录 前言一、超声波模块介绍1、产品特点2、超声波模块的时序图 二、STM32CubeMx创建工程1、配置项目2、keil代码设置3、效果 三、总结四、参考资料 前言 环境: 1、硬件:stm32f103c8t6 核心板 2、软件:STM32CubeMX 6.4.0 3、软件&#xf…

进程通信管道制作

利用父子进程 创建管道利用pipe函数 // 1.创建管道int pipefd[2] {0}; //[0] 读端 &#xff0c;[1]写端int n pipe(pipefd);assert(n ! -1); // debug 在release下会裁减(void)n;//防止在release下报错cout << "fd[0]:" << pipefd[0] << endl…

多用户商城开源-多店铺商城系统平台开发

多用户商城开源是指一种基于开放源代码的电子商务平台&#xff0c;允许多个用户共享一个平台&#xff0c;每位用户可以创建自己的电子商城&#xff0c;并在平台上进行交易、管理、营销等操作。多用户商城开源通常包含多种功能&#xff0c;如商品管理、订单管理、支付集成、促销…

vue diff算法与虚拟dom知识整理(14) patchVNode处理子节点新增和删减

上文 vue diff算法与虚拟dom知识整理(13) 手写patch子节点更新换位策略 我们实现了子节点位置的更新策略 但还有一些匹配不到的情况会导致死循环 那么我们继续来优化一下 我们先将src下的 index.js 代码改成这样 import h from "./snabbdom/h"; import patch from …

Scrapy ImagesPipeline下载图片

一、 ImagesPipeline是啥 ImagesPipeline是scrapy自带的类&#xff0c;用来处理图片(爬取时将图片下载到本地)。 二、ImagesPipeline优势&#xff1a; 将下载图片转换成通用的jpg和rgb格式避免重复下载缩略图生成图片大小过滤异步下载 三、ImagesPipeline工作流程 爬取一个…

Echarts构建指定省份的地图

1. 自行准备好Echarts环境 Echarts官网&#xff1a;https://echarts.apache.org/zh/index.html 2. 下载需要的省份或者城市的json地理信息文件 下载我们需要显示地区的Json数据&#xff0c;这个Json数据用于Echart的地图显示 例如我这里是下载的&#xff1a;湖南、湖北、四川…

同步模式之顺序控制线程执行

tip: 作为程序员一定学习编程之道&#xff0c;一定要对代码的编写有追求&#xff0c;不能实现就完事了。我们应该让自己写的代码更加优雅&#xff0c;即使这会费时费力。 文章目录 一、同步模式之顺序控制线程执行二、代码样例三、三个线程分别输出a、b、c&#xff0c;按顺序输…

作为一个项目管理成员,怎样才能有效监控项目执行?

作为一个项目管理成员&#xff0c;有效监控项目执行是确保项目成功的关键。在项目执行期间&#xff0c;您需要密切关注项目进展&#xff0c;并及时采取行动来纠正任何偏差。以下是几个有效的方法&#xff0c;可以帮助您监控项目执行并确保项目按计划顺利进行。 1. 制定详细的项…

C语言进阶--数据的存储

目录 数据类型介绍 基本内置类型&#xff1a; 类型的意义&#xff1a; 类型的基本归纳&#xff1a; 整型在内存中的存储 原码&#xff0c;反码和补码&#xff1a; 大小端存储模式&#xff1a; 大小端产生原因&#xff1a; 浮点型在内存中的存储 数据类型介绍 基本内…

六、机械手的种类

机械手是机器人能够完成指令的一个重要输出装置&#xff0c;机器臂是否合理、有效&#xff0c;决定了机 器人能否发挥出应有的作用。 机械手是一种能模仿人手和臂的某些动作功能&#xff0c;用以按固定程序抓取、搬运物件或操作工具的自动操作装置。特点是可以通过编程来完成各…

wy的leetcode刷题记录_Day68

wy的leetcode刷题记录_Day68 声明 本文章的所有题目信息都来源于leetcode 如有侵权请联系我删掉! 时间&#xff1a;2023-6-6 前言 目录 wy的leetcode刷题记录_Day68声明前言1019. 链表中的下一个更大节点题目介绍思路代码收获 1019. 链表中的下一个更大节点 2352. 相等行列…

CPU、内存、缓存的关系

术语解释 &#xff08;1&#xff09;CPU&#xff08;Central Processing Unit&#xff09; 中央处理器 &#xff08;2&#xff09;内存 内存用于暂时存放CPU中的运算数据&#xff0c;以及与硬盘等外部存储器交换的数据。它是外存与CPU进行沟通的桥梁&#xff0c;内存的运行决定…

Docker容器管理

docker容器相当于一个进程&#xff0c;性能接近于原生&#xff0c;几乎没有损耗&#xff1b; docker容器在单台主机上支持的数量成百上千&#xff1b; 容器与容器之间相互隔离&#xff1b; 镜像是创建容器的基础&#xff0c;可以理解镜像为一个压缩包 docker容器的管理 容…

深耕电力行业,百度智能云助力电厂节煤降耗

山西省吕梁市汾阳市三泉镇&#xff0c;晋能集团旗下山西国峰煤电有限责任公司的两台300MW循环流化床直接空冷机组正在运行&#xff0c;燃煤通过传送带进入锅炉燃烧&#xff0c;将水加热成高温高压蒸汽&#xff0c;用以推动汽轮机拖动发电机旋转发电&#xff0c;支撑工业生产、点…

CW32-Template CW32F030开发板工程模板

国产MCU Embedded-CW32-Board-Template Embedded-CW32-Board-Template CW32-Template第三方资源集合 CW-Template CW32开发者开发板资料 CW32-Board 开发板资料 合集 官方提供的案例Examples CW32F030_StandardPeripheralLib\Examples CW32-48F大学计划板例程 EX1流…

优思学院|精益和六西格玛都强调的一件东西...

精益和六西格玛有着诸多不同&#xff0c;它们的方法和理念也不尽相同&#xff0c;但却有一件东西&#xff0c;是他们的共同理念和工具&#xff0c;那就是----标准。 标准&#xff0c;是企业管理中至关重要的一环。标准&#xff0c;不仅指导着我们对人、物和流程的处理方式&…

2023年鄂州中级职称水测考试什么时候考试?

今天鄂州中级职称水测考试开始打印准考证了&#xff0c;但是只能打印部分专业的水测准考证&#xff0c;按照专业&#xff0c;按照批次打印的。 具体通知如下: 各位考生&#xff1a; 为积极稳妥做好我市晋升中、初级专业技术职称综合系列水平能力测试工作&#xff0c;现按专业分…

【2023 年第十三届 MathorCup 高校数学建模挑战赛】A 题 量子计算机在信用评分卡组合优化中的应用 37页论文及代码

相关信息 &#xff08;1&#xff09;建模思路 【2023 年第十三届 MathorCup 高校数学建模挑战赛】A 题 量子计算机在信用评分卡组合优化中的应用 详细建模过程解析及代码实现 【2023 年第十三届 MathorCup 高校数学建模挑战赛】 B 题 城市轨道交通列车时刻表优化问题 详细建…