参考: Docker,containerd,CRI,CRI-O,OCI,runc 分不清?看这一篇就够了
Docker, containerd, CRI-O and runc之间的区别?
Docker、Podman、Containerd 谁才是真正王者?
CRI-O vs Podman vs Docker vs CRI-containerd
1 容器的主要标准:
Open Container Initiative (OCI) ,定义容器和镜像的标准
Container Runtime Interface (CRI),它定义了Kubernetes和下面的容器运行时之间的API。
OCI:
OCI (Open Container Initiative),是一个轻量级,开放的治理结构(项目)。在 Linux 基金会的支持下成立,致力于围绕容器格式和运行时创建开放的行业标准。
OCI 项目由 Docker、CoreOS 和容器行业中的其它领导者在 2015 年 6 月的时候启动,OCI 的技术委员会成员包括 Red Hat、Microsoft、Docker、Cruise、IBM、Google、Red Hat 和 SUSE 等。
CRI:
CRI(Container Runtime Interface)是 Kubernetes v1.5 引入的容器运行时接口,它将 Kubelet 与容器运行时解耦,将原来完全面向 Pod 级别的内部接口拆分成面向 Sandbox 和 Container 的 gRPC 接口,并将镜像管理和容器管理分离到不同的服务。
2 CRI-O, Docker, Containerd三者区别
CRI-O:
实现了容器运行时接口(CRI)的高级别容器运行时,实现了CRI规范。
可以使用 OCI(开放容器倡议)兼容的运行时,是 containerd 的一个替代品。
是专门为Kubernetes创建的一个容器运行时,与 containerd 相同,提供了拉取、推送镜像,管理网络,存储的能力,
通过直接调用底层的runc,实现启动、停止和重启容器的管理.
CRI-O 诞生于 RedHat、IBM、英特尔、SUSE、Hyper 等公司。
Podman:
Podman原来是CRI-O项目的一部分,后来被分离成了一个单独的项目libpod。
Docker:
需要先调用dockershim,然后调用docker,再调用containerd,最后调用底层的 runc.
CRI-Containerd:
是CRI的实现,通过Containerd调用底层的runc.
Containerd:
Containerd是一个进程,是CRI-Containerd的实现,用来拉取、推送镜像,管理网络,存储,调用底层runc来运行容器,并且管理容器的运行。
containerd 是一个来自 Docker 的高级容器运行时,并实现了 CRI 规范。
containerd从 Docker 项目中分离出来,使Docker更加模块化,之后 containerd 被捐赠给云原生计算基金会(CNCF)为容器社区提供创建新容器解决方案的基础。
Docker 内部使用 containerd,安装 Docker 时也会安装 containerd。
containerd 通过其 CRI 插件实现了 Kubernetes 容器运行时接口(CRI),它可以管理容器的整个生命周期,包括从镜像的传输、存储到容器的执行、监控再到网络。
runc:
底层容器运行时,或者实际创建和运行容器的组件,它包括libcontainer,这是一个基于go的本地实现,用于创建、启动、停止和重启容器的管理。
runc 是轻量级的通用运行时容器,它遵守 OCI 规范,是实现 OCI 接口的最低级别的组件,与内核交互创建并运行容器。
runc 为容器提供了所有的低级功能,与现有的低级 Linux 功能交互,如命名空间和控制组,它使用这些功能来创建和运行容器进程。
runc 是一个在 Linux 上运行容器的工具,所以这意味着它可以在 Linux 上、裸机上或虚拟机内运行。
runc 的几个替代品:
crun [5]:一个用 C 语言编写的容器运行时(相比之下,runc 是用Go编写的。)来自 Katacontainers 项目的 kata-runtime [6] 它将 OCI 规范实现为单独的轻量级虚拟机(硬件虚拟化)。
Google 的 gVisor [7],创建了拥有自己内核的容器,在其运行时中实现了 OCI,称为 runsc。
dockershim:
Docker比Kubernetes更古老,没有实现CRI。dockershim把Docker连接到Kubernetes上,或者是Kubernetes连接到Docker上。
dockershim支持将 Docker 被硬编码到 Kubernetes 中。随着容器化成为行业标准,Kubernetes 项目增加了对额外运行时的支持,比如通过 Container Runtime Interface (CRI) 容器运行时接口来支持运行容器。因此 dockershim 成为了 Kubernetes 项目中的一个异类,对 Docker 和 dockershim 的依赖已经渗透到云原生计算基金会(CNCF)生态系统中的各种工具和项目中,导致代码脆弱。
2022 年 4 月 dockershim 将会从 Kubernetes 1.24 中完全移除。今后 Kubernetes 将取消对 Docker 的直接支持,而倾向于只使用实现其容器运行时接口的容器运行时,这可能意味着使用 containerd 或 CRI-O。这并不意味着 Kubernetes 不能运行 Docker 格式的容器。
containerd 和 CRI-O 都可以运行 Docker 格式(实际上是 OCI 格式)的镜像,它们只是无需使用 docker 命令或 Docker 守护程序。
3 Docker,k8s,CRI, OCI, containerd和runc关系图
4 Docker VS Podman
Podman与Linux内核交互,通过runC容器运行时进程而不是Daemon来管理容器。Buildah实用程序用于替代Docker build作为容器镜像构建工具,Docker push被Skopeo替代,用于在注册表和容器引擎之间移动容器镜像。
(1) 架构
Docker使用守护进程,一个正在后台运行的程序,来创建镜像和运行容器。Podman是无守护进程的架构,这意味着它可以在启动容器的用户下运行容器。Docker有一个由守护进程引导的客户端——服务器逻辑架构;但Podman不需要此类守护进程。
(2) Root特权
由于Podman没有守护进程来管理其活动,也无需为其容器分配Root特权。Docker最近在其守护进程配置中添加了Rootless模式,但Podman首先使用了这种方法,并将其作为基本特性进行了推广。原因如下。
(3) 安全
Podman比Docker安全吗?Podman允许容器使用Rootless特权。Rootless容器被认为比Root特权的容器更安全。在Docker中,守护进程拥有Root权限,这使得它们易成为攻击者的首选入侵点。
Podman中的容器默认情况下不具有Root访问权限,这在Root级别和Rootless级别之间添加了一个自然屏障,提高了安全性。不过,Podman可以同时运行Root容器和Rootless容器。
(4) Systemd
如果没有守护进程,Podman需要另一个工具来管理服务并支持后台运行的容器。Systemd为现有容器创建控制单元或用来生成新容器。Systemd还可以与Podman集成,允许它在默认情况下运行启用了Systemd的容器,从而无需进行任何修改。
通过使用Systemd,供应商可以将他们的应用程序封装为容器用来安装、运行和管理,因为现在大多数应用程序都是通过这种方式打包和交付的。
(5) 构建镜像
作为一款自给自足的工具,Docker可以自己构建容器镜像。Podman则需要另一种名为Buildah的工具的辅助,该工具充分体现了它的特殊性:它是为构建镜像而设计的,而不是为构建容器而生。
(6) Docker Swarm
Podman不支持Docker Swarm,这可能会在某些项目中被刨除在外,因为使用Docker Swarm命令会产生一个错误。然而,Podman最近增加了对Docker Compose的支持,使其与Swarm兼容,从而克服了这个限制。当然,Docker由于其原生的特性,与Swarm当然融合得很好。
(7) All in one vs 模块化
Docker是一个独立的、强大的工具,在整个循环中处理所有的容器化任务,有优点也有缺点。Podman采用模块化的方法,依靠专门的工具来完成特定的任务。
5 Docker容器运行架构图
当用 docker命令运行一个容器时,实际上是通过 docker守护进程调用 containerd,然后 containerd调用runc运行容器。
docker:命令行工具,终端用户使用这个命令来和docker进行交互
containerd,containerd是一个进程,用来拉取、推送镜像,管理网络,存储,然后使用runc来运行容器,并且管理容器的运行
runc:这是底层容器运行时,或者实际创建和运行容器的组件)。它包括libcontainer,这是一个基于go的本地实现,用于创建容器
6 原始容器运行时Runc
最终用户到实际的容器调用链示意图:
runc 是一个命令行客户端,用于运行根据 Open Container Initiative (OCI) 格式打包的应用程序,并且是 Open Container Initiative 规范的兼容实现。
runc 符合容器和管理容器映像的开放容器计划(OCI) 和规范,也有其他符合 OCI 的运行时,甚至可以运行符合 OCI 标准的虚拟机,Kata Containers 与gVisor就是符合符合 OCI 标准的虚拟机。gVisor 为代表的用户态 Kernel 方案是安全容器的未来,只是现在还不够完善。
runc 希望提供一个“ OCI 包”,它只是一个根文件系统和一个config.json 文件。而不是Podman 或 Docker 那样有“镜像”概念,所以不能只执行runc run nginx:latest这样来启动一个容器。
Runc 符合 OCI 规范(具体来说,是runtime-spec),可以使用 OCI 包并从中运行一个容器。值得重申的是,这些bundle并不是“容器镜像”,它们要简单得多。层、标签、容器注册表和存储库等功能 - 所有这些都不是 OCI 包甚至运行时规范的一部分。有一个单独的 OCI-spec (image-spec )定义镜像。