yarn節點屬性及排程

語言: CN / TW / HK

【節點屬性產生的背景】

在2.X版本中,已經支援節點設定標籤,並且允許容量排程中的佇列,設定可訪問的節點標籤以及預設標籤值,並按照節點標籤進行排程。

但一個節點只能有1個標籤,這樣在yarn叢集中,通過標籤將NM節點劃分為不同的節點池(1個NM節點只能屬於某個固定的節點池)。

實際上,光有節點標籤還不能滿足一些複雜的場景,比如同一個型別標籤中的不同NM節點,可能有不同環境資訊,例如不同的jdk版本、python版本、cpu型號等等。

實際任務排程時,需要在正確的節點上執行,因此引入了節點屬性,節點屬性按K=V的形式設定,並且允許設定多個。【節點屬性的配置與設定】

1. yarn配置

和節點標籤一樣,節點屬性並不是預設開啟的,需要在rm(yarn-site.xml)中進行如下配置:

<property>
  <name>yarn.node-attribute.fs-store.root-dir</name>
  <value>hdfs://hdfsHACluster/root/node-attributes/</value>
</property>

<property>
  <name>yarn.node-attirbute.fs-store.impl.class</name>
  <value>FileSystemNodeAttributeStore</value>
</property>

其中"yarn.node-attribute.fs-store.root-dir"表示節點屬性在RM中的儲存位置可以選擇儲存本地(對應配置為file:///xxx/xxx),也可以是選擇儲存在hdfs上。

"yarn.node-attirbute.fs-store.impl.class"表示節點屬性儲存的實現類,預設為`FileSystemNodeAttributeStore`。

2. 節點屬性的設定

完成配置後,接下來自然就是對節點設定屬性。設定屬性的方式也和節點標籤類似,分為中心集中式和分散式,簡單來說中心集中式就是通過(管理員使用者)執行命令對各節點進行屬性設定;分散式則是由各節點通過自身配置的方式向RM上報所擁有的屬性。

對於中心集中式,主要使用新增、刪除命令,例如:

# 為指定節點新增屬性
yarn nodeattributes -add "172.168.3.51:python2=true"
# 刪除指定節點的屬性
yarn nodeattributes -remove "172.168.3.51:python2=true"

新增或刪除命令,通過指定節點的IP或域名,然後以":"分隔指定一個或多個屬性,屬性之間以","分隔;如果需要同時為多個節點設定屬性,以空格為分隔符,分別指定為不同節點指定屬性。

對於分散式,則需要在NM中進行對應的配置,例如:

<!-- 配置為config時通過 yarn.nodemanager.node-attributes.provider.configured-node-attributes來指定節點屬性 -->
<property>
    <name>yarn.nodemanager.node-attributes.provider</name>
    <value>config</value>
</property>
<property>
    <name>yarn.nodemanager.node-attributes.provider.configured-node-attributes</name>
    <!-- 多個屬性以 ":" 進行分隔 -->
    <!-- 每個屬性必須包含3個欄位, 屬性名,型別,屬性值, 欄位之間以","作為分隔 -->
    <!-- 型別只能為大寫STRIGN -->
    <!-- 屬性名只能為{0-9, a-z, A-Z, -, _} 且不能超過255個字元 -->
    <value>jdk8,STRING,true:python3,STRING,true</value>
</property>

"yarn.nodemanager.node-attributes.provider"除了配置為config外,還可以配置為script,即通過定期執行指定的指令碼來設定節點的屬性,例如:

<property>
    <name>yarn.nodemanager.node-attributes.provider</name>
    <value>script</value>
</property>
<!--指令碼的路徑-->
<!--指令碼的輸出必須為一行或多行這樣的資訊 NODE_ATTRIBUTE:屬性名,型別,屬性值" -->
<property>
    <name>yarn.nodemanager.node-attributes.provider.script.path</name>
    <value>/opt/xxx.sh</value>
</property>
<!--指令碼附帶的引數-->
<property>
    <name>yarn.nodemanager.node-attributes.provider.script.opts</name>
    <value></value>
</property>
<!--指令碼執行的間隔-->
<property>
    <name>yarn.nodemanager.node-attributes.provider.fetch-interval-ms</name>
    <value>600000</value>
</property>
<!--指令碼執行的超時時間-->
<property>
    <name>yarn.nodemanager.node-attributes.provider.fetch-timeout-ms</name>
    <value>1200000</value>
</property>

除此之外,還可以配置自定義開發的實現類該實現類一定要繼承自"org.apache.hadoop.yarn.server.nodemanager.nodelabels.NodeAttributesProvider"。

完成節點的屬性設定後,可以通過下面的命令來檢視已經設定的節點屬性:

[root@rm-0 /]# yarn nodeattributes -attributestonodes
                                Hostname Attribute-value
nm.yarn.io/python3 :
                            172.168.3.51 true
rm.yarn.io/python2 :
                            172.168.3.51 true
nm.yarn.io/jdk8 :
                            172.168.3.51 true

對於節點屬性的設定,有如下需要注意的地方:

  • 同一個key不能賦多個值,也就是說,對同一個Key多次設定屬性值,後面設定的值覆蓋前面設定的值

  • 當前value的型別僅支援string

  • 節點標籤還需要在佇列中設定可以訪問的標籤,而節點屬性則完全與佇列沒有關係

  • 對於節點標籤而言,只能採用集中式或者分散式的方式,而節點屬性則可以同時使用集中式和分散式的方式對接點進行設定對於集中式設定的屬性,會新增"rm.yarn.io"字首,而對於分散式方式設定的屬性,會新增"nm.yarn.io"字首。這就意味著屬性是通過字首加名稱來唯一標識的。

【按節點屬性進行任務排程】

1. Placement Constraints簡介

任務的container能根據節點屬性來進行排程,本質上是用到了Placement Constraints,這裡先來簡單介紹下Placement Constraints。

很多時候,為了提升效能,需要讓同一個application中的多個任務container執行在指定節點上,比如為了避免網路頻寬帶來的損耗,讓container之間具備親和性(執行在同一節點上)。

或者考慮到hdfs讀寫的效能,將應用的所有任務container排程到指定的節點上等等。

Hadoop引入了placement constraint,即AM向RM註冊時,可以設定不同的表示式,後續申請資源時,讓yarn根據此表示式來進行精準排程。

這個表示式就包含了NM節點屬性,因此就可以按照NM節點屬性來正確排程,當然,不僅限於按節點屬性來排程。

2. 按節點屬性匹配排程

要開啟placement的匹配排程,首先需要在RM中進行如下配置:

<property>
    <name>yarn.resourcemanager.placement-constraints.handler</name>
    <value>placement-processor</value>
</property>

然後,可以通過自帶的命令可以進行測試驗證:

yarn org.apache.hadoop.yarn.applications.distributedshell.Client -jar share/hadoop/yarn/hadoop-yarn-applications-distributedshell-3.3.3.jar -shell_command sleep -shell_args 10 -num_containers 3 -placement_spec python2=true

任務的執行情況:

對比下同樣的任務,未指定任何節點屬性的情況:

同樣,在使用中有如下需要注意的地方:

  • 屬性名稱的指定

    對於通過集中式方式指定的屬性,可以不用加字首,直接使用其屬性名即可,而對於分散式(NM自行上報)的屬性,使用時需要增加字首才能正確進行匹配上。因此使用上建議統一方式。

  • placement constraint為硬限制

    節點屬性約束是硬限制的, 即只有當節點的屬性與任務指定的屬性匹配時才能進行分配,否則任務container會一直處於pending狀態,直到找到可以滿足條件的有效節點。

  • 作用於任務container

    從上面的使用方式可以看到,placement constraint是在AM中進行設定的,因此也就只對任務container生效,而AM本身還是由RM按原有的方式進行排程

  • flink/spark還未支援

    當前最新版本的flink與spark都還未支援設定該引數,如需要使用,需要自行修改程式碼支援。

  • 引數不是強制的

    為任務contaienr申請資源時,placement表示式不是必須的,客戶端介面中有兩個介面分別對應攜帶和不帶該引數的情況。

【總結】

本文簡單介紹了節點屬性的背景,如何進行配置,以及如何按照節點屬性進行任務的排程。當然,涉及的placement constraint是一個比較龐大的內容,包括詳細的表示式設定、AM的程式碼中應當如何編寫對應的程式碼、RM中的排程邏輯等等,這裡沒有展開講解,後面單獨來進行整理說明。

 

好了,這就是本文的全部內容,如果覺得本文對您有幫助,請多多轉發,也歡迎加我微信交流~

本文分享自微信公眾號 - hncscwc(gh_383bc7486c1a)。
如有侵權,請聯絡 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。