在幾秒鐘內擴展至 100 萬個並發沙盒

@modal
英語23 小時前 · 2026年7月16日
128K
415
41
14
515

TL;DR

Modal 解釋了他們如何從集中式架構轉型為去中心化、以工作節點為中心的模型,從而實現了在幾秒鐘內啟動 100 萬個沙盒的目標。

本文由 Colin Weld 和 Connor Adams 撰寫。你可以在此處閱讀,或前往 我們的部落格*。

在 Modal,我們除了其他事情,也建構沙箱。Agent 在沙箱中運行,而 Agent 正在吞噬軟體。如今,Modal 每天運行數百萬個沙箱,每個客戶支援多達五萬個並行沙箱,並支援多種大規模用例,從強化學習背景 Agent

越來越多用戶需要更多沙箱,且創建速度愈來愈快。強化學習可能需要同時運行數百萬個沙箱,並在部署初期產生數十萬個沙箱的爆發。同樣地,Agent 也需要大規模運作和高並行創建速率,以應對流量突發。

我們現有的沙箱平台非常優秀,但它並非為這種規模而設計;其他現有解決方案也一樣。我們對規模與效能極度著迷,希望我們的基礎設施能加速 Agent 的成長,而非增加阻力。因此,我們重新思考了整個架構。

在過去幾個月,我們從頭重建了核心沙箱平台,兼顧規模與可靠性。在新的系統中,用戶可以同時運行數百萬個沙箱,並每秒創建數萬個沙箱。我們移除了控制平面中的所有集中式瓶頸,因此沒有實際的擴展限制;我們最佳化了容器排程與啟動的每個環節,將排程路徑簡化為一層直接在工作節點集群上創建容器的負載平衡器。

為了展示平台的能力,我們同時運行了一百萬個沙箱,並在不到一分鐘內創建了全部一百萬個。

Modal - inline image

我們能夠運行大量沙箱的證據。

為何多數解決方案無法擴展

運行一百萬個沙箱會挑戰任何容器平台的極限,不僅因為容器數量龐大,也因為運行這麼多沙箱需要數萬個計算節點。許多操作要麼是 O(容器數)、要麼是 O(節點數),或兩者皆是,這將導致傳統容器平台達到擴展極限。

以 Kubernetes 為例:

  • 排程演算法在最壞情況下是 O(n x p),其中 n 為節點數,p 為 Pod 數,且預設情況下排程是序列化的。
  • 每個 Pod 在其生命週期中會對 etcd(Kubernetes 的集中式持久儲存)進行多次寫入,這在 Pod 創建速率高或 Pod 變動頻繁時會造成嚴重問題,且 etcd 在鍵空間內無法原生分片。
  • 每個節點至少必須在每次心跳間隔向 etcd 寫入一次以表示存活,因此基線 etcd 寫入負載是 O(節點數),完全獨立於 Pod 創建。
Modal - inline image

Kubernetes 排程流程的近似圖。新 Pod 由 API 伺服器寫入 etcd(一個強一致性的持久儲存)。Kubernetes 排程器監控新的未指派 Pod,並透過呼叫 API 伺服器將其指派給節點,這又會寫入 etcd;當這次寫入完成後,節點才能啟動 Pod。

Kubernetes 可以擴展,但需要大量工作。要運行大量節點,etcd 通常必須改寫替換。要支援高排程吞吐量,需要建構一個複雜的 scatter-gather 系統來平行化排程演算法,同時仍維持 Pod 狀態的單一事實來源。預設情況下,分片與平行化並不容易,因為 Kubernetes 的設計核心依賴強一致性。

Modal 原始的沙箱架構也有類似問題。與 Kubernetes 一樣,我們在後端依賴強一致性,因此創建和排程沙箱需要全域協調,並對 Postgres 進行 O(沙箱數) 的寫入,而我們無法輕易對其進行分片。

Modal - inline image

Modal 原始的沙箱控制平面架構。當沙箱被創建時,它們會被放入佇列並寫入 Postgres。排程是樂觀的且平行運行,但需要中央協調以避免衝突。將沙箱指派給工作節點(計算節點)需要額外寫入 Postgres。

由於我們不建構在 Kubernetes 上,因此能夠擴展此系統的許多部分。例如,排程預設就是平行化的,這使我們能達到非常高的沙箱突發創建速率。但隨著我們擴展到越來越多的節點和沙箱,我們不斷遇到新的瓶頸,這些瓶頸來自於 O(沙箱數) 或 O(節點數) 但不容易擴展的操作。

例如,我們為每個完成的沙箱運行一個持久化工作流程,因此高沙箱變動率會造成大量事件積壓。我們反覆遇到以 O(沙箱數) 速率呼叫的 RPC,這在整個系統中造成了意外的負載問題。而運行大量沙箱所需的節點數量,也在節點管理和自動擴展中造成了多個下游問題。最後,即使我們可以繞過,但將未分片的 Postgres 實例留在所有沙箱創建和排程的關鍵路徑上,已被證明是個壞主意。

解鎖無限擴展

我們很快意識到,要達到我們想要的規模,必須從頭重新思考架構。我們希望運行數百萬個沙箱,並每秒創建數萬個沙箱,這需要比現有方案更好的擴展特性。與其嘗試改進現有系統,我們相信最快、最乾淨的路徑是從新開始。

為了最佳化擴展,我們決定:所有產生 O(沙箱數) 或 O(節點數) 負載的操作,必須預設為水平可擴展;沙箱創建路徑應盡可能簡單;其他一切則為次要。我們最終的解決方案與現有系統有顯著不同。我們完全放棄了任何形式的集中協調,並在運行和創建沙箱的關鍵路徑上,以全域一致性換取可擴展性和效能。以下是運作方式:

  • 不使用單一序列化排程器,而是運行一組排程伺服器,並行處理沙箱創建請求。為了處理創建請求,排程伺服器針對記憶體中快取的資料運行快速排程演算法。結果是排程水平擴展,看起來更像負載平衡,而非傳統容器排程。
  • 不像大多數容器平台那樣使用中央持久資料儲存作為沙箱和工作節點狀態的事實來源,我們新系統中的每個工作節點都是自己的事實來源。工作節點定期將其狀態發佈到 Redis 串流。排程伺服器非同步消費此狀態,並用於做出排程決策。一旦排程伺服器決定在哪個工作節點上創建沙箱,它會直接透過 RPC 聯繫該工作節點,請求創建沙箱。如果工作節點有可用資源,則接受排程請求,否則拒絕。
  • 沙箱創建路徑中完全沒有資料儲存,這提高了可擴展性和可靠性。雖然我們確實需要將沙箱元資料和結果寫入持久儲存,但我們主要非同步進行。
  • 除了沙箱創建,我們沒有任何 RPC 是 O(沙箱數) 的。工作節點將多個沙箱的控制訊息批次處理到單個 RPC 中,這符合資料導向設計的精神。
Modal - inline image

我們最終的設計,這是我們第一次在白板上畫出它。

Modal - inline image

Modal v2 沙箱架構中的沙箱創建路徑。沙箱創建請求由水平擴展的排程伺服器處理,然後透過快速記憶體內負載平衡演算法選擇一個工作節點,並直接聯繫該工作節點(計算節點)來創建沙箱。沙箱物件儲存在 Redis 中,但不在關鍵路徑上。

結果是,沙箱創建路徑只需要兩次網路跳躍和一次便宜的 CPU 操作。沒有中央瓶頸或協調成本,沒有單點故障,因此對聚合沙箱規模或沙箱創建吞吐量沒有實際上限。我們可以根據需要添加更多排程器或工作節點。最迫近的瓶頸是所有工作節點將狀態發佈到單一 Redis 串流,但負載測試表明,在工作節點超過十萬個之前,這仍然可行;而且我們並不依賴串流的順序,因此很容易添加更多串流。透過設計,我們避免了現有解決方案無法擴展的問題。

建構這個解決方案並不容易!整個開發過程耗時數月,涵蓋了後端大多數主要系統。我們花了數小時在白板上討論。我們四個人離開辦公室,搬到邁阿密海灘的一間租屋,在沒有干擾的情況下建構新系統的原型。我們花了八天時間寫程式,直到身體無法負荷,期間下下快棋恢復精神,跳進海裡,然後立刻回到程式碼前,努力讓新系統既乾淨又功能完整。

Modal - inline image

我們最優秀的工程師在邁阿密海灘放鬆。

一旦核心組件運作起來(並回到紐約),我們還需要在新的系統上重新實現每個沙箱功能以及所有沙箱可觀測性。這個專案也需要更改我們的核心工作節點管理堆疊以及容器執行環境。例如,我們遇到一個有趣的問題:新的沙箱排程器向工作節點推送容器的速度太快,以至於大量容器同時啟動時,會在設置容器網路規則時爭奪 Linux 核心中的 rtnl 鎖,導致啟動時間長達數十秒。因此,我們不得不更改沙箱的容器網路設置,以確保工作節點在大量沙箱創建湧入時不會崩潰。

我們的效能表現如何

我們透過盡快啟動一百萬個沙箱來對系統進行基準測試。總體而言,我們能在不到一分鐘內創建一百萬個沙箱,其中主要的瓶頸是基準測試本身。單個沙箱從創建到可互動的時間始終保持低延遲,且我們沒有觀察到隨規模擴展而出現的明顯效能退化。

Modal - inline image

沙箱創建請求的分佈與 eCDF。當排程伺服器成功將沙箱指派給工作節點,且沙箱開始啟動時,沙箱創建請求即返回。

我們認為這符合預期,因為我們的設計就是如此。排程路徑中沒有協調,因此排程應該保持非常快速,不受並行性和規模的影響。對我們而言,除了可用容量之外,並行沙箱排程或規模沒有嚴重的限制,而管理容量已經是我們擅長的事

Modal - inline image

從一百萬個沙箱測試中隨機選取的 10k 個沙箱啟動時間散佈圖。

新系統上的沙箱啟動時間(從客戶端首次嘗試創建沙箱到沙箱可以運行用戶程式碼的延遲)中位數不到半秒,且在大規模下依然穩定。它們也遠比舊系統快,主要原因是排程快得多——現在只需要幾十毫秒。延遲的長尾比我們希望的要長一些。我們將此長尾歸因於當許多沙箱在同一工作節點上同時啟動時的核心和網路競爭(包括之前提到的 rtnl 鎖競爭),我們正在努力減少它。此外,大規模下的長尾是真實存在的。我們預計隨著我們最佳化容器啟動路徑,這個情況會改善。

總體而言,我們對這些效能數據非常滿意。隨著 Agent 接管世界,顯然我們可以與它們一起擴展。

親自試試看

這個新系統很快就會支援 Modal 的所有沙箱排程,但現在已經可以在 Beta 版本中使用。你只需要對程式碼做一個簡單的更改即可啟用。如果你需要運行大量沙箱,請試試看,並與我們聯繫!

致謝

許多人為這個專案付出了心血與汗水。我們的邁阿密概念驗證由 Colin Weld(我)、Daniel Shaar、Walter Tang 和 Gleb Posobin 建構,隨後由 Walter、Colin、Connor Adams、Akshay Balwally、Tom Wildenhain、Scott Hao 和 Taylor Baldwin 將其推向生產環境。

一鍵儲存

使用 YouMind AI 深度閱讀爆款文章

保存原文、追問細節、總結觀點,並在一個 AI 工作空間裡把爆款文章沉澱成可複用筆記。

了解 YouMind
寫給創作者

把你的 Markdown 變成乾淨的 𝕏 文章

圖片上傳、表格、程式碼區塊,往 𝕏 上手動重排太痛苦。YouMind 把整篇 Markdown 一鍵轉成乾淨、可直接發佈的 𝕏 文章草稿。

試試 Markdown 轉 𝕏

更多可拆解樣本

近期爆款文章

探索更多爆款文章