容器在多个方面都是不断变化的目标。由于有多种工具、框架、实现和用例来完成任何任务,容器世界可能会快速发展且混乱,这对于一个新兴且流行的事物来说是自然的结果。
好消息是,所有这些创造性的孵化都极具生产力,而且由于这一切都是开源的,每个人都可以分享所有这些美妙创造力的好处。坏消息是,这就像一群精力充沛的猫。我们如何知道该往哪个方向发展?我们是否必须为今天所做的工作在几个月后就过时而做好准备?而且,可移植性又如何呢?
我想对容器的未来以及我们可以期望的先进技术的发展方向提供一些见解。
容器标准的演变
容器标准已变得更像是一种正式的对话,也是一种政治性的对话。但目前在这方面的进展更加标准化和规范化,并且围绕所有不同参与者之间的互动制定了一些正式规则。而在过去几年,或者至少是前三年,唯一的标准是任何给定工具上的配置文件,或实现方式。
Systemd 有其自身的 nspawn 实现方式,而 Linux Containers (LXC) 有其自身的 LXC 实现方式。它们与工具的交互方式各不相同,但当涉及到很多人都在问的问题(“我该如何开始使用容器?”)时,你只能自己制作。根本没有分发镜像的概念。你必须自己解决这个问题。
然后 Docker 出现了,并引起了人们的关注。Docker 为大家带来的一件事实际上是一个新的元软件包。很多人已经熟悉 RPM 和 Debian 软件包,以及 Java 应用程序的 JAR 文件、Ruby gems 和 NPM node 软件包等等。但是,他们想把所有这些放在一起,形成一个容器镜像,就像一个大型的、卷起来的元软件包。然后,开发者想要分发这个元软件包。
在过去一两年里,已经出现了一种非正式标准,它是基于人们对 Docker 的初步尝试,他们现在正在构建这些 Docker 软件包,希望以不同的方式部署,因此他们需要弄清楚自己的用例。由于这种方法受到了关注,它已成为一种非正式标准。
容器标准的重要性
看到人们在哪里进行标准化很有趣,看到一些相互竞争的标准出现也很酷。例如,在网络领域,有 Docker 的容器网络模型 (CNM),还有另一个名为 CNI 的模型,即 容器网络接口。它们有不同的方法来解决一些类似的问题,但人们选择使用其中一个而不是另一个来解决他们特定的用例。尽管 Kubernetes 编排是围绕 Docker 大力构建的,但它最终 绕过了 Docker 的 CNM 模型,并采用了 CNI 网络规范。
另一个新兴的标准是 开放容器 的运行时规范和开放容器的镜像规范。运行时规范的主要用例是为启动容器定义调用模型。有些用例只需要运行一个命令,并将所有附加功能留给更高层级处理。运行时规范的参考实现是 runC。即使在红帽,runC 也被用于早期启动容器;有些东西甚至可能需要在 Docker 守护程序启动之前完成。
这些容器仍然需要分发到主机,这就是 OCI 镜像规范的用武之地。一个为分发容器镜像定义的布局,你可以在其中选择签名和联邦,以及在不同的工具之间移植容器镜像。有一些工具,如 skopeo,可以方便地进行推送、拉取和签名,并在 OCI 和 docker 之间实现互操作性。rkt 的最新版本现在也支持 OCI 镜像。
随着标准的不断发展,我们已经有了相互竞争的标准。在 OCI 之前,有 appc 规范,它涵盖了分发、镜像分配和运行时,以及镜像本身。虽然开放容器倡议只涉及 appc 所做工作的一小部分。但我们在这两者之间也有大量的交叉融合。来自每个规范的维护者都在为另一个规范做出贡献,并且有来自 appc 的维护者也在 OCI 上,反之亦然。
基本上,一种工具不能满足所有需求。人们会有不同的用例。这就是为什么你会看到有些人甚至使用 runC 类型的工具来运行迷你虚拟机 (runv)。现在容器不仅仅是一个容器,它实际上是一个虚拟机 (VM)。但你只是给它一个根文件系统,然后它就可以以相同的布局运行一个小型虚拟机。而镜像规范只是为了实现你可能已经内置的互操作性。
你可以选择 Docker、Rocket、LXC、runC,甚至 sytemd-nspawn...或者其他一些容器工具,如 bubblewrap,用于非 root 容器。当你在研究你的用例时,你仍然可以拥有相同文件系统的可移植性。你可以拥有该文件系统的可移植性和分配该文件系统。然后选择最适合你用例的工具。
标准在这方面非常重要。
容器成功的关键要素
我们已经看到开发者在过去一两年里取得了很大的进步和发展。尽管下一个范式转变即将发生。
目前,开发者正在使用他们熟悉的应用,并将它们塞进容器中。然后他们会问很多与虚拟机相关的问题。我觉得下一代开发者不会仅仅是将现有软件塞进盒子里,而是会编写或重写现有软件或新软件,并将容器概念和基础考虑在内,他们将开始更加意识到其应用所受到的限制。这将是一个有趣的领域,因为对于某些人来说,这可能会非常令人兴奋,他们从未深入到内核级别。他们也不真正关心 capabilities、seccomp、syscalls、SELinux、AppArmor 和所有这些东西。他们只是想把它塞进盒子里并运行。他们可能仍然在考虑虚拟机。
但是下一代开发者将需要更加意识到一个事实,即当他们的应用程序要投入生产时,他们将不会拥有主机上的 root 权限;他们没有对运行它的机器的完全开放访问权限;capabilities 受到限制。他们应该假设他们的软件处于尽可能受限的世界中。
让开发者看到、访问和分析他们的应用程序非常重要,因为即使你正在编写一些高级的 Ruby 或 Python Web 应用程序,你也需要知道该应用程序实际请求了哪些 capabilities 或 syscalls。你的块 I/O 或网络 I/O 行为在哪里?这些都是值得提出的好问题。这将对容器世界产生重大影响,因为你的应用程序可能会立即被部署到在限制下运行的基础设施上,然后你就会遇到未定义的行为,这可能很难调试。
我觉得开发者思考软件编写方式的方式将会发生转变。例如,当他们考虑是否需要 MySQL 时。也许他们只需要它的某些方面。数据库可能会开始改变。人们编写和思考应用程序的方式正在开始改变。将会有更多工具可用于更轻松地看到这类东西。
更重要的是,不仅仅是标准,还有工具。一旦有了标准,各种工具基础设施,如调试和工具,将具有非常一致的期望。例如,关于镜像的可移植性,或镜像的运行时,它们可以以此为基础构建。只要它是一个不断变化的目标,大多数人就会坐等,直到事情变得更加稳定。这对开发者来说非常重要。他们喜欢热点和快速,但他们也不希望花费数周时间来调试未定义的行为。
容器标准的未来
每个人都在关注的大事是如何最好地对冲碎片化。不幸的是,对于像容器这样流行、快速发展和增长的事物来说,它同样有可能蔓延、冲突和碎片化,而没有人需要那样。只要人们都在为特定的用例而努力,并且对所有不同的用例都保持友好态度,容器就会有很多真正的好处。
另一方面,就是不要有相互竞争的标准。这是一个古老的问题,当你有两个事物的实现,但它们都不能完全解决问题时,你就会进行第三个实现。现在你就有三个问题了。这是有道理的,因为如果前两个没有解决所有需要的用例,那么显然也需要其他东西。因此,公平友好地做到这一点将是最大的持续挑战,因为我们都是人。
文森特·巴茨将在加拿大多伦多举行的 2016 年北美 LinuxCon + ContainerCon 大会 上发表演讲。他的几次之前的会议演讲可在 YouTube 上观看
评论已关闭。