Yarn(Yet Another Resource Negotiator)是一個Hadoop集群資源管理系統,Hadoop2時被引入,旨在提高MapReduce的性能,但YARN已足夠通用,使得它可以支持其它的分布式應用。
Yarn本身提供了一系列API用於用戶應用程序與集群資源進行交互,這些API復雜且晦澀難懂,用戶通常不會直接使用。用戶編制應用程序時,通常使用的是分布式計算框架(MapReduce、Spark)提供的高層次API,這些API構建在Yarn之上且隱藏資源管理細節,如下圖所示:
MapReduce、Spark、Tez這樣的計算框架均以Yarn應用程序的形式運行於集群計算層(Yarn)和集群存儲層(HDFS或HBase)之上,而Pig、Hive、Crunch則運行於MapReduce、Spark或Tez之上,並沒有與Yarn直接交互。
Yarn的核心服務由兩個組件提供:
Resource Manager:每個集群一個實例,用於管理整個集群的資源使用;
Node Manager:每個集群多個實例,用於自身Container的啟動和監測(每個Node Manager上可能有多個Container)。
注:根據Yarn配置的不同,Container可能是一個Unix進程或者一個Linux cgroup實例,在受限的資源范圍內(如內存、CPU等)執行特定應用程序的代碼。
運行流程
(1)Client請求Resource Manager運行一個Application Master實例(step 1);
(2)Resource Manager選擇一個Node Manager,啟動一個Container並運行Application Master實例(step 2a、step 2b);
(3)Application Master根據實際需要向Resource Manager請求更多的Container資源(step 3);
(4)Application Master通過獲取到的Container資源執行分布式計算(step 4a、step 4b)。
Application Master的具體邏輯與特定的應用相關,也許直接向Client返回計算結果,也可能請求更多的資源執行分布式計算(如step 3)。此外,Yarn本身並沒有提供應用程序組件之間(Client、Master、Process)的通信實現,需要特定的應用程序自己提供,如使用Hadoop RPC。
資源請求
Yarn在資源請求方面擁有一個可擴展的模型,亦即可表述復雜的請求信息,如某個Container需要的計算資源量(內存或CPU),並可帶有數據本地性約束需求。
數據本地性約束可以很大程度上節約分布式計算處理時的集群帶寬消耗,可以表現為以下三種形式:
(1)請求位於集群特定節點上的Container;
(2)請求位於集群特定機架節點上的Container;
(3)請求位於集群任意節點上的Container。
數據本地性約束並不一定能夠恰好滿足,如果指定的節點無法啟動新的Container(正在運行的Container已將資源耗盡),則嘗試同一個機架的其它節點;如果也失敗,則嘗試集群中的其它節點。MapReduce場景下Map Container的分配就是這樣的一種情況,通常可以粗略地認為每一個Map任務負責處理一個Block的數據,為了避免網絡傳輸數據,應該盡可能的滿足數據本地性約束,優先在存有Block Replica的節點上啟動Container,次之在存有Block Replica的機架節點上啟動Contaier,末之在集群中的其余節點上啟動Container。
一個處於運行狀態的Yarn應用程序可以在任何時候發起資源請求,比如應用啟動時一次性請求所有資源(Spark),或者以動態的方式不斷請求更多的資源滿足應用的需要(MapReduce,首先請求全部的Map資源,稍后請求Reduce資源,如果某些Task失敗,還會申請更多的資源用於失敗恢復)。
應用程序生存期
Yarn應用程序的生存期跨度比較大:從運行幾秒鍾的短任務應用到運行幾天甚至幾月的長任務應用。相對於運行時間而言,一種更有效的方式是根據Application與Job的映射關系划分,常見以下三種情況:
(1)一個Application對應一個Job(MapReduce);
(2)一個Application對應一個Workflow(Session)的所有Jobs,這種方式可以在多個Jobs之間重用Containers並有效緩存中間數據(Spark);
(3)一個Long-Running Application被多個用戶共享,這種應用多數充當“Coordination”角色(Slider、Impala)。
構建Yarn應用程序
我們自己動手從頭到尾構建一個Yarn應用程序是比較復雜的,很多時候也是不必要的,可以根據需要的不同選擇一個優秀的分布式計算框架幫助我們構建應用程序,如需要DAG計算,則選擇Spark、Tez;需要流式處理,則選擇Spark、Samza或Storm。
也有一些開源項目幫助我們簡化Yarn應用程序的構建,如Slider、Twill,目前均處於孵化器狀態,暫時不討論。Yarn本身也自帶了一個例子“Distributed Shell Application”,向我們展示了如果通過Yarn Client API完成Client、Application Master與Yarn Daemons之間的交互。