没了docker,我们还有哪些选择?
云计算时代,容器技术绝对是其核心技术了,媲美原生OS内核的执行效率,又结合了轻量级的资源隔离技术,使得云计算大放异彩,广为流行的Docker,基本上成为了容器技术的代名词。
但是,企业一旦被老美列入实体名单,那么Docker提供的服务就不能继续使用了,那怎么办呢?
请不要混淆,容器和容器管理工具、容器编排系统并不是一回事,如果把容器比作汽车的发动机,那容器管理工具就好比为汽车。容器技术虽然好用,有很多优势,但是脱离了容器编排系统,很难大规模的进行工业化应用,充其量是个单机版的工具,或者说是个不错的玩具。因此,影响最多的还是容器编排生态体系。
Docker基于容器技术,但是容器技术却不仅仅有Docker一家,Docker其实并不是一种新技术,而是一个新瓶装旧酒的工具,它的底层技术,namespace及cgroups都是OS出现很多年的一些解决方案,Docker将其封装加以各种抽象成型为一个工具,业内其实有很多替代产品和类似的解决方案。
先解释几个名词:
Open Container Initiative(OCI)
即为OCI,Linux基金会于2015年6月成立OCI(Open Container Initiative)组织,旨在围绕容器格式和运行时制定一个开放的工业化标准。这就好比浏览器引擎,各大浏览器都有自己的引擎,那么我们制定一个标准吧。OCI就可以类比为容器界的浏览器引擎,市面上琳琅满目的浏览器有很多种,但是其背后的浏览器引擎屈指可数,就那么几种。
The Container Runtime Interface (CRI)
Container Runtime Interface(容器运行时接口) ,k8s作为一个容器编排系统,编排的无疑是容器,而容器有很多实现,docker就是其中之一,为了适配不同的容器产品,就好比一辆汽车可以支持更换多种类型的发动机,那么就制定出一套接口,使得具体的容器实现可以方便的对接到k8s,本质上就是一种适配器模式。
下面是一些开源的替代选择。
podman
Podman目前是Docker强有力的竞争者,主要是由RedHat推动的,结合工具族Buildah和Skopeo,三者配合可以完成Docker所有的功能,命令基本上都和Docker一样,而且不需要守护程序或访问有root权限的组,更加安全可靠,是下一代容器管理工具。Podman可以替换Docker中了大多数子命令(RUN,PUSH,PULL等)。Podman不需要守护进程,而是使用用户命名空间来模拟容器中的root,无需连接到具有root权限的套接字保证容器的体系安全。而且可以兼容Dockerfile进行镜像的构建和pull及push操作。其底层OCI是runc。
地址:https://podman.io/Podman
containerd
Containerd是一个工业标准的容器引擎,重点是它简洁,健壮,便携,在Linux和window上可以作为一个守护进程运行,它可以管理主机系统上容器的完整的生命周期:镜像传输和存储,容器的执行和监控,低级别的存储和网络,
它是从 docker 引擎中分离出的项目:
https://github.com/containerd
Containerd和Docker的定位不同,前者主要是为了适配大规模的容器编排系统如kubernetes而生,不适合于个人开发者,对开发人员或者个人用户并不友好。kubernetes作为一个容器编排系统,其编排管理的无疑是容器,那么使用哪种容器引擎就成了首要选择,为了能适配更多容器引擎,k8s抽象出一套接口称之为CRI(Containner Runntime Interface),用来和具体的容器引擎解耦用来适配不同的容器引擎,就好比一辆汽车可以支持更换多种不同类型的发动机一样,CRI就是适配不同发动机的接口,于是就有了很多CRI的实现,而Containerd正是为了满足该场景而存在而成的一种实现。除此之外,还有cri-o。
CRI-O
cri-o 也是 kubernetes CRI的一个实现,旨在为 kubernetes 提供 CRI 接口支撑。cri-o 提供了一组最小的工具和接口来下载、提取和管理镜像、维护容器生命周期、并提供满足 CRI 所需的监控和日志记录。它可以使用任何实现 OCI 运行时规范的 runtime,默认使用 runc。runc 是一个主要用 go 编写的 CLI 工具(需要 c 语言的中介层 shim 来完成某些 go 不能完成的功能)。runc 是最受欢迎的 OCI runtime,被 containerd 和 cri-o 使用。架构如下:
https://github.com/opencontainers/runc
在大多数情况下,所有 runc 都会在生成进程时配置 namespace 和 cgroup。这实际上就是是一个容器,包括 namespace 和 cgroups。这基本上就是容器技术的核心了。
rktlet
rktlet
是一个使用 rkt 作为容器 runtime 的 Kubernetes 接口实现。从其架构图可以看出来,其背后容器功能的承载是基于rkt,rkt划分namespace和管理cgroups用于容器本身的创建和管理。rkt 是一个在 LInux 上运行容器而编写的 CLI 工具。它采用多层设计,允许 runtime 可根据实现者的需求更改 。默认情况下,rkt 结合使用 systemd
和 systemd-nspawn
来创建容器。systemd-nspawn 用于管理执行 systemd 以管理 cgroup 的命名空间。容器应用程序作为 systemd 单元运行。通过使用不同的 “1阶段” 镜像,可将运行应用程序的工具可以从 systemd 工具更改为其他任何工具。
可以简单的做个类比,如果把containerd,CIR-O、Docker、rktlet比作市面上众多的浏览器产品的话,那么runc、rkt等CLI就是浏览器的引擎。
更多可以参考CNCF:https://landscape.cncf.io/zoom=200