YARN的介紹和一些實踐探索

2020-04-29     sandag

什麼是YARN?

Apache Hadoop YARN 是一種新的 Hadoop資源管理器。 它是一個通用資源管理系統,可為上層應用提供統一的資源管理和調度,它的引入為集群在利用率、資源統一管理和數據共享等方面帶來了巨大好處。也就是說YARN在Hadoop集群中充當資源管理和任務調度的框架。

Apache Hadoop YARN:

Yet Another Resource Negotiator,另一種資源協調者

01

YARN的架構

1.1 ResourceManager

ResourceManager是YARN中的主節點服務,它負責集群中所有資源的 統一管理作業調度

簡單來講,ResourceManager主要完成的功能包括:

與客戶端交互,處理來自客戶端的請求;

啟動和管理ApplicationMaster,並在它運行失敗時重新啟動它;

管理NodeManager,接收來自NodeManager的資源彙報信息,並向NodeManager下達管理指令 (比如殺死container等) ;

資源管理與調度,接收來自ApplicationMaster的資源申請請求,並為之分配資源。

1.2 NodeManager

NodeManager 是YARN集群中的每個具體節點的 資源和任務管理者 。NodeManager的主要功能包括:

定時向ResourceManager彙報本節點上的資源使用情況和各個Container的運行狀態;

接收並處理ApplicationMaster對container的啟動、停止等各種請求;

管理Container的生命周期,監控Container的資源使用;

管理任務日誌和不同應用程式用到的附屬服務 (auxiliary service) 。

1.3 ApplicationMaster

用戶提交的每個應用程式均包含一個ApplicationMaster,主要功能包括:

與ResourceManager調度器協商以獲取資源;

將得到的資源進一步分配給內部的任務;

與NodeManager通信以啟動或停止任務;

監控所有任務的運行狀態,並在任務運行失敗時負責進行容錯處理。

1.4 Container

Container是YARN中的資源抽象,它封裝了某個節點上的多個維度的資源,如CPU、內存、磁碟、網絡等。當ApplicationMaster向ResourceManager申請資源時,ResourceManager為ApplicationMaster 返回的資源是用Container表示的。

02

提交Application到YARN的流程

當用戶向YARN中提交一個應用程式後,YARN將分兩個階段運行該應用程式:

第一階段:啟動ApplicationMaster;

第二階 :由ApplicationMaster創建應用程式;為它申請資源,並監控它的整個運行過程,直到運行完成。

如下圖所示,以一個mapreduce程序提交到YARN的過程進行分析。

2.1 作業提交

第1步:

client 讀取作業配置信息並創建Job的環境,調用job.waitForCompletion 方法,向集群提交一個MapReduce 作業 。

第2步:

資源管理器給任務分配一個新的作業ID 。

第3步:

作業的client核實作業的輸出路徑,計算輸入文件的分片,將作業的資源 (包括:Jar包、配置文件,split信息等) 拷貝到HDFS集群上的作業提交目錄。

第4步:

通過調用資源管理器的submitApplication()來提交作業。

2.2 作業初始化

第5步:

當資源管理器收到submitApplciation()的請求時,就將該請求發給調度器 (scheduler) ,調度器向NodeManager發送一個啟動container的請求。

第6步:

節點管理器NodeManager啟動container,內部運行著一個主類為 MRAppMaster的Java應用。其通過創造一些對象來監控作業的進度,得到各個task的進度和完成報告 。

第7步:

然後其通過分布式文件系統HDFS來獲取由客戶端提前計算好的輸入split,然後為每個輸入split創建一個map任務,根據mapreduce.job.reduces創建 reduce任務對象。

2.3 任務分配

如果作業很小,為了降低延遲,可採用Uber模式。 在該模式下,所有的Map Task和Reduce Task都在ApplicationMaster所在的Container中運行。

第8步:

如果不是小作業,那麼應用管理器向資源管理器請求container來運行所有的map和 reduce 任務 。

這些請求是通過心跳來傳輸的,包括每個map任務的數據位置。比如:存放輸入split的主機名和機架 (rack) ,調度器利用這些信息來調度任務,儘量將任務分配給存儲數據的節點或相同機架的節點。

2.4 任務運行

第9步:

當一個任務由資源管理器的調度器分配給一個container後,AppMaster通過聯繫NodeManager來啟動container。

第10步:

任務由一個主類為YarnChild的Java應用執行,在運行任務之前首先本地化任務需要的資源。比如:作業配置、JAR文件以及分布式緩存的所有依賴文件 。

第11步:

最後,啟動並運行map或reduce任務 。

2.5 進度和狀態更新

YARN中的任務將其進度和狀態 (包括counter) 返回給應用管理器。

客戶端每秒 (通過mapreduce.client.progressmonitor.pollinterval設置) 向應用管理器請求進度更新,展示給用戶。

2.6 作業完成

除了向應用管理器請求作業進度外,客戶端每5秒會通過調用 waitForCompletion()來檢查作業是否完成,時間間隔可以通過 mapreduce.client.completion.pollinterval來設置。

作業完成之後,應用管理器和container會清理工作狀態、作業的執行詳情記錄文件.jhist會被轉移到歷史伺服器目錄、container的執行日誌會被nodemanager上傳到HDFS集群供用戶長期查詢。

03

Yarn-主控程序RM介紹

如圖所示,ResouceManager主要包括以下幾個部分組成:

User Service (用戶交互模塊)

ResouceManager分別針對普通用戶、管理員和Web提供了三種對外服務。 具體實現分別對應:

ClientRMService :

處理普通用戶的提交程序、終止程序、獲取程序狀態等請求

AdminService :

處理管理員的刷新隊列、更新ACL權限等請求

RMWebApp :

展示集群資源使用情況和應用程式執行狀態等信息的web頁面

Manage NMS (nodemanager管理模塊)

該模塊主要包括幾個組件:

NMLivelinessMonitor :

監控nodemanager的存活狀態,如果nodemanager超時未彙報心跳信息,則將從集群中剔除該節點

N odesListManage r:

維護正常節點和異常節點列表,類似於集群的黑名單和白名單節點

ResourceTrackerService :

處理來自NodeManager的請求,主要包括註冊和心跳請求

Security (安全管理模塊)

ResouceManager自帶了非常全面的權限管理機制,主要由以下三個模塊構成:

RMDelegationTokenSecretManager;

DelegationTokenRenewer;

ClientToAMSecretManager。

Manage Apps (Application管理模塊)

該模塊主要包括幾個組件:

ApplicationACLSManager :

管理應用程式的查看和修改權限

RMAppManager :

管理應用程式的啟動和關閉

ContainerAllocationExpirer :

監控AM是否在規定的時間內將獲得的container在NodeManager上啟動

Manage AMS (AM管理模塊)

該模塊主要的組件包括:

AMLivelinessMonitor

監控AM是否存活

ApplicationMasterLauncher

與nodemanager通信以啟動ApplicationMaster

ApplicationMasterService

處理來自ApplicationMaster的註冊和心跳兩種請求

狀態機管理模塊

ResourceManager使用有限狀態機維護有狀態對象的生命周期,共維護了4類狀態機,分別是:

RMApp :

一個Application的運行生命周期

RMAppAttempt :

一個Application運行實例的生命周期

RMContainer :

一個Container的運行生命周期

RMNode :

一個NodeManager的生命周期

ResouceScheduler (資源調度模塊)

該模塊主要就是涉及資源調度一個組件,比較常見的實現是:

FairScheduler:

公平調度器

CapacityScheduler:

容量調度器

YARN採用了基於事件驅動的並發模型,該模型能夠大大增強並發性,從而提高系統的整體性能。

在YARN中所有核心服務實際上都是一個中央異步調度器,包括:

ResourceManager

NodeManager

MRAppMaster等。

它們維護了事先註冊的事件和事件處理器,並根據接收的事件類型驅動服務的運行

上面介紹的ResourceManager的各個服務和組件均是通過中央異步調度器組織在一起的。不同的組件之間通過事件交互,從而實現了一個異步並行的高效系統。

04

一些探索和實踐

為了保障公司的計算資源得到充分利用,大數據平台這邊統一使用YARN進行資源管理與調度。

目前在我們的YARN集群上主要支撐了絕大部分的離線應用 (MapReduce、Hive SQL、Spark-Submit、Spark SQL) 和一部分實時業務 (Spark streaming、Flink) 。

隨著業務快速發展,為了滿足業務的大量計算任務需求,我們對YARN集群做了一些探索和實踐的工作。

目前集群的機器規模由開始的幾百台發展到現在的5000+台、單集群最大節點數2500+、單集群管理的Container數10w+、單集群日調度Container數近1億。

對YARN開展的一些穩定和優化工作,主要包括四個方面:

修復集群日常運維工作中發現的問題;

開發一些特性滿足集群的安全和使用需求;

跟進社區合入相關patch對YARN的調度性能提升;

完善YARN集群的運維管理工作。

4.1對集群暴露的一些嚴重bug的修復:

4.1.1

YARN HA的實現一般是採用基於zookeeper的共享存儲。 YARN將共享存儲系統抽象成RMStateStore,以保存恢復ResourceManager所必需的信息。但一些異常任務寫zk的大小會超過znode的大小,從而會觸發整個YARN服務的異常。

有一次我們收到線上YARN集群主備頻繁切換的告警,隨後業務反應大量的作業處於一直處於NEW_SAVING (等待提交狀態) ,整個系統處於不可用狀態。

因為當時我們只有一個集群,整個的影響面非常大,只能快速備份RM堆棧信息和進程日誌,隨後進行重啟操作。重啟集群後,發現集群恢復了一段時間,隨後又出現了類似反覆的情況,而每次出現的時間和頻率都沒有規律可循。

通過搜索日誌錯誤關鍵字,在社區中找到相關的issue,基本可以判斷是由於異常任務導致的,結合異常發生的頻率可以推測出是非調度任務觸發的。

隨後我們在群里公告目前發現的問題,並緊急合入社區相關patch,後面集群沒有再發現同樣的異常。

我們隨後查閱歷史作業伺服器,發現了類似的異常任務,task數量非常大,依賴的jar包非常多,RMStateStore持久化了這些jar包的引用關係,我們在測試集群也驗證了這個問題。

所以我們要限制RM持久化RMStateStore寫zk的大小,社區相關patch包括:YARN-2368 、YARN-3469、YARN-6125、YARN-5006。

4.1.2

mr任務申請內存和cpu超過yarn調度最大資源問題,特別是大任務的話會寫大量錯誤診斷信息到zk上,影響整個集群其他任務的正常提交。

我們在任務提交的時候能夠快速檢測並失敗這類任務,並減少列印錯誤診斷信息。

4.1.3

修復跨集群的一些問題: spark任務跨集群問題&mr任務跨集群問題:

因為我們的集群是由很多個HDFS集群組建成的一個大YARN集群,而我們每個小集群的defaultFS和客戶端的defaultFS都是不同的。

這樣默認會造成作業的提交目錄無法被appmaster完全清除,長期運行後會導致單級目錄文件數超過namenode的最大限制而導致無法提交新的任務。

4.2 特性開發

4.2.1 YARN隊列權限改造:

YARN隊列權限是解決提交任務的用戶或所屬組是否有隊列的提交權限,而用戶和組映射關係的默認的實現類是ShellBasedUnixGroupsMapping。

它是獲取ResourceManager本地機器的作業系統的用戶和組關係。我們開發了權限插件,新增了自定義的用戶和組映射關係實現類HeyTapGroupsMapping,對接我們內部的權限系統的用戶和組關係;

4.2.2 限制用戶通過rest api提交任務:

默認的情況下,YARN的8088埠未做相關認證,攻擊者可通過rest api 提交任務,下載與集群網絡相通的腳本執行異常攻擊,很多公司都遭受過此攻擊;我們的改動是在YARN的提交任務rest 接口處添加開關支持,一般我們的集群任務是通過授信的客戶端提交,所以我們默認關閉REST API任務的提交。

相關安全漏洞連結:Hadoop Yarn REST API未授權漏洞利用挖礦分析

https://segmentfault.com/a/1190000015264170

4.2.3按隊列限制單個mr任務的task總數量:

我們的集群之前會有很多的大的mr任務,這部分任務會浪費集群比較多的資源,並且容易觸發很多集群bug問題。

針對mr任務支持按隊列配置提交隊列的任務最大task數量,超過直接拒絕任務提交。這部分的實現是在MR任務的AppMaster初始化作業的JobImpl類中對作業的信息進行檢查。

4.2.4 YARN集群熔斷措施:

集群難免會有異常的時候,當異常的時候往往會出現任務大量pending和Running的情況,系統內部大量消息處理堆積。

如果我們不做熔斷處理,ResourceManager會由於事件長期堆積而超過JVM最大內存而oom崩潰。

我們的改動是當集群總的running任務數+accept任務數超過歷史安全閾值則進行拒絕提交;按子隊列熔斷數量限制,考慮實際實施過程中,子隊列一些任務偶爾也會因為集群內部原因 (網絡問題、HDFS抖動問題) 發生阻塞,所以按子隊列熔斷會造成一些問題,暫時不上線。

而集群級別的熔斷是很有必要的。集群的熔斷實現是在RM處理客戶端請求的ClientRMService組件里實現,對集群的調度器不會產生壓力。

4.2.5動態拉取配置:

支持hadoop客戶端、hiveserver、spark任務提交時,通過zk動態拉取配置文件,減少因配置文件改動的重啟頻率。

我們的改動是在hadoop-common包里增加讀取遠程zookeeper配置中心的功能類,hadoop-hdfs包里增加功能類的引用,客戶端通過配置選擇模式和對比本地和遠程配置更新時間,來最終拉取合適的配置。

4.3 性能優化

4.3.1

我們列印收集ResourceManager的堆棧信息和閱讀源碼,發現YARN調度算法有兩個可以優化的地方。a.優化減少不必要的重複計算:YARN在計算兩個隊列的優先級時,有多個地方需要計算隊列的資源使用情況。而它每次都是重新遞歸計算所有子隊列的資源,這個操作很耗cpu資源。

我們的修改是第一次直接計算,後面直接使用第一次的結果,減少了大約2/3的時間消耗。b.優化選取排序的隊列和任務集合:YARN默認會選取所有隊列和任務進行選擇排序,我們剔除了不需要資源的隊列和任務的排序,大大地減少了排序的規模。

4.3.2

集群節點的上的IO很大一部分來源於任務啟動之前的jar包下載,默認是同一個任務的jar包才能共享,這樣會導致很多公共jar包的重複下載問題。

在YARN中合理使用分布式緩存並設置公共資源,可以大幅減少不必要jar包的重複下載,減少集群IO。

4.3.3

YARN中涉及到的HDFS操作主要包括:

RM對失敗APP的處理;

appMaster移動完成任務的作業執行記錄信息;

nodemanager上傳聚合日誌。

這些服務都是公共服務,一旦涉及到的HDFS集群卡了一下就會造成整個計算集群任務的堆積。因此我們逐漸在把這些公共服務拆遷到一個獨立HDFS集群減少由於業務異常大IO任務的干擾。

4.4 運維管理方面

4.4.1 制定YARN集群使用規範並落地:

每個隊列按照業務進行劃分,子隊列都有優先級劃分,便於故障恢復。資源的合理使用,大多數隊列都設置了資源的最小值和最大值。即儘量保障優先級隊列能在集群高峰期拿到最小資源,且集群空閒時大多數任務能充分利用集群資源。每個隊列都限制了運行app的最大數量,避免一個隊列內部過多任務爭搶資源發生死鎖的情況和減少過多任務運行對集群的訪問壓力。

4.4.2 完善YARN集群各種監控告警指標:

通過我們的監控告警工具能提前發現和解決很多問題;主要包括:RM主備切換及可用性監控、慢任務、堵塞的隊列、異常狀態APP數量監控、YARN持久化zk狀態目錄監控、YARN事件堆積監控等。

4.4.3 參數配置一些比較重要的特性:

例如:YARN集群開啟了cgroup對任務使用的cpu資源進行隔離、使用LinuxContainerExecutor限制用戶對nodemanager的危險操作以及限制非法用戶;

4.4.4 開發大任務監控平台:

通過我們的大任務監控平台能夠定位集群中的異常大任務,可以協助業務進行任務的優化工作;

4.4.5 災備計算集群建設:

任何一個系統都不是100%的可靠,如某一個YARN集群在異常情況下無法快速診斷問題並恢復的情況下。我們能通過內部平台的部署系統對提交任務的服務配置進行更新,並快速切換計算任務到其他正常的計算集群;

05

YARN的後續規劃

我們目前單個YARN集群調度性能還有一些提升空間,後續會繼續根據集群情況進行參數調優和合入社區相關的一些patch,對我們的YARN集群進行不斷優化;

社區3.0以後的版本對YARN調度器做了比較大的調整,引入了Global Scheduling,性能測試報告顯示單集群的調度性能得到極大的提升,我們後續也會做一些集群版本的升級測試;

社區的YARN Federation早期的版本有很多問題,現在已經逐步完善了。新的架構可以將多個獨立的YARN集群組合成一個統一對外提供服務的計算集群服務,整個集群調度擴展能力和容災能力會提高很多。我們也在調研和驗證該方案在我們計算平台實施的可行性。

文章來源: https://twgreatdaily.com/zh-my/SG70x3EBfwtFQPkdPCgA.html