High-level 容器运行时
简介
High-level 运行时相对于 Low-level 运行时处于较上层的位置,low-level 运行时负责实际运行容器,high-level 运行时负责传输和管理容器镜像,解压镜像并且传递给 low-level 运行时来运行容器。通常 high-level 运行时提供一个守护进程和一个 API,更上层的应用可以通过他们来运行容器,将实际工作指派给 low-level 运行时或者其他 high-level 运行时。
high-level 运行时还可以提供一些 low-level 运行时的功能,但是这些功能可以让主机上的各个容器使用,例如网络名称空间的管理,运行一个容器加入另一个容器的网络名称空间。
下面这个图表示了各个组件之间的关系。
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。
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 |
使用 ctr 命令列出所有的镜像
1 | sudo ctr images list |
使用运行一个容器
1 | sudo ctr container create docker.io/library/redis:latest redis |
查看运行中的容器:
1 | sudo ctr container create docker.io/library/redis:latest redis |
停止一个容器
1 | sudo ctr container delete redis |
这些命令看起来是不是非常的熟悉,跟 Docker 跟用户交互的方式非常像,然而根 Docker 不同的是 containerd 只专注于运行容器,因此他不提供构建容器的机制,Docker 专注于前端用户,而 containerd 专注于实际执行,比如在服务器上运行容器,但是 containerd 将构建镜像之类的任务留给了其他的工具。
containerd 架构图,向上为 Docker Daemon 提供了 gRPC 接口,使得 Docker Daemon 屏蔽下面的结构变化,确保原有接口向下兼容,向下通过 containerd-shim 结合 runc,使得引擎可以独立升级,避免之前 Docker Daemon 升级会导致所有原有容器不可用的问题。
Docker、containerd、containerd-shim 之间的关系可以通过启动一个 Docker 容器,观察进程之间的关联,首先我们先启动一个容器,当然启动之前我们可以安装 pstree。
1 | yum install psmisc |
虽然 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 | . |
另一个目录 /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 | 拉取远端镜像 |