排解叢集自動配置器未縮減的問題

如果 Google Kubernetes Engine (GKE) 節點未如預期縮減,通常是因為叢集自動調度器無法移除節點,導致產生不必要的費用,且資源使用效率不彰。

本頁說明如何診斷及解決常見問題,避免叢集自動調度器無法執行縮減作業。排解這些問題,有助於確保叢集以符合成本效益的方式運作,並因應工作負載變化。

這項資訊對平台管理員和營運人員來說非常重要,因為他們負責叢集效率、成本最佳化和資源管理。如果應用程式開發人員的工作負載設定 (例如 PodDisruptionBudgets 或節點選取器) 無意間阻止節點移除,他們可能也需要這項資訊。如要進一步瞭解 Google Cloud 內容中提及的常見角色和工作範例,請參閱「常見的 GKE 使用者角色和工作」。

瞭解叢集自動配置器何時會縮減節點

繼續進行疑難排解步驟前,建議先瞭解叢集自動配置器何時會嘗試縮減節點。叢集自動配置器可能不需要縮減規模,因此未執行這項作業。

叢集自動調度器會計算使用率係數,判斷節點是否使用率過低,且符合縮減條件。使用率係數的計算方式,是將節點上 Pod 要求的 vCPU 和記憶體,除以節點上可分配的 vCPU 和記憶體。

叢集自動配置器每 10 秒會檢查節點的使用率係數,確認是否低於必要門檻。如果使用 balanced 自動調度資源設定檔,使用率係數門檻為 0.5。如果您使用 optimize-utilization 設定檔,利用率會有所不同。如果 vCPU 和記憶體的使用率係數都低於必要門檻,叢集自動配置器就會判定節點使用率偏低。

如果節點使用率過低,叢集自動調度器會標記要移除的節點,並在接下來 10 分鐘內監控該節點,確保使用率維持在必要門檻以下。如果節點在 10 分鐘後仍未充分利用,叢集自動配置器應會移除該節點。

範例:計算使用率係數

您有一個叢集,且已啟用叢集自動配置器功能,並使用 balanced 自動調度資源設定檔。這個叢集上的節點是使用 e2-standard-4 機型佈建,提供 4 個 vCPU 和 16 GB 的記憶體。這個節點上的 Pod 要求 0.5 個 vCPU 和 10 GB 的記憶體,因此叢集自動調度器會計算下列利用率因素:

  • vCPU 使用率係數:0.5 個 vCPU / 4 個 vCPU = 0.125
  • 記憶體使用率係數:10 GB / 16 GB = 0.625

在這種情況下,叢集自動配置器不會將這個節點視為使用率偏低,因為記憶體使用率係數 (0.625) 超過 0.5 的門檻。雖然 vCPU 使用率偏低,但記憶體用量較高,因此系統不會縮減資源,確保 Pod 的工作負載有足夠的可用資源。

確認問題是否因限制而起

如果叢集使用率偏低超過 10 分鐘,且未縮減規模,請確認問題並非由叢集自動配置器的限制所導致。

查看錯誤

如果問題並非限制所致,通常只要查看錯誤訊息,即可診斷原因:

查看通知中的錯誤

如果觀察到的問題發生在 72 小時內,請在 Google Cloud 控制台中查看錯誤通知。這些通知可提供實用洞察資訊,說明叢集自動配置器無法縮減的原因,並提供解決錯誤的建議,以及查看相關記錄以進行深入調查。

如要在 Google Cloud 控制台中查看通知,請完成下列步驟:

  1. 前往 Google Cloud 控制台的「Kubernetes clusters」(Kubernetes 叢集) 頁面。

    前往 Kubernetes 叢集

  2. 查看「通知」欄。下列通知與縮減問題相關:

    • Can't scale down nodes
    • Scale down blocked by pod
  3. 按一下相關通知,即可查看窗格,瞭解問題原因和建議的解決方法。

  4. 選用:如要查看這項事件的記錄,請按一下「記錄」。這項動作會將您帶往 Logs Explorer,並預先填入查詢內容,協助您進一步調查調整資源配置事件。如要進一步瞭解縮減事件的運作方式,請參閱「查看叢集自動配置器事件」。

如果參閱通知中的建議後仍遇到問題,請參閱錯誤訊息表,取得進一步協助。

查看事件中的錯誤

如果觀察到的問題發生在 72 小時前,請在 Cloud Logging 中查看事件。發生錯誤時,系統通常會記錄在事件中。

如要在 Google Cloud 控制台中查看叢集自動調度資源記錄檔,請完成下列步驟:

  1. 在 Google Cloud 控制台中,前往「Kubernetes clusters」(Kubernetes 叢集) 頁面。

    前往 Kubernetes 叢集

  2. 選取要調查的叢集名稱,即可查看「叢集詳細資料」頁面。

  3. 在「Cluster details」(叢集詳細資料) 頁面中,按一下「Logs」(記錄) 分頁標籤。

  4. 在「記錄」分頁中,按一下「自動調整規模記錄」分頁,即可查看記錄。

  5. 選用:如要套用更進階的篩選器來縮小結果範圍,請按一下頁面右側有箭頭的按鈕,在記錄檔探索工具中查看記錄。

如要進一步瞭解縮減事件的運作方式,請參閱「查看叢集自動配置器事件」。如要瞭解如何使用 Cloud Logging,請參閱下列疑難排解範例。

範例:排解超過 72 小時的問題

以下範例說明如何調查及解決叢集未縮減的問題。

情境:

一週前,您查看 GKE 資訊主頁時,發現叢集只使用了 10% 的 CPU 和記憶體。儘管使用率偏低,叢集自動配置器並未如預期刪除節點。現在查看資訊主頁時,問題似乎已解決,但您決定找出問題原因,避免再次發生。

調查:

  1. 由於問題發生時間超過 72 小時,因此您使用 Cloud Logging 進行調查,而不是查看通知訊息。
  2. 在 Cloud Logging 中,您可以找到叢集自動配置器事件的記錄詳細資料,如「查看事件中的錯誤」一文所述。
  3. 您搜尋 scaleDown 事件,其中包含 nodesToBeRemoved 欄位中調查的叢集所屬節點。您可以篩選記錄項目,包括依特定 JSON 欄位值篩選。詳情請參閱「進階記錄查詢」。
  4. 找不到任何 scaleDown 事件。不過,如果確實找到 scaleDown 事件,可以搜尋包含相關聯 eventId 的 eventResult 事件。然後在 errorMsg 欄位中搜尋錯誤。
  5. 您決定繼續調查,在節點欄位中搜尋包含您要調查節點的noScaleDown事件。

    您會看到 noScaleDown 事件,其中包含節點未縮減的原因。訊息 ID 為 "no.scale.down.node.pod.not.backed.by.controller",且只有一個參數:"test-single-pod"。

解決方法:

您查閱錯誤訊息表,發現這則訊息表示 Pod 不受控制器支援,因此已封鎖縮減作業。您發現其中一個解決方案是在 Pod 中新增 "cluster-autoscaler.kubernetes.io/safe-to-evict": "true" 註解。您調查 test-single-pod,發現同事新增了註解,且套用註解後,叢集自動配置器正確縮減叢集。您決定在所有其他 Pod 中新增註解 (如果安全無虞),以免再次發生問題。

解決縮減錯誤

找出錯誤後,請參閱下表,瞭解錯誤原因和解決方法。

ScaleDown 錯誤

您可以在對應的 eventResult 事件中,於 resultInfo.results[].errorMsg 欄位找到 scaleDown 事件的錯誤事件訊息。

事件訊息 詳細資料 參數 緩解措施
"scale.down.error.failed.to.mark.to.be.deleted" 無法將節點標示為待刪除。 失敗的節點名稱。 這則訊息應該是暫時性的。 如果問題仍未解決, 請與 Cloud Customer Care 團隊聯絡, 以便進一步調查。
"scale.down.error.failed.to.evict.pods" 無法從節點中移出某些 Pod,因此叢集自動配置器無法縮減資源。 失敗的節點名稱。 查看 Pod 的 PodDisruptionBudget,並確保規則允許在可接受的情況下移出應用程式副本。詳情請參閱 Kubernetes 說明文件中的「為應用程式指定中斷預算」。
"scale.down.error.failed.to.delete.node.min.size.reached" 叢集已達到最小大小,因此叢集自動配置器無法刪除節點,也就無法縮減資源。 失敗的節點名稱。 查看為節點集區自動調度資源設定的最小值,並視需要調整設定。詳情請參閱「錯誤:叢集中的節點已達到大小下限」。

noScaleDown 事件的原因

如果叢集自動配置器無法刪除節點,系統會定期發出 noScaleDown 事件。noScaleDown 事件是盡力而為,並未涵蓋所有可能情況。

NoScaleDown 頂層原因

noScaleDown 事件的頂層原因訊息會顯示在 noDecisionStatus.noScaleDown.reason 欄位中。訊息包含頂層原因,說明叢集自動配置器無法縮減叢集的原因。

事件訊息 詳細資料 緩解措施
"no.scale.down.in.backoff" 叢集自動配置器無法縮減資源,因為縮減作業處於輪詢延遲期間 (暫時遭到封鎖)。

這則訊息應該是暫時性的,通常會在最近發生資源擴充事件時出現。

如果訊息持續顯示,請與 Cloud Customer Care 團隊聯絡,以便進一步調查。

"no.scale.down.in.progress"

叢集自動配置器無法縮減資源配置,因為先前的縮減作業仍在進行中。

這個訊息應該是暫時性的,因為 Pod 最終會移除。如果經常出現這則訊息,請檢查 Pod 終止寬限期,確認是否會阻礙縮減作業。如要加快解決速度,您也可以刪除不再需要的 Pod。

NoScaleDown 節點層級原因

節點層級的 noScaleDown 事件原因訊息會顯示在 noDecisionStatus.noScaleDown.nodes[].reason field 中。訊息會說明叢集自動配置器無法移除特定節點的原因。

事件訊息 詳細資料 參數 緩解措施
"no.scale.down.node.scale.down.disabled.annotation" 節點已加上 cluster-autoscaler.kubernetes.io/scale-down-disabled: true 註解,因此叢集自動配置器無法從節點集區中移除節點。 不適用 叢集自動配置器會略過含有這個註解的節點,不考慮其使用率,且無論節點的使用率係數為何,都會記錄這則訊息。如要讓叢集自動配置器縮減這些節點,請移除註解。
"no.scale.down.node.node.group.min.size.reached"

節點群組大小超過下限時,叢集自動配置器無法縮減資源。

這是因為移除節點會違反節點自動佈建設定中定義的整個叢集資源最低限制。

不適用 查看為節點集區自動調度資源設定的最小值。如要讓叢集自動配置器縮減這個節點,請調整最小值。
"no.scale.down.node.minimal.resource.limits.exceeded"

縮減作業會違反整個叢集的資源最低限制,因此叢集自動配置器無法縮減節點資源。

這些是為自動佈建節點設定的資源限制。

不適用 查看記憶體和 vCPU 的限制,如果您希望叢集自動配置器縮減這個節點,請降低 限制。
"no.scale.down.node.no.place.to.move.pods" 沒有可移動 Pod 的位置,因此叢集自動調度資源功能無法縮減資源。 不適用 如果您認為 Pod 應重新排程,請查看資源使用率偏低的節點上 Pod 的排程需求,判斷是否可將這些 Pod 移至叢集中的其他節點。詳情請參閱「錯誤:沒有可移動 Pod 的位置」。
"no.scale.down.node.pod.not.backed.by.controller"

Pod 不受控制器支援,因此已封鎖縮減作業。

具體來說,由於 Pod 缺少可辨識的控制器,叢集自動調度器無法縮減未充分利用的節點。允許使用的控制器包括 ReplicationController、DaemonSet、Job、StatefulSet 或 ReplicaSet。

封鎖 Pod 的名稱。 為 Pod 設定 "cluster-autoscaler.kubernetes.io/safe-to-evict": "true" 註解,或定義可接受的控制器。
"no.scale.down.node.pod.not.safe.to.evict.annotation" 節點上的 Pod 具有 safe-to-evict=false 註解。 封鎖 Pod 的名稱。 如果可以安全地撤銷 Pod,請編輯 Pod 的資訊清單,並將註解更新為 "cluster-autoscaler.kubernetes.io/safe-to-evict": "true"。
"no.scale.down.node.pod.kube.system.unmovable" Pod 不是 DaemonSet,也不是鏡像 Pod,且 kube-system 命名空間中沒有 PodDisruptionBudget,因此已封鎖縮減作業。 封鎖 Pod 的名稱。

在 1.32.4-gke.1236000 之前的 GKE 版本中,叢集自動調度器不會移除 kube-system 命名空間中的 Pod。從 1.32.4-gke.1236000 版開始,叢集自動調度器會在 Pod 建立一小時後,將這些 Pod 視為可移除的對象。

如要解決這個問題,請為 kube-system Pod 新增 PodDisruptionBudget,或使用節點集區 Taint 和容許規定的組合,將 kube-system Pod 與應用程式 Pod 分開。詳情請參閱「錯誤:kube-system Pod 無法移動」。

"no.scale.down.node.pod.not.enough.pdb" Pod 的 PodDisruptionBudget 不足,因此已封鎖縮減作業。 封鎖 Pod 的名稱。 查看 Pod 的 PodDisruptionBudget,並考慮放寬限制。詳情請參閱「錯誤:PodDisruptionBudget 不足」。
"no.scale.down.node.pod.controller.not.found" 找不到 Pod 控制器 (例如 Deployment 或 ReplicaSet),因此 Pod 已封鎖縮減作業。 不適用 如要判斷在移除控制器後,Pod 仍繼續執行的原因,請查看記錄。如要解決這個問題,請手動刪除 Pod。
"no.scale.down.node.pod.unexpected.error" 發生未預期的錯誤,因此 Pod 已封鎖縮減作業。 不適用 這個錯誤的根本原因不明。 與 Cloud Customer Care 團隊聯絡 ,以進行深入調查。

進行深入調查

下列各節提供相關指引,說明如何使用 Logs Explorer 和 gcpdiag 進一步瞭解錯誤。

在 Logs Explorer 中調查錯誤

如要進一步調查錯誤訊息,可以查看特定錯誤的記錄:

  1. 前往 Google Cloud 控制台的「Logs Explorer」頁面。

    前往 Logs Explorer

  2. 在查詢窗格中輸入下列查詢:

    resource.type="k8s_cluster"
    log_id("container.googleapis.com/cluster-autoscaler-visibility")
    jsonPayload.resultInfo.results.errorMsg.messageId="ERROR_MESSAGE"
    

    將 ERROR_MESSAGE 替換為要調查的訊息。例如:scale.down.error.failed.to.delete.node.min.size.reached。

  3. 點選「執行查詢」。

使用 gcpdiag 偵錯部分錯誤

gcpdiag 是在 Google Cloud技術工程師支援下建立的開放原始碼工具。這並非官方支援的 Google Cloud 產品。

如果收到下列任一則錯誤訊息,請使用 gcpdiag 排解問題:

  • scale.down.error.failed.to.evict.pods
  • no.scale.down.node.node.group.min.size.reached

如需所有 gcpdiag 工具標記的清單和說明,請參閱 gcpdiag 使用說明。

解決複雜的縮減錯誤

下列各節將提供指南,協助解決需要多個步驟才能緩解的錯誤,以及沒有相關聯叢集自動調度器事件訊息的錯誤。

錯誤:叢集中的節點已達大小下限

如果看到下列錯誤,表示叢集自動配置器無法刪除節點,因為叢集中的節點數量已達下限:

通知

叢集自動配置器已達到資源下限,因此未充分運用節點的縮減作業已遭封鎖。

事件

"scale.down.error.failed.to.delete.node.min.size.reached"

如要解決這個問題,請查看並更新自動調度資源的最低限制:

  1. 在 Google Cloud 控制台中,前往「Kubernetes clusters」(Kubernetes 叢集) 頁面:

    前往「Kubernetes clusters」(Kubernetes 叢集)

  2. 按一下通知或 Cloud Logging 中指出的叢集名稱。

  3. 在「叢集詳細資料」頁面中,前往「節點」分頁。

  4. 查看「節點數量」欄中的值,並與「自動調度資源」欄中列出的節點數量下限比較。舉例來說,如果「自動調度資源」Autoscaling欄中列出 4 到 6 個節點,且節點集區中的節點數量為 4,則節點集區的數量已達到下限,因此叢集自動配置器無法進一步縮減節點數量。

  5. 如果設定正確,且節點數量值等於為自動調度資源定義的最小值,則叢集自動配置器會正常運作。如果節點數量下限過高,不符合您的需求,請調低下限,讓節點可以縮減。

錯誤:沒有可移動 Pod 的位置

叢集自動配置器嘗試縮減節點,但因該節點上的 Pod 無法移至其他節點而失敗時,會發生下列錯誤:

通知

未充分運用的節點含有無法移至叢集中其他節點的 Pod,因此該節點的縮減作業已遭封鎖。

事件

"no.scale.down.node.no.place.to.move.pods"

如果不想重新排定這個 Pod 的時間,則會出現這則訊息,且不需要進行任何變更。如果想重新排定 Pod 的排程,請在 Pod 的資訊清單中,檢查 pod.spec block 的下列定義:

  • NodeAffinity:查看使用率偏低節點上 Pod 的排程需求。您可以檢查 Pod 資訊清單,找出任何 NodeAffinity 或 NodeSelector 規則,藉此查看這些需求。如果 Pod 定義了 nodeSelector,且叢集中沒有其他節點 (來自其他節點集區) 符合這個選取器,叢集自動配置器就無法將 Pod 移至其他節點,進而無法移除任何使用率偏低的節點。
  • maxPodConstraint:如果 maxPodConstraint 設為預設值 110 以外的任何其他數字,請確認這是否為預期變更。降低這個值會增加發生問題的可能性。 如果叢集中的所有其他節點都已達到 maxPodConstraint 中定義的值,叢集自動配置器就無法將 Pod 重新排程至其他節點,導致無法排程新的 Pod。增加 maxPodConstraint 值可讓節點排程更多 Pod,叢集自動配置器也會有空間重新排程 Pod,並縮減未充分利用的節點。定義 maxPodConstraint 時,請注意每個節點約有 10 個系統 Pod。
  • hostPort:為 Pod 指定 hostPort,表示該節點只能執行一個 Pod。這可能會導致叢集自動配置器難以減少節點數量,因為如果節點的連接埠已在使用中,Pod 可能就無法移至其他節點。請放心,這是正常情況。
  • 暫時儲存空間:Pod 會使用暫時儲存空間儲存臨時資料。如果節點的臨時儲存空間不足,可能會導致 Pod 排程失敗,以及未充分運用的節點無法縮減。範例:如果 Pod 需要 6 GB 的臨時儲存空間,即使節點有足夠的 CPU 和記憶體資源,只要臨時儲存空間少於 6 GB,系統就無法安排該 Pod 的時程。如要解決暫時儲存空間限制,請增加節點的佈建暫時儲存空間容量。確保 Pod 重新安置和資源調度作業有足夠的容量。

錯誤:kube-system Pod 無法移動

如果系統 Pod 阻礙縮減作業,就會發生下列錯誤:

通知

Pod 不是 DaemonSet,也不是鏡像 Pod,且 kube-system 命名空間中沒有 PodDisruptionBudget,因此已封鎖縮減作業。

事件

"no.scale.down.node.pod.kube.system.unmovable"

kube-system 命名空間中的 Pod 會視為系統 Pod。在 GKE 1.32.4-gke.1236000 以上版本中,叢集自動調度器可以驅逐已執行至少一小時的系統 Pod,藉此縮減節點。在舊版 GKE 中,叢集自動調度器不會移除 kube-system 命名空間中的 Pod,這可能會導致無限期縮減規模。

如要解決這項錯誤,請選擇下列任一解決方法:

  • 為 kube-system Pod 新增 PodDisruptionBudget。如要進一步瞭解如何手動為 Pod 新增 PodDisruptionBudget kube-system,請參閱「Kubernetes 叢集自動配置器常見問題」。

    建立 PodDisruptionBudget 可能會影響系統工作負載的可用性,進而導致叢集停機。叢集自動調度器會在縮減資源程序期間,將這些系統工作負載重新排定至其他工作站節點。

  • 使用節點集區 taint 和容許條件 (例如 workload=stateful:NoSchedule),將 kube-system Pod 與應用程式 Pod 分開。建議您對批次或有狀態工作負載採用這種方法,讓 kube-system Pod 遠離這些節點,避免發生串聯延遲問題。這樣一來,節點就能縮減,不會遭到封鎖。詳情請參閱「GKE 中的自動佈建節點」。

確認節點有 kube-system 個 Pod

如果不確定節點是否正在執行 kube-system Pod,並想進行驗證,請完成下列步驟:

  1. 前往 Google Cloud 控制台的「Logs Explorer」頁面。

    前往 Logs Explorer

  2. 按一下「查詢建立工具」。

  3. 使用下列查詢,找出所有網路政策記錄:

    - resource.labels.location="CLUSTER_LOCATION"
    resource.labels.cluster_name="CLUSTER_NAME"
    logName="projects/PROJECT_ID/logs/container.googleapis.com%2Fcluster-autoscaler-visibility"
    jsonPayload.noDecisionStatus.noScaleDown.nodes.node.mig.nodepool="NODE_POOL_NAME"
    

    更改下列內容:

    • CLUSTER_LOCATION:叢集所在的區域。
    • CLUSTER_NAME:叢集名稱。
    • PROJECT_ID:叢集所屬專案的 ID。
    • NODE_POOL_NAME:節點集區的名稱。

    如果節點集區上執行 kube-system Pod,輸出內容會包含下列項目:

    "no.scale.down.node.pod.kube.system.unmovable"
    

錯誤:PodDisruptionBudget不足

如果 PodDisruptionBudget 阻礙縮減作業,就會發生下列錯誤:

通知

未充分運用的節點含有執行中的 Pod,但 Pod 的 Pod disruption budget 不足,無法剔除,因此該節點的縮減作業已遭封鎖。

事件

NoScaleDownNodePodNotEnoughPdb: "no.scale.down.node.pod.not.enough.pdb"

如要查看「PodDisruptionBudget」是否過於嚴格,請檢查其設定:

kubectl get pdb --all-namespaces

輸出結果會與下列內容相似:

NAMESPACE        NAME    MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
example-app-one  one_pdb       N/A             1                 1               12d
example-app-two  two_pdb       N/A             0                 0               12d

在這個範例中,叢集自動配置器不會撤除任何與 two_pdb 標籤選取器相符的 Pod。這項設定中的 maxUnavailable: 0PodDisruptionBudget 會規定所有副本必須隨時保持可用狀態。此外,disruptionsAllowed: 0 會禁止任何干擾這些 Pod 的行為。因此,執行這些 Pod 的節點無法縮減,因為這麼做會造成中斷並違反 PodDisruptionBudget。

如果 PodDisruptionBudget 運作正常,則無須採取進一步行動。如要調整 PodDisruptionBudget,以便移動資源用量不足節點上的 Pod,請編輯 PodDisruptionBudget 的資訊清單。舉例來說,如果已將 maxUnavailable 設為 0,您可以將其變更為 1,讓叢集自動調度器縮減資源。

問題:節點處於封鎖狀態,且未移除

如果 Google 服務帳戶沒有編輯者角色,叢集自動配置器就無法縮減節點集區大小,並發生類似下列的錯誤:

Required 'compute.instanceGroups.update' permission for 'INSTANCE_GROUP_NAME'.

這項問題的常見症狀是叢集自動配置器嘗試縮減節點集區大小,但節點狀態並未變更。

如要解決這個問題,請檢查預設服務帳戶 (PROJECT_NUMBER@cloudservices.gserviceaccount.com) 是否具備專案的編輯者角色 (roles/editor)。如果服務帳戶沒有這個角色,請新增。GKE 會使用這個服務帳戶管理專案資源。如要瞭解如何執行這項操作,請參閱 IAM 說明文件中的「授予或撤銷單一角色」。

後續步驟