機會性容器

目的

本文檔介紹了機會性容器執行的概念,並討論機會性容器如何配置和執行。

快速指南

我們從提供機會性容器的簡要概觀開始,包括使用者如何啟用此功能以及使用此類容器執行範例工作。

主要目標

與現有的 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 埠。

執行範例作業

MapReduce PI

可以使用下列指令執行範例 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,它允許我們在容器組上執行指定的 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 的值為 OPPORTUNISTICGUARANTEED,我們可以指定在機會性或保證容器中執行的作業。預設類型為 GUARANTEED。透過將旗標 -promote_opportunistic_after_start 加入上述指令,應用程式主控程式會嘗試在機會性容器啟動後將其全部提升為保證容器。透過將旗標 -enforce_execution_type 加入上述指令,排程器會遵守容器的執行類型。

Web UI 中的機會性容器

當啟用機會性容器配置時,可以在 Web UI 的節點頁面 (rm-address:8088/cluster/nodes) 中觀察到下列新欄位

  • 執行中容器 (O):每個節點上執行的機會性容器數目;
  • 已用記憶體 (O):每個節點上機會性容器使用的總記憶體;
  • 已用虛擬核心 (O):每個節點上機會性容器使用的總 CPU 虛擬核心;
  • 排隊容器:每個節點上排隊的容器數目。

當按一下節點上執行的特定容器時,也會顯示容器的執行類型。

在文件其餘部分中,我們會深入說明機會性容器,包括其配置和執行詳細資料。

概觀

YARN 中現有的排程器(公平排程器和容量排程器)僅在排程容器時節點上有未配置資源時,才會將容器配置給節點。這種保證執行類型具有優點,即一旦 AM 將容器調度到節點,容器執行將立即開始,因為保證會有可用資源。此外,除非違背公平性或容量限制,否則保證容器會執行到完成而不會被搶佔。

儘管此設計提供了更可預測的任務執行,但它有兩個主要缺點,可能導致群集資源利用率不佳

  • 回饋延遲。當容器在節點上完成執行時,RM 會透過下一次 NM-RM 心跳獲知有可用資源,然後 RM 會在該節點上排程新的容器,AM 會透過下一次 AM-RM 心跳獲知,最後 AM 會在節點上啟動新的容器。這些延遲會導致節點資源閒置,進而導致資源利用率降低,特別是在工作負載涉及持續時間相對較短的任務時。
  • 已配置資源與已利用資源。RM 會根據每個節點上的已配置資源配置容器,而這些資源可能遠高於實際已利用資源(例如,想想一個已配置 4GB 記憶體,但僅使用 2GB 的容器)。這會降低有效資源利用率,如果 RM 在排程期間考量已利用資源,則可以避免這種情況。然而,這必須以一種方式進行,允許在執行容器的已利用資源增加時回收資源。

為了減輕上述問題,除了現有的容器(我們在此稱之為保證容器)之外,我們引入了機會容器的概念。即使在排程時節點沒有可用(未配置)資源,也可以將機會容器調度到 NM。在這種情況下,機會容器將在 NM 排隊,等待資源可用以開始執行。機會容器的優先順序低於保證容器,這表示它們可以被搶佔,以讓保證容器開始執行。因此,它們可用於改善群集資源利用率,而不會影響現有保證容器的執行。

機會容器的另一個優點是,它們引入了NM 上的執行優先順序的概念。例如,不需要嚴格執行保證的較低優先順序工作,可以使用機會容器或其任務的容器執行類型組合。

我們已介紹了兩種配置機會性容器的方法:集中式分散式。在集中式排程中,機會性容器透過 YARN RM 配置,而在分散式排程中,則透過存在於每個 NM 的本地排程器配置。集中式配置可做出較高品質的配置決策,並實作跨應用程式的更複雜共用政策(例如公平性)。另一方面,分散式排程可提供更快速的容器配置,這對於短暫工作很有用,因為它避免了與 RM 的往返行程。在兩種情況下,保證容器的排程保持不變,並透過 YARN RM(使用現有的公平或容量排程器)進行。

請注意,在目前的實作中,我們根據配置的(而非已使用的)資源配置容器。因此,我們解決了上述的「回饋延遲」問題,但並未解決「已配置與已使用資源」問題。目前正在進行的工作(YARN-1011)使用機會性容器來解決後者問題。

以下,我們將更詳細地說明容器執行類型,以及機會性容器的執行(包括在 NM 的容器排隊)和配置。然後,我們將討論如何透過一些進階配置參數微調機會性容器。最後,我們將討論未來工作的開放項目。

容器執行類型

我們介紹以下兩種容器類型

  • 保證容器對應於現有的 YARN 容器。它們由公平或容量排程器配置,一旦傳送到節點,保證有可用的資源可立即開始執行。此外,這些容器會執行到完成(只要沒有發生故障)。只有在它們所屬的排程器佇列違反公平性或容量限制時,才會被搶先執行。
  • 機會性容器並未保證在傳送到節點時有資源可開始執行。相反地,它們可能會在 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 中引進了一項新的服務,稱為 AMRMProxyServiceAMRMProxyService 實作 ApplicationMasterService 協定,並充當在該節點上執行的 AM 與 RM 之間的代理。當啟用 AMRMProxyService(透過參數)時,我們會強制在特定節點上執行的所有 AM 與同一節點的 AMRMProxyService 通訊,而不是直接連線到 RM。此外,為了確保 AM 不會直接與 RM 對話,當新的 AM 初始化時,我們會將其 AMRMToken 取代為由 AMRMProxyService 簽署的權杖。

可以向 AMRMProxyService 註冊一連串攔截器。其中一個攔截器是 DistributedScheduler,負責以分散的方式配置機會性容器,無需連線到 RM。這種模組化設計也讓 AMRMProxyService 在其他場景中發揮作用,例如 YARN 聯盟(YARN-2915)或限制行為不當的 AM,只要在攔截器鏈中新增其他攔截器即可輕鬆啟用這些功能。

當啟用分散機會性排程時,每個 AM 會將其資源要求傳送給在同一節點上執行的 AMRMProxyServiceAMRMProxyService 會將資源要求拆分成兩組

  • 保證組會轉發給 RM。在這種情況下,AMRMProxyService 僅充當 AM 與 RM 之間的代理,而容器配置保持不變(使用 Fair 或 Capacity Scheduler)。
  • 機會主義集合不會轉發到 RM。相反地,它由在節點上本地執行的 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_lengthqueue_max_length 值之間 (這些值分別用來避免從非常短的佇列中取消佇列工作,以及積極地從長佇列中取消佇列工作),所有 NM 都應該尊重該值。可以如下列方式指定參數 kqueue_min_lengthqueue_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)。如前所述,為了進一步改善叢集資源使用率,我們可以排程容器,但不是根據已配置的資源,而是根據實際使用的資源。在超額承諾資源時,如果已執行的容器的已使用資源增加,則有耗盡資源的風險。因此,機會性執行應該用於配置超出節點容量的容器。這樣一來,我們可以選擇機會性容器來終止以回收資源。
  • NM 佇列重新排序 (YARN-5886)。我們可以採用重新排序策略,動態決定接下來要執行哪個機會性容器,而不是以 FIFO 順序執行佇列中的容器。例如,我們可以優先執行預期執行時間短的容器,或屬於接近完成的應用程式的容器。
  • 在 NMs 中強制終止 (YARN-5887)。如上所述,當我們需要釋放資源以便保證容器開始執行時,我們會按抵達順序反向終止機會性容器(首先終止最近啟動的容器)。這可能並非總是正確的決定。例如,我們可能希望將終止的容器數量減至最少,或避免終止接近完成的作業的容器。
  • 容器暫停 (YARN-5292):目前,我們會終止機會性容器,以便在資源競爭時為保證容器騰出空間。在繁忙的叢集中,這可能會降低有效的叢集使用率:每當我們終止正在執行的機會性容器時,都必須重新啟動它,因此我們會失去工作。為此,我們可以暫停正在執行的機會性容器。請注意,這需要容器執行器(例如,所使用的容器技術)和應用程式的支援。
  • 容器提升 (YARN-5085)。在某些情況下,在執行期間變更容器的執行類型可能是有益的。例如,應用程式可能會提交一個容器作為機會性容器,而當其執行開始時,它可以要求將其提升為保證容器,以避免被終止。