本文來自OPPO互聯網基礎技術團隊,轉載請註名做者。同時歡迎關注咱們的公衆號:OPPO_tech,與你分享OPPO前沿互聯網技術及活動。
什麼是YARN?html
Apache Hadoop YARN:Yet Another Resource Negotiator,另外一種資源協調者。node
Apache Hadoop YARN 是一種新的Hadoop資源管理器。它是一個通用資源管理系統,可爲上層應用提供統一的資源管理和調度,它的引入爲集羣在利用率、資源統一管理和數據共享等方面帶來了巨大好處。也就是說YARN在Hadoop集羣中充當資源管理和任務調度的框架。web
ResourceManager是YARN中的主節點服務,它負責集羣中全部資源的統一管理和做業調度。算法
簡單來說,ResourceManager主要完成的功能包括:apache
NodeManager是YARN集羣中的每一個具體節點的資源和任務管理者。NodeManager的主要功能包括:segmentfault
用戶提交的每一個應用程序均包含一個ApplicationMaster,主要功能包括:api
Container是YARN中的資源抽象,它封裝了某個節點上的多個維度的資源,如CPU、內存、磁盤、網絡等。當ApplicationMaster向ResourceManager申請資源時,ResourceManager爲ApplicationMaster 返回的資源是用Container表示的。緩存
當用戶向YARN中提交一個應用程序後,YARN將分兩個階段運行該應用程序:安全
第一階段:啓動ApplicationMaster;性能優化
第二階段:由ApplicationMaster建立應用程序;爲它申請資源,並監控它的整個運行過程,直到運行完成。
以下圖所示,以一個mapreduce程序提交到YARN的過程進行分析。
第1步:
client 讀取做業配置信息並建立Job的環境,調用job.waitForCompletion 方法,向集羣提交一個MapReduce 做業 。
第2步:
資源管理器給任務分配一個新的做業ID 。
第3步:
做業的client覈實做業的輸出路徑,計算輸入文件的分片,將做業的資源 (包括:Jar包、配置文件,split信息等) 拷貝到HDFS集羣上的做業提交目錄。
第4步:
經過調用資源管理器的submitApplication()來提交做業。
第5步:
當資源管理器收到submitApplciation()的請求時,就將該請求發給調度器 (scheduler),調度器向NodeManager發送一個啓動container的請求。
第6步:
節點管理器NodeManager啓動container,內部運行着一個主類爲 MRAppMaster的Java應用。其經過創造一些對象來監控做業的進度,獲得各個task的進度和完成報告 。
第7步:
而後其經過分佈式文件系統HDFS來獲取由客戶端提早計算好的輸入split,而後爲每一個輸入split建立一個map任務,根據mapreduce.job.reduces建立 reduce任務對象。
若是做業很小,爲了下降延遲,可採用Uber模式。在該模式下,全部的Map Task和Reduce Task都在ApplicationMaster所在的Container中運行。
第8步:
若是不是小做業,那應用管理器向資源管理器請求container來運行全部的map和reduce任務 。
這些請求是經過心跳來傳輸的,包括每一個map任務的數據位置。好比:存放輸入split的主機名和機架(rack),調度器利用這些信息來調度任務,儘可能將任務分配給存儲數據的節點或相同機架的節點。
第9步:
當一個任務由資源管理器的調度器分配給一個container後,AppMaster經過聯繫NodeManager來啓動container。
第10步:
任務由一個主類爲YarnChild的Java應用執行,在運行任務以前首先本地化任務須要的資源。好比:做業配置、JAR文件以及分佈式緩存的全部依賴文件 。
第11步:
最後,啓動並運行map或reduce任務 。
YARN中的任務將其進度和狀態 (包括counter)返回給應用管理器。
客戶端每秒 (經過mapreduce.client.progressmonitor.pollinterval設置) 嚮應用管理器請求進度更新,展現給用戶。
除了嚮應用管理器請求做業進度外,客戶端每5秒會經過調用 waitForCompletion()來檢查做業是否完成,時間間隔能夠經過 mapreduce.client.completion.pollinterval來設置。
做業完成以後,應用管理器和container會清理工做狀態、做業的執行詳情記錄文件.jhist會被轉移到歷史服務器目錄、container的執行日誌會被nodemanager上傳到HDFS集羣供用戶長期查詢。
如圖所示,ResouceManager主要包括如下幾個部分組成:
ResouceManager分別針對普通用戶、管理員和Web提供了三種對外服務。具體實現分別對應:
ClientRMService:處理普通用戶的提交程序、終止程序、獲取程序狀態等請求
AdminService:處理管理員的刷新隊列、更新ACL權限等請求
RMWebApp:展現集羣資源使用狀況和應用程序執行狀態等信息的web頁面
該模塊主要包括幾個組件:
NMLivelinessMonitor:監控nodemanager的存活狀態,若是nodemanager超時未彙報心跳信息,則將從集羣中剔除該節點
NodesListManager:維護正常節點和異常節點列表,相似於集羣的黑名單和白名單節點
ResourceTrackerService:處理來自NodeManager的請求,主要包括註冊和心跳請求
ResouceManager自帶了很是全面的權限管理機制,主要由如下三個模塊構成:
RMDelegationTokenSecretManager;
DelegationTokenRenewer;
ClientToAMSecretManager。
該模塊主要包括幾個組件:
ApplicationACLSManager :管理應用程序的查看和修改權限
RMAppManager:管理應用程序的啓動和關閉
ContainerAllocationExpirer:監控AM是否在規定的時間內將得到的container在NodeManager上啓動
該模塊主要的組件包括:
AMLivelinessMonitor:監控AM是否存活
ApplicationMasterLauncher:與nodemanager通訊以啓動ApplicationMaster
ApplicationMasterService:處理來自ApplicationMaster的註冊和心跳兩種請求
ResourceManager使用有限狀態機維護有狀態對象的生命週期,共維護了4類狀態機,分別是:
RMApp:一個Application的運行生命週期
RMAppAttempt:一個Application運行實例的生命週期
RMContainer:一個Container的運行生命週期
RMNode:一個NodeManager的生命週期
該模塊主要就是涉及資源調度一個組件,比較常見的實現是:
FairScheduler:公平調度器
CapacityScheduler:容量調度器
YARN採用了基於事件驅動的併發模型,該模型可以大大加強併發性,從而提升系統的總體性能。
在YARN中全部核心服務實際上都是一箇中央異步調度器,包括:
ResourceManager
NodeManager
MRAppMaster等。
它們維護了事先註冊的事件和事件處理器,並根據接收的事件類型驅動服務的運行
上面介紹的ResourceManager的各個服務和組件均是經過中央異步調度器組織在一塊兒的。不一樣的組件之間經過事件交互,從而實現了一個異步並行的高效系統。
爲了保障公司的計算資源獲得充分利用,大數據平臺這邊統一使用YARN進行資源管理與調度。
目前在咱們的YARN集羣上主要支撐了絕大部分的離線應用(MapReduce、Hive SQL、Spark-Submit、Spark SQL)和一部分實時業務(Spark streaming、Flink)。
隨着業務快速發展,爲了知足業務的大量計算任務需求,咱們對YARN集羣作了一些探索和實踐的工做。
目前集羣的機器規模由開始的幾百臺發展到如今的5000+臺、單集羣最大節點數2500+、單集羣管理的Container數10w+、單集羣日調度Container數近1億。
對YARN開展的一些穩定和優化工做,主要包括四個方面:
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-346九、YARN-612五、YARN-5006。
mr任務申請內存和cpu超過yarn調度最大資源問題,特別是大任務的話會寫大量錯誤診斷信息到zk上,影響整個集羣其餘任務的正常提交。
咱們在任務提交的時候可以快速檢測並失敗這類任務,並減小打印錯誤診斷信息。
修復跨集羣的一些問題:spark任務跨集羣問題&mr任務跨集羣問題:
由於咱們的集羣是由不少個HDFS集羣組建成的一個大YARN集羣,而咱們每一個小集羣的defaultFS和客戶端的defaultFS都是不一樣的。
這樣默認會形成做業的提交目錄沒法被appmaster徹底清除,長期運行後會致使單級目錄文件數超過namenode的最大限制而致使沒法提交新的任務。
YARN隊列權限是解決提交任務的用戶或所屬組是否有隊列的提交權限,而用戶和組映射關係的默認的實現類是ShellBasedUnixGroupsMapping。
它是獲取ResourceManager本地機器的操做系統的用戶和組關係。咱們開發了權限插件,新增了自定義的用戶和組映射關係實現類HeyTapGroupsMapping,對接咱們內部的權限系統的用戶和組關係;
默認的狀況下,YARN的8088端口未作相關認證,攻擊者可經過rest api 提交任務,下載與集羣網絡相通的腳本執行異常攻擊,不少公司都遭受過此攻擊;咱們的改動是在YARN的提交任務rest 接口處添加開關支持,通常咱們的集羣任務是經過授信的客戶端提交,因此咱們默認關閉REST API任務的提交。
相關安全漏洞連接:Hadoop Yarn REST API未受權漏洞利用挖礦分析
https://segmentfault.com/a/11...
咱們的集羣以前會有不少的大的mr任務,這部分任務會浪費集羣比較多的資源,而且容易觸發不少集羣bug問題。
針對mr任務支持按隊列配置提交隊列的任務最大task數量,超過直接拒絕任務提交。這部分的實現是在MR任務的AppMaster初始化做業的JobImpl類中對做業的信息進行檢查。
集羣不免會有異常的時候,當異常的時候每每會出現任務大量pending和Running的狀況,系統內部大量消息處理堆積。
若是咱們不作熔斷處理,ResourceManager會因爲事件長期堆積而超過JVM最大內存而oom崩潰。
咱們的改動是當集羣總的running任務數+accept任務數超過歷史安全閾值則進行拒絕提交;按子隊列熔斷數量限制,考慮實際實施過程當中,子隊列一些任務偶爾也會由於集羣內部緣由(網絡問題、HDFS抖動問題)發生阻塞,因此按子隊列熔斷會形成一些問題,暫時不上線。
而集羣級別的熔斷是頗有必要的。集羣的熔斷實現是在RM處理客戶端請求的ClientRMService組件裏實現,對集羣的調度器不會產生壓力。
支持hadoop客戶端、hiveserver、spark任務提交時,經過zk動態拉取配置文件,減小因配置文件改動的重啓頻率。
咱們的改動是在hadoop-common包裏增長讀取遠程zookeeper配置中心的功能類,hadoop-hdfs包裏增長功能類的引用,客戶端經過配置選擇模式和對比本地和遠程配置更新時間,來最終拉取合適的配置。
咱們打印收集ResourceManager的堆棧信息和閱讀源碼,發現YARN調度算法有兩個能夠優化的地方。
YARN在計算兩個隊列的優先級時,有多個地方須要計算隊列的資源使用狀況。而它每次都是從新遞歸計算全部子隊列的資源,這個操做很耗cpu資源。
咱們的修改是第一次直接計算,後面直接使用第一次的結果,減小了大約2/3的時間消耗。
YARN默認會選取全部隊列和任務進行選擇排序,咱們剔除了不須要資源的隊列和任務的排序,大大地減小了排序的規模。
集羣節點的上的IO很大一部分來源於任務啓動以前的jar包下載,默認是同一個任務的jar包才能共享,這樣會致使不少公共jar包的重複下載問題。
在YARN中合理使用分佈式緩存並設置公共資源,能夠大幅減小沒必要要jar包的重複下載,減小集羣IO。
YARN中涉及到的HDFS操做主要包括:
這些服務都是公共服務,一旦涉及到的HDFS集羣卡了一下就會形成整個計算集羣任務的堆積。所以咱們逐漸在把這些公共服務拆遷到一個獨立HDFS集羣減小因爲業務異常大IO任務的干擾。
每一個隊列按照業務進行劃分,子隊列都有優先級劃分,便於故障恢復。資源的合理使用,大多數隊列都設置了資源的最小值和最大值。即儘可能保障優先級隊列能在集羣高峯期拿到最小資源,且集羣空閒時大多數任務能充分利用集羣資源。每一個隊列都限制了運行app的最大數量,避免一個隊列內部過多任務爭搶資源發生死鎖的狀況和減小過多任務運行對集羣的訪問壓力。
經過咱們的監控告警工具能提早發現和解決不少問題;主要包括:RM主備切換及可用性監控、慢任務、堵塞的隊列、異常狀態APP數量監控、YARN持久化zk狀態目錄監控、YARN事件堆積監控等。
例如:YARN集羣開啓了cgroup對任務使用的cpu資源進行隔離、使用LinuxContainerExecutor限制用戶對nodemanager的危險操做以及限制非法用戶;
經過咱們的大任務監控平臺可以定位集羣中的異常大任務,能夠協助業務進行任務的優化工做;
任何一個系統都不是100%的可靠,如某一個YARN集羣在異常狀況下沒法快速診斷問題並恢復的狀況下。咱們能經過內部平臺的部署系統對提交任務的服務配置進行更新,並快速切換計算任務到其餘正常的計算集羣;