本文已超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

Kubernetes 1.28:Linux 上使用交換空間的 Beta 支援

1.22 版本引入了 Alpha 支援,可在每個節點的基礎上,為在 Linux 上執行的 Kubernetes 工作負載配置交換記憶體使用量。現在,在 1.28 版本中,Linux 節點上的交換記憶體支援已升級至 Beta 版,並進行了許多新的改進。

在 1.22 版本之前,Kubernetes 不支援 Linux 系統上的交換記憶體。這是因為當涉及交換記憶體時,很難保證和計算 Pod 記憶體使用率。因此,交換記憶體支援在 Kubernetes 的初始設計中被認為超出範圍,並且 kubelet 的預設行為是,如果在節點上偵測到交換記憶體,則無法啟動。

在 1.22 版本中,Linux 的交換功能最初在其 Alpha 階段引入。這代表著重大的進展,為 Linux 使用者提供了首次試驗交換功能的機會。然而,作為 Alpha 版本,它尚未完全開發,並且存在一些問題,包括對 cgroup v2 的支援不足、指標和摘要 API 統計資訊不足、測試不足等等。

Kubernetes 中的交換記憶體對於廣泛的使用者來說有許多使用案例。因此,Kubernetes 專案中的節點特殊興趣小組已投入大量精力來支援 Linux 節點上的交換記憶體以用於 Beta 版。與 Alpha 版相比,kubelet 對於啟用交換記憶體執行的支援更穩定、更強大、更使用者友善,並解決了許多已知的缺點。這次升級到 Beta 版代表著朝著完全支援 Kubernetes 中的交換記憶體目標邁出的關鍵一步。

我該如何使用它?

在已配置交換記憶體的節點上使用交換記憶體,可以透過在 kubelet 上啟用 NodeSwap 功能閘道來實現。此外,您必須停用 failSwapOn 組態設定,或者必須停用已棄用的 --fail-swap-on 命令列旗標。

可以配置 memorySwap.swapBehavior 選項,以定義節點使用交換記憶體的方式。例如,

# this fragment goes into the kubelet's configuration file
memorySwap:
  swapBehavior: UnlimitedSwap

swapBehavior 的可用組態選項為

  • UnlimitedSwap(預設):Kubernetes 工作負載可以使用與其請求一樣多的交換記憶體,最高可達系統限制。
  • LimitedSwap:Kubernetes 工作負載對交換記憶體的使用受到限制。只有 Burstable QoS 的 Pod 才允許使用交換記憶體。

如果未指定 memorySwap 的組態且功能閘道已啟用,則預設情況下,kubelet 將應用與 UnlimitedSwap 設定相同的行為。

請注意,NodeSwap 僅支援 cgroup v2。對於 Kubernetes v1.28,不再支援將交換記憶體與 cgroup v1 一起使用。

使用 kubeadm 安裝啟用交換記憶體的叢集

開始之前

此示範需要安裝 kubeadm 工具,請按照 kubeadm 安裝指南中概述的步驟進行。如果節點上已啟用交換記憶體,則可以繼續建立叢集。如果未啟用交換記憶體,請參閱提供的說明以啟用交換記憶體。

建立交換檔案並開啟交換記憶體

我將示範建立 4GiB 的未加密交換記憶體。

dd if=/dev/zero of=/swapfile bs=128M count=32
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
swapon -s # enable the swap file only until this node is rebooted

若要在啟動時啟動交換檔案,請將類似 /swapfile swap swap defaults 0 0 的行新增至 /etc/fstab 檔案。

設定使用啟用交換記憶體節點的 Kubernetes 叢集

為了更清楚起見,以下是啟用交換記憶體叢集的範例 kubeadm 組態檔案 kubeadm-config.yaml

---
apiVersion: "kubeadm.k8s.io/v1beta3"
kind: InitConfiguration
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
failSwapOn: false
featureGates:
  NodeSwap: true
memorySwap:
  swapBehavior: LimitedSwap

然後使用 kubeadm init --config kubeadm-config.yaml 建立單節點叢集。在初始化期間,會有一個警告,指出節點上已啟用交換記憶體,並且在 kubelet failSwapOn 設定為 true 的情況下。我們計劃在未來的版本中移除此警告。

LimitedSwap 的交換記憶體限制是如何確定的?

交換記憶體的組態,包括其限制,提出了一個重大挑戰。它不僅容易配置錯誤,而且作為系統級屬性,任何配置錯誤都可能危及整個節點,而不僅僅是特定的工作負載。為了減輕這種風險並確保節點的健康狀況,我們在 Beta 版中實作了交換記憶體,並自動配置了限制。

使用 LimitedSwap 時,不屬於 Burstable QoS 分類的 Pod(即 BestEffort/Guaranteed QoS Pod)禁止使用交換記憶體。BestEffort QoS Pod 表現出不可預測的記憶體消耗模式,並且缺乏有關其記憶體使用情況的資訊,因此難以確定交換記憶體的安全分配。相反地,Guaranteed QoS Pod 通常用於依賴工作負載指定的精確資源分配的應用程式,並且記憶體是立即可用的。為了維護上述安全性和節點健康保證,當 LimitedSwap 生效時,不允許這些 Pod 使用交換記憶體。

在詳細說明交換記憶體限制的計算之前,有必要定義以下術語

  • nodeTotalMemory:節點上可用的實體記憶體總量。
  • totalPodsSwapAvailable:節點上可用於 Pod 的交換記憶體總量(某些交換記憶體可能保留供系統使用)。
  • containerMemoryRequest:容器的記憶體請求。

交換記憶體限制配置為:(containerMemoryRequest / nodeTotalMemory) × totalPodsSwapAvailable

換句話說,容器能夠使用的交換記憶體量與其記憶體請求、節點的實體記憶體總量以及節點上可用於 Pod 的交換記憶體總量成比例。

重要的是要注意,對於 Burstable QoS Pod 內的容器,可以透過指定等於記憶體限制的記憶體請求來選擇不使用交換記憶體。以這種方式配置的容器將無法存取交換記憶體。

它是如何運作的?

關於節點上的交換記憶體使用,有許多可能的設想方式。當交換記憶體已在節點上配置且可用時,SIG Node 建議 kubelet 應可配置為

  • 它可以從啟用交換記憶體開始。
  • 依預設,它會指示容器執行階段介面為 Kubernetes 工作負載分配零交換記憶體。

節點上的交換記憶體配置透過 KubeletConfiguration 中的 memorySwap 公開給叢集管理員。作為叢集管理員,您可以透過設定 memorySwap.swapBehavior 來指定節點在存在交換記憶體時的行為。

kubelet 採用 CRI(容器執行階段介面)API 來指示 CRI 配置特定的 cgroup v2 參數(例如 memory.swap.max),以實現容器所需的交換記憶體配置。然後,CRI 負責將這些設定寫入容器層級的 cgroup。

我該如何監控交換記憶體?

Alpha 版本的一個顯著缺陷是無法監控和內省交換記憶體使用情況。Kubernetes 1.28 中引入的 Beta 版本已解決此問題,現在透過幾種不同的方法提供了監控交換記憶體使用情況的功能。

kubelet 的 Beta 版本現在收集節點層級的指標統計資訊,可以從 /metrics/resource/stats/summary kubelet HTTP 端點存取。這允許可以直接查詢 kubelet 的用戶在使用 LimitedSwap 時監控交換記憶體使用情況和剩餘交換記憶體。此外,cadvisor 中新增了 machine_swap_bytes 指標,以顯示機器的實體交換記憶體總容量。

注意事項

系統上提供交換記憶體會降低可預測性。交換記憶體的效能比一般記憶體差,有時差幾個數量級,這可能會導致意外的效能衰退。此外,交換記憶體會改變系統在記憶體壓力下的行為。由於啟用交換記憶體允許 Kubernetes 中無法預測地計算的工作負載使用更多的記憶體,因此也會增加雜訊鄰居和意外封裝配置的風險,因為排程器無法計算交換記憶體使用量。

啟用交換記憶體的節點效能取決於底層實體儲存裝置。當使用交換記憶體時,在每秒 I/O 運算次數 (IOPS) 受限的環境(例如具有 I/O 節流的雲端 VM)中,效能將會顯著降低,而與固態硬碟或 NVMe 等更快的儲存媒體相比。

因此,我們不建議在受效能限制的工作負載或環境中使用交換記憶體。此外,建議使用 LimitedSwap,因為這可以顯著減輕對節點造成的風險。

叢集管理員和開發人員應在生產環境情境中使用交換記憶體之前,對其節點和應用程式進行基準測試,並且我們需要您的協助

安全性風險

在未加密的系統上啟用交換記憶體會帶來安全性風險,因為重要資訊(例如代表 Kubernetes Secret 的磁碟區)可能會交換到磁碟。如果未經授權的人員存取磁碟,他們可能會取得這些機密資料。為了減輕這種風險,Kubernetes 專案強烈建議您加密交換空間。但是,處理加密的交換記憶體不在 kubelet 的範圍內;相反地,這是一個一般的作業系統組態問題,應在該層級解決。管理員有責任配置加密的交換記憶體以減輕此風險。

此外,如前所述,使用 LimitedSwap,使用者可以選擇透過指定等於記憶體限制的記憶體請求,完全停用容器的交換記憶體使用。這將防止相應的容器存取交換記憶體。

展望未來

Kubernetes 1.28 版本引入了 Linux 節點上交換記憶體的 Beta 支援,我們將繼續努力朝著此功能的正式發布邁進。我希望這將包括

  • 新增從 kubelet 在主機上偵測到的交換記憶體中設定系統保留數量的能力。
  • 新增透過 cgroup 控制 Pod 層級交換記憶體消耗量的支援。
    • 這一點仍在討論中。
  • 收集來自測試使用者案例的回饋。
    • 我們將考慮為交換記憶體引入新的組態模式,例如工作負載的全節點交換記憶體限制。

我該如何瞭解更多資訊?

您可以檢閱目前關於搭配 Kubernetes 使用交換記憶體的文件

如需更多資訊,以及協助測試和提供回饋,請參閱 KEP-2400 及其設計提案

我該如何參與?

隨時歡迎您的回饋!SIG Node 定期舉行會議,並且可以透過 Slack (頻道 #sig-node) 或 SIG 的 郵寄清單 聯絡。專用於交換記憶體的 Slack 頻道也位於 #sig-node-swap

如果您想提供協助或提出進一步的問題,請隨時與我 Itamar Holder (Slack 和 GitHub 上的 @iholder101) 聯繫。