继续上一篇文章,我们了解到构建容器的两个主要组件是 Linux namespace和 Cgroup。在这篇文章中,我们将了解什么是 Container Runtime 以及它如何与 Container 一起工作?

这是深入容器系列的第二部分:

  1. 深入容器运行时


容器和容器运行时?


创建容器是为了帮助我们在完全独立于同一台计算机上的其他程序的环境中运行程序。但是如果只使用 Linux namespace和 Cgroup 来运行容器,我们之后会遇到一些问题。

  • 第一个问题是,创建一个容器,我们需要运行很多命令,分别是创建Linux namespace的命令,包括创建Cgroup进程的命令、为Cgroup进程配置限制的命令。那么如果我们要删除容器,我们必须运行命令来清除namespace和 Cgroup。
  • 第二个问题是,当我们使用 Linux namespace和 Cgroup 命令运行数十个容器时,我们如何管理这些容器?如何知道容器正在运行什么以及它用于哪个进程?
  • 第三个问题是,有些容器已经有了我们需要的东西,而且它在 Container Registry 上,我们如何下载并运行它,而不必从头开始创建容器?

有了上面的问题,与其运行那么多命令,不如自己做一个工具来减少这个工作量,我们只需要运行一个命令就可以创建容器并删除它。而且那个工具还可以帮助我们管理很多正在运行的容器,我们知道哪个容器正在被哪个进程使用。我们还可以使用该工具下载互联网上可用的容器。这就是容器运行时诞生的原因。

总结一下,Container Runtime (容器运行时)是一个管理容器所有运行进程的工具,包括创建和删除容器、打包和共享容器。容器运行时分为两种:

  • 低级容器运行时:主要任务是创建和删除容器。
  • 高层容器运行时:管理容器,下载容器镜像,然后提取容器镜像传递给底层容器运行时,由它创建并运行容器。
一些高级容器运行时甚至包括将容器打包成容器镜像并将其传输到容器注册表的功能。


低级容器运行时


正如我上面所说,低级容器运行时的主要任务是创建和删除容器。低级容器运行时要做的是:

  • 创建 cgroup。
  • 在 cgroup 中运行 CLI。
  • 运行unshare命令以创建隔离进程。
  • 设置根文件系统。
  • 命令完成后清理 cgroup。

底层容器运行时还做其他的事情,但以上是主要的工作。比如模拟容器运行时创建容器的过程。

ROOTFS=$(mktemp -d) && UUID=9999


创建一个cgroup。

sudo cgcreate -g cpu,memory:$UUID

为这个 cgroup 设置 memory 限制。

sudo cgset -r memory.limit_in_bytes=100000000 $UUID

为这个 cgroup 设置 CPU 限制。

sudo cgset -r cpu.shares=512 $UUID && sudo cgset -r cpu.cfs_period_us=1000000 
$UUID && sudo cgset -r cpu.cfs_quota_us=2000000 $UUID

创建一个容器。

sudo cgexec -g cpu,memory:$UUID unshare -uinpUrf --mount-proc sh -c "/bin/hostname $UUID && chroot $ROOTFS /bin/sh"

删除这个 cgroup。

sudo cgdelete -r -g cpu,memory:$UUID


以上就是模拟容器运行时创建容器的过程。

runc
$ runc run runc-container 
/# echo "Hello from in a container" 
Hello from in a container

非常简单~


高级容器运行时


低级容器运行时专注于创建和删除容器,而高级容器运行时将专注于管理多个容器、传输和管理容器镜像,以及将容器镜像加载和解压到低级容器运行时。
或许,containerd 就是一个常见的高级容器运行时,它为我们提供了以下特性:

  • 从容器注册表下载容器镜像。
  • 管理容器镜像。
  • 使用容器镜像来运行容器。
  • 管理容器。

例如,我们将运行以下命令来创建一个 Redis 容器,容器注册表上有可用的 Redis 容器镜像。
下载容器镜像。

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

运行一个容器。

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

如果你想删除一个容器,运行下面的命令

sudo ctr container delete redis

你可以用下面的命令列出容器和镜像

sudo ctr images list sudo ctr container list
containerd

Docker

Docker 是最早完全支持容器交互的工具之一。Docker支持:

  • 镜像构建(Dockerfile/docker build)。
  • 管理容器镜像(docker images)。
  • 创建、删除和管理容器(docker run、docker rm、docker ps)。
  • 共享容器镜像(docker push)。
  • 提供 UI 供用户操作,而不是使用 CLI。
dockerddocker-containerddockerd-runc


使用 dockerd 将为我们提供构建映像功能,docker-containerd 类似于 containerd,docker-runc 类似于 runc。

总结

通过本文,我们了解了容器运行时。低级容器运行时负责创建和删除容器。高级容器运行时负责管理容器镜像和容器。而 Docker 是我们通过容器运行时与底层容器交互的完整工具,包括构建容器镜像。