背景

使用过hadoop的人基本都会考虑集群里面资源的调度和优先级的问题,假设你现在所在的公司有一个大hadoop的集群,有很多不同的业务组同时使用。但是A项目组经常做一些定时的BI报表,B项目组则经常使用一些软件做一些临时需求。那么他们肯定会遇到同时提交任务的场景,这个时候到底如何分配资源满足这两个任务呢?是先执行A的任务,再执行B的任务,还是同时跑两个?

目前一些使用EMR的大公司,会使用一个比较大的集群,来共公司内部不同业务组的人共同使用,相对于使用多个小集群,使用大的集群一方面可以达到更高的最大性能,根据不同业务的峰谷情况来调度从而获得更高的资源利用里,降低总成本。另外一个方面,能够更好地在不同的业务组之间实现资源的共享和数据的流动。下面结合EMR集群,介绍一下如何进行大集群的资源quota管控。

yarn默认提供了两种调度规则,capacity scheduler和fair scheduler。现在使用比较多的是capacity scheduler。具体的实现原理和调度源码可以google一下capacity scheduler。

什么是capacity调度器

Capacity调度器说的通俗点,可以理解成一个个的资源队列。这个资源队列是用户自己去分配的。比如我大体上把整个集群分成了queue1queue2两个队列,queue1是给一个业务组使用queue2给另外一个业务组使用。如果第一个业务组下面又有两个方向,那么还可以继续分,比如专门做BI的和做实时分析的。那么队列的分配就可以参考下面的树形结构:

root
------default[20%]
------q1[60%]
      |---q1.q11[70%]
      |---q1.q12[30%]
------q2[20%]

整个集群的queue必须挂在root下面。分成三个queue:default,q1和q2。三个队列使用集群资源的quota配比为:20%,60%,20%。default这个queue是必须要存在的。

虽然有了这样的资源分配,但是并不是说提交任务到q2里面,它就只能使用20%的资源,即使剩下的80%都空闲着。它也是能够实现(通过配置),只要资源实在空闲状态,那么q2就可以使用100%的资源。但是一旦其它队列提交了任务,q2就需要在释放资源后,把资源还给其它队列,直到达到预设de配比值。粗粒度上资源是按照上面的方式进行,在每个队列的内部,还是按照FIFO的原则来分配资源的。

capacity调度器特性

capacity调度器具有以下的几个特性:

  • 层次化的队列设计,这种层次化的队列设计保证了子队列可以使用父队列设置的全部资源。这样通过层次化的管理,更容易合理分配和限制资源的使用。
    容量保证,队列上都会设置一个资源的占比,这样可以保证每个队列都不会占用整个集群的资源。
  • 安全,每个队列又严格的访问控制。用户只能向自己的队列里面提交任务,而且不能修改或者访问其他队列的任务。
  • 弹性分配,空闲的资源可以被分配给任何队列。当多个队列出现争用的时候,则会按照比例进行平衡。
  • 多租户租用,通过队列的容量限制,多个用户就可以共享同一个集群,同事保证每个队列分配到自己的容量,提高利用率。
  • 操作性,yarn支持动态修改调整容量、权限等的分配,可以在运行时直接修改。还提供给管理员界面,来显示当前的队列状况。管理员可以在运行时,添加一个队列;但是不能删除一个队列。管理员还可以在运行时暂停某个队列,这样可以保证当前的队列在执行过程中,集群不会接收其他的任务。如果一个队列被设置成了stopped,那么就不能向他或者子队列上提交任务了。

capacity调度器的配置

登录EMR集群master节点,编辑配置文件:
/etc/emr/hadoop-conf/capacity-scheduler.xml这里先贴出来完整的比较复杂一点的配置,后面再详细说明:

<?xml version="1.0" encoding="utf-8"?> <configuration> <property> <name>yarn.scheduler.capacity.maximum-applications</name> <value>10000</value> <description>Maximum number of applications that can be pending and running.</description> </property> <property> <name>yarn.scheduler.capacity.maximum-am-resource-percent</name> <value>0.25</value> <description>Maximum percent of resources in the cluster which can be used to run application masters i.e. controls number of concurrent running applications.</description> </property> <property> <name>yarn.scheduler.capacity.resource-calculator</name> <value>org.apache.hadoop.yarn.util.resource.DefaultResourceCalculator</value> <description>The ResourceCalculator implementation to be used to compare Resources in the scheduler. The default i.e. DefaultResourceCalculator only uses Memory while DominantResourceCalculator uses dominant-resource to compare multi-dimensional resources such as Memory, CPU etc.</description> </property> <property> <name>yarn.scheduler.capacity.root.queues</name> <value>default,q1,q2</value> <description>The queues at the this level (root is the root queue).</description> </property> <property> <name>yarn.scheduler.capacity.root.q1.queues</name> <value>q11,q12</value> <description>The queues at the this level (root is the root queue).</description> </property> <property> <name>yarn.scheduler.capacity.root.default.capacity</name> <value>20</value> <description>Default queue target capacity.</description> </property> <property> <name>yarn.scheduler.capacity.root.q1.capacity</name> <value>60</value> <description>Default queue target capacity.</description> </property> <property> <name>yarn.scheduler.capacity.root.q2.capacity</name> <value>20</value> <description>Default queue target capacity.</description> </property> <property> <name>yarn.scheduler.capacity.root.q1.q11.capacity</name> <value>70</value> <description>Default queue target capacity.</description> </property> <property> <name>yarn.scheduler.capacity.root.q1.q11.maximum-capacity</name> <value>90</value> <description>Default queue target capacity.</description> </property> <property> <name>yarn.scheduler.capacity.root.q1.q11.minimum-user-limit-percent</name> <value>25</value> <description>Default queue target capacity.</description> </property> <property> <name>yarn.scheduler.capacity.root.q1.q12.capacity</name> <value>30</value> <description>Default queue target capacity.</description> </property> <property> <name>yarn.scheduler.capacity.root.q1.q12.user-limit-factor</name> <value>0.7</value> <description>Default queue target capacity.</description> </property> <property> <name>yarn.scheduler.capacity.root.q2.user-limit-factor</name> <value>0.4</value> <description>Default queue user limit a percentage from 0.0 to 1.0.</description> </property> <property> <name>yarn.scheduler.capacity.root.q2.maximum-capacity</name> <value>100</value> <description>The maximum capacity of the default queue.</