Kubernetes containerd 是一个高级容器运行时,又名 容器管理器。简单来说,它是一个守护进程,在单个主机上管理完整的容器生命周期:创建、启动、停止容器、拉取和存储镜像、配置挂载、网络等。 containerd 旨在轻松嵌入到更大的系统中。Docker 在底层使用 containerd 来运行容器。Kubernetes 可以通过 CRI 使用 containerd 来管理单个节点上的容器。但是较小的项目也可以从与 containerd 的轻松集成中受益——例如,faasd 使用 containerd(我们需要更多的 d!)在独立服务器上启动一个服务。

K8s 弃用 Docker,containerd ctr、crictl 使用介绍 - 图1

但是,以编程方式使用 containerd 并不是唯一的选择。它还可以通过可用客户端之一从命令行使用。由此产生的容器 UX 可能不像 docker 客户端提供的那样全面和用户友好,但它仍然是有用的,例如,用于调试或学习目的。

K8s 弃用 Docker,containerd ctr、crictl 使用介绍 - 图2

如何在 ctr 中使用 containerd

ctr 是作为 containerd 项目的一部分提供的命令行客户端。如果在机器上运行了 containerd,则 ctr 二进制文件很可能也在那里。 该 ctr 界面 与 Docker CLI 不兼容,乍一看,可能看起来不那么用户友好。显然,它的主要受众是测试守护进程的容器开发人员。但是,由于它是最接近实际 containerd API 的东西,因此它可以作为一种很好的探索手段——通过检查可用命令,可以大致了解 containerd 可以做什么和不能做什么。 ctr 也非常适合学习的能力低级别的使用人员,因为 ctr + containerd 是更接近实际的容器比 docker + dockerd。

使用 ctr 处理容器镜像

拉取镜像,似乎是必需和完全合规的,但是你不能忽略注册表或标签部分:
  1. $ ctr images pull docker.io/library/nginx:1.21
  2. $ ctr images pull docker.io/kennethreitz/httpbin:latest
  3. $ ctr images pull docker.io/kennethreitz/httpbin:latest
  4. $ ctr images pull quay.io/quay/redis:latest
要列出本地镜像,可以使用:
  1. $ ctr images ls
令人惊讶的是,containerd 不提供开箱即用的镜像构建支持。但是 containerd 经常被更高级别的工具用来构建镜像。 ctr 可以导入使用 docker build 或其他 OCI 兼容软件构建的现有镜像,而不是使用构建镜像:
  1. $ docker build -t my-app .
  2. $ docker save -o my-app.tar my-app
  3. $ ctr images import my-app.tar
使用 ctr,还可以学习和探索下挂载镜像:
  1. $ mkdir /tmp/httpbin
  2. $ ctr images mount docker.io/kennethreitz/httpbin:latest /tmp/httpbin
  3. $ ls -l /tmp/httpbin/
  4. total 80
  5. drwxr-xr-x 2 root root 4096 Oct 18 2018 bin
  6. drwxr-xr-x 2 root root 4096 Apr 24 2018 boot
  7. drwxr-xr-x 4 root root 4096 Oct 18 2018 dev
  8. drwxr-xr-x 1 root root 4096 Oct 24 2018 etc
  9. drwxr-xr-x 2 root root 4096 Apr 24 2018 home
  10. drwxr-xr-x 3 root root 4096 Oct 24 2018 httpbin
  11. ...
  12. $ ctr images unmount /tmp/httpbin
要使用删除镜像 ctr,请运行:
  1. $ ctr images remove docker.io/library/nginx:1.21

使用 ctr 处理容器

可以运行一个容器用<font style="color:rgb(239, 112, 96);">ctr run image-ref container-id</font>。例如:
  1. $ ctr run --rm -t docker.io/library/debian:latest cont1
请注意,ctr 与用户友好地 docker run 生成唯一容器 ID 不同,必须自己提供唯一容器 ID。该 ctr run 命令还只支持一些熟悉的 docker run 标志:<font style="color:rgb(239, 112, 96);">--env</font>,-t,—tty,-d,—detach,—rm等,但没有端口指定或自动重启容器<font style="color:rgb(239, 112, 96);">--restart=always</font> 与镜像类似,可以使用以下命令列出现有容器:
  1. $ ctr containers ls
有趣的是,该 ctr run 命令实际上是快捷方式<font style="color:rgb(239, 112, 96);">ctr container create + ctr task start</font>
  1. $ ctr container create -t docker.io/library/nginx:latest nginx_1
  2. $ ctr container ls
  3. CONTAINER IMAGE RUNTIME
  4. nginx_1 docker.io/library/nginx:latest io.containerd.runc.v2
  5. $ ctr task ls
  6. TASK PID STATUS # Empty!
  7. $ ctr task start -d nginx_1 # -d for --detach
  8. $ ctr task list
  9. TASK PID STATUS
  10. nginx_1 10074 RUNNING
我喜欢 container 和 task 子命令的这种分离,因为它反映了 OCI 容器经常被遗忘的性质。尽管普遍认为容器不是进程 -容器是资源被隔离和执行受限制的进程。 使用 ctr task attach,可以重新连接到在容器内运行的现有任务的 stdio 流:
  1. $ ctr task attach nginx_1
  2. 2021/09/12 15:42:20 [notice] 1#1: using the "epoll" event method
  3. 2021/09/12 15:42:20 [notice] 1#1: nginx/1.21.3
  4. 2021/09/12 15:42:20 [notice] 1#1: built by gcc 8.3.0 (Debian 8.3.0-6)
  5. 2021/09/12 15:42:20 [notice] 1#1: OS: Linux 4.19.0-17-amd64
  6. 2021/09/12 15:42:20 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1024:1024
  7. 2021/09/12 15:42:20 [notice] 1#1: start worker processes
  8. 2021/09/12 15:42:20 [notice] 1#1: start worker process 31
  9. ...
与 docker 非常相似,可以在现有容器中执行命令:
  1. $ ctr task exec -t --exec-id bash_1 nginx_1 bash
  2. # From inside the container:
  3. $ root@host:/# curl 127.0.0.1:80
  4. <!DOCTYPE html>
  5. <html>
  6. <head>
  7. <title>Welcome to nginx!</title>
  8. <style>
  9. ...
在删除容器之前,必须停止其所有任务:
  1. $ ctr task kill -9 nginx_1
或者,可以使用以下标志<font style="color:rgb(0, 0, 0);">--force</font> 删除正在运行的任务:
  1. $ ctr task rm -f nginx_1
最后,要删除容器,请运行:
  1. $ ctr container rm nginx_1

如何在 nerdctl 中使用 containerd

nerdctl 是一个相对较新的 containerd 命令行客户端。与 ctr,nerdctl 旨在用户友好且与 Docker 兼容。在某种程度上,nerdctl + containerd可以无缝替换docker + dockerd. 但是,这似乎不是该项目的目标: nerdctl 其目标是促进试验 Docker 中不存在的 containerd 的尖端功能。此类功能包括但不限于延迟拉取 (stargz) 和图像加密 (ocicrypt)。预计这些功能最终也将在 Docker 中可用,但是,这可能需要几个月甚至几年的时间,因为 Docker 目前被设计为仅使用容器子系统的一小部分。重构 Docker 以使用整个 containerd 是可能的,但并不简单。所以我们决定创建一个完全使用 containerd 的新 CLI,但我们不打算用 Docker 来完成。我们一直在为 Docker/Moby 以及 containerd 做出贡献,并将继续这样做。 从基本使用的角度来看,与 相比 ctr,nerdctl 支持:
  • 镜像管理 <font style="color:rgb(1, 1, 1);">nerdctl build</font>
  • 容器网络管理
  • Docker 与 <font style="color:rgb(1, 1, 1);">nerdctl compose up</font>
最酷的部分是 nerdctl 尝试提供与 docker(和 podman)相同的命令行用户体验。因此,如果熟悉 docker(或 podman)CLI,那么您已经熟悉 nerdctl。

如何在 crictl 中使用 containerd

crictl 是 Kubernetes CRI 兼容容器运行时的命令行客户端。 引入了 Kubernetes 容器运行时接口 (CRI)以使 Kubernetes 容器运行时充满魔法。Kubernetes 节点代理 kubelet 实现了 CRI 客户端 API,可以使用任何实现 CRI 服务器 API 的容器运行时来管理其节点上的容器和 pod。

K8s 弃用 Docker,containerd ctr、crictl 使用介绍 - 图3

从 1.1 版开始,containerd 带有一个内置的 CRI 插件。因此,containerd 是一个兼容 CRI 的容器运行时。因此,它可以与 crictl 共存. crictl 创建用于检查和调试 Kubernetes 节点上的容器运行时和应用程序。它支持以下操作:
  1. attach: Attach to a running container
  2. create: Create a new container
  3. exec: Run a command in a running container
  4. version: Display runtime version information
  5. images, image, img: List images
  6. inspect: Display the status of one or more containers
  7. inspecti: Return the status of one or more images
  8. imagefsinfo: Return image filesystem info
  9. inspectp: Display the status of one or more pods
  10. logs: Fetch the logs of a container
  11. port-forward: Forward local port to a pod
  12. ps: List containers
  13. pull: Pull an image from a registry
  14. run: Run a new container inside a sandbox
  15. runp: Run a new pod
  16. rm: Remove one or more containers
  17. rmi: Remove one or more images
  18. rmp: Remove one or more pods
  19. pods: List pods
  20. start: Start one or more created containers
  21. info: Display information of the container runtime
  22. stop: Stop one or more running containers
  23. stopp: Stop one or more running pods
  24. update: Update one or more running containers
  25. config: Get and set crictl client configuration options
  26. stats: List container(s) resource usage statistics
这里有趣的部分是,通过 crictl + containerdbundle 可以了解 pod 是如何实现的,但是这个话题值得自己去探索。