High-level容器运行时

High-level 容器运行时

简介

High-level 运行时相对于 Low-level 运行时处于较上层的位置,low-level 运行时负责实际运行容器,high-level 运行时负责传输和管理容器镜像,解压镜像并且传递给 low-level 运行时来运行容器。通常 high-level 运行时提供一个守护进程和一个 API,更上层的应用可以通过他们来运行容器,将实际工作指派给 low-level 运行时或者其他 high-level 运行时。

high-level 运行时还可以提供一些 low-level 运行时的功能,但是这些功能可以让主机上的各个容器使用,例如网络名称空间的管理,运行一个容器加入另一个容器的网络名称空间。

下面这个图表示了各个组件之间的关系。

image

High-Level 运行时

Docker

Docker 是第一个开源的容器运行时,由 dotCloud 公司开发,公司后面改名叫 Docker 了,用于在容器中运行用户的 Web 程序。

Docker 是一个包含 packing、sharing、building 和运行容器的容器运行时,Docker 是 client/server 架构,最初是一个单一的守护进程、dockerd 和 Docker client 构建,这个守护进程提供了构建容器、管理镜像和运行容器的大多数逻辑,以及一个 API。Docker Client 可以发送命令从守护进程获取信息。

Docker 最初包含了实现 high-level 和 low-level 运行时的特性,但是后来这些特性被分解为 runc 和 containerd 两个独立的项目,Docker 现在由 dockerdd守护进程、docker-containerd 守护进程和 docker-runc 组成,docker-containerd 和 docker-runc 只是 Docker 打包了 containerd 和 runc。

image

dockerd 提供了构建镜像等功能,dockerd 使用了 docker-containerd 提供的镜像管理和运行容器等功能。Docker 的构建逻辑是解释 Dockerfile,使用 containerd 在容器中运行必要的命令,并将生成的容器文件系统保存为镜像。

containerd

containerd 是从 Docker 中拆出去的 high-level 运行时,就像 runc 一样,他作为 low-level 运行时组件,containerd 也被 Docker 作为 high-level 运行时组件。

containerd 也提供了可用于其交互的 API 和客户端应用程序,就像 Docker 有 Docker Client 一样,containerd 的客户端命令是 ctr。

我们可以使用 ctr 来拉取镜像。

1
sudo ctr images pull docker.io/library/redis:latest

image

使用 ctr 命令列出所有的镜像

1
sudo ctr images list

image

使用运行一个容器

1
sudo ctr container create docker.io/library/redis:latest redis

查看运行中的容器:

1
sudo ctr container create docker.io/library/redis:latest redis

image

停止一个容器

1
sudo ctr container delete redis

这些命令看起来是不是非常的熟悉,跟 Docker 跟用户交互的方式非常像,然而根 Docker 不同的是 containerd 只专注于运行容器,因此他不提供构建容器的机制,Docker 专注于前端用户,而 containerd 专注于实际执行,比如在服务器上运行容器,但是 containerd 将构建镜像之类的任务留给了其他的工具。

containerd 架构图,向上为 Docker Daemon 提供了 gRPC 接口,使得 Docker Daemon 屏蔽下面的结构变化,确保原有接口向下兼容,向下通过 containerd-shim 结合 runc,使得引擎可以独立升级,避免之前 Docker Daemon 升级会导致所有原有容器不可用的问题。

image

Docker、containerd、containerd-shim 之间的关系可以通过启动一个 Docker 容器,观察进程之间的关联,首先我们先启动一个容器,当然启动之前我们可以安装 pstree。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
yum install psmisc

# 启动容器
docker run -d busybox sleep 1000

# 使用如下命令可以查看 dockerd 的进程 id 1为 8124
ps -ef|grep dockerd
root 8124 1 0 Apr06 ? 00:55:12 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
root 12422 11179 0 23:28 pts/2 00:00:00 grep --color=auto dockerd

#使用 pstree 输出结果如下
pstree -l -a -A 8124


dockerd
|-docker-containe --config /var/run/docker/containerd/containerd.toml
| |-docker-containe -namespace moby -workdir /var/lib/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/5f65905c8c2682b9e746c210225d55bc17ff4f5b5b5449f2e0dc4d48bd0e6677 -address /var/run/docker/containerd/docker-containerd.sock -containerd-binary /usr/bin/docker-containerd -runtime-root /var/run/docker/runtime-runc
| | |-sleep 1000
| | `-8*[{docker-containe}]
| `-23*[{docker-containe}]
`-21*[{dockerd}]

虽然 pstree 命令截断了命令,但我们还是能够看出,当 Docker daemon 启动之后,dockerd 和 docker-containerd 进程一直存在。当启动容器之后,docker-containerd 进程(也是这里介绍的 containerd 组件)会创建 docker-containerd-shim 进程,其中的参数 b9a04a582b66206492d29444b5b7bc6ec9cf1eb83eff580fe43a039ad556e223 就是要启动容器的 id。最后 docker-containerd-shim 子进程,已经是实际在容器中运行的进程(既 sleep 1000)

docker-containerd-shim 另一个参数,是一个和容器相关的目录 /var/run/docker/containerd/5f65905c8c2682b9e746c210225d55bc17ff4f5b5b5449f2e0dc4d48bd0e6677,里面的内容有:

1
2
3
.
├── init-stdin
└── init-stdout

另一个目录 /var/run/docker/containerd/daemon/io.containerd.runtime.v1.linux/moby/5f65905c8c2682b9e746c210225d55bc17ff4f5b5b5449f2e0dc4d48bd0e6677 包含了 config.json 等

其中包括了容器配置和标准输入、标准输出、标准错误三个管道文件

rkt

rkt 也是一个既有 high-level 也有 low-level 的运行时。与 Docker 非常的相似,rkt 也允许你构建镜像,拉取和管理镜像,也可以通过命令运行容器,但是 rkt 没有 Docker 的长时间守护进程和远程 API。

rkt 社区虽然不是非常的活跃,但是也是容器历史中的一个重要组成部分。

1
2
3
4
5
6
7
8
# 拉取远端镜像
sudo rkt fetch coreos.com/etcd:v3.3.10

# 查看本地镜像列表
sudo rkt image list

# 删除镜像
sudo rkt image rm coreos.com/etcd:v3.3.10

相关链接

high-level runtimes
Docker、Containerd、RunC 你应该知道的所有