OpenAI 將 Kubernetes 擴展至 7,500 節點

OpenAI 已將單一 Kubernetes 叢集擴展至 7,500 節點,以讓機器學習研究團隊在不修改程式碼的情況下擴展工作負載。此基礎設施支援大規模作業,其中單一 Pod 常佔據整個節點,透過 NVLink 和 GPUDirect 最大化硬體效率。

工作負載特性

OpenAI 的 Kubernetes 工作負載與典型企業應用程式顯著不同。主要焦點是大規模機器學習作業,優先考慮硬體資源存取,而非 bin-packing 或碎片化。

  • 資源利用率: Pods 通常佔據整個節點,以允許 GPU 透過 NVLink 直接通訊,以及 NIC 透過 GPUDirect,減少基於 NUMA 或 CPU 競爭的複雜排程需求。
  • 工作負載性質: 工作常執行 MPI(Message Passing Interface),使其成為「半有狀態」。如果 MPI 通訊器中的某個 Pod 死亡,整個作業將停止並從最後一個檢查點重新啟動。
  • 網路模式: 對 Kubernetes 負載平衡、HTTPS 流量或服務發現的依賴極小。Pods 透過 Pod IP 位址使用 MPI over SSH 直接通訊。
  • 儲存: 系統主要依賴 blob 儲存來進行資料流和檢查點,僅在需要 POSIX 語義時使用 PersistentVolumes。

網路最佳化

為支援 7,500 節點和約 200,000 個併發 IP 位址,OpenAI 已從 Flannel 轉向 Azure VMSS(虛擬機器擴展集)和相關 CNI 外掛的原生 Pod 網路。

高吞吐量網路

使用基於別名的 IP 位址而非基於路由的網路,避免了有效路由數量的限制,並提供主機層級的網路吞吐量。此方法消除了封裝,簡化了設置,並避免了與 MTU 相關的封包碎片問題。

網路監控

OpenAI 使用 iptables mangle 規則將封包標記為內部或網際網路導向。這些計數器透過開源的 iptables-exporter 追蹤,並整合到 Prometheus 中,使研究人員能夠視覺化網路瓶頸。

叢集隔離

叢集採樞輻模型組織。研究人員可透過樞紐存取個別叢集(輻條),但叢集間無法相互通訊,以確保故障隔離。

API 伺服器和 etcd 穩定性

為維持大規模叢集的健康,OpenAI 在叢集外的專用節點上執行 API 伺服器和 etcd。

  • 部署: 最大的叢集使用五個 API 伺服器和五個 etcd 節點來分配負載。
  • 資源使用: API 伺服器記憶體使用量隨叢集大小線性增長,對於 7,500 節點可達 70GB 堆積。
  • EndpointSlices: 採用 EndpointSlices(Kubernetes 1.17 引入)將 Endpoints 上的 WATCH 負載降低了 1,000 倍,防止在節點新增或移除時出現 $N^2$ 頻帶尖峰。
  • 擴展策略: 為避免 API 伺服器過載,OpenAI 避免使用 DaemonSets 進行 API 互動,並在自動擴展事件期間平滑新節點的加入。

使用 Prometheus 和 Grafana 進行監控

OpenAI 使用 Prometheus 進行時間序列指標,Grafana 進行視覺化,但遇到了顯著的擴展障礙。

  • 記憶體洩漏: /api/v1/series API 的一個錯誤導致 Prometheus 在 Grafana 查詢直方圖指標時因無限制的記憶體消耗而崩潰。OpenAI 透過使用 Context 強制執行逾時來修補 Prometheus。
  • WAL 重播效能: Prometheus 啟動時間因 Write-Ahead-Log(WAL)重播而延遲數小時。設定 GOMAXPROCS=24 透過減少高核心伺服器上的 CPU 競爭來緩解此問題。
  • 指標過濾: 為管理資料量,Prometheus 規則用於「丟棄」擷取過程中的細粒度或未使用指標。

節點健康與 GPU 驗證

自動化用於透過被動和主動健康檢查的組合來偵測並移除行為異常的節點。

被動健康檢查

系統透過 dcgm-exporter 和 NVML Device Query API 監控網路可達性、磁碟健康和 GPU 錯誤(例如無法更正的 ECC 錯誤)。失敗的節點會自動被 cordon;嚴重失敗會觸發 Pod 驅逐,最終導致 VM 終止。

主動 GPU 測試

由於某些 GPU 問題不會觸發錯誤碼,OpenAI 使用「預先檢查」系統。新節點在加入叢集時會帶有汙點和標籤;DaemonSet 會在移除汙點以允許一般工作負載之前執行詳盡的 GPU 測試。

資源管理與排程

OpenAI 實施了自訂機制來處理競爭研究團隊的資源分配和幫派排程。

  • 團隊汙點: team-resource-manager 服務使用汙點 (openai.com/team=teamname:NoSchedule) 和準入 webhook 來為研究團隊分配特定節點容量,同時允許低優先級 Pod 借用未使用的容量。
  • 資源氣球: 為防止 cluster-autoscaler 移除閒置節點(這會增加啟動延遲和 API 伺服器壓力),OpenAI 使用「氣球」Deployments。這些低優先級 Pod 佔據空間,但在實際工作到來時會立即被驅逐。
  • 幫派排程: 為防止多個實驗各佔一半所需叢集容量導致的死鎖,OpenAI 使用 Coscheduling 外掛(Kubernetes 1.18 引入)來確保 StatefulSet 中的所有 Pod 在訓練開始前完成排程。

剩餘挑戰

OpenAI 識別出兩個主要未解決的問題:

  1. 指標儲存: Prometheus TSDB 引擎壓縮緩慢且易發生「樣本過多」錯誤。OpenAI 正在遷移至不同的 Prometheus 相容儲存和查詢引擎。
  2. 流量塑造: 研究人員使用的總網際網路頻寬可能會對外部資料集和軟體套件儲存庫造成壓力,因而需要更好的 Pod 網路流量塑造。

Sources