K8s/Docker/containerd的关系

3,173 阅读4分钟

容器世界里面有很多层,它们都并不是唯一的,它们的界限也不是那么清晰,可能相互依赖,可能相互包含,也可能有同样的功能的.下面我将把它们一一展现出来.

一. 简单介绍

K8s(Kubernetes)是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化.

Docker 是一个开源的应用容器引擎.

Containerd 是一个工业级标准的容器运行时,它强调简单性、健壮性和可移植性,可以在宿主机中管理完整的容器生命周期

二. 架构

Docker跟kubernetes都位于Containerd上层,所以kubernetes并不需要使用完整的Docker,他只是使用了Docker实现的Containerd.

Docker 公司与 CoreOS 和 Google 共同创建了 OCI (Open Container Initial),并提供了两种规范:

三. 什么是CRI -Container Runtime Interface?

CRI 在 Kubernetes 1.5 中引入,并充当 kubelet 和容器运行时之间的桥梁。 期望与Kubernetes集成的高级容器运行时将实现CRI。预期runtimes将负责镜像的管理,并支持Kubernetes pods,以及管理各个容器。CRI仅具有一个功能:对于Kubernetes,它描述了容器应具有的操作以及每个操作应具有的参数。

CRI 工作在 kubelet 与 container runtime之间,目前常见的 runtime 有:

docker: 目前 docker 已经将一部分功能移至 containerd 中,CRI 可以直接与 containerd 交互。 因此,Docker本身并不需要支持CRI(containerd已经支持)。

containerd:containerd 可以通过 shim 对接不同 low-level runtime,这部分后文会详细介绍

cri-o:一种轻量级的 runtime,支持runc和Clear Containers作为low-level runtimes。

CRI 大体包含三部分接口:Sandbox 、 Container 和 Image,其中提供了一些操作容器的通用接口,包括 Create Delete List 等。

- Sandbox 为 Container 提供一定的运行环境,这其中包括 pod 的网络等

- Container 包括容器生命周期的具体操作

- Image 则提供对镜像的操作

四. Containerd是什么?

                 [k8s中的containerd]

Containerd 可以在宿主机中管理完整的容器生命周期:

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

  • 拉取/推送容器镜像

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

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

  • 管理容器网络接口及网络

Containerd架构

Containerd 分为三大块: 

- Storage 管理镜像文件的存储

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

- 由 Task 触发运行时。

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

Images Service 提供镜像相关的操作;

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

Containerd 的设计是一个大的插件系统,对外提供 GRPC 方式的 API 以及 Metrics 接口。

containerd 主要流程

图中的 containerEngine 在 docker 中就是 docker-containerd 组件,创建容器记录的metadata,并请求 containerd 的 task 模块,task 模块会在 runtime 中创建 task 实例,分别会加入 task list, 监控 cgroup 等操作,每个 task 实例则调用 shim 去创建container。

containerd-shim

containerd-shim 是 containerd 的一个组件,主要是用于剥离 containerd 守护进程与容器进程。containerd 通过 shim 调用 runc 的包函数来启动容器。当我们执行 pstree 命令时,可以看到如下的进程关系:

引入shim,允许runc 在创建和运行容器之后退出,并将 shim 作为容器的父进程,而不是 containerd 作为父进程,这样做的目的是当 containerd 进程挂掉,由于 shim 还正常运行,因此可以保证容器不受影响。

此外,shim 也可以收集和报告容器的退出状态,不需要 containerd 来 wait 容器进程。

当我们有需求去替换 runc 运行时工具库时,例如替换为安全容器 kata container 或 Google 研发的 gViser,则需要增加对应的shim(kata-shim等),以上两者均有自己实现的 shim。

--------------------

五. 推荐containerd文章

Container Runtimes Part 1: An Introduction to Container Runtimes

Container Runtimes Part 2: Anatomy of a Low-Level Container Runtime

Container Runtimes Part 3: High-Level Runtimes

Container Runtimes Part 4: Kubernetes Container Runtimes & CRI