本文檔介紹了機會性容器執行的概念,並討論機會性容器如何配置和執行。
我們從提供機會性容器的簡要概觀開始,包括使用者如何啟用此功能以及使用此類容器執行範例工作。
與現有的 YARN 容器不同,後者僅在有未配置資源時才在節點中排程,機會性容器可以傳送到 NM,即使它們在該節點的執行無法立即開始。在這種情況下,機會性容器將在該 NM 排隊,直到資源可用。機會性容器執行的主要目標是提高叢集資源利用率,進而增加任務處理量。資源利用率和任務處理量改善對於包含相對較短任務(以秒為單位)的工作負載更為明顯。
若要啟用機會性容器配置,以下兩個屬性必須存在於 conf/yarn-site.xml 中
屬性 | 說明 | 預設值 |
---|---|---|
yarn.resourcemanager.opportunistic-container-allocation.enabled |
啟用機會性容器配置。 | false |
yarn.nodemanager.opportunistic-containers-max-queue-length |
決定可以在 NM 排隊的最大機會性容器數目。 | 0 |
上面的第一個參數必須設定為 true
。第二個參數必須設定為正值,才能在 NM 排隊機會性容器。可以使用 10
的值來開始嘗試機會性容器。最佳值取決於工作特徵、叢集組態和目標利用率。
預設情況下,機會性容器的配置是透過 RM 集中執行。但是,使用者可以選擇啟用機會性容器的分布式配置,這可以進一步改善短任務的配置延遲。可以透過將以下參數設定為 true
來啟用分布式排程(請注意,非機會性容器將繼續透過 RM 排程)
屬性 | 說明 | 預設值 |
---|---|---|
yarn.nodemanager.distributed-scheduling.enabled |
啟用分布式排程。 | false |
若要將工作提交到已開啟 AMRMProxy 的叢集,必須為將提交工作的用戶端建立一組獨立的組態。在這些組態中,conf/yarn-site.xml 應具有以下其他組態
屬性 | 值 | 說明 |
---|---|---|
yarn.resourcemanager.scheduler.address |
localhost:8049 |
將作業重新導向至節點管理員的 AMRMProxy 埠。 |
可以使用下列指令執行範例 pi map-reduce 作業,使用 40% 的映射器執行機會性容器
$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.6.jar pi -Dmapreduce.job.num-opportunistic-maps-percent="40" 50 100
透過變更上述指令中 mapreduce.job.num-opportunistic-maps-percent
的值,我們可以指定可透過機會性容器執行的映射器百分比。
另一個範例作業是分散式 Shell,它允許我們在容器組上執行指定的 Shell 指令。可以使用下列指令在 10 個機會性容器中執行 sleep 10
指令
$ yarn org.apache.hadoop.yarn.applications.distributedshell.Client -jar share/hadoop/yarn/hadoop-yarn-applications-distributedshell-3.3.6.jar.jar -shell_command sleep -shell_args 10 -num_containers 10 -container_type OPPORTUNISTIC
透過變更上述指令中 container_type
的值為 OPPORTUNISTIC
或 GUARANTEED
,我們可以指定在機會性或保證容器中執行的作業。預設類型為 GUARANTEED
。透過將旗標 -promote_opportunistic_after_start
加入上述指令,應用程式主控程式會嘗試在機會性容器啟動後將其全部提升為保證容器。透過將旗標 -enforce_execution_type
加入上述指令,排程器會遵守容器的執行類型。
當啟用機會性容器配置時,可以在 Web UI 的節點頁面 (rm-address:8088/cluster/nodes
) 中觀察到下列新欄位
當按一下節點上執行的特定容器時,也會顯示容器的執行類型。
在文件其餘部分中,我們會深入說明機會性容器,包括其配置和執行詳細資料。
YARN 中現有的排程器(公平排程器和容量排程器)僅在排程容器時節點上有未配置資源時,才會將容器配置給節點。這種保證執行類型具有優點,即一旦 AM 將容器調度到節點,容器執行將立即開始,因為保證會有可用資源。此外,除非違背公平性或容量限制,否則保證容器會執行到完成而不會被搶佔。
儘管此設計提供了更可預測的任務執行,但它有兩個主要缺點,可能導致群集資源利用率不佳
為了減輕上述問題,除了現有的容器(我們在此稱之為保證容器)之外,我們引入了機會容器的概念。即使在排程時節點沒有可用(未配置)資源,也可以將機會容器調度到 NM。在這種情況下,機會容器將在 NM 排隊,等待資源可用以開始執行。機會容器的優先順序低於保證容器,這表示它們可以被搶佔,以讓保證容器開始執行。因此,它們可用於改善群集資源利用率,而不會影響現有保證容器的執行。
機會容器的另一個優點是,它們引入了NM 上的執行優先順序的概念。例如,不需要嚴格執行保證的較低優先順序工作,可以使用機會容器或其任務的容器執行類型組合。
我們已介紹了兩種配置機會性容器的方法:集中式和分散式。在集中式排程中,機會性容器透過 YARN RM 配置,而在分散式排程中,則透過存在於每個 NM 的本地排程器配置。集中式配置可做出較高品質的配置決策,並實作跨應用程式的更複雜共用政策(例如公平性)。另一方面,分散式排程可提供更快速的容器配置,這對於短暫工作很有用,因為它避免了與 RM 的往返行程。在兩種情況下,保證容器的排程保持不變,並透過 YARN RM(使用現有的公平或容量排程器)進行。
請注意,在目前的實作中,我們根據配置的(而非已使用的)資源配置容器。因此,我們解決了上述的「回饋延遲」問題,但並未解決「已配置與已使用資源」問題。目前正在進行的工作(YARN-1011
)使用機會性容器來解決後者問題。
以下,我們將更詳細地說明容器執行類型,以及機會性容器的執行(包括在 NM 的容器排隊)和配置。然後,我們將討論如何透過一些進階配置參數微調機會性容器。最後,我們將討論未來工作的開放項目。
我們介紹以下兩種容器類型
當 AM 將其資源要求提交給 RM 時,它會為每個容器指定類型(預設為保證),決定容器將以何種方式配置。隨後,當容器由 AM 在 NM 上啟動時,其類型決定了它將如何由 NM 執行。
當容器到達 NM 時,其執行由 NM 上的可用資源和容器類型決定。保證容器立即開始執行,如果需要,NM 將終止正在執行的機會容器,以確保有足夠的資源讓保證容器啟動。另一方面,如果在機會容器到達 NM 時沒有可用的資源來啟動其執行,則它們可以在 NM 上排隊。為此,我們通過允許在每個節點排隊容器來擴充 NM。NM 會監控本地資源,當有足夠的可用資源時,它會開始執行位於隊列開頭的機會容器。
特別是,當容器到達 NM 時,會執行本地化(即下載所有必需的資源),然後容器移動到SCHEDULED
狀態,在該狀態下容器會排隊,等待其執行開始
在以下未來工作項目中,我們會討論優先執行任務(隊列重新排序)和終止機會容器以騰出空間給保證容器的不同方式。
如上所述,我們提供了集中式和分散式兩種配置機會容器的方式,我們在下面進行說明。
我們在 RM 中引進了一項新的服務,即 OpportunisticContainerAllocatorAMService
,它擴充了 ApplicationMasterService
。當啟用集中式機會性配置時,AM 的資源要求會由 OpportunisticContainerAllocatorAMService
在 RM 端提供服務,它會將這些要求拆分成兩組資源要求
ApplicationMasterService
,然後由 Fair 或 Capacity Scheduler 處理。OpportunisticContainerAllocator
處理,它會執行機會性容器到節點的排程。OpportunisticContainerAllocator
會維護一個清單,其中包含叢集在每個時刻的 負載最小的節點,並以循環方式將容器指派給這些節點。請注意,在目前的實作中,我們故意不考慮節點區域限制。由於機會性容器(與保證容器不同)可能會在執行開始前在 NM 的佇列中等待,因此將它配置到負載較小的節點(即佇列延遲會較小的節點)比遵守其區域限制更為重要。此外,我們目前不會考慮機會性容器的共用(公平性/容量)限制。如果需要,可以在未來新增對區域和共用限制的支援。
為了啟用機會性容器的分散排程,我們在每個 NM 中引進了一項新的服務,稱為 AMRMProxyService
。AMRMProxyService
實作 ApplicationMasterService
協定,並充當在該節點上執行的 AM 與 RM 之間的代理。當啟用 AMRMProxyService
(透過參數)時,我們會強制在特定節點上執行的所有 AM 與同一節點的 AMRMProxyService
通訊,而不是直接連線到 RM。此外,為了確保 AM 不會直接與 RM 對話,當新的 AM 初始化時,我們會將其 AMRMToken
取代為由 AMRMProxyService
簽署的權杖。
可以向 AMRMProxyService
註冊一連串攔截器。其中一個攔截器是 DistributedScheduler
,負責以分散的方式配置機會性容器,無需連線到 RM。這種模組化設計也讓 AMRMProxyService
在其他場景中發揮作用,例如 YARN 聯盟(YARN-2915
)或限制行為不當的 AM,只要在攔截器鏈中新增其他攔截器即可輕鬆啟用這些功能。
當啟用分散機會性排程時,每個 AM 會將其資源要求傳送給在同一節點上執行的 AMRMProxyService
。AMRMProxyService
會將資源要求拆分成兩組
AMRMProxyService
僅充當 AM 與 RM 之間的代理,而容器配置保持不變(使用 Fair 或 Capacity Scheduler)。DistributedScheduler
處理。特別是,DistributedScheduler
維護一個清單,其中包含叢集中最少載入的節點,並以循環的方式將容器分配給它們。RM 會透過 NM-RM 心跳,定期告知 DistributedScheduler
最少載入的節點。上述程序類似於上述集中式機會主義排程中 OpportunisticContainerAllocatorAMService
執行的程序。主要差別在於,在分散式案例中,將要求拆分為保證和機會主義會在節點上本地發生,而只有保證要求會轉發到 RM,而機會主義要求會在不連絡 RM 的情況下處理。
每個 NM 會透過 NM-RM 心跳定期告知 RM 正在執行的保證和機會主義容器數量,以及排隊的機會主義容器數量。RM 會從所有節點收集這些資訊,並決定最少載入的節點。
在集中式分配機會主義容器的情況下,這些資訊會立即提供,因為分配是集中進行的。在分散式排程的情況下,最少載入節點的清單會透過 RM 對 NM 的心跳回應傳播到所有 NM(因此 DistributedSchedulers
可以取得)。傳送到 NM 的最少載入節點數量是可以設定的。
目前,我們只考慮每個節點排隊的機會主義容器數量,以估計如果將機會主義容器傳送到該節點,它必須等待的時間,並因此決定最少載入的節點。如果 AM 提供了有關估計任務持續時間的資訊,我們可以將它們考慮在內,以便對排隊等待時間有更好的估計。
偶爾可能會對機會主義容器做出不佳的配置選擇(由於過時的佇列長度估計),這可能導致節點之間的負載不平衡。在高叢集負載下,以及在分散式排程的情況下,這個問題會更明顯(多個 DistributedSchedulers
可能會將容器配置在同一個 NM 上,因為它們不會彼此協調)。為了處理 NM 佇列之間的負載不平衡,我們會執行負載捨棄,以動態重新平衡 NM 之間的負載。特別是,在 RM 中彙總每個 NM 發布的佇列時間估計時,我們會建構一個分配,並找出 NM 佇列長度的目標最大值(根據分配的平均值和標準差)。然後,RM 會透過心跳回應將這個值傳播到各種 NM。隨後,NM 會使用這些資訊,如果節點上的佇列長度超過閾值,則會捨棄機會主義容器,以符合這個最大值。這會強制相關的個別 AM 在其他地方重新排程這些容器。
啟用機會主義容器分配,以及在集中式和分散式分配之間進行選擇的主要屬性已在本文件開頭的 快速指南 中說明。在此,我們提供更進階的設定。請注意,在大多數情況下,使用這些參數的預設值就已足夠。以下所有參數都必須在 conf/yarn-site.xml 檔案中定義。
若要決定排程機會性容器時將使用的負載最小的節點數量,以及更新此清單的頻率,我們使用下列參數:
屬性 | 說明 | 預設值 |
---|---|---|
yarn.resourcemanager.opportunistic-container-allocation.nodes-used |
機會性容器配置器在容器配置期間用來調度容器的負載最小的節點數量。較高的值可以改善大型叢集的負載平衡。 | 10 |
yarn.resourcemanager.nm-container-queuing.sorting-nodes-interval-ms |
計算負載最小的節點的頻率。 | 1000 |
如上方的節點負載重新平衡區段所述,RM 會定期收集所有 NM 佇列長度,並計算其平均值 (avg
) 和標準差 (stdev
),以及值 avg + k*stdev
(其中 k
是浮點數)。此值會透過 NM-RM 心跳傳播到所有 NM,只要其目前的佇列長度介於 queue_min_length
和 queue_max_length
值之間 (這些值分別用來避免從非常短的佇列中取消佇列工作,以及積極地從長佇列中取消佇列工作),所有 NM 都應該尊重該值。可以如下列方式指定參數 k
、queue_min_length
和 queue_max_length
:
屬性 | 說明 | 預設值 |
---|---|---|
yarn.resourcemanager.nm-container-queuing.queue-limit-stdev |
k 參數。 |
1.0f |
yarn.resourcemanager.nm-container-queuing.min-queue-length |
queue_min_length 參數。 |
5 |
yarn.resourcemanager.nm-container-queuing.max-queue-length |
queue_max_length 參數。 |
15 |
最後,如果使用分散式排程,可以再使用兩個屬性進一步調整 AMRMProxyService
:
屬性 | 說明 | 預設值 |
---|---|---|
yarn.nodemanager.amrmproxy.address |
AMRMProxyService 繫結到的地址/埠。 |
0.0.0.0:8049 |
yarn.nodemanager.amrmproxy.client.thread-count |
每個 NM 使用的執行緒數量,用於讓不同的工作將攔截器註冊到 AMRMProxyService 。 |
3 |
我們在此說明我們可以延伸/增強機會性容器的配置和執行的多種方式。我們也提供追蹤每個項目的 JIRA。
YARN-1011
)。如前所述,為了進一步改善叢集資源使用率,我們可以排程容器,但不是根據已配置的資源,而是根據實際使用的資源。在超額承諾資源時,如果已執行的容器的已使用資源增加,則有耗盡資源的風險。因此,機會性執行應該用於配置超出節點容量的容器。這樣一來,我們可以選擇機會性容器來終止以回收資源。YARN-5886
)。我們可以採用重新排序策略,動態決定接下來要執行哪個機會性容器,而不是以 FIFO 順序執行佇列中的容器。例如,我們可以優先執行預期執行時間短的容器,或屬於接近完成的應用程式的容器。YARN-5887
)。如上所述,當我們需要釋放資源以便保證容器開始執行時,我們會按抵達順序反向終止機會性容器(首先終止最近啟動的容器)。這可能並非總是正確的決定。例如,我們可能希望將終止的容器數量減至最少,或避免終止接近完成的作業的容器。YARN-5292
):目前,我們會終止機會性容器,以便在資源競爭時為保證容器騰出空間。在繁忙的叢集中,這可能會降低有效的叢集使用率:每當我們終止正在執行的機會性容器時,都必須重新啟動它,因此我們會失去工作。為此,我們可以暫停正在執行的機會性容器。請注意,這需要容器執行器(例如,所使用的容器技術)和應用程式的支援。YARN-5085
)。在某些情況下,在執行期間變更容器的執行類型可能是有益的。例如,應用程式可能會提交一個容器作為機會性容器,而當其執行開始時,它可以要求將其提升為保證容器,以避免被終止。