随着阿里云生态的蓬勃发展,我们看到越来越多的开发者开始基于ECS体系开发自己的分布式应用。的确,阿里云ECS提供的弹性云计算服务、多样化的规格配置支持、安全网络隔离等多种灵活便利的一站式服务,大大降低了用户开发新应用的技术门槛与成本消耗。
然而我们也看到,拥有ECS资源仅仅是漫漫开发路的一个开始。举个最简单的栗子,用户买了三台ECS自建ElasticSearch,有一天用户发现需要扩到5台ECS才够满足业务增长的需求,那么需要做以下操作:
- 登录ECS控制台,购买2台ECS
- 选择装机镜像
- 配置跟现有集群统一的VPC
- 配置VPC内安全组
- 配置VPC外部访问白名单
- 配置ECS用户名密码
- 登录新节点,下载各种依赖包
- 安装ElasticSearch binary
- 修改5台机器的配置文件,将新机器ip添加到server列表
-
依次重启每台ECS的进程,使配置生效
看似简单的几步操作,只要有一个环节出了问题,都可能导致集群出现异常。如果用户经验丰富,可以很快手动debug出原因并解决,自然是最好的情况。然而也不排除最坏的场景,即集群停服,导致的损失就难以估量了。
究其原因,无非人工操作过多,一来耗费工时,二来出错概率也会增加。
针对这一问题,我们团队开发了一套基于ECS体系的分布式调度框架,能够实现全自动部署、运维用户ECS内的分布式应用,真正实现一键部署的运维平台,这个分布式运维组件就是shuttle。
shuttle定位
shuttle是针对ECS生态设计的分布式应用资源调度组件,目前已经为搜索事业部的ElasticSearch产品(以下简称ES)提供了分布式运维系统的实现方案。利用shuttle不仅可以快速实现ECS本身的创建、释放、扩容、缩容等弹性配置,更可以支持ECS之上的云计算产品的升级、回滚、更新配置等一系列运维操作。shuttle的愿景是帮助开发者快速搭建ECS体系的分布式运维平台,使开发者无需关心底层组件细节,只要告诉shuttle一个运维的策略及目标,shuttle即可快速实现分布式运维服务。
设计思想
shuttle的设计目标是能够同时运维多种异构的分布式服务,而调度本身又高度依赖被调度模块的状态及行为,因此shuttle的设计采用实时轮询及异步回调机制,不依赖持久化信息,从而保证尽可能简单高效。
shuttle的实时轮询+异步回调是基于搜索事业部的另一任务调度框架Tyson实现的。利用Tyson的TaskChain,将shuttle调度的每个流程转化为一个单向任务链。前端业务系统向shuttle提交一个事件及上下文,shuttle将事件分解为一系列串行的Task,每个Task提供状态查询接口,可以让Tyson知道当前Task的进度情况,从而决定是重复执行当前Task还是推进下一个,这就要求每个Task为可重入的。
目前shuttle是针对ecs公有云体系开发的,但未来不排除shuttle会直接搭建在用户的私有云之上,支持私有云体系。所以为应对变化,shuttle需要做成组件可插拔的架构,当替换其它依赖组件时,做到尽量少的代码改动。
实现方案
- 策略层
虽然分布式应用的结构、功能、表现千变万化,从运维角度来看,均可以归结为调度策略的多样性。因此策略层可以看做是shuttle的业务层,该层无需关心底层细节,使用者只要根据具体的应用流程,实现固定的策略模板,剩下的工作即可交给shuttle完成。
以ES为例,ES的节点角色分为master、data、ingest等,拓扑也不尽相同。目前我们关心的两类拓扑为DedicatedMaster和非DedicatedMaster。
(1) dedicated master
- 在es cluster中,区分data节点和master节点,一般取3个独立的node作为master进行事务操作,其它节点均为data,提供数据服务
- 在用户购买超过10个data节点时,系统赠送dedicated master服务,即额外赠送3个master节点
(2) 非dedicated master
- 每个节点同时拥有data角色和master角色,在shuttle中统称为worker节点,所有节点地位等同,均有能力提供数据服务和事务操作
- 当用户购买小于10个data节点,并未额外购买dedicated master服务时,用户的每个节点均为data+master。
每个配置项也区分全局配置或单点配置,考虑以下几个场景:
1. 灰度更新其中几台data节点配置,观察性能指标变化
2. 在线替换一台master节点ECS
3. 弹性扩容、缩容
可以发现,这些集群角度的拓扑变化是与ES内部的逻辑紧密相关的,为保证通用性,拓扑级别的变化策略被封装在业务层中。比如更新master节点配置时,尽量保证当前es的真正master放在最后一个rolling。而往下的资源层,则负责根据策略具体实施Rolling更新工作。
- 调度层
一个通用的分布式应用运维框架,通常可以抽象为节点级运维与集群级运维的组合。由于每个节点的操作流程大同小异,但每个节点的行为都可能会影响集群的表现,因此我们这里利用状态机实现了通用的分布式调度层。状态机内部针对节点设计,为节点运维的流程抽象,而状态机的入口及出口,我们抽象为集群级别的先决和终止条件。以ES为例,我们希望操作某个节点的前提是集群数据健康,因此ES的健康状态为Green成为了进入节点状态机的先决条件。进入状态机后,每个节点依次去做下线、运维等工作,完成后,还需要检查集群健康状态是否有变化。这就是节点状态机的终止条件,能够保证把风险控制在当前节点的范围内。
ES调度层状态机的设计如下图所示
- 负载均衡层
从该层开始,每一层均为单个节点依赖的组件逻辑。
目前我们使用的是阿里云的SLB服务。每次需要下线节点时,都要先把该节点从对应的SLB Vip上摘下来,保证不会有请求命中该节点后,才会具体进行下线操作。该节点运维完成后,需要再次挂载到vip上。我们针对ES实现了SLB的节点健康检查策略,当健康检查不通过时,我们也会认为这个节点有问题,该节点会卡顿在状态机内部,直到检查通过才会继续rolling流程。
- 应用管理层
应用管理(Application manager,简称AM)隶属于经典的二层调度框架的第二层,这里我们使用的是搜索事业部的Carbon组件,目前利用carbon实现资源申请、服务拉起、依赖包管理等功能。carbon本身也支持搜索场景下的多副本、多分片rolling管理,但在我们的场景中,每一个节点都需要具备独立可控的能力,因此在rolling策略的部分我们放到了上文的调度层进行管理。
在一台ecs上拉起es进程需要做很多准备工作:
1. 保证ecs的cpu、mem等资源足够es进程使用
2. 保证依赖的docker镜像可以成功拖到本地ecs
3. 保证ecs宕机恢复,或es进程本身挂掉后,es进程可自动拉起
4. 保证可以随时更新es进程的启动参数
这些需求在shuttle看来,都可以利用给carbon提交plan来解决。plan中可指定资源需求、启动命令、重启策略、依赖包地址等,carbon成功收到plan后,跟之前的plan比对出差值,即会自动更新es进程的各项配置并重新拉起。比如更新es集群的种子列表参数,即可把这个列表放在plan的启动参数中提交给carbon,carbon会异步更新这个应用。shuttle通过轮询carbon返回的状态,即可判断是否更新成功,继而进行下一步操作。
- 资源管理层
资源管理层(Resource manager,简称RM)即为经典二层调度框架的第一层,这里我们使用的也是搜索事业部的Hippo组件。当我们买了一台新的ECS,做好一些初始化工作后,即要将这台ECS挂在Hippo的Slave列表中,至此该ecs资源可以被shuttle真正使用。我们这里采用分槽策略使用ECS,保证各进程复用同一台ecs的同时,实现资源隔离。
- 机器层
顾名思义,机器层负责具体ECS的功能配置,如规格、网络等。由于用户的ecs实例均封闭在用户的vpc网络中,shuttle无法直接访问,因此需要在创建ECS阶段配置好mapping pool,将用户私有的ip、port映射为外部可访问的透传接口,并保证shuttle、carbon、hippo等组件可访问的在address pool内,即可通过mapping port访问用户实例。
2017年9月,阿里云基于开源Elasticsearch及商业版X-Pack插件,提供云上ELK服务,同时阿里云ES技术人员会分享解决云上业务痛点的案例实践,敬请期待!了解产品更多详情 https://data.aliyun.com/product/elasticsearch
阿里云Elasticsearch 1核2G首月免费试用,开始云上实践吧