排解 GKE 儲存空間問題

Google Kubernetes Engine (GKE) 叢集的儲存空間問題可能以多種方式呈現,包括效能瓶頸、磁碟區掛接失敗,以及特定磁碟類型與特定機型搭配使用時發生錯誤。這些問題可能會影響應用程式的狀態、資料持續性,以及整體工作負載健康狀態。

本文說明如何解決叢集儲存功能常見問題。瞭解如何排解磁碟區佈建和連結、資料存取和效能,以及儲存空間容量管理等相關問題。

對於管理叢集基礎架構和儲存空間的平台管理員和營運人員,以及工作負載依賴永久儲存空間的應用程式開發人員而言,這項資訊非常重要。如要進一步瞭解 Google Cloud 內容中提及的常見角色和範例工作,請參閱「常見的 GKE 使用者角色和工作」。

錯誤 400:無法將 RePD 附加至最佳化 VM

區域永久磁碟限制與記憶體最佳化機器或運算最佳化機器搭配使用。

如果並非一定要使用區域性永久磁碟,建議您使用非區域性永久磁碟儲存空間類別。如果必須使用區域性永久磁碟,請考慮採用污點和容忍等排程策略,確保需要區域性永久磁碟的 Pod 排定在非最佳化機器的節點集區中。

排解磁碟效能問題

開機磁碟的效能很重要,因為 GKE 節點的開機磁碟不僅用於作業系統,還用於下列用途:

  • Docker 映像檔。
  • 未以磁碟區形式掛接的容器檔案系統 (即疊加檔案系統),通常包含 /tmp 等目錄。
  • 磁碟支援的 emptyDir 磁碟區,除非節點使用本機 SSD。

節點上所有相同磁碟類型的磁碟會共用磁碟效能。舉例來說,如果您有 100 GB 的 pd-standard 開機磁碟,以及 100 GB 的 pd-standard PersistentVolume,且有大量活動,則開機磁碟的效能會是 200 GB 磁碟的效能。此外,如果 PersistentVolume 上有大量活動,也會影響開機磁碟的效能。

如果節點上出現類似下列內容的訊息,可能是磁碟效能不佳的徵兆:

INFO: task dockerd:2314 blocked for more than 300 seconds.
fs: disk usage and inodes count on following dirs took 13.572074343s
PLEG is not healthy: pleg was last seen active 6m46.842473987s ago; threshold is 3m0s

如要解決這類問題,請參閱下列說明:

由於 fsGroup 設定,掛接磁碟區停止回應

如果 Pod 設有 fsGroup 設定,可能會導致 PersistentVolume 掛接失敗。一般來說,掛接作業會自動重試,並自行解決掛接失敗的問題。不過,如果 PersistentVolume 含有大量檔案,kubelet 會嘗試變更檔案系統中每個檔案的擁有權,這可能會增加磁碟區掛接延遲時間。

Unable to attach or mount volumes for pod; skipping pod ... timed out waiting for the condition

如要確認掛接失敗錯誤是否是由 fsGroup 設定所致,請檢查 Pod 的記錄。如果問題與 fsGroup 設定有關,您會看到下列記錄項目:

Setting volume ownership for /var/lib/kubelet/pods/POD_UUID and fsGroup set. If the volume has a lot of files then setting volume ownership could be slow, see https://github.com/kubernetes/kubernetes/issues/69699

如果 PersistentVolume 未在幾分鐘內掛接,請嘗試下列步驟解決問題:

磁碟作業緩慢,導致 Pod 建立失敗

詳情請參閱 containerd 問題 #4604。

受影響的 GKE 節點版本:1.18、1.19、1.20.0 至 1.20.15-gke.2100、1.21.0 至 1.21.9-gke.2000、1.21.10 至 1.21.10-gke.100、1.22.0 至 1.22.6-gke.2000、1.22.7 至 1.22.7-gke.100、1.23.0 至 1.23.3-gke.700、1.23.4 至 1.23.4-gke.100

下列範例錯誤可能會顯示在 k8s_node container-runtime 記錄中:

Error: failed to reserve container name "container-name-abcd-ef12345678-91011_default_12131415-1234-5678-1234-12345789012_0": name "container-name-abcd-ef12345678-91011_default_12131415-1234-5678-1234-12345789012_0" is reserved for "1234567812345678123456781234567812345678123456781234567812345678"

緩解措施

  1. 如果 Pod 失敗,請考慮在 PodSpec 中使用 restartPolicy:Always 或 restartPolicy:OnFailure。
  2. 提高開機磁碟 IOPS (例如升級磁碟類型或增加磁碟大小)。

修正

這個問題已在 containerd 1.6.0 以上版本中修正。包含這項修正的 GKE 版本為 1.20.15-gke.2100+、1.21.9-gke.2000+、1.21.10-gke.100+、1.22.6-gke.2000+、1.22.7-gke.100+、1.23.3-gke.1700+ 和 1.23.4-gke.100+

磁碟區擴充變更未反映在容器檔案系統中

執行磁碟區擴充作業時,請務必更新 PersistentVolumeClaim。直接變更 PersistentVolume 可能會導致磁碟區無法擴充。這可能會導致下列其中一種情況:

  • 如果直接修改 PersistentVolume 物件,PersistentVolume 和 PersistentVolumeClaim 值都會更新為新值,但檔案系統大小不會反映在容器中,仍會使用舊的磁碟區大小。

  • 如果直接修改 PersistentVolume 物件,然後更新 PersistentVolumeClaim,將 status.capacity 欄位更新為新的大小,可能會導致 PersistentVolume 變更,但 PersistentVolumeClaim 或容器檔案系統不會變更。

如要解決這個問題,請完成下列步驟:

  1. 保留修改後的 PersistentVolume 物件。
  2. 編輯 PersistentVolumeClaim 物件,並將 spec.resources.requests.storage 設為高於 PersistentVolume 中使用的值。
  3. 確認 PersistentVolume 是否已調整為新值。

完成這些變更後,kubelet 應會自動調整 PersistentVolume、PersistentVolumeClaim 和容器檔案系統的大小。

確認變更是否已反映在 Pod 中。

kubectl exec POD_NAME  -- /bin/bash -c "df -h"

將 POD_NAME 替換為附加至 PersistentVolumeClaim 的 Pod。

所選機型應具備本機 SSD

建立使用本機 SSD 的叢集或節點集區時,可能會遇到下列錯誤:

The selected machine type (c3-standard-22-lssd) has a fixed number of local SSD(s): 4. The EphemeralStorageLocalSsdConfig's count field should be left unset or set to 4, but was set to 1.

在錯誤訊息中,您可能會看到 LocalNvmeSsdBlockConfig 而不是 EphemeralStorageLocalSsdConfig,具體取決於您指定的內容。

如果指定的本機 SSD 磁碟數量與機器類型隨附的本機 SSD 磁碟數量不符,就會發生這個錯誤。

如要解決這個問題,請指定與所需機型相符的本機 SSD 磁碟數量。如果是第 3 代機器系列,您必須省略本機 SSD count 標記,系統會自動設定正確的值。

Hyperdisk 儲存空間集區:無法建立叢集或節點集區

嘗試在 Hyperdisk 儲存空間集區中,將 Hyperdisk Balanced 磁碟佈建為節點的開機磁碟或附加磁碟時,可能會遇到 ZONE_RESOURCE_POOL_EXHAUSTED 錯誤或類似的 Compute Engine 資源錯誤。

當您嘗試在資源不足的可用區中建立 GKE 叢集或節點集區時,就會發生這種情況,例如:

  • 該可用區的 Hyperdisk Balanced 磁碟可能不足。
  • 可用區的容量可能不足,無法建立您指定的機器類型節點,例如 c3-standard-4。

如何解決這個問題:

  1. 在相同區域內選取新的可用區,該可用區必須有足夠容量,可容納所選機器類型,且提供 Hyperdisk Balanced 儲存空間集區。
  2. 刪除現有儲存空間集區,然後在新區域重新建立。這是因為儲存空間集區是可用區資源。
  3. 在新可用區中建立叢集或節點集區。

偵測到節點儲存空間壓力偏高

StoragePressureRootFileSystemStoragePressureDetected

使用 kubectl describe node NODE_NAME 指令描述節點時,您可能會看到類似下列的事件:

Events:
  Type     Reason                      Age   From                     Message
  ----     ------                      ----  ----                     -------
  ...
  Warning  StoragePressureDetected     46m   device-capacity-monitor  Node condition StoragePressureRootFileSystem is now: True, reason: StoragePressureDetected, message: "Disk /dev/nvme0n1 usage 89% exceeds threshold 85%"

原因:

StoragePressureDetected 原因表示節點根檔案系統 (通常是 mnt/stateful_partition 或相關掛接點) 的磁碟用量已超過預先定義的門檻 (例如 85%)。可能原因如下:

  • 工作負載將過多資料寫入未由本機 SSD 支援的 emptyDir 磁碟區。
  • 將大型容器映像檔提取至節點。
  • 節點上累積的記錄檔。
  • 其他占用磁碟空間的程序。

如果磁碟使用率持續偏高,可能會導致節點不穩定、Pod 遭逐出,以及應用程式故障。

偵錯與解決:

找出磁碟用量:使用 SSH 連線至受影響的節點,並使用 df -h 等指令檢查各個掛接點的磁碟用量,特別注意 /mnt/stateful_partition 和任何臨時儲存空間掛接點。

分析工作負載儲存空間模式:查看節點上執行的 Pod 的儲存空間要求和使用模式。找出是否有任何特定工作負載耗用過多暫時性儲存空間。

增加節點儲存空間容量:請注意,主要解決方法通常是確保節點有足夠的儲存空間容量來處理工作負載。請考量下列事項:

  • 使用較大的開機磁碟:建立節點集區時,如果工作負載在根檔案系統上需要更多臨時儲存空間,請選取較大的開機磁碟。
  • 使用較大的本機 SSD 做為臨時儲存空間:如要處理需要高效能、低延遲臨時儲存空間的工作負載,請將節點集區設定為使用本機 SSD。這會為 emptyDir 磁碟區提供獨立且更大的容量。
  • 調整工作負載要求或限制:確認 Pod 規格包含適當的暫時性儲存空間要求和限制,協助排程器將 Pod 放置在空間充足的節點上,並防止磁碟用量暴增。
  • 清除未使用的資源:如果節點中不必要的檔案、舊容器映像檔或記錄導致磁碟用量過高,請移除這些項目。

只要解決節點的儲存空間容量和用量問題,就能減少與 StoragePressureDetected 相關的問題,並協助節點運作。

排解 Cloud Storage FUSE 記憶體不足 (OOM) 事件

如果 Pod 發生記憶體使用率偏高或記憶體不足 (OOM) 事件,且與 Cloud Storage FUSE CSI 驅動程式有關,您可以使用 Cloud Profiler 收集及分析 CPU 和記憶體快照。在「設定 Cloud Storage FUSE CSI 驅動程式邊車容器」中設定這些選項。

當 Pod 發生 OOM 終止事件時,您可以按照下列工作流程,將事件與正確的 Cloud Profiler 快照建立關聯:

  1. 檢查 Cloud Logging:前往 Cloud Logging 尋找 Kubernetes OOM 事件。
  2. 依 Pod 名稱篩選:執行下列查詢,找出特定 Pod 的事件記錄,並將 POD_NAME 替換為工作負載 Pod 的名稱:

    jsonPayload.involvedObject.name="POD_NAME"
    jsonPayload.involvedObject.kind="Pod"
    OOMKilled
    
  3. 擷取 Pod UID:展開相關的 OOM 事件記錄,並記下時間戳記和位於 jsonPayload.involvedObject.uid 的確切 Pod UID。

  4. 在 Cloud Profiler 中進行分析:前往 Cloud Profiler,使用 POD_NAME_POD_UID 格式篩選「服務版本」,並調整日期範圍,與 OOM 時間戳記相符。這樣一來,您就能確保查看的是特定容器執行個體在終止前的確切記憶體設定檔。

後續步驟