侧边栏壁纸
博主头像
里奥的博客博主等级

行动起来,活在当下

  • 累计撰写 24 篇文章
  • 累计创建 7 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

Docker, Containerd 和 CRI 关系

里奥
2024-05-03 / 0 评论 / 0 点赞 / 61 阅读 / 27292 字

Docker

从 Docker 1.11 版本开始,Docker 容器运行就不是简单通过 Docker Daemon 来启动了,而是通过集成 containerd、runc 等多个组件来完成的。虽然 Docker Daemon 守护进程模块在不停的重构,但是基本功能和定位没有太大的变化,一直都是 CS 架构,守护进程负责和 Docker Client 端交互,并管理 Docker 镜像和容器。现在的架构中组件 containerd 就会负责集群节点上容器的生命周期管理,并向上为 Docker Daemon 提供 gRPC 接口。

当我们要创建一个容器的时候:

  1. 现在 Docker Daemon 并不能直接帮我们创建了,而是请求 containerd 来创建一个容器,containerd 收到请求后,也并不会直接去操作容器,而是创建一个叫做 containerd-shim 的进程,让这个进程去操作容器

  2. 然后创建容器需要做一些 namespaces 和 cgroups 的配置,以及挂载 root 文件系统等操作,这些操作其实已经有了标准的规范,那就是 OCI(开放容器标准),runc 就是它的一个参考实现(Docker 被逼无耐将 libcontainer 捐献出来改名为 runc 的),这个标准其实就是一个文档,主要规定了容器镜像的结构、以及容器需要接收哪些操作指令,比如 create、start、stop、delete 等这些命令。runc 就可以按照这个 OCI 文档来创建一个符合规范的容器

CRI

CRI(Container Runtime Interface 容器运行时接口)本质上就是 Kubernetes 定义的一组与容器运行时进行交互的接口,所以只要实现了这套接口的容器运行时都可以对接到 Kubernetes 平台上来。不过 Kubernetes 推出 CRI 这套标准的时候还没有现在的统治地位,所以有一些容器运行时可能不会自身就去实现 CRI 接口,于是就有了 shim(垫片), 一个 shim 的职责就是作为适配器将各种容器运行时本身的接口适配到 Kubernetes 的 CRI 接口上,其中 dockershim 就是 Kubernetes 对接 Docker 到 CRI 接口上的一个垫片实现。

Kubelet 通过 gRPC 框架与容器运行时或 shim 进行通信,其中 kubelet 作为客户端,CRI shim(也可能是容器运行时本身)作为服务器。

调用关系对比

如果我们使用的是 Docker 的话,当我们在 Kubernetes 中创建一个 Pod 的时候,首先就是 kubelet 通过 CRI 接口调用 dockershim,请求创建一个容器,kubelet 可以视作一个简单的 CRI Client, 而 dockershim 就是接收请求的 Server,不过他们都是在 kubelet 内置的。

dockershim 收到请求后, 转化成 Docker Daemon 能识别的请求, 发到 Docker Daemon 上请求创建一个容器,请求到了 Docker Daemon 后续就是 Docker 创建容器的流程了,去调用 containerd,然后创建 containerd-shim 进程,通过该进程去调用 runc 去真正创建容器。

其实我们仔细观察也不难发现使用 Docker 的话其实是调用链比较长的,真正容器相关的操作其实 containerd 就完全足够了,Docker 太过于复杂笨重了,当然 Docker 深受欢迎的很大一个原因就是提供了很多对用户操作比较友好的功能,但是对于 Kubernetes 来说压根不需要这些功能,因为都是通过接口去操作容器的,所以自然也就可以将容器运行时切换到 containerd 来。

containerd 1.1 版本后就去掉了 CRI-Containerd 这个 shim,直接把适配逻辑作为插件的方式集成到了 containerd 主进程中,现在这样的调用就更加简洁了。

常用命令

ctr 是 containerd 的一个客户端工具。 crictl 是 CRI 兼容的容器运行时命令行接口,可以使用它来检查和调试 k8s 节点上的容器运行时和应用程序。 ctr -v 输出的是 containerd 的版本,crictl -v 输出的是当前 k8s 的版本,从结果显而易见你可以认为 crictl 是用于 k8s 的。

docker

ctr(containerd)

crictl(kubernetes)

查看运行的容器

docker ps

ctr task ls/ctr container ls

crictl ps

查看镜像

docker images

ctr image ls

crictl images

查看容器日志

docker logs

crictl logs

查看容器数据信息

docker inspect

ctr container info

crictl inspect

查看容器资源

docker stats

crictl stats

启动/关闭已有的容器

docker start/stop

ctr task start/kill

crictl start/stop

运行一个新的容器

docker run

ctr run

无(最小单元为 pod)

修改镜像标签

docker tag

ctr image tag

创建一个新的容器

docker create

ctr container create

crictl create

导入镜像

docker load

ctr image import

导出镜像

docker save

ctr image export

删除容器

docker rm

ctr container rm

crictl rm

删除镜像

docker rmi

ctr image rm

crictl rmi

拉取镜像

docker pull

ctr image pull

ctictl pull

推送镜像

docker push

ctr image push

在容器内部执行命令

docker exec

crictl exec

参考文档

  1. 一文搞懂容器运行时 Containerd-阳明的博客|Kubernetes|Istio|Prometheus|Python|Golang|云原生 (qikqiak.com)

  2. 一文带你了解Docker与Containerd的区别-腾讯云开发者社区-腾讯云 (tencent.com)

0

评论区