2021年云栖技术大会-可持续技术发展正在直播中 了解详情
写点什么

不止 Docker:8 款容器管理开源方案

2021 年 7 月 02 日

不止Docker:8款容器管理开源方案

Docker 诞生于 2013 年,并普及了容器的概念,以至于大多数人仍然将容器的概念等同于“Docker 容器”。


作为第一个吃螃蟹的人,Docker 设置了新加入者必须遵守的标准。例如,Docker 有一个大型系统镜像库。所有的替代方案都必须使用相同的镜像格式,同时试图改变 Docker 所基于的整个堆栈的一个或多个部分。


在此期间,出现了新的容器标准,容器生态系统朝着不同方向发展。现在除了 Docker 之外,还有很多方法可以使用容器。


在本文中,我们将介绍以下内容:


  • 将 Chroot、cgroups 和命名空间作为容器的技术基础

  • 定义 Docker 所基于的软件堆栈

  • 说明 Docker 和 Kubernetes 需要坚持和遵守的标准

  • 介绍替代解决方案,这些解决方案尝试使用具有更好更安全的组件来替换原始 Docker 容器。

容器的软件堆栈

像 Chroot 调用、 cgroups 和命名空间等 Linux 特性帮助容器在与所有其他进程隔离的情况下运行,从而保证运行时的安全性。

Chroot

所有类似 Docker 的技术都起源于类似 Unix 操作系统(OS)的根目录。在根目录上方是根文件系统和其他目录。


从长远来看,这是很危险的,因为根目录中任何不需要的删除都会影响整个操作系统。这就是为什么存在一个系统调用 chroot()。它创建了额外的根目录,例如一个用于运行遗留软件,另一个用于包含数据库等等。


对于所有这些环境,chroot 似乎是一个真正的根目录,而是实际上,它只是将路径名添加到任何以/开头的名字上。真正的根目录仍然存在,并且任何进程都可以引用指定根目录以外的任何位置。

Linux cgroups

自 2008 年 2.6.24 版本以来,Control groups (cgroups)一直是 Linux 内核的一项功能。Cgroup 将同时限制、隔离和测量多个进程的系统资源(内存、CPU、网络和 I/O)使用情况。


假设我们想阻止用户从服务器发送大量电子邮件。我们创建了一个内存限制为 1GB、CPU 占用率为 50%的 cgroup,并将应用程序的 processid 添加到该组中。当达到这些限制时,系统将限制电子邮件发送过程。它甚至可能终止进程,这取决于托管策略。

Namespaces

Linux 命名空间是另一个有用的抽象层。命名空间允许我们拥有许多进程层次,每个层次都有自己的嵌套“子树(subtree)”。命名空间可以使用全局资源,并将其呈现给其成员,就像它是自己的资源一样。


具体来看,Linux 系统开始时的进程标识符(PID)为 1,并且所有其他进程将包含在其树中。PID 命名空间允许我们跨越一棵新树,它拥有自己的 PID 1 进程。现在有两个值为 1 的 PID,每个命名空间可以产生自己的命名空间,并且相同的过程可以附加了几个 PID。


子命名空间中的一个进程将不知道父级的进程存在,而父命名空间将可以访问整个子命名空间。


有七种类型的名称空间:cgroup、IPC、网络、mount、PID、用户和 UTS。

Network Namespace

一些资源是稀缺的。按照惯例,有些端口具有预定义的角色,不应用于其他任何用途:端口 80 仅服务于 HTTP 调用,端口 443 仅服务于 HTTPS 调用等等。在共享主机环境中,两个或多个站点可以监听来自端口 80 的 HTTP 请求。第一个获得该端口的站点不允许任何其他应用程序访问该端口上的数据。第一个应用程序在互联网上是可见的,而其他所有应用程序将不可见。


解决方案是使用网络命名空间,通过网络命名空间,内部进程将看到不同的网络接口。


在一个网络命名空间中,同一端口可以是开放的,而在另一个网络命名空间中,可以关闭该端口。为此,我们必须采用额外的“虚拟”网络接口,这些接口同时属于多个命名空间。中间还必须有一个路由器进程,将到达物理设备的请求连接到相应的名称空间和其中的进程。


复杂吗?这就是为什么 Docker 和类似工具如此受欢迎。现在让我们来介绍一下 Docker,以及它的替代方案。

Docker: 人人可用的容器

在容器统治云计算世界之前,虚拟机非常流行。如果你有一台 Windows 机器,但想为 iOS 开发移动应用程序,你可以购买一台新的 Mac,或者将其虚拟机安装到 Windows 硬件上。虚拟机也可能是笨重的,它们经常吞噬不需要的资源,而且启动速度通常很慢(长达一分钟)。


容器是标准软件单元,具有运行程序所需的一切:操作系统、数据库、镜像、图标,软件库、代码和所需的其他组件。容器的运行也与所有其他容器,甚至与操作系统本身隔离。与虚拟机相比,容器是轻量级的,所以它们可以快速启动,并且容易被替换。


要运行隔离和保护,容器需要基于 Chroot、cgroups 和命名空间。


容器的镜像是在实际机器上形成应用程序的模板,能够根据单个镜像创建尽可能多的容器,一个名为 Dockerfile 的文本文件包含了组装镜像所需的所有信息。


Docker 带来的真正革命是创建了 Docker 镜像仓库和开发了 Docker 引擎,这些镜像以相同的方式在各地运行,作为第一个被广泛采用的容器镜像,形成了一个不成文的世界标准,所有后来的入局者都必须关注它。

CRI and OCI

OCI 全称为 Open Container Initiative,它发布镜像和容器的规范。它于 2015 年由 Docker 发起,并被微软、Facebook、英特尔、VMWare、甲骨文和许多其他行业巨头接受。


OCI 还提供了规范的一个实现,被称为 runc ,它可以直接使用容器,创建并运行它们等。


容器运行时接口(Container Runtime Interface,简称 CRI)是一个 Kubernetes API,它定义了 Kubernetes 如何与容器运行时交互。它也是标准化的,所以我们可以选择采用哪个 CRI 实现。

用于 CRI 和 OCI 的容器的软件堆栈

Linux 是运行容器的软件堆栈中最基本的部分:



请注意,Containerd 和 CRI-O 都坚持 CRI 和 OCI 规范。对于 Kubernetes 而言,这意味着它可以使用 Containerd 或 CRI-O,而用户不会注意到其中的区别。它还可以使用我们现在要提到的任何其他替代方案——这正是创建和采用了 OCI 和 CRI 等软件标准的目标。

Docker 软件堆栈

Docker 的软件堆栈包括:


  • docker-cli,面向开发者的 Docker 命令行界面

  • containerd,最初由 Docker 编写,后来作为一个独立的项目启动; 它实现了 CRI 规范

  • runc,它实现了 OCI 规范

  • 容器(使用 chroot、cgroups、命名空间等)


Kubernetes 的软件堆栈几乎是相同的;Kubernetes 使用 CRI-O,而不是 Containerd,这是由 Red Hat / IBM 和其他人创建的 CRI 实现。

containerd

containerd 作为一个守护程序在 Linux 和 Windows 上运行。它加载镜像,将其作为容器执行,监督底层存储,并负责整个容器的运行时间和生命周期。


Containerd 诞生于 2014 年,一开始作为 Docker 的一部分,2017 年成为云原生计算基金会(CNCF)中的一个项目,并于2019年年初毕业。如果你想了解一些 Containerd 的使用技巧,欢迎查看下方的文章:

配置 containerd 镜像仓库完全攻略

runc

runc 是 OCI 规范的参考实现。它创建并运行容器以及其中的进程。它使用较低级别的 Linux 特性,比如 cgroup 和命名空间。


runc 的替代方案包括 Kata-Runtime、GVisor 和 CRI-O。


Kata-Runtime 使用硬件虚拟化作为单独的轻量级 VM 实现 OCI 规范。它的运行时与 OCI、CRI-O 和 Containerd 兼容,因此它可以与 Docker 和 Kubernetes 无缝工作。

Google 的 gVisor 创建包含自己内核的容器。它通过名为 runsc 的项目实现 OCI,该项目与 Docker 和 Kubernetes 集成。有自己内核的容器比没有内核的容器更安全,但它不是万能的,而且这种方法在资源使用上要付出代价。


CRI-O 是一个纯粹为 Kubernetes 设计的容器堆栈,是 CRI 标准的第一个实现。它从任何容器镜像仓库中 提取镜像,可以作为使用 Docker 的轻量级替代方案。

今天它支持 runc 和 Kata Containers 作为容器运行时,但也可以插入任何其他 OC 兼容的运行时(至少在理论上)。


它是一个 CNCF 孵化项目。

Podman

Podman 是一个没有守护进程的 Docker 替代品。它的命令有意与 Docker 尽可能兼容,以至于您可以在 CLI 界面中创建一个别名并开始使用单词“Docker”而不是“podman”。

 

Podman 的目标是取代 Docker,因此坚持使用相同的命令集是有意义的。Podman 试图改进 Docker 中的两个问题。

 

首先,Docker 总是使用内部守护进程执行。守护进程是在后台运行的单进程。如果它失败了,整个系统就会失败。

 

第二,Docker 作为后台进程运行,具有 root 权限,所以当你给一个新的用户访问权时,你实际上是给了整个服务器的访问权。

 

Podman 是一个远程 Linux 客户端,可直接从操作系统运行容器。你也可以以 rootless 模式运行它们。它从 DockerHub 下载镜像,并以与 Docker 完全相同的方式运行它们,具有完全相同的命令。


Podman 以 root 以外的用户身份运行命令和镜像,所以它比 Docker 更安全。另一方面,有许多为 Docker 开发的工具在 Podman 上是不可用的,如 Portainer 和 Watchtower。摆脱 Docker 意味着放弃你之前建立的工作流程。

 

Podman 的目录结构与 buildah、skopeo 和 CRI-I 类似。它的 Pod 也非常类似于 KubernetesPod。

Linux 容器:LXC 和 LXD

LXC(LinuX Containers)于 2008 年推出,是 Linux 上第一个上游内核的容器。Docker 的第一个版本使用了 LXC,但在后来的发展中,由于已经实现了 runc,所以 LXC 被移除了。

 

LXC 的目标是使用一个 Linux 内核在一个控制主机上运行多个隔离的 Linux 虚拟环境。为此,它使用了 cgroups 功能,而不需要启动任何虚拟机;它还使用命名空间,将应用程序与底层系统完全隔离。

 

LXC 旨在创建系统容器,几乎就像你在虚拟机中一样——但硬件开销很小,因为这些硬件是被虚拟化的。

 

LXC 不模拟硬件和软件包,只包含需要的应用程序,所以它几乎以裸机速度执行。相反,虚拟机包含整个操作系统,然后模拟硬件,如硬盘、虚拟处理器和网络接口。

 

所以,LXC 是小而快的,而虚拟机是大而慢的。另一方面,虚拟环境不能被打包成现成的、可快速部署的机器,而且很难通过 GUI 管理控制台进行管理。LXC 要求技术人员有很高的技术水平,并且优化后的机器可能与其他环境不兼容。

LXC VS Docker

LXC 就像 Linux 上的一个增压 chroot,它产生的“小”服务器启动更快,需要更少的 RAM。然而,Docker 提供了更多特性:


  • 跨机器的可移植部署:使用一个版本的 Docker 创建的对象可以传输并安装到任何其他支持 Docker 的 Linux 主机上。

  • 版本控制:Docker 可以用一种类似 git 的方式跟踪版本——您可以创建容器的新版本,将它们回滚等等。

  • 重复使用组件:使用 Docker,您可以将已经创建的包堆叠到新包中。如果您想要一个 LAMP 环境,可以安装一次它的组件,然后将它们作为预先制作的 LAMP 镜像重新使用。

  • Docker 镜像存档:可以从专用站点下载数十万个 Docker 镜像,并且很容易将新镜像上传到这样的镜像仓库中。

 

LXC 面向系统管理员,而 Docker 更面向开发人员。这就是 Docker 更受欢迎的原因所在。

LXD

LXD 有一个特权守护进程,它通过本地 UNIX socket 和网络(如果启用)公开 REST API。您可以通过命令行工具访问它,但它总是使用 REST API 调用进行通信。无论客户端是在本地机器上还是在远程服务器上,它的功能都是一样的。

 

LXD 可以从一台本地机器扩展到几千台远程机器。与 Docker 类似,它是基于镜像的,所有更流行的 Linux 发行版都可以使用镜像。Ubuntu 的公司 Canonical 正在资助 LXD 的开发,因此它将始终运行在 Ubuntu 以及其他类似 Linux 操作系统的最新版本上。LXD 可以与 OpenNebula 和 OpenStack 标准无缝集成。

 

从技术上讲,LXD 是站在 LXC 的肩膀上(两者都使用相同的 liblxc 库和 Go 语言创建容器),但 LXD 的目标是改善用户体验。

Docker 会永远存在吗?

Docker 拥有 1100 万开发者、700 万个应用程序和每月 130 亿次的镜像下载。如果仅仅说 Docker 仍然是领导,那就太轻描淡写了。然而,在这篇文章中,我们已经看到,现在已经有许多产品可以取代 Docker 软件栈的一个或多个部分,并且通常情况下没有兼容性问题。而且与 Docker 提供的服务相比,其他软件的主要目标是安全性。


本文转载自:RancherLabs(ID:RancherLabs)

原文链接:不止Docker:8款容器管理开源方案

2021 年 7 月 02 日 08:005479

评论 2 条评论

发布
暂无评论
发现更多内容

12周架构

FreeOcean

hadoop mapreduce YARN

程序员成长第六篇:如何选择公司?

石云升

职业发展 2月春节不断更 选择公司

前端冲刺必备指南-HTTP/HTTPS/HTTP2/DNS/TCP/经典题

魔王哪吒

学习 程序员 面试 前端 2月春节不断更

香,聊聊TiDB的分布式事务模型

程序员jinjunzhu

分布式数据库 TiDB Percolator

一个人的春节,也要过得开心

程序员架构进阶

个人感悟 七日更 2月春节不断更

【STM32】stm32f407 + DS18B20 碰出不一样的火花

AXYZdong

硬件 stm32 2月春节不断更

7. ✎会查新华字典不?会。Python字典已经掌握了

梦想橡皮擦

Python 爬虫 2月春节不断更 python入门

日记 2021年2月12日(周五)

Changing Lin

2月春节不断更

机器学习·笔记之:inverse and transpose

Nydia

Elasticsearch 分词器

escray

elastic 七日更 死磕Elasticsearch 60天通过Elastic认证考试 2月春节不断更

Python优化机制:常量折叠

Python猫

Python

LeetCode 数据库刷题 - 596. 超过5名学生的课

小马哥

七日更 二月春节不断更

日记 2021年2月11日(周四)

Changing Lin

2月春节不断更

编写优雅Javascript代码的最佳实践

devpoint

js 纯函数

鼠年最后一天

IT蜗壳-Tango

七日更 2月春节不断更

【LeetCode】杨辉三角Java题解

HQ数字卡

算法 LeetCode 2月春节不断更

Ray 1.0 架构解读

lipi

分布式计算 Apache Arrow ray

CNCF 2021年展望:外围有亮点,核心还有硬仗

杨明越

Java反射--2021面试题系列教程(附答案解析)--大白话解读--JavaPub版本

JavaPub

Java 面试 反射 java反射 javapub

给自己的新年指南

boshi

七日更 新年

牛年到 春节快乐

小马哥

2021年展望

走进 Tokio 的异步世界

lipi

rust 异步 tokio

6. Python 元组,不可变的列表,滚雪球学 Python

梦想橡皮擦

Python 2月春节不断更 python入门

业务中台建设 - C端用户中心

孝鹏

中台架构 用户

【LeetCode】数据流中的第 K 大元素Java题解

HQ数字卡

算法 LeetCode 2月春节不断更

过节 劝你少喝酒(一)

三号无名指

GitHub 上的优质 Linux 开源项目,真滴牛逼!

JackTian

GitHub Linux 开源 运维工程师 2月春节不断更

产品经理训练营-第四周作业

羽室

微信限量纪念版code封面来啦,速看领取方式

孙叫兽

视频号 2月春节不断更 孙叫兽 微信红包封面 纪念版

定投,积沙成塔的财富增长方式

boshi

理财 七日更

香烟缭绕的岁末

ITCamel

开源中间件技术学习路线

开源中间件技术学习路线

不止Docker:8款容器管理开源方案-InfoQ