操作系統模型與樂高積木 · OSDI 2018
『看看論文』是一系列分析計算機和軟件工程領域論文的文章,我們在這個系列的每一篇文章中都會閱讀一篇來自 OSDI、SOSP 等頂會中的論文,這里不會事無巨細地介紹所有的細節,而是會篩選論文中的關鍵內容,如果你對相關的論文非常感興趣,可以直接點擊鏈接閱讀原文。
本文要介紹的是 2018 年 OSDI 期刊中的論文 —— LegoOS: A Disseminated, Distributed OS for Hardware Resource Disaggregation[^1],它是 OSDI 2018 的最佳論文(Awarded Best Paper),這篇論文實現的 LegoOS 操作系統可以將數據中心中的單體服務器拆分成通過網絡連接的分散硬件,其中每個硬件都由獨立的控制器管理。因為現有的操作系統都無法處理類似的場景,所以這篇論文提出了一種分離內核(Split kernel)的操作系統模型來管理和控制底層的硬件資源。
我們在集群中部署服務時經常會遇到資源碎片化的問題,這是因為在今天的集群中,單獨的 CPU 或者內存無法直接對外提供服務,不同的硬件需要組合成主機才能運行用戶提交的工作負載,而為了減少集群中可能存在的碎片化,很多云服務廠商都會提供 CPU 和內存比例不同的多種主機[^2]:
圖 1 - 谷歌云提供的主機類型
除了常見的 CPU 和內存資源之外,集群中的 GPU 也無法獨立對外提供服務,我們需要將不同的資源插入到主板上才可以被應用程序使用,物理機一旦按照特定的規格組裝,想要拆分其中的資源就需要用到虛擬化等技術了。
而 LegoOS 可以更好地解決集群中的碎片化問題,提高整體的資源利用率。LegoOS 是個非常好的名字,它準確的描述了該操作系統的很多特征,不同的硬件在系統中是標準化的樂高積木,我們可以任意組合這些硬件構建具有海量資源的主機、集群甚至數據中心,同一個應用程序使用的 CPU、內存和存儲資源可能來自使用網絡連接的多個硬件。
圖 2 - LogoOS[^3]
將計算機中的不同硬件解耦可以自然地提高對資源的利用率,但是使用網絡連接硬件會帶來兩個比較棘手的問題,首先是由基礎設施支撐的網絡會帶來不確定性,與分布式系統一樣,很多問題都是網絡的不穩定帶來的,如果網絡完全可靠,那么我們也不再需要重試或者冪等來保證數據的一致性;其次是網絡帶來的延遲是 CPU 緩存或者內存索引的 1,000x ~ 1,000,000x:
Work | Latency |
---|---|
L1 cache reference | 0.5 ns |
Branch mispredict | 5 ns |
L2 cache reference | 7 ns |
Mutex lock/unlock | 25 ns |
Main memory reference | 100 ns |
Compress 1K bytes with Zippy | 3,000 ns |
Send 1K bytes over 1 Gbps network | 10,000 ns |
Read 4K randomly from SSD* | 150,000 ns |
Read 1 MB sequentially from memory | 250,000 ns |
Round trip within same datacenter | 500,000 ns |
Read 1 MB sequentially from SSD* | 1,000,000 ns |
Disk seek | 10,000,000 ns |
Read 1 MB sequentially from disk | 20,000,000 ns |
Send packet CA->Netherlands->CA | 150,000,000 ns |
表 1 - 2012 年延遲數字對比[^4]
雖然網絡延遲受限于物理條件,但是隨著網絡設備和計算資源的發展和進步,我們可以緩解網絡延遲帶來的諸多問題,這不僅因為硬件設備擁有了更多的帶寬和計算能力,還因為網卡與硬件設備變得更近。
我們在這篇文章中將介紹分布式操作系統 LegoOS 的架構與設計思路,包括它如何拆分現有操作系統的各個模塊,各個模塊的功能以及如何通過網絡連接這些不同的模塊對外提供服務。
架構與設計
LegoOS 使用全新的操作系統架構提供資源分離的功能,分離內核將操作系統分割成了具有不同功能的模塊,操作系統中的全部組件都會通過網絡進行通信,例如下圖中的處理器、GPU、內存以及 NVM 等硬件:
圖 3 - 分離內核架構[^5]
分離內核架構中包含以下四個關鍵的概念,分析這些概念能夠幫助我們理解該架構的特性:
- 分離操作系統(Split OS functionalities)— 將傳統操作系統的功能拆分到不同的監視器(Monitor)中,每個處理器都會管理硬件組件,虛擬化并保護這些物理資源;分離內核中監視器之間的耦合是很松的,它們會通過其他的監視器訪問遠程資源;
- 在硬件組件上運行監視器(Run monitors at hardware components)— 集群中的所有非處理器組件都會運行獨立的監視器,不同的控制器可以使用不同的實現管理自己持有的資源,這可以讓數據中心中的異構硬件更好地集成;
- 不一致組件之間的消息傳遞(Message passing across non-coherent components)— 分離內核依賴以太網等通用網絡層進行通信,不同組件之間的通信都是通過網絡進行的,我們只會保證組件內的一致性,應用程序可以在操作系統之上實現期望的一致性保證;
全局資源管理和錯誤處理(Global resource management and failure handling)— 單個組件可以同時為多個應用程序提供服務,而組件的失效也會影響多個應用程序,為了管理集群中的不同組件、減少性能損耗和擴展性的瓶頸,我們在全局的維度管理組件并通過冗余處理組件的失效;
LegoOS 的核心設計思想就是將操作系統的功能拆分成多個模塊并由全局的組件負責管理資源并處理錯誤,不同的硬件上運行不同的監視器來管理硬件資源,硬件之間會通過不可靠的網絡傳遞消息,開發者需要在應用程序中實現期望的一致性。
資源管理
LegoOS 在設計上將硬件分成了處理器、內存和存儲三種,分別是 pComponent、mComponent 和 sComponent,這三種硬件是互相獨立的設備,有不同的硬件控制器和網絡設備,我們會在 pComponent 中使用 CPU、在 mComponent 中使用 DRAM 并在 sComponent 中使用 SSD 或者 HDD。
圖 4 - LegoOS 的組件
LegoOS 使用了兩層的資源管理機制,在頂層使用三個全局的資源管理器來管理進程、內存和存儲資源,分別是 GPM(Global Process Manager)、GMM(Global Memory Manager) 和 GSM(Global Storage Manager),這些跑在普通 Linux 服務器上的全局資源管理器會負責處理粗粒度的全局資源分配和負載均衡,它們會定期做出資源分配策略或者從監視器中獲取負載等信息,底層的所有監視器會采用特定的策略和機制管理本地的資源。
圖 5 - 兩層資源管理機制
我們在本節中會分別介紹 LegoOS 對 pComponent、mComponent 和 sComponent 三種不同組件的管理方式。
CPU
在每一個 pComponent 中,LegoOS 都會使用簡單的本地線程調度模型處理數據中心中的應用程序,它會使用幾個 CPU 在后臺處理內核的相關任務并將剩余的 CPU 分配給應用程序的線程。當操作系統啟動新的進程時,LegoOS 會使用全局的策略為當前進程的線程分配 CPU 并等待線程執行完成,在通常情況下,LegoOS 中運行的所有線程都不會被搶占。
圖 6 - 進程管理器
LegoOS 的進程監視器除了持有和管理 CPU 資源之外,它還會配置和管理 ExCache 組件,當 pComponent 中處理器訪問 ExCache 未命中時,LegoOS 會從對應的 mComponent 中讀取相應的緩存行,與其他的緩存系統一樣,ExCache 也實現了 FIFO 和 LRU 的緩存驅逐機制保證緩存的時效性。
內存
mComponent 主要會用于處理三種類型的數據:匿名內存(堆和棧)、內存映射文件和存儲緩存區,它會同時管理虛擬和物理內存空間的分配、釋放以及映射。每個應用程序進程都會使用一個或者多個 mComponent 保存數據,其中包含一個主 mComponent 會負責初始化加載進程、檢查所有與虛擬內存管理相關的系統調用,每個進程的主 mComponent 都是由 LegoOS 中的全局內存資源管理器(Global Memory Resource Manager,GMM)統一分配的。
LegoOS 使用兩層的機制管理分布式的虛擬內存空間,其中主 mComponent 負責粗粒度的、高層的虛擬內存分配決策,其他的 mComponent 負責執行細粒度的虛擬內存分配,這種策略可以減少正常內存訪問和虛擬內存操作的網絡通信。
我們將虛擬內存空間地址分成多個粗粒度、固定大小的虛擬地區(Virtual Region、vRegion),每個虛擬地區中的內存地址都屬于一個 mComponent,底層會存儲用戶進程虛擬空間的區域信息。當應用程序進程想要分配虛擬內存空間時,它會執行如下所示的步驟:
圖 7 - 分布式內存管理
- pComponent 會將內存分配請求轉發給主 mComponent;
主 mComponent 會使用它存儲的 vRegion 的可用虛擬內存空間信息選擇合適的區域分配內存;
如果當前 mComponent 中沒有合適的內存區域,它會向 GMM 發出內存分配請求獲取新的 mComponent 以及 vRegion;
- 如果候選的 mComponent 不是主 mComponent,那么主 mComponent 會將內存分配的請求轉發給對應的 mComponent;
收到請求的 mComponent 會負責分配本地虛擬內存區域并初始化虛擬內存空間樹;
- 獲得 mComponent 信息后,pComponent 會直接與上述過程中選擇的 mComponent 進行通信,并在為它分配的 vRegion 中申請內存;
與虛擬內存相比,物理內存的管理相對比較直接,每個 mComponent 都會負責管理它持有的物理內存,也可以自定義虛擬內存到物理內存之間的映射關系。
存儲
LegoOS 在 sComponent 中實現了核心的存儲能力,它通過 vNode 的抽象向后兼容了 POSIX 并支持了具有多個層級的文件接口,用戶可以在 vNode 掛載點中正常存儲目錄和文件等數據并執行正常的讀寫和其他操作。
為了保證文件系統的簡單,我們在 sComponent 中應用了無狀態的設計,所有的 I/O 請求必須包含該請求所需要的全部信息,而 LegoOS 的存儲監視器也選擇使用哈希表來存儲文件名到文件的映射,這也可以減少 sComponent 查找文件時所需要的計算資源,最大化的分離 CPU、內存和存儲資源。
圖 8 - 分布式存儲緩沖區
因為我們不僅要分離內存和存儲資源,還要保證存儲的訪問速度,操作系統原本的存儲緩沖區(Storage Buffer Cache)也被放到 mComponent 中。當 pComponent 想要讀取存儲節點中的數據時,它會先從 mComponent 中查找是否有緩存的數據,只有當存儲緩沖區中不包含對應數據時,它才會調用 sComponent 的接口獲取數據并將數據寫入 mComponent 的緩沖區中。
總結
今天的軟件與硬件與幾十年前剛剛誕生時已經有了天翻地覆的差別,各種各樣的分布式系統、復雜的軟件都需要多種多樣的硬件支持,硬件的異構也導致資源的管理和調度在單機上變得更加復雜。
作為 2018 年 OSDI 的最佳論文,分布式操作系統 LegoOS 中的工作確實非常有趣,因為網絡設備的發展,將服務器上的硬件資源打散重新管理變成了可能,在數據中心成為基礎設施的今天,分布式操作系統這一設計變得非常有價值,這也可能會改變我們在未來組織和管理硬件的模式。
本文轉載自微信公眾號「真沒什么邏輯 」,可以通過以下二維碼關注。轉載本文請聯系真沒什么邏輯 公眾號。