微信扫描登录
或者
请输入您的邮件地址来登录或者创建帐号
提 交取 消
GITBOOK.CN需要您的浏览器打开cookies设置以支持登录功能

Mesos在360搜索的实践

本篇文章整理自奇虎360搜索引擎资深工程师谭博侃7月6日在『ITA1024大数据技术精英群』里的分享实录:Mesos在360搜索的实践。

enter image description here

一、Mesos原理和特点

目前快速发展的容器技术和分布式系统以及碰撞出来的微服务架构正在改变着我们对数据中心的运行和管理方式。

Mesos是Apache下的开源分布式资源管理框架,最早是由Twitter从Google的数据中心资源管理系统Borg系统中得到启发。按照官网的介绍,Mesos致力于成为是数据中心的Kernel,把数据中心当成一个资源池来给应用使用。

目前Mesos在国外和国内的互联网公司都有广泛应用,如Twitter使用Mesos管理超过30w台服务器,还有像Airbnb,EBay, Apple等优秀公司也广泛使用了Mesos高效的管理系统。

Mesos采用两级调度架构的模式:

enter image description here

第一级是Mesos-Master对资源的调度。

首先从Slave节点收集可用资源的信息,然后以资源邀约(resource offer)的形式,将这些资源提供给注册其上的Framework。

第二级调度是由独立于Mesos的Framework组件组成。

Framework包括调度器(Scheduler)和执行器(Executor),每个节点上都会运行执行器,而调度器可以独立运行在Mesos之外。

Framework可以根据应用程序的需求,选择接受或拒绝来自Mesos-Master的资源邀约(resource offer)。一旦接受邀约(offer),Mesos-Master协调Framework和Mesos-Slave,调度参与节点上任务, 并以Container为单元启动。Executor负责提供Slave上任务的运行环境,包括准备二进制文件,设置必要的环境变量,进行必要的资源隔离等。

这种模块化的划分让Mesos只专注于资源的调度,而把任务的调度交给Framework来实现,在保持高度灵活性的前提下也避免了机器和应用规模上来之后的容量和性能问题,同时也让自身的代码非常轻量。目前在Mesos上通用的Framework有Marathon, Aurora, Chronos等,也有很多针对分布式系统的如Spark,Storm,Hadoop,Kafka的Framework。

目前跟Mesos具有可比性的还有Hadoop Yarn和 Google Kubernetes。Yarn通常更适合与Hadoop的生态系统结合,Kubernetes目前还在快速发展中,前景一片大好,但目前只能和Docker结合,在大规模生产环境还需要进行一段时间的考验。Mesos目前相对更为成熟,在很多大公司在生产环境下经过了验证。同时Mesos只专注于资源的调度,把任务调度交个不同的Framework来实现相对更加灵活。

目前360搜索部门的应用规模大,种类多,小应用也多。机器使用超过2w台,而这些机器通常是按照业务进行的静态划分,这样带来了资源利用不均衡的问题。同时很多访问量小的应用为了保证高可用也都申请了双倍的机器,而访问量大的应用为了应对流量高峰也会额外申请一定配额的机器,这就带来了资源利用不均衡及资源浪费。

静态划分部署会导致流量突增时无法及时做到弹性扩展,机器故障时迁移效率低,同时给开发者养成不好的习惯,如硬编码机器地址、文件目录等。Mesos的出现,帮助我们解决了资源利用不均衡及静态部署带来的扩展性和故障恢复的问题。Mesos的资源管理器配合不同的调度器,让所有应用程序共享所有节点组成的资源池,安全地、最大化地利用资源。

下图描述了混合部署带来的好处:

enter image description here

应用迁移到Mesos之后开发者不再需要关注进程具体部署在哪些机器上,而是关注每个应用实例使用多少资源(cpu,mem,disk...),以及需要部署多少个实例。即应用对物理机器的依赖转换成对资源的依赖, 从而实现应用与物理机器的解耦。

目前我们对Mesos的使用仅处于起步阶段,整个资源池有上百台物理节点,运行了几百个应用实例。在把应用迁移到Mesos的过程中遇到一些问题和挑战,在后面章节会详细阐述这些问题及解决方案。

二、Marathon调度框架

上一节提到Mesos两级调度模型中,开发者提交的任务交给第二级调度的Framework来部署。Marathon是Mesos生态系统中非常重要的框架,用于调度长时间运行的应用,比如Web服务。如果把Mesos比喻成Kernel的话,那么Marathon就是Mesos的守护进程Daemon。Marathon使用起来非常容易上手,开发者可以通过json来定义需要发布的应用。

Marathon有如下几个重要特性:

1、高可用,通过Leader选举来保证始终有一个活跃实例;

2、通过Web页面对应用进行创建,管理和部署的能力,使用起来非常方便;

3、提供服务发现的机制和负载均衡;

enter image description here

enter image description here

4、REST API用于发布服务;

比如发布一个MesosContainer的应用(需要提供程序打包好的URI):

enter image description here

比如发布一个Docker容器:

enter image description here

5、提供约束性条件(Constraints)来约束部署的机器范围。比如我们对不同机房的机器打了机房的属性,有些应用需要部署到特定机房就可以可以通过Constraints来进行设置。

三、使用Mesos+Marathon来构建云平台

使用概况:

目前我们在Mesos运行的程序,涵盖了多种主流语言c++,python,php,java,go。场景有WebServer,UCS服务(UCS是自研发通用RPC框架),DataChannel(自研发的数据分发调度服务),离线计算等。

技术栈:

下面这张图列出了我们使用的技术栈。

enter image description here

Puppet:自动化配置和部署工具,通过抽象资源的方式来实现自动化部署,让管理者不需要关心部署的细节。同时很多开源软件都有对应的puppetmodule,可以极大的降低我们的部署成本;

Mesos:整个系统的的核心,调度资源;

HDFS:为部署在Mesos+Marathon上的应用提供资源文件;

ELK:为了方便用户部署之后查看日志,我们使用Filebeat收集Mesos上的程序产生的日志,通过Logstash提取日志路径里面对应的Framework和Task的名字, 通过ElasticSearch进行索引,使用Kibana进行搜索和展现;

Sensu:开源的监控平台,监控我们的基础组件;

Marathon:为长时间运行的服务提供调度的Framework,我们部署的大部分为无状态的服务,状态尽量存储在分布式服务上。另外我们考虑到多租户下权限管理的问题,我们在RootMarathon上为不同用户部署不同的Marathon实例,方便进行隔离和管理;

Chronos: 提供分布式定时任务调度的Framework;

Kafka: 分布式队列服务;

NoSQL:提供分布式KV存储, 目前我们使用了Redis,RethinkDB, HBase, Stored(搜索自研发的分布式存储);

InfluxDB:时间序列数据库,我们有很多监控的Metrics写入到InfluxDB, 也有一些基于InfluxDB的数据监控和报警;

Telegraf:用于收集系统和服务的统计数据到InfluxDB;

Kapacitor:针对InfluxDB的数据进行处理,监控和报警;

Grafana:提供InfluxDB上不同数据指标的图表展现;

Jenkins:提供持续集成服务;

Marathon-lb(HAProxy):提供TCP/HTTP的代理,在Marathon创建的服务可以自动注册到HAProxy上,不同的应用分配不同的端口, 服务发生变化的时候会重新生成HAProxy的配置并reload;

SmartClient:是自研的让客户端直接连接后端服务的框架, 通过和Marathon定期保持通讯来更新最新的服务列表。

发布和部署:

Container是Mesos部署和调度的最基本的可执行单元。Mesos主要提供了下面两种Container的方案:一是大家非常熟悉的DockerContainer的方案,另外是Mesos默认的MesosContainer的方案,这个也是我们目前选择比较多的方案。

DockerContainer:Docker对于依赖和安装复杂的应用来说非常合适。但是和Mesos结合也有一些缺点,需要额外的安装和维护,升级时Docker的任务会退出,不能很好的利用mesos内置的一些特性,由DockerDaemon管理导致和Mesos的结合不是很完美。

MesosContainer:性能隔离方面提供Cpu/Mem/Disk/Networkbandwidth的隔离,可见性方面提供了pid和networkport mapping的隔离,这些隔离器可以通过配置来进行选择和组合。MesosContainer和Mesos的集成更为优雅。

这两种方案目前我们都有使用,对于大部分人来说更愿意选择MesosContainer。原因是对于用户来说迁移成本最低,这种方案只需要管理员在Mesos-Slave启动的时候进行简单的配置,而对于用户来说只需要提供自己应用二进制包的URI即可上线完成部署,并且和之前发布部署方案也更为接近,用户更容易接受和操作。

对于MesosContainer的程序的所需资源URI,可以是file(本地磁盘)/http/hdfs/s3/ftp。在实践中, 我们的持续集成环境Jenkins会把程序都发布到HDFS中,同时Ops的同事保证每台Mesos-Slave的机器都挂载对应的fuse。当通过Mesos+Marathon发布程序的时候只需要填写程序本地file路径即可。

服务发现:

把C/S模式的应用迁移上来之后会遇到服务定位的问题。原来会把服务的静态地址写在在客户端的配置文件或者LVS配置中,当服务扩容或者迁移的时候需要人工介入修改。而现在都是动态的ip和port,如果还通过人工介入是不可能的。于是就需要建立一种客户端能实时感知服务端部署位置的机制,这个过程叫服务发现或者服务定位。

服务发现通常有以下两种:

反向代理(LVS,HAProxy,Nginx反向代理等),这种方式的客户端通常很简单,不需要知道后端服务的部署信息,只需要知道代理部署的地址。

SmartClient,客户端需要通过定位服务感知后端服务的位置,并直接跟后端服务建立连接(通常还会定制负载均衡算法),这种方式适合高并发的服务或者有状态的存储服务。

这两种本质没有太多区别,只不过第一种把服务查找放到了后端,对客户端屏蔽了细节,第二种把需要定制客户端,添加服务定位功能,让客户端可以更灵活的实现负载均衡策略,同时也节省了经过代理的额外网络开销。

这两种服务发现我们都有应用,主要使用第一种反向代理的接入方案,这种方案的优点是接入成本比较低,也更为透明(通过代理暴露的统计信息,可以了解每个接入的客户端的调用情况)。第二种需要对客户端进行定制,只有特殊对性能要求比较高的应用我们建议选用第二种方案。

Marathon-lb目前是构建在HAProxy的基础上,能够代理Marathon上动态部署的后端服务,下图是使用Marathon-lb做为接入层的结构图:

enter image description here

Marathon-lb通过HTML5里SSE(Server SentEvents )来实时获取Marathon上最新的事件。如果有新的事件产生则从Marathon上拉取最新的服务注册列表,并生成对应的HAProxy的配置,最后HAProxy的reload来让配置生效。

HAProxy可以带来很好的灵活性,但是这种灵活性是有代价的,服务变化的时候需要对HAProxy进行reload。这种方式可能会导致新老进程交替时SYN包丢失,导致部分客户端请求超时,这个对一些重要的服务影响还是比较大的。

Linux内核3.4之后支持网络队列规则插件plug qdisc配合iptable 可以在reload之前对SYN包进行buffer,并在reload之后释放buffer。通过这个方法有效的避免reload过程中带来的请求超时和流量中断。有兴趣的朋友可以阅读这篇文章:http://engineeringblog.yelp.com/2015/04/true-zero-downtime-haproxy-reloads.html

灰度发布:

由于在Marathon上的应用只能存在一个版本,当升级新版本之后如果存在bug可能会影响客户的请求。我们需要一种灰度发布或蓝绿发布的方法来逐步升级,保证整体系统的稳定性。力争在初始灰度的时候就可以发现、调整问题,以保证其影响度。

下图展示了蓝绿发布的大体流程,升级过程中有一段时间新旧服务同时在线提供服务。等发布者确认新服务正常之后再把所有流量切换到新服务上之后,下线旧服务。

enter image description here

目前Marathon-lb通过blue-greep-deploy的脚本来实现了这种蓝绿发布机制,原理是把更新操作变成多个步骤,先创建一个新的App,逐步迭代的增加新实例和减少旧实例,中间需要发布者确认才能继续发布,并在生成HAProxy配置时合并新旧服务配置。下图时蓝绿发布具体实现的时候的细节。

enter image description here

有状态的服务:

目前Mesos上部署了一些有状态的服务,完全动态部署可能会出现应用启动时无法拿到所需要的状态。比如有些服务需要在启动的时候从本地加载指定的词典文件,同时这些词典文件还需要定期更新和外部数据源保持一致。

对于有状态的服务部署在Mesos上,按场景通常可以采用下面几种方式来解决:

1、存储在分布式文件系统或者分布式存储服务中
2、存储在指定的Mesos-Slave机器上本地磁盘上,部署的时候只能选择这些机器部署
3、或者应用内部可以自己处理数据冗余和复制,比如Cassandra,HDFS
4、使用Mesos内置的Persistent Volume
5、Docker Volume Plugin

目前针对有状态的服务的部署在Mesos上,没有统一的完美的方案,这几种方案各有优缺点,需要根据各自的场景来进行选择。我们的场景主要是一些在线服务需要读取指定的词典文件。因为词典文件相对比较大,同时更新比较频繁,也为了让业务不改动就能迁移到Mesos上,我们选择了使用方案2。

这种方案需要提前对机器有一定的规划,比如提前为一些应用保留特定的机器,在Mesos-Slave启动时通过配置来给这些机器添加特殊的属性,同时利用Marathon的约束性条件来限制这些服务只能部署在这些特殊标签的机器上。

另外词典文件的通常是在一台Build机器上产生的,为了方便数据同步,我们研发了名为DataChannel的分布式数据同步系统。设计的目的是为了完成数据从一台源机器到一批目的机器的数据同步。

DataChannel采用了类似任务调度的方式来进行文件的分发。主要有三个模块Publish,Agent和Scheduler。

enter image description here

Publish:给开发者使用,用于文件分发的提交。提交时需要指定一台源机器和一批目的机器,还有同步目录和版本等一些信息。

Agent:和Mesos-Slave部署在一起,通过和Scheduler保持心跳,接受Scheduler的分发的下载任务并汇报进度。为了加快分发速度, 已经下载完成的Agent还可以作为数据源提供下载服务给其他Agent(类似P2P的模式)。

Scheduler:接受Publish传入的信息,按照下载完成情况进行Agent的任务分发,还需要控制并发和跨机房传输的情况。同时提供WebUI显示任务详情DataChannel帮助我们把一台机器的数据文件定期分发到特定Mesos的服务器上,配合Mesos的属性标签和Marathon的约束性条件可以帮助解决我们的问题。这套系统也在不断完善中,等下次有机会可以把一些细节分享给大家。

监控和报警:

监控系统是整个生态系统非常重要的一部分,因为用户的应用都拖管到平台上,这就需要我们对用户的应用能够及时预警和发现故障,事后提供翔实的数据用于追查定位问题。监控系统作为一个成熟的运维产品,业界有很多开源的实现可供选择。

我们选用了Sensu作为基础的软件的监控,通过定制的check脚本检查应用和服务的可用性,当某个条件满足时触发handlers,为所有基础的组件提供报警服务。

Sensu也有很多开源的插件,比如可以检测HAProxy的服务不可用的比例,具体可以参考http://sensu-plugins.io列出的插件。

Uchiwa是Sensu 监控框架的一个简单面板,可以方便的查看集群报警。

enter image description here

有了Sensu还是不够的,我们需要对一些数据进行持久化,方便方便后续进行问题定位和分析。

我们使用Telegraf采集了Mesos和HAProxy的metrics并写入到InfluxDB中。这样就可以通过Grafana可以展示出Mesos的内部状态报表以及所有通过HAProxy调用的应用的响应时间和调用次数,最后基于Kapacitor对InfluxDB的数据进行计算及监控报警。

四、总结

Mesos以两级调度框架为模型,让自身专注于资源调度,将任务调度的细节交给了外部的Framework。保证自身代码的轻量级的同时也带来了极大的灵活性和可扩展性。Marathon目前作为Mesos生态系统里最常用的Framework,为长时间运行的服务提供调度服务。

构建数据中心共享的资源池,提供混合部署能力的系统,并高效的利用数据中心资源是很多公司的共同诉求。本次分享主要介绍了360搜索团队在面对当前的问题和场景下,如何使用Mesos+Marathon为中心构建Paas云平台。这套系统可以帮助数据中心能够以高资源率运行,让机器流转更简单,降低运维成本和机器成本。同时帮助托管开发者的应用,实现应用的自动部署和弹性调度。

希望本次分享能够给大家一些启发和帮助,也希望Mesos和ITA1024社区越来越壮大,发展越来越好。如有纰漏欢迎大家批评和指正。

五、问答

问:我看到有状态部署的服务 全部都是通过配置约束 任务和服务部署都是分发到特定机器上的 这一点是不是为了数据存储更为方便? 谭博侃:你指的用hdfs类似的方案存储吧,我们的数据更新比较频繁,文件相对更大,机器规模也大,而且也有跨机房的情况存在,简单的用dfs不能解决所有问题。

问:mesos在使用docker作为容器部署的时候 是如何实现网络和磁盘的分配的 我记得docker只做了cpu 内存的隔离? 谭博侃:docker本身基于cgroup可以实现的网络的隔离,磁盘是mesos内置的,使用定期du来计算MesosContainer占用的磁盘容量。

问:aurora有没有比较过? 谭博侃:aurora本身在twitter应用的非常广泛,对于新手来说建议marathon,WebUI管理起来非常好用。同时跟marathon-lb(HAProxy)结合起来非常好用。具体的比较可以参考 http://stackoverflow.com/questions/28651922/marathon-vs-aurora-and-their-purposes/

问:那你们的存储是如何实现的 能指点一下吗? 谭博侃:我们这边存储主要是通过我们的DataChannel来把数据传输到Mesos的机器上,让Mesos上的程序读取本地的数据文件。

问:这些数据应该都是实现和服务部署一起配置好的吧。如果是中间数据呢 这种就会有点麻烦呢? 谭博侃:需要提前规划好机器,通过约束性条件来部署,一般是最终数据,不同场景可以选用不同的方案。

问:哦 对于中间数据的迁移和存储 这一块可有相关的案例呢? 谭博侃:建议通过服务化的方式让状态集中到后面的分布式存储,也可以看看docker的 Volume Plugin机制, 比如flocker,rexray这种。

问:mesos-dns与haproxy使用场景有区别吗? 谭博侃:有区别,marathon-lb(haproxy)目前只能和marathon相结合.而mesos-dns使用更为广泛,可以和任何调度的服务结合。但是mesos-dns毕竟是dns,不太适合作为服务发现,服务升级无法做到快速感知 。