YARN調度器(Scheduler)詳解

理想狀況下,咱們應用對Yarn資源的請求應該馬上獲得知足,但現實狀況資源每每是有限的,特別是在一個很繁忙的集羣,一個應用資源的請求常常須要等待一段時間才能的到相應的資源。在Yarn中,負責給應用分配資源的就是Scheduler。其實調度自己就是一個難題,很難找到一個完美的策略能夠解決全部的應用場景。爲此,Yarn提供了多種調度器和可配置的策略供咱們選擇。YARN架構以下:算法

  • ResourceManager(RM):負責對各NM上的資源進行統一管理和調度,將AM分配空閒的Container運行並監控其運行狀態。對AM申請的資源請求分配相應的空閒Container。主要由兩個組件構成:調度器(Scheduler)和應用程序管理器(Applications Manager)。
  • 調度器(Scheduler):調度器根據容量、隊列等限制條件(如每一個隊列分配必定的資源,最多執行必定數量的做業等),將系統中的資源分配給各個正在運行的應用程序。調度器僅根據各個應用程序的資源需求進行資源分配,而資源分配單位是Container,從而限定每一個任務使用的資源量。Scheduler不負責監控或者跟蹤應用程序的狀態,也不負責任務由於各類緣由而須要的重啓(由ApplicationMaster負責)。總之,調度器根據應用程序的資源要求,以及集羣機器的資源狀況,爲用程序分配封裝在Container中的資源。調度器是可插拔的,例如CapacityScheduler、FairScheduler。(PS:在實際應用中,只須要簡單配置便可)
  • 應用程序管理器(Application Manager):應用程序管理器負責管理整個系統中全部應用程序,包括應用程序提交、與調度器協商資源以啓動AM、監控AM運行狀態並在失敗時從新啓動等,跟蹤分給的Container的進度、狀態也是其職責。ApplicationMaster是應用框架,它負責向ResourceManager協調資源,而且與NodeManager協同工做完成Task的執行和監控。MapReduce就是原生支持的一種框架,能夠在YARN上運行Mapreduce做業。有不少分佈式應用都開發了對應的應用程序框架,用於在YARN上運行任務,例如Spark,Storm等。若是須要,咱們也能夠本身寫一個符合規範的YARN application。
  • NodeManager(NM):NM是每一個節點上的資源和任務管理器。它會定時地向RM彙報本節點上的資源使用狀況和各個Container的運行狀態;同時會接收並處理來自AM的Container 啓動/中止等請求。ApplicationMaster(AM):用戶提交的應用程序均包含一個AM,負責應用的監控,跟蹤應用執行狀態,重啓失敗任務等。
  • Container:是YARN中的資源抽象,它封裝了某個節點上的多維度資源,如內存、CPU、磁盤、網絡等,當AM向RM申請資源時,RM爲AM返回的資源即是用Container 表示的。YARN會爲每一個任務分配一個Container且該任務只能使用該Container中描述的資源。

1. Yarn調度器介紹

1.1. FIFO Scheduler(先進先出調度器)

FIFO Scheduler把應用按提交的順序排成一個隊列,這是一個先進先出隊列,在進行資源分配的時候,先給隊列中最頭上的應用進行分配資源,待最頭上的應用需求知足後再給下一個分配,以此類推。FIFO Scheduler是最簡單也是最容易理解的調度器,也不須要任何配置,但它並不適用於共享集羣。大的應用可能會佔用全部集羣資源,這就致使其它應用被阻塞。在共享集羣中,更適合採用Capacity Scheduler或Fair Scheduler,這兩個調度器都容許大任務和小任務在提交的同時得到必定的系統資源。下面「Yarn調度器對比圖」展現了這幾個調度器的區別,從圖中能夠看出,在FIFO 調度器中,小任務會被大任務阻塞
apache

 1.2.Capacity Scheduler(容量調度器) 

yarn-site.xml中默認配置的資源調度器。而對於Capacity調度器,有一個專門的隊列用來運行小任務,可是爲小任務專門設置一個隊列會預先佔用必定的集羣資源,這就致使大任務的執行時間會落後於使用FIFO調度器時的時間。用這個資源調度器,就能夠配置yarn資源隊列,這個後面後介紹用到。網絡

 

1.3. FairS cheduler(公平調度器)

Fair調度器的設計目標是爲全部的應用分配公平的資源(對公平的定義能夠經過參數來設置)。在上面的「Yarn調度器對比圖」展現了一個隊列中兩個應用的公平調度;固然,公平調度在也能夠在多個隊列間工做。舉個例子,假設有兩個用戶A和B,他們分別擁有一個隊列。當A啓動一個job而B沒有任務時,A會得到所有集羣資源;當B啓動一個job後,A的job會繼續運行,不過一下子以後兩個任務會各自得到一半的集羣資源。若是此時B再啓動第二個job而且其它job還在運行,則它將會和B的第一個job共享B這個隊列的資源,也就是B的兩個job會用於四分之一的集羣資源,而A的job仍然用於集羣一半的資源,結果就是資源最終在兩個用戶之間平等的共享。在Fair調度器中,咱們不須要預先佔用必定的系統資源,Fair調度器會爲全部運行的job動態的調整系統資源。當第一個大job提交時,只有這一個job在運行,此時它得到了全部集羣資源;當第二個小任務提交後,Fair調度器會分配一半資源給這個小任務,讓這兩個任務公平的共享集羣資源。
a) 公平調度器,就是可以共享整個集羣的資源
b) 不用預先佔用資源,每個做業都是共享的
c) 每當提交一個做業的時候,就會佔用整個資源。若是再提交一個做業,那麼第一個做業就會分給第二個做業一部分資源,第一個做業也就釋放一部分資源。再提交其餘的做業時,也同理。。。。也就是說每個做業進來,都有機會獲取資源。架構

 

 

1.4. Fair Scheduler與Capacity Scheduler區別

  • 資源公平共享:在每一個隊列中,Fair Scheduler可選擇按照FIFO、Fair或DRF策略爲應用程序分配資源。Fair策略即平均分配,默認狀況下,每一個隊列採用該方式分配資源
  • 支持資源搶佔:當某個隊列中有剩餘資源時,調度器會將這些資源共享給其餘隊列,而當該隊列中有新的應用程序提交時,調度器要爲它回收資源。爲了儘量下降沒必要要的計算浪費,調度器採用了先等待再強制回收的策略,即若是等待一段時間後尚有未歸還的資源,則會進行資源搶佔;從那些超額使用資源的隊列中殺死一部分任務,進而釋放資源
  • 負載均衡:Fair Scheduler提供了一個基於任務數的負載均衡機制,該機制儘量將系統中的任務均勻分配到各個節點上。此外,用戶也能夠根據本身的需求設計負載均衡機制
  • 調度策略靈活配置:Fiar Scheduler容許管理員爲每一個隊列單獨設置調度策略(當前支持FIFO、Fair或DRF三種)
  • 提升小應用程序響應時間:因爲採用了最大最小公平算法,小做業能夠快速獲取資源並運行完成

2.Yarn調度器配置

yarn資源調度器是在yarn-site.xml中配置app

2.1. FairScheduler

 Fair Scheduler的配置選項包括兩部分:負載均衡

  •  一部分在yarn-site.xml中,主要用於配置調度器級別的參數
  •  一部分在一個自定義配置文件(默認是fair-scheduler.xml)中,主要用於配置各個隊列的資源量、權重等信息。

 

2.1.1 yarn-site.xml

yarn-site.xml框架

    <!– scheduler start –>
    <property>
        <name>yarn.resourcemanager.scheduler.class</name>
        <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>
        <description>配置Yarn使用的調度器插件類名;Fair Scheduler對應的是:org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</description>
    </property>
    <property>
        <name>yarn.scheduler.fair.allocation.file</name>
        <value>/etc/hadoop/conf/fair-scheduler.xml</value>
        <description>配置資源池以及其屬性配額的XML文件路徑(本地路徑)</description>
    </property>
    <property>
        <name>yarn.scheduler.fair.preemption</name>
        <value>true</value>
        <description>開啓資源搶佔,default is True</description>
    </property>
    <property>
        <name>yarn.scheduler.fair.user-as-default-queue</name>
        <value>true</value>
        <description>設置成true,當任務中未指定資源池的時候,將以用戶名做爲資源池名。這個配置就實現了根據用戶名自動分配資源池。default is True</description>
    </property>
    <property>
        <name>yarn.scheduler.fair.allow-undeclared-pools</name>
        <value>false</value>
        <description>是否容許建立未定義的資源池。若是設置成true,yarn將會自動建立任務中指定的未定義過的資源池。設置成false以後,任務中指定的未定義的資源池將無效,該任務會被分配到default資源池中。,default is True</description>
    </property>
    <!– scheduler end –>

 

2.1.2 fair-scheduler.xml

假設在生產環境Yarn中,總共有四類用戶須要使用集羣,production、spark、default、streaming。爲了使其提交的任務不受影響,咱們在Yarn上規劃配置了四個資源池,分別爲production,spark,default,streaming。並根據實際業務狀況,爲每一個資源池分配了相應的資源及優先級等,default用於開發測試目的.分佈式

ResourceManager上fair-scheduler.xml配置以下:oop

<?xml version="1.0"?>
<allocations>
    <queue name="root">
        <aclSubmitApps></aclSubmitApps>
        <aclAdministerApps></aclAdministerApps>
        <queue name="production">
            <minResources>8192mb,8vcores</minResources>
            <maxResources>419840mb,125vcores</maxResources>
            <maxRunningApps>60</maxRunningApps>
            <schedulingMode>fair</schedulingMode>
            <weight>7.5</weight>
            <aclSubmitApps>*</aclSubmitApps>
            <aclAdministerApps>production</aclAdministerApps>
        </queue>
        <queue name="spark">
            <minResources>8192mb,8vcores</minResources>
            <maxResources>376480mb,110vcores</maxResources>
            <maxRunningApps>50</maxRunningApps>
            <schedulingMode>fair</schedulingMode>
            <weight>1</weight>
            <aclSubmitApps>*</aclSubmitApps>
            <aclAdministerApps>spark</aclAdministerApps>
        </queue>
        <queue name="default">
            <minResources>8192mb,8vcores</minResources>
            <maxResources>202400mb,20vcores</maxResources>
            <maxRunningApps>20</maxRunningApps>
            <schedulingMode>FIFO</schedulingMode>
            <weight>0.5</weight>
            <aclSubmitApps>*</aclSubmitApps>
            <aclAdministerApps>*</aclAdministerApps>
        </queue>
        <queue name="streaming">
            <minResources>8192mb,8vcores</minResources>
            <maxResources>69120mb,16vcores</maxResources>
            <maxRunningApps>20</maxRunningApps>
            <schedulingMode>fair</schedulingMode>
            <aclSubmitApps>*</aclSubmitApps>
            <weight>1</weight>
            <aclAdministerApps>streaming</aclAdministerApps>
        </queue>
    </queue>
    <user name="production">
        <!-- 對於特定用戶的配置:production最多能夠同時運行的任務 -->
        <maxRunningApps>100</maxRunningApps>
    </user>
    <user name="default">
        <!-- 對於默認用戶配置最多能夠同時運行的任務 -->
        <maxRunningApps>10</maxRunningApps>
    </user>

    <!-- users max running apps -->
    <userMaxAppsDefault>50</userMaxAppsDefault>
    <!--默認的用戶最多能夠同時運行的任務 -->
    <queuePlacementPolicy>
        <rule name="specified"/> 
        <rule name="primaryGroup" create="false" />
        <rule name="secondaryGroupExistingQueue" create="false" />
        <rule name="default" queue="default"/>
    </queuePlacementPolicy>
</allocations>

參數介紹:測試

  • minResources:最少資源保證量,設置格式爲「X mb, Y vcores」,當一個隊列的最少資源保證量未知足時,它將優先於其餘同級隊列得到資源,對於不一樣的調度策略(後面會詳細介紹),最少資源保證量的含義不一樣,對於fair策略,則只考慮內存資源,即若是一個隊列使用的內存資源超過了它的最少資源量,則認爲它已獲得了知足;對於drf策略,則考慮主資源使用的資源量,即若是一個隊列的主資源量超過它的最少資源量,則認爲它已獲得了知足。
  • maxResources:最多可使用的資源量,fair scheduler會保證每一個隊列使用的資源量不會超過該隊列的最多可以使用資源量。
  • maxRunningApps:最多同時運行的應用程序數目。經過限制該數目,可防止超量Map Task同時運行時產生的中間輸出結果撐爆磁盤。
  • weight:資源池權重,主要用在資源共享之時,weight越大,拿到的資源越多。好比一個pool中有20GB內存用不了,這時候能夠共享給其餘pool,其餘每一個pool拿多少,就是由權重決定的
  • aclSubmitApps:可向隊列中提交應用程序的Linux用戶或用戶組列表,默認狀況下爲「*」,表示任何用戶都可以向該隊列提交應用程序。須要注意的是,該屬性具備繼承性,即子隊列的列表會繼承父隊列的列表。配置該屬性時,用戶之間或用戶組之間用「,」分割,用戶和用戶組之間用空格分割,好比「user1, user2 group1,group2」。
  • aclAdministerApps:容許管理任務的用戶名和組;一個隊列的管理員可管理該隊列中的資源和應用程序,好比可殺死任意應用程序。
  • minSharePreemptionTimeout :最小共享量搶佔時間。若是一個資源池在該時間內使用的資源量一直低於最小資源量,則開始搶佔資源。
  • schedulingMode/schedulingPolicy:隊列採用的調度模式,能夠是fifo、fair或者drf。

管理員也可爲單個用戶添加maxRunningJobs屬性限制其最多同時運行的應用程序數目。此外,管理員也可經過如下參數設置以上屬性的默認值:

  • userMaxJobsDefault:用戶的maxRunningJobs屬性的默認值。
  • defaultMinSharePreemptionTimeout :隊列的minSharePreemptionTimeout屬性的默認值。
  • defaultPoolSchedulingMode:隊列的schedulingMode屬性的默認值。
  • fairSharePreemptionTimeout:公平共享量搶佔時間。若是一個資源池在該時間內使用資源量一直低於公平共享量的一半,則開始搶佔資源。

這樣,每一個用戶組下的用戶提交任務時候,會到相應的資源池中,而不影響其餘業務。隊列的層次是經過嵌套<queue>元素實現的。全部的隊列都是root隊列的孩子,即便沒有配到<root>元素裏。Fair調度器中的隊列有一個權重屬性(這個權重就是對公平的定義),並把這個屬性做爲公平調度的依據。在這個例子中,當調度器分配集羣7.5,1,1,0.5資源給production,spark,streaming,default時便視做公平,這裏的權重並非百分比。注意,對於在沒有配置文件時按用戶自動建立的隊列,它們仍有權重而且權重值爲1。每一個隊列內部仍能夠有不一樣的調度策略。隊列的默認調度策略能夠經過頂級元素<defaultQueueSchedulingPolicy>進行配置,若是沒有配置,默認採用公平調度。儘管是Fair調度器,其仍支持在隊列級別進行FIFO調度。每一個隊列的調度策略能夠被其內部的<schedulingPolicy> 元素覆蓋,在上面這個例子中,default隊列就被指定採用fifo進行調度,因此,對於提交到default隊列的任務就能夠按照FIFO規則順序的執行了。須要注意,spark,production,streaming,default之間的調度仍然是公平調度。每一個隊列可配置最大、最小資源佔用數和最大可運行的應用的數量。

Fair調度器採用了一套基於規則的系統來肯定應用應該放到哪一個隊列。在上面的例子中,<queuePlacementPolicy> 元素定義了一個規則列表,其中的每一個規則會被逐個嘗試直到匹配成功。例如,上例第一個規則specified,則會把應用放到它指定的隊列中,若這個應用沒有指定隊列名或隊列名不存在,則說明不匹配這個規則,而後嘗試下一個規則。primaryGroup規則會嘗試把應用放在以用戶所在的Unix組名命名的隊列中,若是沒有這個隊列,不建立隊列轉而嘗試下一個規則。當前面全部規則不知足時,則觸發default規則,把應用放在default隊列中。
固然,咱們能夠不配置queuePlacementPolicy規則,調度器則默認採用以下規則:

<queuePlacementPolicy>
      <rule name="specified" />
      <rule name="user" />
</queuePlacementPolicy>

上面規則意思是除非隊列被準確的定義,不然會以用戶名爲隊列名建立隊列。還有一個簡單的配置策略可使得全部的應用放入同一個隊列(default),這樣就可讓全部應用之間平等共享集羣而不是在用戶之間。這個配置的定義以下:

<queuePlacementPolicy>
     <rule name="default" />
</queuePlacementPolicy>

實現上面功能咱們還能夠不使用配置文件,直接設置yarn.scheduler.fair.user-as-default-queue=false,這樣應用便會被放入default 隊列,而不是各個用戶名隊列。另外,咱們還能夠設置yarn.scheduler.fair.allow-undeclared-pools=false,這樣用戶就沒法建立隊列了。

當一個job提交到一個繁忙集羣中的空隊列時,job並不會立刻執行,而是阻塞直到正在運行的job釋放系統資源。爲了使提交job的執行時間更具預測性(能夠設置等待的超時時間),Fair調度器支持搶佔。搶佔就是容許調度器殺掉佔用超過其應占份額資源隊列的containers,這些containers資源即可被分配到應該享有這些份額資源的隊列中。須要注意搶佔會下降集羣的執行效率,由於被終止的containers須要被從新執行。能夠經過設置一個全局的參數yarn.scheduler.fair.preemption=true來啓用搶佔功能。此外,還有兩個參數用來控制搶佔的過時時間(這兩個參數默認沒有配置,須要至少配置一個來容許搶佔Container):

minSharePreemptionTimeout
fairSharePreemptionTimeout

若是隊列在minimum share preemption timeout指定的時間內未得到最小的資源保障,調度器就會搶佔containers。咱們能夠經過配置文件中的頂級元素<defaultMinSharePreemptionTimeout>爲全部隊列配置這個超時時間;咱們還能夠在<queue>元素內配置<minSharePreemptionTimeout>元素來爲某個隊列指定超時時間。

與之相似,若是隊列在fair share preemption timeout指定時間內未得到平等的資源的一半(這個比例能夠配置),調度器則會進行搶佔containers。這個超時時間能夠經過頂級元素<defaultFairSharePreemptionTimeout>和元素級元素<fairSharePreemptionTimeout>分別配置全部隊列和某個隊列的超時時間。上面提到的比例能夠經過<defaultFairSharePreemptionThreshold>(配置全部隊列)和<fairSharePreemptionThreshold>(配置某個隊列)進行配置,默認是0.5。

須要注意的是,全部客戶端提交任務的用戶和用戶組的對應關係,須要維護在ResourceManager上,ResourceManager在分配資源池時候,是從ResourceManager上讀取用戶和用戶組的對應關係的,不然就會被分配到default資源池。在日誌中出現」UserGroupInformation: No groups available for user」相似的警告。而客戶端機器上的用戶對應的用戶組可有可無。

 

 每次在ResourceManager上新增用戶或者調整資源池配額後,須要執行下面的命令刷新使其生效.

yarn rmadmin -refreshQueues
yarn rmadmin -refreshUserToGroupsMappings

動態更新只支持修改資源池配額,若是是新增或減小資源池,則須要重啓Yarn集羣.

 

 Fair Scheduer各資源池配置及使用狀況,在ResourceManager的WEB監控頁面上也能夠看到: http://ResourceManagerHost:8088/cluster/scheduler

 

 

Reference:

1.Hadoop多用戶資源管理–Fair Scheduler介紹與配置

2.yarn公平調度詳細分析

 

2.2 Capacity Scheduler配置(默認配置)

hadoop2.7默認使用的是Capacity Scheduler容量調度器

yarn-site.xml

<property>
  <name>yarn.resourcemanager.scheduler.class</name>
  <value>org.apache.hadoop.yarn.server.resourcemanager.capacity.CapacityScheduler</value>
</property>

Capacity 調度器容許多個組織共享整個集羣,每一個組織能夠得到集羣的一部分計算能力。經過爲每一個組織分配專門的隊列,而後再爲每一個隊列分配必定的集羣資源,這樣整個集羣就能夠經過設置多個隊列的方式給多個組織提供服務了。除此以外,隊列內部又能夠垂直劃分,這樣一個組織內部的多個成員就能夠共享這個隊列資源了,在一個隊列內部,資源的調度是採用的是先進先出(FIFO)策略。

一個job可能使用不了整個隊列的資源。然而若是這個隊列中運行多個job,若是這個隊列的資源夠用,那麼就分配給這些job,若是這個隊列的資源不夠用了呢?其實Capacity調度器仍可能分配額外的資源給這個隊列,這就是「彈性隊列」(queue elasticity)的概念。

在正常的操做中,Capacity調度器不會強制釋放Container,當一個隊列資源不夠用時,這個隊列只能得到其它隊列釋放後的Container資源。固然,咱們能夠爲隊列設置一個最大資源使用量,以避免這個隊列過多的佔用空閒資源,致使其它隊列沒法使用這些空閒資源,這就是」彈性隊列」須要權衡的地方。

 

假設咱們有以下層次的隊列:

root
├── prod
└── dev
    ├── eng
    └── science

下面是一個簡單的Capacity調度器的配置文件,文件名爲capacity-scheduler.xml。在這個配置中,在root隊列下面定義了兩個子隊列proddev,分別佔40%和60%的容量。須要注意,一個隊列的配置是經過屬性yarn.sheduler.capacity.<queue-path>.<sub-property>指定的,<queue-path>表明的是隊列的繼承樹,如root.prod隊列,<sub-property>通常指capacitymaximum-capacity

 

咱們能夠看到,dev隊列又被分紅了eng和science兩個相同容量的子隊列。dev的maximum-capacity屬性被設置成了75%,因此即便prod隊列徹底空閒dev也不會佔用所有集羣資源,也就是說,prod隊列仍有25%的可用資源用來應急。咱們注意到,eng和science兩個隊列沒有設置maximum-capacity屬性,也就是說eng或science隊列中的job可能會用到整個dev隊列的全部資源(最多爲集羣的75%)。而相似的,prod因爲沒有設置maximum-capacity屬性,它有可能會佔用集羣所有資源。Capacity容器除了能夠配置隊列及其容量外,咱們還能夠配置一個用戶或應用能夠分配的最大資源數量、能夠同時運行多少應用、隊列的ACL認證等。

關於隊列的設置,這取決於咱們具體的應用。好比,在MapReduce中,咱們能夠經過mapreduce.job.queuename屬性指定要用的隊列。若是隊列不存在,咱們在提交任務時就會收到錯誤。若是咱們沒有定義任何隊列,全部的應用將會放在一個default隊列中。

注意:對於Capacity調度器,咱們的隊列名必須是隊列樹中的最後一部分,若是咱們使用隊列樹則不會被識別。好比,在上面配置中,咱們使用prod和eng做爲隊列名是能夠的,可是若是咱們用root.dev.eng或者dev.eng是無效的。

2.3 FIFO Scheduler

 yarn-site.xml

<property>
  <name>yarn.resourcemanager.scheduler.class</name>
  <value>org.apache.hadoop.yarn.server.resourcemanager.fifo.FifoScheduler</value>
</property>
相關文章
相關標籤/搜索