Spark on Yarn|Spark,從入門到精通

歡迎閱讀美圖數據技術團隊的「Spark,從入門到精通」系列文章,本系列文章將由淺入深為大家介紹 Spark,從框架入門到底層架構的實現,相信總有一種姿勢適合你,歡迎大家持續關注:)

往期直通車:

為什麼需要 Yarn?

Yarn 的全稱是 Yet Anther Resource Negotiator(另一種資源協商者)。它作為 Hadoop 的一個組件,官方對它的定義是一個工作調度和集群資源管理的框架

Yarn 最早出現於 Hadoop 0.23 分支中,0.23 分支是一個實驗性分支,之後經過了幾次迭代,最後發佈於 2014 年 6 月的 0.23.11 版本(該分支的最後一個版本)。在 0.23.0 發佈後不久的 2011 年 12 月,Hadoop 的 0.20 分支發展成了 Hadoop1.0,一直到 1.0 的最後一個版本 1.2.1-stable 都沒有出現 Yarn 的身影,而在 Hadoop2.0 的第一個版本 2.0.0-alpha,Yarn 已經作為一個正式組件加入。在 2.0.2-alpha 版本,它已經支持了 2k 臺機器的集群,接著在 2.0.3-alpha 版本中已經可以支持 30k 臺機器的集群。在 2.0.3-alpha 版本中同時還支持了多種資源,如 cpu&memory 的調度和 ResourceManager restart。

Spark on Yarn|Spark,從入門到精通

圖 1

如圖 1 所示, Hadoop1.0 的運作流程如下:

  1. 客戶端提交任務給集群;
  2. JobTracker 接收 Job 請求;
  3. JobTracker 根據 Job 的輸入參數向 NameNode 請求包含這些文件數據塊的 DataNode 節點列表;
  4. JobTracker 確定 Job 的執行計劃:確認 Map、Reduce 的 Task 數量,並分配 Task 到離數據塊最近的節點上執行。

最初,Hadoop1.0 能夠很好地支撐大數據計算,但是隨著計算規模的擴大和計算模型的多樣化,它逐漸力不從心。眾所周知當集群性能不足的時候可以簡單粗暴地加機器,但 JobTracker 同時部署多個時只有一個是處於 active 狀態,因此受限於這個 active JobTracker 的負載上限,整個集群能夠容納的機器也有限,有數據顯示整個集群的管理上限約為 4k 臺機器。同時應用程序相關和資源管理相關的邏輯全部放在 JobTracker中,當集群規模擴大的時候,會存在一個瓶頸。除此之外,Map-Reduce 計算模型與 JobTracker 的耦合過高,其他計算模型難以在 Hadoop1.0 上運行。

Yarn 是 Hadoop 基於這些問題的一個解決方案,接下來通過了解 Yarn 的組件、架構以及運作機制來分析 Yarn 是如何解決這些問題的。

Yarn 是什麼?

Yarn 的組件&基本架構

如圖 2 所示 Yarn 採用 Master/Slave 結構,整體採用雙層調度架構。在第一層的調度是 ResourceManager 和 NodeManager:ResourceManager 是 Master 節點,相當於 JobTracker,包含 Scheduler 和App Manager 兩個組件,分管資源調度和應用管理;NodeManager 是 Slave 節點,可以部署在獨立的機器上,用於管理機器上的資源。NodeManager 會向 ResourceManager 報告它的資源數量、使用情況,並接受 ResourceManager 的資源調度。

*ResourceManager 同 JobTracker 一樣可以多機部署,並且只有一臺處於 active 狀態。但是在 ResourceManager 中將調度管理和應用管理作了拆分,兩個組件的功能更專一。

Spark on Yarn|Spark,從入門到精通

圖 2

第二層的調度指的是 NodeManager 和 Container。NodeManager 會將 Cpu&內存等資源抽象成一個個的 Container,並管理它們的生命週期。

通過採用雙層調度結構將 Scheduler 管理的資源由細粒度的 Cpu&內存變成了粗粒度的 Container,降低了負載。在 App Manager 組件中也只需要管理 App Master,不需要管理任務調度執行的完整信息,同樣降低了負載。通過降低 ResourceManager 的負載,變相地提高了集群的擴展性。

Yarn 運作流程

Spark on Yarn|Spark,從入門到精通

圖 3

如圖 3 所示 Yarn 的運作流程如下:

  1. 客戶端向 ResourceManager 的 App Manager 提交應用並請求一個 AppMaster 實例;
  2. ResourceManager 找到可以運行一個 Container 的 NodeManager,並在這個 Container 中啟動 AppMaster 實例;
  3. App Master 向 ResourceManager 註冊,註冊之後,客戶端就可以查詢 ResourceManager 獲得自己 App Master 的詳情以及直接和 App Master 交互;
  4. 接著 App Master 向 Resource Manager 請求資源,即 Container;
  5. 獲得 Container 後,App Master 啟動 Container,並執行 Task;
  6. Container 執行過程中會把運行進度和狀態等信息發送給 AppMaster;
  7. 客戶端主動和 App Master 交流應用的運行狀態、進度更新等信息;
  8. 所有工作完成 App Master 向 RM 取消註冊然後關閉,同時所有的 Container 也歸還給系統。

通過這個 Job 的處理過程可以看到 App Master 是作為 Job 的驅動角色,它驅動了 Job 任務的調度執行。在這個運作流程中,App Manager 只需要管理 App Master 的生命週期以及保存它的內部狀態,而 App Master 這個角色的抽象使得每種類型的應用都可以定製自己的 App Master,這樣其他的計算模型就可以相對容易地運行在 Yarn 集群上。

Yarn HA(容災備援)

接下來介紹的是 Yarn 集群高可用中關於容錯備援的設計。根據圖 3 所示的 Yarn 架構圖,假如 Container 故障 Resource Manager 可以分配其他的 Container 繼續執行,當運行 App Master 的 Container 故障後也將分配新的 Container,App Master 可以從 App Manager 獲取信息恢復。當 NodeManager 故障的時候系統可以先把這個節點移除,在其他 NodeManager 重啟再繼續任務。

Spark on Yarn|Spark,從入門到精通

圖 4

那麼當 ResourceManager 故障的時候呢?如上文所說的在 Yarn 集群中,ResourceManager 可以啟動多臺,只有其中一臺是 active 狀態的,其他都處於待命狀態。這臺 active 狀態的 ResourceManager 執行的時候會向 ZooKeeper 集群寫入它的狀態,當它故障的時候這些 RM 首先選舉出另外一臺 leader 變為 active 狀態,然後從 ZooKeeper 集群加載 ResourceManager 的狀態。在轉移的過程中它不接收新的 Job,轉移完成後才接收新 Job。

Spark on Yarn

首先介紹 Spark 的資源管理架構。Spark 集群考慮到了未來對接一些更強大的資源管理系統(如 Yarn、Mesos 等)沒有在資源管理的設計上對外封閉,所以Spark 架構設計時將資源管理抽象出了一層,通過這種抽象能夠構建一種插件式的資源管理模塊。

Spark on Yarn|Spark,從入門到精通

圖 5

如圖 5 所示是 Spark 的資源管理架構圖。Master 是 Spark 的 主控節點,在實際的生產環境中會有多個 Master,只有一個 Master 處於 active 狀態。Worker 是 Spark 的工作節點,向 Master 彙報自身的資源、Executeor 執行狀態的改變,並接受 Master 的命令啟動 Executor 或 Driver。Driver 是應用程序的驅動程序,每個應用包括許多小任務,Driver 負責推動這些小任務的有序執行。Executor 是 Spark 的工作進程,由 Worker 監管,負責具體任務的執行。

以上就是 Spark 在資源管理上的抽象出來的架構,這個架構跟 Yarn 的架構十分相似,因此 Spark 很容易地構建於 Yarn 之上。在 Spark 和 Yarn 兩邊的角色對比中:Master 和 ResourceManager 對應,Worker 和 NodeManager 對應,Driver 和 App Master 對應,Executor 和 Container 對應。

根據 Spark 部署模式的不同資源管理架構也會有不同的形態。Spark 大致包括四種部署模式:

  • Local 模式:部署在同一個進程上,只有 Driver 角色。接受任務後創建 Driver 負責應用的調度執行,不涉及 Master 和 Worker;
  • Local-Cluster 模式:部署在同一個進程上,存在 Master 和 Worker 角色,它們作為獨立線程存在於這個進程內;
  • Standalone 模式:Spark 真正的集群模式,在這個模式下 Master 和 Worker 是獨立的進程;
  • 第三方部署模式:構建於 Yarn 或 Mesos 之上,由它們提供資源管理。

接著看看 Spark on Yarn 對 Job 的處理過程。客戶端提交一個任務給 Yarn ResourceManager 後,App Manager 接受任務並找到一個 Container 創建App Master,此時 App Master 上運行的是 Spark Driver。之後 App Master 申請 Container 並啟動,Spark Driver 在 Container 上啟動 Spark Executor,並調度 Spark Task 在 Spark Executor 上運行,等到所有的任務執行完畢後,向 App Manager 取消註冊並釋放資源。

Spark on Yarn|Spark,從入門到精通

圖 6

可以看出這個執行流程和 Yarn 對一個任務的處理過程幾乎一致,不同的是在 Spark on Yarn 的 Job 處理過程中 App Master、Container 是交由 Spark 相對應的角色去處理的。

Spark on Yarn|Spark,從入門到精通

圖 7

Spark on Yarn 還有另外一種運行模式:Spark on Yarn-Client。不同於上述的 Spark on Yarn-Cluster,Spark on Yarn-Client 的客戶端在提交完任務之後不會將 Spark Driver 託管給 Yarn,而是在客戶端運行。App Master 申請完 Container 之後同樣也是由 Spark Driver 去啟動 Spark Executor,執行任務。

那為什麼使用 Yarn 作為 Spark 的資源管理呢?我們來對比 Spark 集群模式 Standalone 和 Spark on Yarn 在資源調度能力上的區別:Spark 的 Standalone 模式只支持 FIFO 調度器,單用戶串行,默認所有節點的所有資源對應用都是可用的;而 Yarn 不止支持 FIFO 的資源調度,還提供了彈性和公平的資源分配方式。

Yarn 是通過將資源分配給 queue 來進行資源分配的,每個 queue 可以設置它的資源分配方式,接著展開介紹 Yarn 的三種資源分配方式。

FIFO Scheduler

如果沒有配置策略的話,所有的任務都提交到一個 default 隊列,根據它們的提交順序執行。富裕資源就執行任務,若資源不富裕就等待前面的任務執行完畢後釋放資源,這就是 FIFO Scheduler 先入先出的分配方式。

Spark on Yarn|Spark,從入門到精通

圖 8

如圖 8 所示,在 Job1 提交時佔用了所有的資源,不久後 Job2提交了,但是此時系統中已經沒有資源可以分配給它了。加入 Job1 是一個大任務,那麼 Job2 就只能等待一段很長的時間才能獲得執行的資源。所以先入先出的分配方式存在一個問題就是大任務會佔用很多資源,造成後面的小任務等待時間太長而餓死,因此一般不使用這個默認配置。

Capacity Scheduler

Capacity Scheduler 是一種多租戶、彈性的分配方式。每個租戶一個隊列,每個隊列可以配置能使用的資源上限與下限(譬如 50%,達到這個上限後即使其他的資源空置著,也不可使用),通過配置可以令隊列至少有資源下限配置的資源可使用。

Spark on Yarn|Spark,從入門到精通

圖 9

圖 9 中隊列 A 和隊列 B 分配了相互獨立的資源。Job1 提交給隊列 A 執行,它只能使用隊列 A 的資源。接著 Job2 提交給了隊列B 就不必等待 Job1 釋放資源了。這樣就可以將大任務和小任務分配在兩個隊列中,這兩個隊列的資源相互獨立,就不會造成小任務餓死的情況了。

Fair Scheduler

Fair Scheduler 是一種公平的分配方式,所謂的公平就是集群會儘可能地按配置的比例分配資源給隊列。

Spark on Yarn|Spark,從入門到精通

圖 10

圖 10 中 Job1 提交給隊列 A,它佔用了集群的所有資源。接著 Job2 提交給了隊列 B,這時 Job1 就需要釋放它的一半的資源給隊列 A 中的 Job2 使用。接著 Job3 也提交給了隊列 B,這個時候 Job2 如果還未執行完畢的話也必須釋放一半的資源給 Job3。這就是公平的分配方式,在隊列範圍內所有任務享用到的資源都是均分的。

the Future of Spark

Mesos 的資源調度和 Yarn 類似,但是它提供了粗粒度和細粒度的兩種模式。所謂的粗粒度和細粒度的差別在於:Executor 申請的資源是在執行前申請,還是在執行過程中按需申請。集群資源緊張時可能有一個 Executor 申請的資源在當時處於閒置狀態,如果處於粗粒度模式下,這些資源在當時就浪費了。但是在細粒度模式下,Executor 執行時所需的資源是按照它的需求分配的,這樣就不存在資源閒置的情況了。

因為 Mesos 的 Executor 是可以動態調整,而 Yarn 使用的 Container 是不可以動態調整的,所以目前 Yarn 是不支持細粒度的調度模式的,但 Yarn 已經有計劃支持細粒度的資源管理方式。

除此之外在 Hadoop3.1.0 中 Yarn 提供了對 gpu 資源的支持,目前只支持 Nvidia gpu。期待 Spark 在其他方面的更多探索,下一篇我們將具體介紹 RDD,歡迎持續關注。


分享到:


相關文章: