Ray2-0 架構 - 中文翻譯版(Part3-
原文地址:https://docs.ray.io/en/latest/ray-contribute/whitepaper.html
集羣管理
集羣管理中涉及的流程。藍色進程是位於 Head 節點上的單進程。粉色進程在節點啓動,並管理其本地節點的輔助進程。
Autoscaler 用於自動縮放,根據節點資源情況和利用率添加或刪除節點。
Autoscaler 負責從集羣中添加和刪除節點。它會監測分佈式調度器暴露的邏輯資源需求、集羣中當前的節點、集羣的節點配置文件,計算所需的集羣配置,並嘗試擴縮容(比如調用雲提供商添加或刪除機器)。
Autoscaler 的工作流程如下:
- 應用程序提交任務、Actor、預佔用組,這些任務請求諸如 cpu 之類的資源。
-
調度器查看需求和可用性,如果無法滿足,則將其置於掛起狀態。該信息被快照到 GCS 中。
-
自動縮放器作爲單獨的進程運行,將定期從 GCS 獲取快照。它查看集羣中可用的資源、請求的資源、掛起的資源、爲集羣指定的工作節點配置,並運行 bin-packing 算法來計算節點數量,以滿足正在運行和掛起的任務、Actor 和預佔用組請求。
-
自動縮放器然後通過節點供應商接口從集羣中添加或刪除節點。節點供應商接口允許 Ray 插入不同的雲提供商(例如 AWS、GCP、Azure)、集羣管理器(例如 Kubernetes)或本地數據中心。
-
當新的節點啓動時,它向集羣註冊並接受應用程序的工作負載。
如果節點空閒超時(默認情況下爲 5 分鐘),則會將其從集羣中刪除。當沒有活動任務、Actor 或對象的主要副本時,節點被視爲空閒。
可擴容節點的數量有限制,這取決於擴容速度。速度定義爲擴容的節點數與當前節點數的比率。值越高,擴容得越多。例如,如果將其設置爲 1.0,則集羣的大小在任何時候都最多可以增長 100%,因此如果集羣當前有 20 個節點,則最多允許 20 個新增節點。可擴容的最小數量爲 5,以確保即使對於小集羣也有足夠的擴容速度。
Ray 也支持雲廠商的不同實例類型和設置鏡像、IAM 角色等。還可以指定這個機器是否有特殊資源。
Ray Client server 是 Ray Client 用的代理服務,用於支持集羣的交互開發。
API server + Dashbord server,提供儀表盤服務和集羣狀態管理 API 的入口。
API agent,在本地節點上收集集羣管理需要的指標,安裝用於任務和 Actor 執行的運行時環境。
Log monitor, 負責監聽本地的日誌,默認在 /tmp/ray/session_last/logs,如果有錯誤日誌會給到 Driver。
Job 提交
Job 可以通過命令行、Python SDK 或者 REST API 提交到 Ray 集羣,CLI 調用 PythonSDK,後者反過來向 Ray 集羣上的 Jobs RESTAPI 服務器發出 HTTP 請求。REST API 當前託管在 Ray 儀表板後端,但將來可能會移動到獨立的 API 服務器。
每個 Job 都由自己的專用 Job 主管 Actor 管理,該角色在 Ray Head 節點上運行。這個 Actor 在 Job 的用戶指定的運行時環境中運行,Job 的用戶指定的端點命令在繼承了這個運行環境的子進程中運行。如果這個命令包含 Ray 的腳本,則 Ray 的腳本將附加到正在運行的 Ray 集羣。
Job 會報告結構化的狀態(如 PENDING, RUNNING, SUCCEEDED)和通過 API 獲取到的消息。這些數據都會存儲到 GCS 中。
Job 管理的 Actor 及其啓動的子流程命運共享。如果 Job 的 Actor 死亡,則保留最新的工作狀態。下次用戶請求作業狀態時,狀態將更新爲 “FAILED”。
通過在相應的 Job 管理的 Actor 上設置 “停止” 事件,可以異步停止 Job。這個 Actor 會負責終止 Job 子流程,更新其狀態並退出。
Job 的管理和 Job 的 管理 的 Actor 和日誌會在入口點腳本的輸出中直接寫入 Head 節點上的文件裏,該文件可以通過 HTTP 端點讀取或流式傳輸。
Ray 2.0 允許在除 Head 節點之外調度管理 job 的 Actor,以便減輕多租戶的 Head 節點的壓力。
運行時和多租戶
它在運行時動態安裝在集羣上,可以在 Ray Job 中或特定的 Actor 和任務中指定 Python 腳本運行所需的依賴關係,如文件、包和環境變量。
運行環境的安裝和刪除由運行在每個節點上的 RuntimeEnvAgent gRPC 服務器處理。RuntimeEnvAgent 命運與 raylet 共享,raylet 是調度任務和參與者的核心組件。
當任務或 Actor 需要運行時環境時,raylet 會向 RuntimeEnvAgent 發送一個 gRPC 請求來創建環境(如果環境還不存在)。
創建環境可能需要做:
-
通過
pip install
下載和安裝軟件包。 -
爲 Ray 的 worker 進程設置環境變量。
-
在啓動 Ray 的 worker 進程前使用 conda 切換環境。
-
從遠程雲存儲下載文件。
運行環境資源(如下載的文件和安裝的 conda 環境)會緩存在每個節點上,以便它們可以在不同的任務、Actor 和 Job 之間共享。
當超過緩存大小限制時,將刪除當前沒有 Actor、任務或 Job 在使用的資源。
KubeRay
Kuberray operator 可以在 Kubernetes 設置和管理 Ray 集羣。每個 Ray 的節點都作爲 Kubernetes pod 運行在 k8s 上。
可觀測性
Dashbord
Ray 提供了像 Dashbord 之類的可視化工具和觀測工具來方便檢查狀態、排查問題。
日誌聚合
Ray driver 會聚合並輸出從 actor 和任務中打印的所有日誌消息。當任務或 actor 將日誌打印到其 stdout 或 stderr 時,它們會自動重定向到相應的工作日誌文件。日誌監視器的進程會在每個節點上運行,定時讀取並通過 GCS pubsub 將日誌發送到 driver。
指標觀測
Ray 與 OpenCensus 集成了,默認支持將可以觀測的指標導出到 Prometheus。
狀態 API
自 Ray 2.0 以來,Ray 支持允許用戶通過 CLI 或 Python SDK 方便地訪問當前 Ray 的狀態的快照。狀態 API 支持查詢特定 Ray 任務、 Actor 等的查詢。
流程詳細示例
分佈式任務調度
我們將從 worker 1 執行 A 開始。任務 B 和 C 提交給 worker。worker 1 的本地所有權表已經包含 X 和 Y 的條目。首先,我們將介紹一個調度 B 執行的示例:
-
Worker 1 向其本地調度器請求執行 B 的資源。
-
調度器 1 作出響應,告訴 worker 1 在節點 2 重試調度請求。
-
Worker 1 更新其本地所有權表,要求任務 B 在節點 2 上掛起。
-
Worker 1 向節點 2 上的調度器請求執行 B 的資源。
-
調度器 2 將資源授予 worker 1,並用 worker 2 的地址進行響應。調度器 2 確保沒有其他任務被分配給 worker 2,而 worker 1 仍然擁有資源。
-
Worker 1 發送任務 B 給 worker 2 執行。
任務的執行
接下來,我們將展示一個 worker 執行任務並將返回值存儲在分佈式對象存儲中的示例:
-
Worker 2 完成執行 B 並將返回值 X 存儲在其本地對象存儲中。
a. 節點 2 異步更新對象表, X 現在位於節點 2 上(虛線箭頭)。
b. 因爲是創建的 X 的第一個副本,所以節點 2 還固定 X 的副本,直到 worker 1 通知節點 2 可以釋放對象。這將確保對象值在引用期間是可訪問的。 -
Worker 2 回覆 worker 1 ,任務 B 已經完成。
-
Worker 1 更新其本地所有權表,將 X 存儲在分佈式內存中。
-
Worker 1 將資源返回給調度器 2。worker 2 現在可以被重用來執行其他任務。
分佈式任務調度和參數解析
既然任務 B 已經完成,任務 C 就可以開始執行了。Worker 1 使用與任務 B 類似的協議安排下一個任務 C:
-
對象表響應調度器 3,表明 X 位於節點 2 上。
-
調度器要求節點 2 上的對象庫發送一份 X 的副本
-
X 被從節點 2 複製到節點 3。
a. 節點 3 也異步更新對象表,表明 X 也在節點 3 上(虛線箭頭)。
b. 節點 3 的 X 的副本被緩存了,但沒有被固定。當本地 worker 正在使用它時,該對象不會被驅逐。然而,與節點 2 上的 X 的副本不同,當對象存儲區 3 處於內存壓力之下時,節點 3 的副本可能會根據 LRU 被驅逐。如果這種情況發生,而節點 3 又需要該對象,它可以使用這裏顯示的相同協議從節點 2 或不同的副本重新獲取它。 -
由於節點 3 現在有一個 X 的本地副本,調度器 3 將資源授予 worker 1,並 worker 3 的地址作爲迴應。
任務執行和對象內聯
任務 C 執行並返回一個小到足以存儲在進程內存存儲中的對象:
-
Worker 1 發送任務 C 到 worker 3 執行。
-
Worker 3 從其本地對象存儲中獲取 X 的值(類似於
ray.get
),並運行 C(X)。 -
Worker 3 完成 C 並返回 Y,這次是直接通過值而不是存儲在其本地對象存儲中。
-
Worker 1 將 Y 存儲在其進程中的內存存儲中。它也刪除了任務 C 的 specification 和位置,因爲 C 已經執行完畢。此時,任務 A 中未完成的
ray.get
調用將從 worker 1 的進程內存儲中找到並返回 Y 的值。 -
Worker 1 將資源返回給調度器 3。Worker 3 現在可以被重新使用來執行其它任務。這可以在步驟 4 之前完成。
垃圾回收
最後,我們將展示 worker 是如何清理內存的:
- Worker 1 刪除了對象 X 的記錄。這樣做是安全的,因爲等待中的任務 C 有對 X 的唯一引用,而且 C 現在已經完成了。Worker 1 保留其對 Y 的記錄,因爲應用程序仍然有對 Y 的 ObjectID 的引用。
a. 最終,X 的所有副本都從集羣中刪除。這可以在步驟 1 之後的任何時間進行。如上所述,如果節點 3 的對象存儲處於內存壓力之下,節點 3 的 X 的副本也可能在步驟 1 之前被刪除。
作者介紹:大家好!我是 Andy.Qin,一個想創造哆啦 A 夢的 Maker,連續創業者。我最熟悉的領域是分佈式應用開發、高併發架構設計,其次是機器學習、自然語言處理和理解方向。我對開源社區和開源項目的建設也有極大的熱忱,期望能與大家多多交流討論!本次利用業務時間,花了一個月翻譯了將近 60 多頁的 Ray2.0 架構白皮書,期望對大家能夠有所幫助!大家有任何問題或者疑問(當然也包括鼓勵,請點擊閱讀原文,在論壇中留下你的寶貴意見!
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/NwoUm60ZEJCIb9Dvf0wNTA