今天我将分享《美团云容器实践之路》,跟大家介绍一下美团云在容器技术方面的一些实践经验。我会先简单介绍美团云,点明为什么美团要开始探索容器,再介绍我们在容器方面做了哪些事情,以及做这些事情的效果,最后也会提到美团云未来的一些发展思路。
一、关于美团云
我们是美团的基础设施部门,叫云计算部,同时负责管理美团的私有云和公有云。美团的私有云承载美团自有业务,已经完全虚拟化,美团所有业务都运行在私有云之上,包括美团团购、外卖、酒店、猫眼等业务线。与大众点评合并之后,点评的基础设置也由美团云来管理和支撑。我们同时通过公有云业务对外把美团的技术包装成服务产品,面向公众,让外部的开发者、企业也能够使用我们的基础设施和服务。
美团云的发展相对比较早。我们在2012年就已经开始规划平台,并开始研发美团云的云主机管理平台。2012年9月份,开始逐步把线上业务往美团云的虚拟机里面迁移。当时美团规模还相对比较小,业务迁移的代价比较低,因此到2013年7月就基本完成了整个基础设施上云的迁移。在这中间,我们开始考虑怎么把云平台能够包装成一个通用技术产品。2013年5月开始把云主机通过美团云MOS面向公众开放,后面不断发展和完善美团云基础设施、技术和服务,2015年3月我们开始有自建的机房和网络基础设施,并在7月通过了可信云认证。
二、引进容器技术的原因
有了美团云后,美团整体的基础设施交付效率有了很大的提升。在这之前必须要用物理机,而物理机存在很多问题。首先,物理机里面部署服务,多个服务相互影响,不方便运维管理。其次, 服务器交付时间比较长,部署周期也比较长。引入虚拟化之后,围绕虚拟机就把整个主机交付流程自动化了,整体效率有一个很大的提升,整体基础设施运营效率走在了行业的前列。
2015年左右,以Docker为代表的容器技术逐步成熟,并开始在各个互联网公司被逐步使用。那时面临的几个问题,让我们感觉到可能需要把容器技术引入进来,作为一个在原有虚拟机基础之上让主机资源交付更加弹性、更加自动化的升级技术。
1、私有云压力
先介绍一下私有云面临的问题。私有云承载着美团自己的业务。美团业务一个最大的特点是业务流量有非常明显的周期性和突发性。比如外卖或者团购每天都有上午和下午两个请求高峰,夜间则请求量很低。同时还有一些突发情况导致的突发流量,例如情人节,七夕等活动大促。还有美团点评有一些直播,一开直播,马上就会有一些突发的请求流量。另外一些异常天气也会引起突发的请求流量。例如, 在下雨、下雪等异常天气时,外卖流量会比平时高很多。这些特点就要求我们的业务容量必须要做N倍的冗余。我们规划系统容量时,不能仅按照平常的波峰来设计,还得在这个基础上高2~3倍,这样才能应对突发的业务请求。
虽然美团点评的主机已经完全虚拟化,交付效率已经比较高,但面对这样突发的业务请求,这样的交付效率还是无法满足在高峰来临前立即分配资源来应对突发业务的需求。因为云平台交付给业务的还是虚拟机,交付完之后业务还需要做很多操作,包括环境部署、代码发布,配置变更等。所以一般虚拟机交付业务团队之后,他们就不太愿意把虚拟机还回来,一般在做扩容之后就不再会缩容。
为了应对突发流量,刚才说需要按照峰值的2到3倍冗余去部署。用虚拟机的方式,系统容量就是峰值的2到3倍,这些冗余的处理能力在平时是用不了的,但也不会被释放,所以就出现了资源的浪费。这就导致我们希望能够更自动化的让应用部署起来,更自动化地让业务能够提供服务,这样可以让业务系统容量弹性起来,降低系统资源的浪费。
2、公有云压力
同时,公有云也面临一些变更效率的问题。美团云的公有云业务除了基础的云主机产品之外,还会提供PaaS产品。一个典型的PaaS产品就是MySQL的RDS服务实例。比如用户购买一个MySQL实例,后台会自动化为他创建一对一主一从的虚拟机,里面部署一对主从同步的MySQL实例,对用户提供MySQL数据库服务。用虚拟机实现这种PaaS产品的问题是,虚拟机的部署时间比较长,达到分钟级。用户提交一个创建MySQL的请求,需要创建两个虚拟机,上面部署MySQL,等待他们启动,启动完了用户才开始使用,整个流程需要几分钟。扩容流程也很复杂,这里给了一个扩容流程的简单示例。
两台主备的MySQL实例,如果要扩容CPU和内存,需要首先关机扩容备份节点,备份节点扩容完成启动后启动,与主节点追同步,等数据同步完成,开始做主备切换,切换完成后,关机扩容原来的主节点,扩容完成启动后,再次追数据同步,整个一个扩容也可能要十几二十分钟的时间,流程太长,也容易出错。
3、对容器技术的调研与考量
通过调研,发现容器技术能够帮助我们解决以上问题。
(1)虚拟机和容器的区别
首先,我们调研了虚拟机和容器的区别。上图的左边是虚拟机的架构。虚拟机是在宿主机上虚拟出一个个的虚拟机实例。每个虚拟机是一个完整的主机,包括虚拟硬件,操作系统内核,用户态环境。一个虚拟机启动需要等内核启动,然后虚拟设备、应用环境准备好,应用才能启动运行。因此虚拟机的启动时间较长。右边是容器。容器虚拟化的是应用环境,容器里的进程其实还是共享宿主机的内核,但通过Linux namespace伪造了一个独立的运行环境,让运行在容器里的应用感觉自己是在一个独立的运行环境里面。启动一个容器,其实就是在宿主机上启动了一系列进程。这些进程启动后,立即就能提供服务。因此,容器的启动速度要大大快于虚拟机的启动速度。
与此同时,因为虚拟机需要从通过虚拟化的硬件设备去访问底层的硬件设备,所以它的磁盘IO和网络虚拟化的消耗都很高,性能不如容器。我们做过虚拟机和容器的性能对比测试。在同一台宿主机上对比同样配置的虚拟机和容器,在磁盘IO上,虚拟机的性能大概是容器的80%到90%。
(2)容器镜像
容器除了上面说的特性外,还有一个更好的特性,就是容器镜像。虽然容器技术出现非常早,在80年代就已经有类似容器的技术出现。但2013年、2014年出现的Docker容器才让容器技术火爆起来。
Docker最大的亮点就是 Docker镜像。Docker镜像能够把应用和运行环境一起打包交付,容器启动后应用立即就能运行,不需要做额外的配置,真正做到build once,run anywhere。同时Docker镜像是分层的。一个Docker镜像可以基于更基础的Docker镜像构建,保存这个镜像的时候,会把差异部分做为一个层和基础镜像的层一起打包。拉取镜像时,只会拉取镜像仓库中不存在的层次。
例如一个Java Tomcat web app的Docker镜像,一般是四个层次,最底层是基础的Linux运行环境,第2层包含了Java运行环境和配置,第3层包含了Tomcat的运行环境和配置,最上层则是web app的war包。当第一次部署时,会把整个镜像的4个层次都拉取到本地镜像仓库,之后应用升级时,构建Docker镜像一般就更新第4层的war包。这样后续部署,则只会拉取变化的第4层,那么拉取的数据量就大大降低了。通过分层和按需拉取的机制,Docker镜像使得容器能够做到秒级启动、非常高效地部署一个独立的应用环境。
我们在虚拟机时代交付的是一台虚拟机,用户获得虚拟机之后,先要部署运行环境,然后再部署应用才能够使用。但到了容器时代,这个流程就大大简化了。用户提交应用代码后,系统就会自动把代码编译打包成一个Docker镜像。用户扩容系统时,系统只需要拉取应用的镜像,启动容器,应用立刻就可以提供服务了。原来基于虚拟机的扩容是小时级别,用户不愿意缩容。但用了容器技术之后,扩容秒级完成。容器的这个特点可以帮助我解决私有云弹性的问题。
(3)容器资源限制的技术
下面说一下容器资源限制的技术。容器使用Linux内核的cgroups技术对每个容器的资源在内核层次做限制。比如一个容器,它最多能用多少内存、多少CPU资源、多少IO带宽等。这个限制方式也跟虚拟机不一样。虚拟机的资源限制是在虚拟机启动时指定的,一般不能在启动之后更改。要变就得先关闭虚拟机,然后用新的参数重新启动。对于容器,对资源限制的变更是非常低代价的,比如启动了一个4G的容器,现在想改成8G的,内核里cgroups的内存限制参数从4G改成8G就可以,容器不需要做任何改变。因为这个特点,更改容器的配置效率也非常高,基本没有任何代价。所以前面说到的PaaS遇到的配置变更效率的问题也迎刃而解。
基于以上的原因,我们在2015年中开始着手实施美团云平台引入容器技术。这个过程并不是一帆风顺的,也遇到了一些技术困难和技术切换的挑战。容器技术虽然很火,但它其实是个不断发展、不断成熟的过程。整体上容器的特性都不错,能够解决我们的问题,但在细节上还存在不少缺陷和问题,把容器集成在云平台上也需要很多工作。三、美团云的容器实践之路
我们引入容器的初期,确定了一个切合实际的目标和执行策略。
首先定了一个初始目标,要实现一个统一的虚拟机和容器的管理平台,把公司的资源作为一个整体的资源池提供给虚拟机和容器使用,避免资源的碎片化。同时要能够实现业务容器的一键发布,无需人工干预,从而支持业务的秒级扩容和缩容,不再需要预留资源。
其次,在推进策略上,前提是“稳”字当先。因为我们的云平台是给美团的自有业务,同时对外给用户使用,都是真正的生产环境,不能出现偏差。基于这个“稳”字,我们的策略第一是基于美团现有的云平台去升级改造,让它能够支持容器。先做好架构,再去优化。基于这样的策略路径,我们开始把容器引入到美团云。
1、对Docker技术的改造
首先,我们没有因为容器再去新引入一套云管理的平台,而是基于美团已有的比较成熟的云平台开发改造,提供对容器的支持。因为虚拟机和容器的区别主要体现在镜像、创建、变更、删除等方面,在整体云平台的视角看,引入容器只是给云平台增加了另外一种计算资源的交付方式。云平台现有的很多组件,例如资源管理,调度,虚拟网络管理,任务管理等方面,技术上基本都是一致的, 完全可以复用现有云平台的组件。只有在容器独特的地方,比如镜像管理、容器生命周期管理等这些方面,我们加入新的代码和组件,让我们的云平台能够支持 容器的管理和运行。这样可以最小风险地引入容器,并迅速实现大规模的部署,并且和虚拟机共享资源池。避免了因为引入新的云管理平台在资源池管理,调度、虚拟网络等方面必然出现的磨合和折腾。
其次,在容器技术上选用的是Docker 1.11版本,并且把版本固定下来,在这个版本的基础上修正发现的BUG,并针对美团云的需求进行改造。我们没有选择跟随社区的最新版本,这样也能最大程度地低降低跟随社区引入不稳定因素的风险。我们修正了Docker的一些常见问题,比如说Docker一个比较大的问题是Docker Daemon退出会导致管理的所有容器退出,这对生产环境的稳定有致命的影响,因此我们在这方面做了改进。
同时容器在某些资源限制上并不支持持久化,在容器重启之后就重置了,我们也做了相应的改造。支持美团云的底层网络,我们开发了MosBridge让Docker支持美团云的虚拟网络。另外也改造了Docker registry mirror,以支持后端存储使用美团云的云存储。还有一些其它扩展,这里就不详细介绍。总之,我们基于Docker1.11维护了一个相对稳定可靠、符合美团对容器需求的Docker版本。
2、构建容器化生态环境
除了改造Docker技术外,为了让Docker能融入到美团整体的研发流程里,我们还需要构建一个容器化的生态环境,从而让容器能够被用户使用。
首先, 在公有云,我们通过PaaS产品来让用户使用上容器。在私有云,则通过公司其他部门负责的组件,主要是PLUS和HULK两个组件,来让业务接入容器。其中,PLUS负责代码仓库的维护和容器的构建,HULK负责业务的弹性伸缩。另外,还需要改造公司的应用发布流程,以支持容器化的流程。在这个过程中,比较头疼的一个问题是从虚拟机切换到容器,容器镜像的打包由谁来负责。如果我们用原生的Docker镜像的打包方式,就需要用户自己去写Docker file,根据自身业务应用的特点编写Docker file,由研发负责Docker镜像的打包。但是,这要求所有研发要去学习Docker技术,不太切实可行。
因此,我们其实是把Docker镜像打包放在PLUS系统中实现。对业务来说研发还是把代码提交到仓库,但增加了一个构建镜像的步骤,PLUS的构建系统会自动构建出包含业务代码的Docker镜像。当业务发布时,原来是发布发布代码,现在发布的是Docker镜像。这样,我们把做镜像的流程放到以前发布流程里,Docker镜像对研发透明化了,这样就能让业务比较平滑地从以前的基于虚拟机的业务发布流程切换到基于容器的发布流程中去。
3、实施效果评估
经过多个团队的努力,容器化取得了一些初步的效果。到2015年11月,云平台对容器的支持基本开发上线了,同时HULK PLUS团队开始基于云平台的容器开始业务流程改造。2016年3月,HULK的弹性伸缩服务上线。2016年6月,公有云的PaaS产品也开始逐步接入容器。
美团业务容器化后效果初步显现。首先表现在性能方面。由于虚拟化开销降低,同配置的容器提供的服务的能力提高了。单机QPS可以提高85%。更重要的是,通过弹性伸缩,为应对业务高峰的资源预留不再需要那么高的荣誉度了。引入容器之后,业务的服务实例数量是动态变化的,每天比如说在业务高峰来临前面扩容上去,订单数下降后,这些容器就被销毁。通过基于容器的弹性伸缩服务,平均资源占用大约降低30-60%。
同时,PaaS产品通过容器部署也有较明显的收益。首先是性能有一定的提高。而最明显的是实例部署时间的降低。原来基于虚拟机部署MySQL实例可能要3分钟,通过容器化后30秒就能够部署成功。配置变更的代价则几乎可以忽略。把MySQL实例从2核4G提高到4核8G,只要改一下cgroup配置就可以了,瞬间完成。但如果是虚拟机,就得经过关机、切换这么一个复杂的过程。
四、未来的发展思路
综上所述,通过引入容器技术,我们解决了一些基于虚拟机无法解决问题,收益明显。后续还会继续深入容器在业务中的应用。
首先是会进一步提高资源利用率。目前容器主要是针对在线业务的弹性伸缩,下一步希望能够把了离线/在线业务混部,探索通过离线业务的削峰填谷,进一步提高资源利用率。离线业务的一个特点是不要求实时性,只要在某个时间点之前输出结果即可。目前公司的在线业务和离线业务集群还是分开部署的,所以离线集群的资源在离线计算不需要时,其实也是空置浪费的。所以,下一步希望把离线和在线的业务也能混合部署在一起。当在线业务繁忙时,离线业务就把资源让出来;当在线业务处于业务低谷时,离线业务再全速运行。这样能进一步提高资源的利用率,节省成本。
其次,公司整体研发流程围绕容器的重构和再造。现在我们只在生产环境引入了容器,实现在线业务自动化的弹性伸缩。我们希望能把容器引入到研发的全流程,从开发、测试到真正生产环境,都基于容器。不仅开发时用容器环境开发,测试时也是通过自动化Docker镜像的方式发布到测试环境测试,这样就保证了我们测试环境和生产环境的流程一致,更进一步提高研发的效率。
原文发布时间为:2018-04-2
本文作者:邱剑