專屬伺服器

裸機伺服器上的容器資源限制與 cgroups

容器的優點在於可以封裝應用程式及其依賴,而不必為每項工作負載各自運行完整作業系統。然而在裸機伺服器上,容器執行環境會與主機共用核心,以及實體 CPU、記憶體、儲存和網絡路徑。因此,清晰的資源政策十分重要。容器資源限制可以把實體容量轉化為可執行的邊界,避免單一工作負載耗盡其他服務所需的餘裕。

Linux 控制組(通常稱為 cgroups)就是這些邊界背後的核心機制。它會把程序組織成階層並記錄資源使用量,讓營運人員或編排平台對容器、Pod、服務或主機 slice 套用政策。了解 cgroups 對專屬硬件尤其重要,因為管理者可以控制核心,並調整主機、容器執行環境與工作負載之間的關係。

cgroups 在裸機伺服器上控制甚麼

cgroup 並不是虛擬機器,也不會模擬硬件,而是圍繞一組程序建立的核心層資源邊界。視乎控制器及 Linux 版本,它可以限制或調整 CPU 時間、記憶體、程序數目、區塊 I/O、裝置存取,以及 CPU 或 NUMA 位置。容器執行環境在啟動工作負載時建立及管理這些群組,而 systemd 和 Kubernetes 亦可能為服務及 Pod 建立額外的父層群組。

  • 現時大部分發行版使用 cgroup v2,提供統一階層及一致介面,例如 cpu.max、memory.max、memory.high、pids.max 及 io.max。較舊的系統仍可能使用 cgroup v1,控制器會分開掛載。檔案名稱及執行行為會有所不同,因此營運團隊在記錄限制或編寫自動化前,應先確認主機的 cgroup 版本。
  • 資源路徑通常有多個層次:主機核心、系統或服務管理器、容器執行環境,以及使用 Kubernetes 時的 kubelet 和 Pod 階層。一層的限制可能會與另一層互相影響。容器即使看似有可用 CPU,仍可能受 Pod 配額或 system slice 限制;節點即使有空閒記憶體,也可能為作業系統及重要背景服務保留容量。

如要比較不同隔離模式,可參閱 Dataplugs 的 〈裸機上的容器化與虛擬化:隔離及效能〉文章。文章有助於理解容器如何共用核心、虛擬機器如何引入獨立的客戶作業系統,以及為何專屬硬件上的資源邊界必須明確設計。

實際目標不是把每個容器縮到最小,而是為每項工作負載提供可預測的運行範圍,為恢復工作及平台服務保留足夠主機餘裕,並在資源耗盡演變成故障前讓問題可被看見。

CPU 及記憶體限制是第一層控制

CPU 限制可以用一段時間內的配額、相對權重,或指定工作負載可使用的 CPU 集合表示。配額限制持續 CPU 消耗;權重影響競爭時 CPU 時間如何分配;cpuset 則可以把對延遲敏感的工作隔離到指定核心。這些控制解決不同問題。若未考慮突發流量便套用配額,可能增加排隊;只使用權重,則無法阻止繁忙容器在節點閒置時使用全部可用容量。

記憶體限制較難處理,因為記憶體未必能夠優雅地回收。在 cgroup v2 中,memory.high 是會觸發回收及節流的壓力門檻,而 memory.max 是硬上限。當主機受壓時,memory.min 或 memory.low 可以保護重要服務。正確數值取決於應用程式的工作集、快取行為、啟動峰值,以及 sidecar 或輔助程序使用的記憶體,而不只是平均常駐集。

  • 當工作負載達到記憶體硬上限,而回收又無法釋放足夠空間時,核心可能啟動 cgroup 的記憶體不足處理流程並終止程序。這比讓整台主機不穩定更安全,但不能代替應用程式層面的容量規劃。應輸出記憶體工作集、回收、節流及 OOM 事件,再與部署及重啟政策連結,讓營運人員分辨錯誤限制、記憶體洩漏或流量突升。
  • pids 控制器限制 cgroup 可以建立的程序及執行緒數目,有助於防止 fork bomb、工作程序失控增加及程序池配置錯誤。設定時要了解執行環境、應用程式工作程序、語言執行緒、健康檢查及短期工作。PID 限制過低時,即使 CPU 及記憶體指標正常,也可能看起來像應用程式故障。

io.max 及 io.weight 等區塊 I/O 控制,可以保護對延遲敏感的服務,避免受批次工作或大量映像部署影響。裝置層限制在了解儲存布局時最有用:NVMe 卷、RAID 裝置及檔案系統可能在不同位置出現壓力。如果工作負載需要直接存取 GPU 或其他裝置,應結合適當的執行環境及安全政策處理裝置權限,不要把裝置存取當成一般資源限制。

為裸機工作負載設計資源限制

先從量度開始,而不是隨意選一個整數。記錄正常及突發流量下的 CPU 使用率、節流時間、記憶體工作集、頁面錯誤、I/O 延遲、吞吐量、程序數目及啟動峰值。新工作負載在暖機、填充快取及穩定運行期間都應量度。這些觀察為請求、限制及主機規模提供可靠依據,也令日後調校不必過度依賴猜測。

  • 要有意識地為主機保留餘裕。作業系統、容器執行環境、日誌、監控、儲存代理程式、安全控制及編排元件,即使應用程式容器繁忙也需要資源。在裸機上,管理者亦應計算核心記憶體、中斷處理、檔案系統快取及恢復工作。把所有已安裝 RAM 或所有邏輯 CPU 都視為可分配給應用程式的容量,可能令單一容器突增變成節點級事故。
  • 把有保障的基本容量與最大值分開。請求或保留值表示工作負載通常應獲得的容量;限制則定義它最多可以增長到哪裡。在 Kubernetes 中,requests 影響排程,而 limits 由執行環境及核心執行。在獨立 Docker 主機上,同類政策可以寫在 Compose 檔案、systemd 單元或部署腳本。把兩個概念分開,有助釐清容量計劃,避免所有數值都設定成一樣。

硬件拓撲同樣重要。在多插槽或 NUMA 系統中,可以在不同節點自由移動的容器,每次運行可能面對不同的記憶體延遲及快取局部性。只有在量度顯示有益時才應固定位置,因為過度嚴格的 CPU 或 NUMA 配置會降低可排程性。應記錄 cpuset 設定、記憶體位置、中斷親和性與工作負載延遲目標之間的關係。如果設計包含 Kubernetes,可參閱 Dataplugs 關於 執行 Kubernetes 的專屬伺服器型號建議的指南,了解如何按叢集角色配對 CPU 拓撲、記憶體容量、NVMe 儲存及網絡行為。

監察及測試資源邊界

監控應同時展示使用量及是否受到限制。把 CPU 使用量與節流秒數並列,把記憶體使用量與記憶體事件及 OOM 終止並列,再把 I/O 吞吐量與延遲及佇列深度並列。Kubernetes 應結合節點、Pod 及容器指標;獨立主機則應加入 systemd slice 及執行環境統計。只顯示使用率的儀表板,可能看不出工作負載已在被節流。

  • 要有意測試競爭情況。在非生產環境執行受控 CPU 壓力、記憶體配置、程序建立或 I/O 工作,確認目標工作負載仍符合服務目標。驗證故障訊號、重啟行為、日誌訊息、警報及恢復時間。同時測試相反情況:移除人為壓力後,確認工作負載能再次使用獲准的突發容量,而不是永久處於節流狀態。
  • 把資源政策與應用程式發布放在一起。把 cgroup 設定、節點標籤、執行環境旗標及監控規則一併版本化,並記錄每次改變限制的原因。審查人員應能回答量度了哪項工作負載、要防止哪種故障,以及哪個警報會發現錯誤數值。當團隊由 cgroup v1 遷移至 v2 或更換容器執行環境時,這點尤其重要。

利用結果作容量規劃。經常觸及的限制可能表示需要調校應用程式、增加節點、把工作負載移到更大型的裸機配置,或改變排程類別。未檢查競爭情況便提高限制,只會把瓶頸移到另一處。更改硬件或政策前,應一併檢視飽和、節流、OOM 事件、排隊及恢復時間。

總結

容器資源限制及 cgroups 把裸機容量轉化為一組受控且可量度的運行範圍。最穩健的設計會分開處理 CPU、記憶體、程序、I/O 及裝置問題;區分基本容量與上限;為主機保留餘裕;驗證產生的階層;並測試觸及邊界時應出現的行為。

Dataplugs 專屬伺服器提供硬件隔離及管理權限,讓團隊可以為容器化應用程式調校這些控制。至於部署及可觀察性所需的營運工具,可參閱 Dataplugs 關於 以 Prometheus 及 Grafana 監察伺服器健康狀況的文章,並把資源政策版本化,隨工作負載變化定期檢討。

如需了解更多專屬伺服器基礎設施資料,請瀏覽 Dataplugs 網站或聯絡 sales@dataplugs.com。

主頁 » 最新消息 » 專屬伺服器 » 裸機伺服器上的容器資源限制與 cgroups