基于Chronos和Docker的任务调度系统

相关背景

Mesos

Mesos是一个开源的分布式弹性资源管理系统。目前,Twitter、Apple等公司在大量使用Mesos管理集群资源。国内也有一些公司在使用Mesos,比如豆瓣、爱奇艺等。

Mesos是仿照Google内部的资源管理系统Borg实现的。Mesos对Docker的支持较好,其采用的资源分配算法叫做DRF.

Chronos

Chronos是一个运行在Mesos之上的具有分布式容错特性的作业调度器。在Airbnb公司,它是cron的替代品。与cron相比,Chronos在很多方面具备优势。比如,它支持ISO8601标准,允许更灵活地定义调度时间;Chronos也支持任务依赖,即一个作业的开始依赖于一些任务的完成。

Docker

Docker是一个开源的应用容器引擎,允许开发者打包应用以及相关依赖到一个可移植的容器中,然后发布到任何流行的Linux机器上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在数据中心运行。

系统结构

下图是这个任务调度系统的基本框图。

基于Chronos和Docker的任务调度系统_第1张图片
调度系统框图

整体上来看,该系统由业务队列、业务调度器、Chronos和Mesos组成。每个组成部分的说明如下:

  • 业务队列:实际存放任务的队列,队列中的任务可以是按照优先级排序,也可以是FIFO. 多个业务队列表示不同的业务,或者同一业务的不同队列。
  • 业务调度器:根据一定的调度算法从多个业务队列中选择任务来调度。业务调度器接受Chronos的资源汇报,然后给这些资源分配任务。
  • Chronos:向业务调度器汇报剩余资源,接受业务调度器提交的任务然后在Mesos集群上面运行。
  • Mesos:运行各个Docker容器的载体。每个任务都在Docker容器中执行。

有一点需要解释的是,在这个任务调度系统中,存在多个调度器:

  • Mesos中的调度器:一种通用的集群资源分配算法,也就是DRF
  • Chronos中的调度器:在我们这个场景中,不需要定时调度任务。我们只需使用Chronos的Rest API提交一个Docker任务就可以了,这个Docker任务然后由Chronos调度到Mesos集群上面运行。为什么不绕过Chronos直接提交任务到Mesos呢?Mesos本身是个两级调度架构,如果绕过Chronos,那么业务调度器就需要实现Mesos的上级调度接口,增加了复杂性。
  • 业务调度器:这就是和业务联系最紧密的地方了,此处必须考虑各种业务特性,比如各个业务队列的任务总量、到达速率、优先级等等。

系统实现

系统的核心在于业务调度器。经过调研各种调度算法,觉得YARN资源管理系统中的容量调度(Capacity Scheduler)适合多业务多队列的场景。

容量调度

以两级队列为例来说明容量调度算法。下图是Chronos资源的容量配置示例:

基于Chronos和Docker的任务调度系统_第2张图片
Chronos容量分配

在该示意图中,Chronos资源容量的20%分配给了业务1,80%分配给了业务2. 接着,20%容量中的40%分配给了业务队列11,60%分配给了业务队列12. 业务1和业务2是业务层次的队列,业务队列11、业务队列12和业务队列21是具体业务下的子队列。

父队列

父队列具有如下基本属性:

  • 队列名称
  • 队列容量:表示给这个队列分配使用的资源占总资源的百分比
  • 队列最大容量:表示这个队列可以使用的最大资源占总资源的百分比。如果没有设置最大容量限制,则当其它队列空闲时,该队列可能使用过多资源。
  • 子队列
  • 是否启用

父队列维护如下运行时信息:

  • 已使用资源量:其子队列已使用资源量的总和
  • 已使用容量:已使用资源量除以资源总量

子队列

子队列具有如下基本属性:

  • 队列名称
  • 队列容量
  • 队列最大容量
  • 是否启用

子队列维护如下运行时信息:

  • 正在排队的任务
  • 正在运行的任务
  • 已使用资源量:正在运行的任务占用的资源量
  • 已使用容量:已使用资源量除以资源总量
  • 绝对容量:子队列的容量乘以父队列的容量
  • 绝对最大容量:子队列的最大容量乘以父队列的最大容量
  • 相对资源使用率:已使用资源量除以绝对容量

调度算法

  1. 计算每个子队列的相对资源使用率
  2. 将子队列按照相对资源使用率从小到大排序
  3. 遍历排序后的队列,从队列中选择一个任务调度

最后一步需要考虑如下条件:

  • 跳过超过最大容量限制的队列
  • 跳过没有等待任务的队列
  • 跳过父队列超过最大容量限制的队列
  • 剩余资源满足任务对资源的需求

资源总量估计

容量调度需要知道资源总量。以Chronos为例说明如何估计Chronos的资源总容量。Chronos是运行在Mesos上的调度框架,Chronos上报资源时,会列出本次上报中一些Mesos Slave机器的空闲资源量。

假如某次上报各个Mesos Slave机器的空闲资源量如下:

  • slave-1: c11 cpus, m11 mem
  • slave-2: c21 cpus, m21 mem

根据这次上报,估计当前资源总容量为 ( c11 + c21 ) cpus, ( m11 + m21 ) mem. 其中,slave-1、slave-2的容量分别如上。

假如接下来上报各个Mesos Slave机器的空闲资源量如下:

  • slave-2: c22 cpus, m22 mem
  • slave-3: c32 cpus, m32 mem

综合此次上报以及上次上报,估计当前资源总容量为 ( c11 + max(c21, c22) + c32) cpus, ( m11 + max(m21, m22) + m32 ) mem. 其中,各个slave的容量分别如下:

  • slave-1: c11 cpus, m11 mem
  • slave-2: max(c21, c22) cpus, max(m21, m22) mem
  • slave-3: c32 cpus, m32 mem

如此继续......以上即为资源总容量估计算法。

实际情况下,有些slave会被下线、宕机等等,这些slave的容量应当从总容量中扣除。但是业务调度器无法得知slave是否下线或宕机,所以一个解决办法是对每个slave容量设置一个失效时间,各个slave容量的失效时间最好不一样。

这种资源总容量估计算法估计出来的结果可能不是准确的。可以有一个备用方案,就是直接在配置文件中或者数据库中配置资源的总容量。

参考资料

  • Capacity Scheduler Guide
  • Hadoop-2.4.1学习之容量调度器
  • MapReduce多用户任务调度器——容量调度器原理和源码研究
  • Hadoop Capacity Scheduler源码实现剖析
  • Hadoop计算能力调度器算法解析

你可能感兴趣的:(基于Chronos和Docker的任务调度系统)