http://blog.cloudera.com/blog/2018/06/yarn-fairscheduler-preemption-deep-dive/
揭秘Apache Hadoop YARN 系列博客中介绍了YARN 调度如何工作。
本文中我们讨论公平调度(FairScheduler)抢占执行的技术细节, 和配置公平调度抢占的最佳时间。
还会介绍CDH 5.11中公平调度抢占近期的一些调整,CDH 5.11尝试解决很多问题,这些问题都列在YARN-4752中。
https://issues.apache.org/jira/browse/YARN-4752?subTaskView=all
![深入理解YARN 公平调度器的抢占](http://p2.ttnews.xyz/loading.gif)
定义(Definitions)
开始之前,有必要解释一下公平调度队列的一些关键属性。
FairShare 是公平调度器的概念,表示资源的度量值,格式一般为<memory>
Steady FairShare(理论FairShare)
公平调度使用分层的队列。父级一样的队列是兄弟队列。队列的weight决定了一个队列相对于其兄弟队列应该分得多少资源。 这些资源的值就是Steady FairShare。Steady FairShare 在队列的层级计算,root 队列的值就是集群的所有资源。Steady FairShare 的计算公式为:
![深入理解YARN 公平调度器的抢占](http://p2.ttnews.xyz/loading.gif)
计算的数值只是队列资源的期待值,开启抢占时,并不是调度的最终决定。换句话说,这只是队列的理论FairShare。
举个例子,假定YARN共有12 核心和24GB 内存。需要配置3个队列,那么Steady FairShare 值根据weight计算如下:
Instantaneous FairShare(即时FairShare)
为了满足多租户集群的灵活性。 公平调度器允许队列在集群有空闲资源时使用比 Steady FairShare 更多的资源。
活跃队列( active queue)是指至少正在运行一个应用的队列,非活跃队列就是没有正在运行应用的队列。
Instantaneous FairShare 是活跃队列计算后FairShare。它并不是指队列的预留资源值。要使Instantaneous FairShare 生效, 必须要配置抢占(preemption)可用和下面讨论的FairShare Starvation。
和Steady FairShare的不同之处是非活跃队列不分配Instantaneous FairShare。当所有队列都处于活跃状态时,两个值是一样的。
在上面的例子中,如果只有tenant1和tenant2是活跃的,那么Instantaneous FairShare 的计算如下:
注意 FairShare 通常用来模糊的指代 两种 FairShare 中的一个。 理解不同场景下指代的是哪一种FairShare是很重要的。本文中,除非明确指出,否则FairShare指的是Instantaneous FairShare。
最小Share(Minimum Share)
队列可以指定需求资源的最小值。也指代队列的MinShare 。MinShare 并不是队列保留的最小资源。MinShare 只有在下面条件都为真时生效:
- 队列时活跃的
- 抢占时可用的
- MinShare Starvation(下面章节讨论) 已配置
饥饿和抢占(Starvation and Preemption)
Starvation 和 Preemption 是相关的,最好放在一起讨论。
由于公平调度器的弹性特点,队列在运行应用时,可以使其它应用(运行在相同或则不同队列中的应用)保持饥饿(starved)状态。在上面的例子中,假如只有tenant1和tenant2 队列是活跃的,并且分别持有33.3%和66.6%的资源。
随后,如果tenant3变成活跃状态。各个租户的Instantaneous FairShare会变成25%, 50% 和 25%。tenant3中的应用必须等待tenant1 和 tenant2中的应用结束使用资源。在那之前,tenant3一直会有为满足需求或者饥饿的待定容器 。
抢占允许通过一种可预见的方式纠正这种不平衡。它可以从队列回收超过他们FairShare的资源,而不必等他们释放资源。
使抢占有效
YARN 公平调度器会抢占那些超过自己的 Instantaneous FairShare 值的队列中正在运行的容器, 抢占条件要满足:
- 有一个或者多个饥饿状态的应用。
- 抢占有效
当下面条件满足时,抢占有效
- 通过配置yarn.scheduler.fair.preemption 使YARN 服务的抢占有效
- 集群层次的资源使用超过yarn.scheduler.fair.preemption.cluster-utilization-threshold 的配置,默认使80%
集群使用率是抢占经常被忽略的一个前提条件。当一个集群使用率很低而又发生了抢占容器,引发不必要的容器交换,影响性能。集群级别资源使用率是基于核心和内存使用百分比计算的,取他们较大的一个。
有需要时,队列可以被标记为不可被抢占。例如一个高优先级别队列的资源是不可被抢占的。配置队列不可抢占,可以参考文档。https://www.cloudera.com/documentation/enterprise/latest/topics/admin_preemption.html
两种类型的饥饿状态(starvation)
1. FairShare Starvation
2. MinShare Starvation
FairShare Starvation
满足下列条件时,应用是FairShare Starvation
- 应用需求的资源没有满足
- 应用使用的资源少于他的Instantaneous FairShare.
- 应用使用的资源在他Instantaneous FairShare 的FairShare 抢占限制(FairShare Preemption Threshold)以下的状态,至少保持了FairShare 抢占超时时间(FairShare Preemption Timeout)。
FairShare Preemption Threshold 默认是0.5。FairShare Preemption Timeout 默认不设置,为了是应用饥饿,需要明确设置。这两个参数都可以全局设置和按队列设置。
例如,假定有一个队列,FairShare Preemption Timeout是5秒,FairShare Preemption Threshold是0.8。这就暗示了,如果抢占有效和条件1,2满足,当应用在5秒内没有得到相当于队列Instantaneous FairShare值的80%的资源,公平调度器会任务应用是饥饿的。
需要注意的是:抢占有效并不保证应用或者队列会获取全部的Instantaneous FairShare。只能保证应用或者队列在获取到足够资源时,不再被认为是饥饿的。这就意味着只会在超时时间(FairShare Preemption Timeout )之后,队列资源才会提升到对列的Instantaneous FairShare 值的 FairShare 抢占上限那么多。除了需要使抢占有效,还需要Resource Manager 能找到可以被抢占的容器。
对于一个高优先级的队列,通过设置FairShare Preemption Threshold 高比例, 设置FairShare Preemption Timeout 为比较小的时间间隔,并且设置为不可抢占,来使队列很容易饥饿。查看这篇博客(https://blog.cloudera.com/blog/2017/02/untangling-apache-hadoop-yarn-part-5-using-fairscheduler-queue-properties/)
的几个例子,可以了解到怎么通过设置抢占属性来控制应用优先级。
在一个队列中向应用分配FairShare。
运行在一个队列中应用总是平均的分配队列的Instantaneous FairShare。FairShare是按队列配置的,对于实现应用级别的FairShare 分配, FairShare starvation 是很关键的。
之所以重要是因为,即使对列不是饥饿状态,队列中的一个或者多个应用也可以是饥饿的。一个应用超过了他的 Instantaneous FairShare, 在任何队列中的饥饿状态的应用都可以抢占他的容器。同一个队列中的应用也可以。
MinShare(最小资源) Starvation
满足以下条件时,队列是MinShare Starvation 的:
- 队列中一个或者多个应用资源未满足需求
- 队列的资源使用少于他的MinShare
- 队列的资源使用保持在MinShare以下至少MinShare Preemption Timeout 这么久
MinShare Preemption Timeout 默认不设置,为了让对列饥饿,需要明确设置。这个参数可以全局设置,也可按队列设置。
队列中向应用分配最小资源
MinShare可以指定到队列粒度,和FairShare不同的是,应用不能MinShare(最小资源) Starvation。
在分配最小资源时,处于同一MinShare(最小资源) Starvation的队列中应用按资源需求量排序。这可能导致即使队列的最小资源分配完了,队列中一些应用仍然处于饥饿状态。
比如, 假定队列的最小内存设置,对列只有6G内存,比最小内存小。这个队列中有App1, App2, App3 和App4 4个应用,分别需求内存3G, 2G, 1G, 和0.5G。 App1会得到3G,App2会得到2G, App3 会得到1G, App4因为内存已经分配完而得不到内存。
抢占的容器
应用的资源请求可能会通过抢占一个或多个节点上的容器来达成。当有多个节点上的容器满足需求时,拥有最少Application Master 容器的节点会优先被抢占。另外,当下面2点满足时,容器才会被抢占。
- 容器中应用的队列时可抢占的
- kill掉容器不会让应用资源调到FairShare之下。换句话说,如果应用在被抢占之后资源少于他的FairShare,那么他是不会被抢占。
MinShare 不是在决定哪个容器抢占的时候用。MinShare只用在配置Starvation。这一点很重要值得重复说明。即便,FairShare或者MinShare 配置了,也只有在应用超过FairShare的时候才会被抢占,如下:
配置饥饿(Starvation)的最佳实践
推荐配置FairShare starvation 。不推荐配置 MinShare starvation 或者最小资源, 因为增加了调试抢占问题的复杂度,而没有明显的好处:
- 当最小资源饥饿发生时,容器所在队列超过MinShare 而没有超过FairShare捕获被抢占。
- 最小饥饿状态的资源,不是均匀的分配给队列中的应用,而时按需求量来分。不同于FairShare 饥饿状态的分配方式。
- 如果队列的最小资源值大于他的FairShare值,最小资源值就会变成队列的FairShare。会降低其它队列的Fair'Share。
队列的权重对于核心和内存是相同百分比的。有些队列会针对核心和内存进行不同配置。这时有理由配置MinShare Starvation。尽管如此,也必须确保所有队列的最小资源总和不大于总资源。否则,饥饿和抢占行为会变得不可预测。例如,一些队列会总是MinShare 饥饿,但是不会去抢占容器,因为其它应用的资源可能一直小于他们的FairShare。
抢占的大修改
最近的代码改动包括了一些改进和bug修复。 CDH 5.11.0 及以后的版本,下列改进可用:
- 抢占之后的资源满足饥饿应用的需求时,才会发生抢占。确保抢占的资源不会不被使用。
- 除非没有其它的容器抢占,否则不会抢占Application Master的容器。
抢占相关配置大都没有改变,除了yarn.scheduler.fair.preemptionInterval 变得不可用。
挑选抢占容器的方式也有改变。以前,超过FairShare 最多的容器会优先抢占。这次改动后,会从所有超出FairShare的应用抢占。
已知的问题
当应用饥饿,会从兄弟应用或者其它对列中的应用抢占资源。然而,不保证饥饿应用会收到抢占的容器。
有可能,另外一个饥饿应用会受到那些容器资源。这个问题在YARN-6432 和YARN-6895 被Fixed, 在CDH6.0以后可用。
抢占调优的工具
检测FairShare 和队列指标
在Cloudera Manager中, 可使用YARN服务中资源池tab ,观察Steady 和 Instantaneous FairShare,以及实际资源分配。
Cloudera Manager 同时可以监控对列的其它指标。
- 在CM 报告页面,点击Clusters > ClusterName > Reports > Historical Applications By YARN Pool.
- 使用tsquery 检索和绘制YARN pool 指标
当前应用,队列和FairShare 也能通过Resource Manager的调度部分检测。注意如展示的一样,只展示内存使用,不展示核心使用。
閱讀更多 陳序猿9527 的文章