本文是 Mesos 专家Timothy Chen 在 7 月 23 日数人云对话 Docker&Mesos 沙龙活动上做的分享实录,Tim畅谈了 Mesos 架构的设计特点。
无独有偶,2016 年 7 月 27 日 Apache 社区发布了 Apache Mesos 1.0.0。 1.0.0 版本的推出,印证了Tim在分享中提到的很多改进: Docker daemon 的弃置,接口规范化、对 CNI 和 GPU 的支持以及更细粒度的授权验证机制等等,让我们来看看这位大神对他所热爱的 Mesos 技术的深刻解读——
大家好,我叫Timothy。两三年前我加入了 Mesosphere,是 Mesosphere 比较早的一个员工。Mesos 容器发展得非常迅速,借这个机会,我准备了今年在美国 MesosCon 讲过的题目《Container in Mesos》与大家分享。
什么是 Containerizer?
说起 Mesos Containerizer,大家可能都只听说过 Mesos 跟 Kubernetes 有点像,Mesos 可以把资源管理分配,可以跑容器、可以跑 Docker,以及很多公司在用 Mesos。事实上 Mesos 里面大约一半以上的代码全部都是在写怎么跑容器,而不只是把容器交给 Docker。在三四年前或是更早以前,Mesos 刚开始的时候,我们就想跑容器,于是从 LXC 开始慢慢研发,写了一套类似 Docker Daemon 的系统,但是那时候并没有足够重视它,直到 Docker 出来之后发现大家对容器那么关注,我们才开始出来与大家分享 Mesos Containerizer到底是做什么的。
Mesos 里面有两个Containerizer,第一个是上面提到的 Docker Containerizer,由我和 Ben Hindman 一起编写,完全把容器所有的工作全部丢给 Docker deamon,而 Mesos 基本上不参与容器管理的任何部分。另一个是 Mesos Containerizer,它是在很久以前就开始编写的。实践 Mesos 时间最长的公司是 Twitter,其次是 Apple,实际的数字不便透露,总量大概超过十几万台电脑。事实上它们跑的是最底层的 Mesos Containerizer,而上层的 Docker Containerizer 用 at large scale 的时间并没有比 Mesos Containerizer 多,所以我认为最成熟稳定的 agent 的确是 Mesos Containerizer,比 Docker 跑得更久、更稳定、更成熟,并且应该没有比它跑得更久、更成熟的 open source option 了。
两个 Containerizer 的抉择
在今年年初的时候,我们一直在跑两个 Containerizer,Docker Containerizer 完全支持 Docker,让 Docker 跑所有的容器;另一个 Mesos Containerizer 则由 Mesos 管理和执行。这样做的好处是当使用者想要使用 Docker 所有的工具,比如说今天想要跑 Docker,想要直接 SSH 到我的 server 里面去,跑 Docker PS,想要 Docker exec,想要做一些 Mesos 以外的事情,就可以去跑 Docker Containerizer。可是我们发现两个 Containerizer 很难 maintain:当我们从 Persistent volumes 到新的 IP per Container 到 GPU support 时,每一步都很难,而 Docker 那边也不会让我们轻易改他们的 code。这中间拉扯了好几次之后发现我们为了长久地支持 Mesos 必须要有一个最稳定的平台,同时可以有很多新的 feature,于是我们就决定把我们的重心全部放在 Mesos Containerizer 上。
Unifed Containerizer 这个名字很好听,其实就是把 Mesos Containerizer 单独拿出来,把 Docker 有的、Mesos 还没有的东西加进去。我会大致描述一下到底 Docker 有什么、我们没有什么,但是在这之前我要先解释一下 Mesos Containerizer 的特别之处。
解析 Mesos Containerizer
我们在设计 Mesos Containerizer 的时候就已经想要把它变得非常弹性化。无论是想要添加一个 Isolator、想要跑各种各样的 OS,还是 Linux 有一个新的 Linux Base 或 Cgroups,都可以很容易地添加,也很容易去掉,并且每一个使用者都可以选择到底要跑哪一种 Isolation。
基本上 Mesos Containerizer 有三个主要部分——Launcher,Isolator 以及 Provisioner。Launcher 很简单,当用户跑容器的时候,每一个容器都是一个 process,在跑 process 里有几种方式,一种是用 Linux 的方式,我们现在正在做的就是把 Systemd 很好地集成到 Mesos 里面去,所以 Launcher 基本上就是如何支持,如何管理一个简单的 Posix。
我认为 Mesos Containerizer 里面最重要也最强大的一个功能就是 Isolator。我们当时在设计的时候,就在想可以让使用者(运维人员或是开发者)需要容器做任何事情或者是不想让它做任何事情,都可以自由的选择想要的 Isolator。
强大而美妙的 Isolator
Isolator 也很简单,只是一个 interface。严格来说,跑 Docker 的容器里面有相当大的一部分的代码都是在做 Isolator 这件事,Isolator 就是把 Cgroups 设置好,Cgroup 有 CPU shares、Memory 等各式各样子的 Cgroups,还有各式各样子的 Linux Base,这是一种隔离,一种 Isolator 的机制。如果跑 Docker, 既没有办法让 Docker 不把 Linux Base 放上去,也不能添加新的 Linux Base,因为 Docker 并不能弹性化地增加或者减少 Isolator。用户在 slave 或 agent 上的时候,可以选择想要跑哪一些 Isolation,这可能对于小型用户来说并不重要,但是对于我们 Mesosphere 支持的大型客户来说是非常需要的功能。Isolator 基本上是在每一个容器开始之前或者是在开始之后或者是 destroy 之后发生的每一个 life cycle 都有的一个 hook,所以用户在任何阶段都可以自己定一个 Isolator,放到 Mesos 里面,在每一个容器上都可以增加或减少一个容器所有的功能。
我拿 Mesos 其中一个 Isolator 举例。刚刚讲到 Cgroups 是其中一种隔离机制,那么 Cgroups Memory Isolator 是如何工作的呢?
以 Cgroups Memory 来讲,当容器在 run 之前,首先要先确定好 Cgroups 以下的 hierarchy,需要在 Cgroups 里面创建一个 Memory 的子目录。当容器开始跑之后,就可以把容器放到 Cgroups Memory 目录底下,写 Cgroups Memory Isolator 时直接创建一个 directory。当容器 fork 之后,拿到 pid,就可以说 Isolator 直接把 pid 放到了刚刚创建的容器里面。其它 process 都是由 Mesos Containerizer 帮忙都处理好的。然后当我们 in Mesos 以后,一种特别的跑容器的方式是跑一个 Executor,如果大家对 Executor 不了解,可以去看看 Mesos 的 Docker documentation,有许许多多像 Spark、HDFS 都写一个特别的 Executor,是专门为了那种容器可以有更强大的功能而写的。
Executor 最特别之处在于容器在跑的同时直接 realtime update 它现在的 resouce limit,例如跑一个容器跑两个 CPU,那么如果多跑一个 task 在同一个容器里面,就不用跑新的容器,Memory Isolator 直接把那个容器底下的 Cgroups 改到 4 就可以了。
所以 Isolator 是一个很强大的 Mesos Containerizer 功能,Mesos 里面有许多不同种已经 built-in 的 Isolator,像刚才讲的 Cgroups Isolators、GPU Isolators、Memory Isolators、Disk Isolators 等等。
Mesos 还支持 Docker Volume Plugin,用户可以在 Mesos Containerizer 里面直接跑 Docker Volume。现在 Mesos 也支持两种 Network,之后会慢慢增加。我们大概三个月前开始研发 GPU,1.0 里面已经有 GPU 的支持了,所有 GPU 支持的代码都写在一个 Isolators 里面,几乎都不用触及其它的代码。对我们研发者来讲,当要增加许多功能的时候,这是一种非常好用的方式。
这是我们研发的 GPU Isolator,如果大家对 GPU 跟 Container 有兴趣,可以去试试看 Mesos1.0。在 Mesos 里面,GPU 的方式是只让特定的容器使用某种特定的 GPU,用户有四个 GPU,跑四个容器,每一个容器可能都只能跑一个 GPU,Mesos 会确保每一个容器只会跑可以使用的特定的那个 GPU,所以在 Cgroups 层面其实就有一些机制让用户 allow 跟 deny。现在我们只支持 Nvidia 的 GPU,它会自动在 host 里面找所有 Nvidia 需要的 runtime libraries 跟 drivers,然后直接添加到 Docker 容器或者 Mesos 容器里面,这也是非常方便的一个新的功能。
Provisioner——容器镜像支持
Unified Containerizer 基本上是想把 Docker 有的、我们还没有的放到 Mesos 里面来,这中间最大的差别就是 Docker 发明出来的新事物——镜像,这是 Docker 的一大贡献。用户可以不用安装 Docker 就跑 Docker 容器,但是需要镜像的支持。从 0.28 开始,Mesos 就已经有 Provisioner,它可以帮助用户跑 Docker 容器,但是不需要 Docker daemon。
最重要的是,我们之所以可以这样做是因为 Mesos 支持镜像,支持 Docker 现在的 registry,无论是 private registry 还是 public registry。对于大型的企业来说,可能需要在防火墙里面放一个镜像的 registry,这些情况 Mesos 都支持,既可以 download cache,也可以把所有 Docker 镜像里面的 layers 组成一个 filesystem。我们把 Docker 有的一些 feature 直接加在 Mesos 里面来,从而不被 Docker 镜像 standard 捆绑。
现在硅谷那边我们有一个新的 project 叫 OCI,所以未来不只是 Docker 或者是 APPC,OCI 也会加入,可以直接支持每一种新镜像的 standard。目前我们正在增加 CVMFS,这是一个非常强大的 standard,它只需要下载用户所需要用的档案,例如 Ubuntu 今天只跑一个 iOS,那么只要下载 iOS 所需要的那一块 library,它的大小可能只有 10KB。
API 的加入
当资源跑 Docker 容器不再需要 Docker 的时候,就需要 Mesos framework 作为代替,所以我们增加了这些 protobuf API。Mesos 从 1.0 之前或者是 0.28 之前大部分通信都是用 protobuf 信,现在则多了一些 Docker 的选项,用户可以跑 Mesos Containerizer,但是如果要跑 Docker 或 APPC 的镜像,Mesos agent 也会自动支持这个 feature。
跑 Unified Containerizer 最大的好处是当我们把 Mesos 正在做的所有这些 feature、包括我们之前就已经做过的甚至 Kubernetes 跟 Docker 都还没有的一些 feature 加入后,可以把用户资源利用率提高到 50%到 60%以上,秘诀就是在 Google Borg paper 里面写的 resource reservation,比如用户的资源可能只有四个 CPU,Mesos 可以把它超到八个,因为实际上用户并没有在使用那么多的资源。network 的 spec 是 Mesos 正在增加的一个 CNI,有点像刚才讲 OCI 是一个镜像的 standard,CNI 就是一个 networking 的 standard,是 CoreOS 开始的,目前已经加入到 1.0 版本当中。CIN 有很多类似不同种 networking 的后端,我们都支持。包括 Docker Volume Plugins,我们也开始支持了。
当我们集中所有的精力在 Mesos Containerizer 之后,我们开始做一些 Docker 有的、Mesos 还没有的功能,像 Linux Capabilities 就是其中一个。Capabilities 很重要,是大型的 Container 都需要的功能。同时,我们也正在做 User namespace。
走的更长久的 Mesos Containerizer
我与大家分享一下我们近期内在做的有关容器的一些开发。第一个是 Nested Container,当我们跑容器的时候,可以在容器里面将它分割成更小的容器。当大容器里面可以管理一定资源 boundary 的时候,重新再贴上更小的容器,这个对于跑 CI/CD、Jenkins 在 Mesos 上时很有用,每一个 Jenkins 都可以有自己的一个资源上限,它要跑十个 CI job,Mesos 就把已经有的资源给它们,但是它们确保不会跑出 Mesos 给的资源上限。VM support 就是 Mesos 可以不跑容器,直接跑 VM,对于比较传统的一些 IT 企业来说,他们还没有办法从 OpenStack 或者从 VM 里面直接跳到容器里面,所以这是非常重要的一个功能。当然,还有其它一些对于 Mesos 来说更容易开发和使用的功能。
接下来我们继续会把所有的精力放在 Unified Containerizer 上,Unified Containerizer 已经在 Twitter 和 Apple 用了三四年,是比现在 Docker 或是 APPC、Rocket 更成熟稳定的 Containerizer。当我们比较 Mesos 跟 Kubernetes 甚至以后还有更新的一些 Container scheduler 时,对比容器的 runtime 所谓的成熟度,在生产环境里面跑得最久的依然是 Mesos Containerizer。