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 的文章