隨著分布式計算集群規(guī)模的不斷擴(kuò)張,任務(wù)調(diào)度系統(tǒng)的穩(wěn)定性成為了整個集群穩(wěn)定的關(guān)鍵因素。隨著容器技術(shù)的快速興起,基于容器的計算平臺被大量應(yīng)用,任務(wù)調(diào)度的規(guī)模及頻率快速上升,這對任務(wù)調(diào)度系統(tǒng)提出了更為嚴(yán)苛的挑戰(zhàn)。常見的調(diào)度系統(tǒng)往往兼顧了準(zhǔn)確度卻犧牲了性能,容器調(diào)度的復(fù)雜性使得在準(zhǔn)確和效率之間找到平衡點很難,尤其是在交互式調(diào)度的場景下,可取的解決方案更是捉襟見肘。本篇文章就以此為背景,介紹大規(guī)模調(diào)度場景下分布式任務(wù)調(diào)度的難點、解決策略及現(xiàn)有的一些方案。
任務(wù)調(diào)度框架的設(shè)計目標(biāo)
計算任務(wù)通常分為兩個大的類別,即以守護(hù)進(jìn)程形式運(yùn)行的長任務(wù)和以批處理形式運(yùn)行的短任務(wù),前者資源的使用率變化幅度小,而后者資源使用率變化大。本篇我們討論的主要是針對計算密集型的場景,即以批處理形式運(yùn)行的數(shù)據(jù)處理任務(wù)。
調(diào)度系統(tǒng)的核心目標(biāo): 快速準(zhǔn)確地為任務(wù)匹配合適的計算資源。但快速(Low Placement latency)和準(zhǔn)確(High Quality Placement
)這兩個目標(biāo)會產(chǎn)生矛盾,即必須在二者間權(quán)衡。尤其是在交互式調(diào)度場景下,只追求準(zhǔn)確度而忽視效率會使得調(diào)度失去意義。
調(diào)度系統(tǒng)的本質(zhì)是為計算任務(wù)匹配合適的資源,使其能夠穩(wěn)定高效地運(yùn)行,而影響應(yīng)用運(yùn)行的因素非常多,比如CPU、內(nèi)存、網(wǎng)絡(luò)、端口等等一系列因素都會影響應(yīng)用運(yùn)行的表現(xiàn)。于此同時,整個計算集群的資源使用情況是動態(tài)變化的,大量的應(yīng)用被創(chuàng)建、銷毀和遷移,調(diào)度決策的過程如果不夠快,那么實際運(yùn)行時面對的資源情況可能與決策時千差萬別。
計算任務(wù)的調(diào)度不僅僅要考慮資源本身的狀況,而且還要結(jié)合任務(wù)本身的優(yōu)先級來考慮搶占式調(diào)度的情景。比如系統(tǒng)出現(xiàn)異常,臨時增加診斷性任務(wù),就必須以高于其他任務(wù)的優(yōu)先級來運(yùn)行。有資源搶占就涉及到任務(wù)驅(qū)逐、重調(diào)度等情況,這里面會涉及驅(qū)逐相關(guān)的算法策略、調(diào)度流程的復(fù)用等。
目前的主流任務(wù)調(diào)度框架
從目前常用的任務(wù)調(diào)度框架來看,Apache Mesos是面向數(shù)據(jù)中心資源管理的典型代表。Hadoop YARN調(diào)度器是面向計算任務(wù)的,與Mesos相似之處在于也是兩層調(diào)度機(jī)制,不同在于考慮了資源搶占機(jī)制,能夠處理任務(wù)的優(yōu)先級對調(diào)度結(jié)果的影響。這些年發(fā)展迅速的Kubernetes也包含調(diào)度器,其本質(zhì)上還是面向應(yīng)用運(yùn)行層面,默認(rèn)調(diào)度器的策略比較豐富,擴(kuò)展性也比較好,但在面對大規(guī)模的調(diào)度時,吞吐性能表現(xiàn)不是那么完美。
Apache Mesos
Apache Mesos將CPU、內(nèi)存、存儲和其他計算資源從機(jī)器(物理或虛擬)中抽象出來,使容錯和彈性分布式系統(tǒng)能夠輕松構(gòu)建并有效運(yùn)行。Mesos采用的Resource Offer
使得任務(wù)框架能夠自行決定是否接受Mesos Master的Offer
,在實際使用過程中,資源框架中的調(diào)度機(jī)制需要用戶自行實現(xiàn),還是略微有些工作量的。
上述調(diào)度過程分為四個步驟:
- Agent1 向Master匯報節(jié)點當(dāng)前的資源情況,Master根據(jù)某種策略決定將Resource Offer給Framework1。
- Master將Resource Offer給Framework1,即將Agent1的所有資源分配給Framework1使用。
- Agent1 回復(fù)Master的Resource Offer,告訴Master將有兩個任務(wù)運(yùn)行在Agent1上,及各任務(wù)需要的資源情況。
- 最后,Master將任務(wù)發(fā)給Agent1,Agent1會為Framework的executor分配合適的資源,F(xiàn)ramework的executor隨即會啟動兩個任務(wù)。剩下的資源Master的Allocation Module會發(fā)Resource Offer給Framework2。
這里著重需要關(guān)注兩個問題:
- Mesos Master發(fā)送Resource Offer的時候,并不知道Framework的資源需求,如何知道該把Resource Offer發(fā)給哪個Framework?
- 在任務(wù)量比較大的時候,F(xiàn)ramework 與Master通信的性能如何保證?
對于第一個問題,Mesos提供了”reject offer”的機(jī)制,允許Framework暫時拒絕不滿足其資源需求的Resource Offer,具體拒絕的策略由各個框架自行決定。
因此在Master與Framework通信的問題上,Mesos提供了”filter”和”rescinds”機(jī)制,前者可以只接收剩余資源量大于L的Resource Offer,從而屏蔽掉部分流量,后者則允許某個Framework在一定的時間內(nèi)沒有為分配的資源返回對應(yīng)的任務(wù),則Mesos會回收其資源量,并將這些資源分配給其他framework。
Mesos調(diào)度采用Dominant Resource Fairness(DRF)策略,是一種支持多資源的max-min fair資源分配機(jī)制。在調(diào)度時先找出用戶(這里指具體的Framework)的支配性資源,DRF將均衡所有用戶的支配性資源,確保每個用戶獲取了最大比例的支配性資源。
Hadoop YARN調(diào)度
Hadoop 的YARN模塊也具有為計算任務(wù)分配資源的能力,相應(yīng)地也具有調(diào)度能力。YARN將應(yīng)用的資源請求抽象為一個容器(Container),具體的Application Master會接收容器,然后在容器中啟動這個任務(wù)。對于Hadoop來說,任務(wù)注意分為兩類: Map 和 Reduce。
注意: 這里的容器不是云計算中所說的具體容器技術(shù),而是Hadoop YARN中一個抽象的資源的集合的概念。
在MapReduce應(yīng)用程序中,有多個map任務(wù),每個任務(wù)都在集群中某個工作主機(jī)上的容器中運(yùn)行。同樣,還有多個reduce任務(wù),每個還在運(yùn)行主機(jī)上的容器中運(yùn)行。
同時在YARN端,ResourceManager,NodeManager和ApplicationMaster一起工作以管理集群的資源,并確保任務(wù)以及相應(yīng)的應(yīng)用程序完整地完成。
調(diào)度本身并不是一個新的概念,個人計算機(jī)可以有多個CPU核,每個核運(yùn)行一個進(jìn)程,但同時運(yùn)行多達(dá)幾百個進(jìn)程。調(diào)度程序是操作系統(tǒng)的一部分,它將進(jìn)程分配給CPU內(nèi)核以在短時間內(nèi)運(yùn)行。
對于大規(guī)模的計算集群也一樣,應(yīng)用程序由群集上的多個任務(wù)(通常在不同的主機(jī)上)組成。集群調(diào)度程序基本上必須解決:
- 多租戶: 在群集上,許多用戶代表多個組織啟動了許多不同的應(yīng)用程序。 集群調(diào)度程序允許不同的工作負(fù)載同時運(yùn)行。即調(diào)度時必須考慮應(yīng)用發(fā)起者的身份,根據(jù)身份將任務(wù)分發(fā)到與用戶身份對應(yīng)的資源上。
- 可伸縮性: 集群調(diào)度程序需要擴(kuò)展到運(yùn)行許多應(yīng)用程序的大型集群。這意味著增加群集的大小應(yīng)該可以提高整體性能,而不會對系統(tǒng)延遲產(chǎn)生負(fù)面影響。調(diào)度程序需要確保在計算集群規(guī)模非常大的時候,依然可以高效地提供調(diào)度服務(wù)。
YARN使用隊列(Queue)在多個租戶之間共享資源。當(dāng)應(yīng)用程序提交給YARN時,調(diào)度程序會將它們分配給隊列。根隊列是所有隊列的父級。所有其他隊列都是根隊列或另一個隊列(也稱為分層隊列)的子節(jié)點。隊列通常與用戶,部門或優(yōu)先級相對應(yīng)。Application Master跟蹤每個任務(wù)的資源需求并協(xié)調(diào)容器請求。這種方式允許更好的擴(kuò)展,因為RM/調(diào)度程序不需要跟蹤在集群上運(yùn)行的所有容器。
在YARN支持的調(diào)度程序中,公平調(diào)度(Fair Scheduler)是一個受歡迎的方式。在最簡單的形式中,它在集群上運(yùn)行的所有作業(yè)中公平地共享資源。
在實際的復(fù)雜調(diào)度場景中,還會有水平隊列的形式出現(xiàn),其實是上述隊列的一種嵌套形式,即在隊列的中還包含子隊列,不同的子隊列在父隊列的權(quán)重的基礎(chǔ)上有各自的權(quán)重設(shè)置,這里不再贅述。
Firmament 調(diào)度
Firmament 通過對調(diào)度算法的優(yōu)化使得大規(guī)模計算集群的任務(wù)調(diào)度可以很好地在性能和準(zhǔn)確之間找到平衡。Firmament 的設(shè)計出發(fā)點主要有如下兩個:
- 良好的決策很重要: 對于關(guān)鍵服務(wù)應(yīng)用程序,單個糟糕的調(diào)度決策可能會產(chǎn)生重大影響。
- 靈活的策略是關(guān)鍵: 不同的用戶和應(yīng)用程序具有不同的調(diào)度需求,因此根據(jù)工作負(fù)載定制調(diào)度策略非常重要。
既要保證單個決策的準(zhǔn)確性,又要保證調(diào)度策略的靈活性,這對于調(diào)度程序的性能提出了很高的要求,而Firmament的基于流圖的決策模式能夠有效解決這個問題。這個調(diào)度程序的核心來自于Google的開發(fā)者,開發(fā)語言為C++,目前作為一個開源項目,大家都可以共享自己的代碼。Firmament主要有以下三個特性:
- 通過對圖進(jìn)行最小成本優(yōu)化,F(xiàn)irmament根據(jù)調(diào)度策略為每個任務(wù)或容器找到最佳位置。
- 通過自定義底層圖形并通過回調(diào)接口設(shè)置其邊緣成本,用戶可以自定義Firmament以應(yīng)用自己的策略。
- Firmament的增量最小成本,最大流量解算器甚至可以在Google規(guī)模(12k機(jī)器)上做出快速的亞秒級調(diào)度決策。
- 最重要一點: Firmament是全開源的。
Firmament既可以獨(dú)立工作,也可以在集群管理器中工作,如Kubernetes這樣的容器管理集群,開源項目Poseidon正是出于這樣的目的,將Firmament引入容器管理集群。
目前Firmament通過與容器管理集群結(jié)合,大幅度提升容器應(yīng)用的調(diào)度管理能力,解決像Kubernetes原生調(diào)度器在10K節(jié)點時,性能急劇下降且對批處理作業(yè)任務(wù)支持不夠完善的情況。Kubernetes原生調(diào)度器采用的基于隊列的模型,需要依賴于隊列的性能,而在任務(wù)調(diào)度失敗后,又再次回到隊列等待繼續(xù)調(diào)度,在對于計算密集型的任務(wù)調(diào)度時,對優(yōu)先級、資源狀態(tài)的共享支持都有待提升。
Firmament 采用的流圖的機(jī)制,綜合考慮了很多種影響調(diào)度結(jié)果的因素,比如Rack,AZ,Region等,甚至包括SSD硬件屬性,綜合這些因素考慮最小的成本,最大的流量來決定最終的調(diào)度結(jié)果。
Poseidon 主流應(yīng)用場景
Posedion 會充當(dāng) Firmament 與 Kubernetes 之間的橋梁,即通過Kubernetes API 獲取對象的事件(Event),然后結(jié)合資源使用狀況,調(diào)用 Firmament 獲取調(diào)度的結(jié)果,最終完成 Pod 調(diào)度的過程。
Firmament ???以理解為獨(dú)立的核心算法模塊,功能與原來的默認(rèn)scheduler 相同,都是根據(jù)目前資源情況,給出最佳的調(diào)度結(jié)果。Firmament 本身由一系列的復(fù)雜算法組成,但對于 Posedion 來說,這些細(xì)節(jié)可以不必關(guān)系,只需要了解輸入和輸出的標(biāo)準(zhǔn)數(shù)據(jù)結(jié)構(gòu)就好。
在具體使用的時候,F(xiàn)irmament、Poseidon 及 heapster 等模塊都是以 Deployment 形式部署在 Kubernetes 集群中的。在部署 Pod 的時候,我們知道 Kubernetes 支持多調(diào)度器機(jī)制,可以在 Pod 的定義中指定使用哪個調(diào)度器,具體示例如下:
apiVersion: batch/v1 kind: Job metadata: name: cpuspin5 spec: completions: 1 parallelism: 1 template: metadata: name: cpuspin5 labels: schedulerName: poseidon spec: schedulerName: poseidon containers: - name: cpuspin image: firmament/libhdfs3 resources: requests: memory: "10Mi" cpu: "10m" limits: memory: "12Mi" cpu: "20m" command: ["/bin/sh", "-c", "/cpu_spin 60"] restartPolicy: Never
我們在這里選擇 posedion 作為其調(diào)度器,那么就可以通過 Firmament 算法來更高效、精細(xì)地決策 Pod 在哪個節(jié)點運(yùn)行更合適,值得一提的是,其他的 Pod 如果不適合這些調(diào)度機(jī)制,完全可以選擇默認(rèn)調(diào)度器、甚至自定義的調(diào)度器,從而保證了平臺的靈活性。
任務(wù)調(diào)度框架的未來趨勢
任務(wù)調(diào)度框架其實已經(jīng)有很多,集中式和分布式的都有,一時間難以決定孰優(yōu)孰劣,畢竟調(diào)度跟具體的業(yè)務(wù)場景息息相關(guān)。在未來,調(diào)度會更加精細(xì)化、更靈活,根據(jù)用戶角色、業(yè)務(wù)類型、資源需求等等一系列復(fù)雜的因素,結(jié)合歷史調(diào)度情況綜合給出最終的結(jié)論。有些類似梯度遞減形式的機(jī)器學(xué)習(xí)模型可以開始應(yīng)用在調(diào)度上,已經(jīng)有一些公司在做相關(guān)的探索,相信在未來大規(guī)模分布式調(diào)度會變得越來越重要。