集群管理系統 Mesos 的設計原理
『看看論文』是一系列分析計算機和軟件工程領域論文的文章,我們在這個系列的每一篇文章中都會閱讀一篇來自 OSDI、SOSP 等頂會中的論文,這里不會事無巨細地介紹所有的細節,而是會篩選論文中的關鍵內容,如果你對相關的論文非常感興趣,可以直接點擊鏈接閱讀原文。
本文要介紹的是 2011 年 NSDI 期刊中的論文 —— Mesos: A Platform for Fine-Grained Resource Sharing in the Data Center[^1],該論文實現的 Mesos 能夠在集群中管理不同的計算框架,例如 Hadoop 和 MPI 等。雖然 Mesos 集群管理系統是 10 多年前發布的技術,今天已經逐漸被更主流、更通用的容器編排系統 Kubernetes 取代,但是它確實可以解決集群管理上的部分問題。
Apache Mesos 和 Kubernetes 都是優秀的開源框架,也都支持大規模的集群管理,但是它們兩個管理的集群規模仍然差一個數量級,單個 Mesos 集群可以管理 50,000 節點,而 Kubernetes 集群卻只能管理 5,000 節點,需要做很多優化和限制,才能達到相同的數量級。
圖 1 - Kubernetes 和 Mesos 集群
雖然 Kubernetes 是今天集群管理的主流技術,但是 Mesos 在剛剛出現時也是很先進的集群管理系統,它想要取代的是當時更為常見的靜態分片集群。靜態分片集群雖然可以同時運行屬于不同框架的工作負載(例如:Hadoop、MPI),但是因為框架的異構性,使用靜態分片技術會將集群中的機器預先分配給不同的框架,再由這些框架分配和管理資源。
圖 2 - 靜態分片
Mesos 在最初設計時并不會直接管理和調度開發者提交的工作負載,而是提供一組接口暴露集群的資源,并通過這組輕量級的接口同時對接 Hadoop、MPI 等框架。
架構
如下圖所示的 Mesos 集群同時運行了 Hadoop 和 Mesos 兩個框架,如果忽略圖中與 Hadoop、MPI 框架的相關模塊,我們會發現架構會變得非常簡單,它僅由 Zookeeper 集群、Mesos 主節點和工作節點組成。
圖 3 - Mesos 架構圖
- Zookeeper 集群提供了高可用的數據存儲和選舉等功能;
- Mesos 主節點收集工作節點上報的數據并向框架的調度器提供資源;
- Mesos 工作節點上報數據并通過框架的執行者在本地啟動任務;
每個 Mesos 集群中運行的框架都由調度器和執行者兩部分組成,調度器會處理主節點提供的資源,與 Kubernetes 的調度器有著相同的作用,當調度器接受主節點提供的資源后,它會返回待運行任務的相關信息;而執行者會在工作節點上運行框架創建的任務。
Mesos 為了保證更好的可擴展性,它定義了一套能夠滿足資源共享的最小接口,將任務調度和執行的控制權都通過如下所示的接口交給框架,其本身僅保留較粗粒度的調度和資源管理功能。
圖 4 - Mesos 接口
因為 Mesos 中的任務調度是分布式的過程,所以為了保證該過程的效率和可靠性,它引入了下面的這三種機制:
節點過濾器:框架使用過濾器剔除集群中不滿足自身調度條件的節點;
資源主動分配:為了提高框架的調度速度,會將預先提供給框架的資源計入框架的總分配資源,直到框架完成調度,這能激勵框架實現更快的調度器;
資源撤回:如果框架在一段時間內沒有處理主節點提供的資源,Mesos 會撤回資源并提供給其他框架;
除了提供良好的擴展性和性能之外,作為集群調度管理系統,Mesos 也面臨著隔離不同任務資源的問題。在 Mesos 剛剛發布時,容器技術還沒有像今天這么普及,但是它也利用操作系統的容器隔離不同工作負載的影響[^2],并利用可插拔式的隔離模塊支持多種隔離機制。
調度模型
我們在文章開篇就已經介紹過 Mesos 和 Kubernetes 能夠管理的集群規模有數量級的差距,這里簡單對比分析下兩者在調度器上的差異,這能幫助我們理解 Kubernetes 調度器在設計時做出的決策,以及這些決策是如何影響它的可擴展性。
需要注意的是,提升系統可擴展性往往都是復雜的問題,而在 Kubernetes 這樣龐大的系統中會顯得更加復雜,Kubernetes 的調度器不是影響其可擴展性的唯一因素,想要提升單個集群的規模要從多個方面入手。
Mesos 的調度器選擇了兩層的調度設計,其中頂層調度器僅會根據底層框架調度器的需求粗粒度地過濾集群中的節點,而框架調度器會執行真正的任務調度,將任務綁定到相應的節點上。
圖 5 - 兩層調度器
這種兩層的調度器設計看起來雖然很復雜,但是實際上它能夠降低 Mesos 調度器的復雜度并提高了它的可擴展性:
- 降低復雜度:頂層調度器不需要處理真正的調度過程,它僅通過資源提供(Resource Offer)機制將一組節點交給底層調度器控制;
- 提高可擴展性:兩層調度器設計可以更方便地接入新的框架調度器,兼容不同復雜的調度策略,不同框架調度器內部可以串行為任務選擇節點,提高整體調度的吞吐量;
雖然 Mesos 通過兩層調度器設計提供了很強的擴展性,但是它卻不能為調度決策提供全局最優解。這是因為所有的調度決策都是在整個集群中的一部分節點中做出的,所有的調度決策都只是局部最優的,而這也是多調度器中的常見問題[^3]。
在調度系統中,想要實現更好的擴展性就一定面臨著分片,分片必然導致調度器無法提供全局最優解并且顯著地增加系統的復雜性。我們從 Linux、Go 語言等 CPU 調度器的演進可以觀察到這點,最初的調度器大多數都是單線程的,為了提高調度器的性能,會使用多調度器并引入工作竊取機制處理多調度器中待調度任務隊列的不平衡。
Kubernetes v1.21 版本的內置調度器仍然是單線程的,它為了在全局 5,000 個節點中做出最優的調度決策,需要使用不同的插件遍歷這 5,000 個節點并排序,而這也是影響其擴展性的重要原因之一。全局最優解聽起來是非常美好的設計,但是在調度這種比較復雜的場景中,局部最優解往往也都可以滿足需求,在業務上不需要保證該約束時,就可以通過多調度器來提升性能了。
總結
當對比 Mesos 和靜態分片集群的資源利用率時,我們會發現 Mesos 在 CPU 和內存的集群資源利用率上都明顯高于使用靜態分片的集群,而這個結果也不會造成太多的意外,因為動態的資源分配策略一般都能夠提高集群的資源利用率。
圖 6 - Mesos 和靜態集群的資源利用率對比
了解 Mesos 出現時解決的問題以及它的設計可以讓我們更好地理解今天面臨的挑戰,Mesos 在剛剛出現時是非常新穎的技術,與同期的其他產品來講確實提供了很強的靈活性,但是隨著 Yarn、Kubernetes 等技術的出現,它的很多場景也都被新技術取代,而這也是技術發展的必然趨勢。
[^1]: Benjamin Hindman, Andy Konwinski, Matei Zaharia, Ali Ghodsi, Anthony D. Joseph, Randy Katz, Scott Shenker, and Ion Stoica. 2011. Mesos: a platform for fine-grained resource sharing in the data center. In Proceedings of the 8th USENIX conference on Networked systems design and implementation (NSDI'11). USENIX Association, USA, 295–308.
[^2]: What's LXC? https://linuxcontainers.org/lxc/introduction/
[^3]: 調度系統設計精要 https://draveness.me/system-design-scheduler/
本文轉載自微信公眾號「真沒什么邏輯」,可以通過以下二維碼關注。轉載本文請聯系真沒什么邏輯公眾號。