目前线上我们选择的是yarn作为我们spark的资源管理和调度层,主要好处是hadoop自带了yarn,不用额外引入mesos减少了管理的成本,以下所有介绍都是基于hadoop 2.7.3版本。
yarn目前我们使用的版本主要管理了CPU和内存资源,CPU以VCore的形式,但是其实yarn不能严格管理具体container使用的资源。以spark为例,我们为每个container配置了最大46G的内存,但是为了给堆外内存等提供空间,spark的executor只配置了42~40G的内存。即便如此,还是经常遇到异常,spark executor使用的内存超出了container的最大容量。yarn无法限制这种情况,所以它只能去侦测每个container使用的内存情况,一旦超出,就会kill掉这个container,代价就是运行的任务失败,需要重试。如果频繁的失败重试,就会最终导致整个job的失败。yarn可以通过配置关闭这一特性(yarn.nodemanager.pmem-check-enabled=false),然后这同样会导致内存使用的失控,考虑之后我们保留了默认的配置,通过观察任务失败的日志,调整executor的Xmx配置来避免被yarn干掉。对于CPU,yarn实际上只是一个虚拟的管理,所以其实并不会具体分配CPU资源给某个container,我觉得这某些时候也是OK的,OS本身会调度cpu资源,做好虚拟管理其实也是没问题。我们目前整体集群其实也并不需要严格的CPU资源隔离。基于这些考虑,就一直使用yarn而没有替换为mesos。
Yarn的源码中有org.apache.hadoop.yarn.server.nodemanager.containermanager.monitor.ContainersMonitorImpl
实现类,其中会启动一个MonitoringThread
用于做资源监控,参见下面的部分源码。
代码首先判断是否开启了内存使用监控,如果开启了,则会去判断container目前使用物理内存。如果是在Linux环境下,是检查进程的/proc/
另外一块是不同job之间优先级的管理。任何线上跑的任务,需求肯定是不同的。有些是要在zeppelin上运行的统计任务,有些是要对算法做小规模测试的,有些是一天运行一次的定时任务,还有些是实时性要求更高的比如一小时一次的任务。yarn的资源调度有个queue的概念,不同queue之间可以配置weight,设定每个queue可以使用最大、最小资源(包括内存和vcore)。所以这里为了不同的需求我们设计出了三个queue。优先级由高到低分别为test\online\offline, 分配的最小保证资源也是从少到多:test(20%) online (80%) offline(100%)。 我们配置了schedule方式为抢占式的,所以当在配置的时间内高权重queue如果无法获取到满足最小条件的资源时,他就会从低优先级队列中抢占资源。通过这种方式保证高优先级任务进入yarn时可以第一时间获取到资源。同时,在没有高优先级任务时,offline能使用整个集群的资源,保证集群资源利用率是最大的。