Mesos大神Tim实录分享 | 解读Mesos 1.0 + 更长久的Mesos Containerizer

本文是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。