深入理解YARN 公平调度器的抢占

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 公平调度器的抢占

定义(Definitions)

开始之前,有必要解释一下公平调度队列的一些关键属性。

FairShare 是公平调度器的概念,表示资源的度量值,格式一般为<memory>

Steady FairShare(理论FairShare)

公平调度使用分层的队列。父级一样的队列是兄弟队列。队列的weight决定了一个队列相对于其兄弟队列应该分得多少资源。 这些资源的值就是Steady FairShare。Steady FairShare 在队列的层级计算,root 队列的值就是集群的所有资源。Steady FairShare 的计算公式为:

深入理解YARN 公平调度器的抢占

计算的数值只是队列资源的期待值,开启抢占时,并不是调度的最终决定。换句话说,这只是队列的理论FairShare。

举个例子,假定YARN共有12 核心和24GB 内存。需要配置3个队列,那么Steady FairShare 值根据weight计算如下:

深入理解YARN 公平调度器的抢占

Instantaneous FairShare(即时FairShare)

为了满足多租户集群的灵活性。 公平调度器允许队列在集群有空闲资源时使用比 Steady FairShare 更多的资源。

活跃队列( active queue)是指至少正在运行一个应用的队列,非活跃队列就是没有正在运行应用的队列。

Instantaneous FairShare 是活跃队列计算后FairShare。它并不是指队列的预留资源值。要使Instantaneous FairShare 生效, 必须要配置抢占(preemption)可用和下面讨论的FairShare Starvation。

深入理解YARN 公平调度器的抢占

和Steady FairShare的不同之处是非活跃队列不分配Instantaneous FairShare。当所有队列都处于活跃状态时,两个值是一样的。

在上面的例子中,如果只有tenant1和tenant2是活跃的,那么Instantaneous FairShare 的计算如下:

深入理解YARN 公平调度器的抢占

注意 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 值的队列中正在运行的容器, 抢占条件要满足:

  1. 有一个或者多个饥饿状态的应用。
  2. 抢占有效

当下面条件满足时,抢占有效

  1. 通过配置yarn.scheduler.fair.preemption 使YARN 服务的抢占有效
  2. 集群层次的资源使用超过yarn.scheduler.fair.preemption.cluster-utilization-threshold 的配置,默认使80%

集群使用率是抢占经常被忽略的一个前提条件。当一个集群使用率很低而又发生了抢占容器,引发不必要的容器交换,影响性能。集群级别资源使用率是基于核心和内存使用百分比计算的,取他们较大的一个。

有需要时,队列可以被标记为不可被抢占。例如一个高优先级别队列的资源是不可被抢占的。配置队列不可抢占,可以参考文档。https://www.cloudera.com/documentation/enterprise/latest/topics/admin_preemption.html

深入理解YARN 公平调度器的抢占

两种类型的饥饿状态(starvation)

1. FairShare Starvation

2. MinShare Starvation

FairShare Starvation

满足下列条件时,应用是FairShare Starvation

  1. 应用需求的资源没有满足
  2. 应用使用的资源少于他的Instantaneous FairShare.
  3. 应用使用的资源在他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 的:

  1. 队列中一个或者多个应用资源未满足需求
  2. 队列的资源使用少于他的MinShare
  3. 队列的资源使用保持在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的时候才会被抢占,如下:

深入理解YARN 公平调度器的抢占

配置饥饿(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,以及实际资源分配。

深入理解YARN 公平调度器的抢占

Cloudera Manager 同时可以监控对列的其它指标。

  • 在CM 报告页面,点击Clusters > ClusterName > Reports > Historical Applications By YARN Pool.
  • 使用tsquery 检索和绘制YARN pool 指标

当前应用,队列和FairShare 也能通过Resource Manager的调度部分检测。注意如展示的一样,只展示内存使用,不展示核心使用。

深入理解YARN 公平调度器的抢占


分享到:


相關文章: