水平 Pod 自動擴充

在 Kubernetes 中,HorizontalPodAutoscaler 會自動更新工作負載資源 (例如 DeploymentStatefulSet),目的是自動擴充工作負載以符合需求。

水平擴充表示回應增加的負載是部署更多 Pod。這與垂直擴充不同,對於 Kubernetes 而言,垂直擴充表示為已為工作負載執行的 Pod 指派更多資源 (例如:記憶體或 CPU)。

如果負載減少,且 Pod 數量高於設定的最小值,則 HorizontalPodAutoscaler 會指示工作負載資源 (Deployment、StatefulSet 或其他類似資源) 向下縮減。

水平 Pod 自動擴充不適用於無法擴充的物件 (例如:DaemonSet)。

HorizontalPodAutoscaler 實作為 Kubernetes API 資源和控制器。資源決定控制器的行為。水平 Pod 自動擴充控制器在 Kubernetes 控制平面內執行,定期調整其目標 (例如,Deployment) 的所需規模,以符合觀察到的指標,例如平均 CPU 使用率、平均記憶體使用率或您指定的任何其他自訂指標。

有一個關於使用水平 Pod 自動擴充的逐步解說範例

HorizontalPodAutoscaler 如何運作?

graph BT hpa[Horizontal Pod Autoscaler] --> scale[Scale] subgraph rc[RC / Deployment] scale end scale -.-> pod1[Pod 1] scale -.-> pod2[Pod 2] scale -.-> pod3[Pod N] classDef hpa fill:#D5A6BD,stroke:#1E1E1D,stroke-width:1px,color:#1E1E1D; classDef rc fill:#F9CB9C,stroke:#1E1E1D,stroke-width:1px,color:#1E1E1D; classDef scale fill:#B6D7A8,stroke:#1E1E1D,stroke-width:1px,color:#1E1E1D; classDef pod fill:#9FC5E8,stroke:#1E1E1D,stroke-width:1px,color:#1E1E1D; class hpa hpa; class rc rc; class scale scale; class pod1,pod2,pod3 pod

圖 1. HorizontalPodAutoscaler 控制 Deployment 及其 ReplicaSet 的規模

Kubernetes 將水平 Pod 自動擴充實作為間歇性執行的控制迴圈 (它不是連續程序)。間隔由 kube-controller-manager--horizontal-pod-autoscaler-sync-period 參數設定 (預設間隔為 15 秒)。

在每個期間內,控制器管理員會針對每個 HorizontalPodAutoscaler 定義中指定的指標查詢資源使用率。控制器管理員會找到由 scaleTargetRef 定義的目標資源,然後根據目標資源的 .spec.selector 標籤選取 Pod,並從資源指標 API (適用於每個 Pod 的資源指標) 或自訂指標 API (適用於所有其他指標) 取得指標。

  • 對於每個 Pod 的資源指標 (例如 CPU),控制器會從資源指標 API 擷取 HorizontalPodAutoscaler 目標的每個 Pod 的指標。然後,如果設定了目標使用率值,控制器會將使用率值計算為每個 Pod 中容器上對等資源請求的百分比。如果設定了目標原始值,則直接使用原始指標值。然後,控制器會取得所有目標 Pod 的使用率或原始值的平均值 (取決於指定的目標類型),並產生用於擴充所需副本數量的比率。

    請注意,如果某些 Pod 的容器未設定相關的資源請求,則 Pod 的 CPU 使用率將不會定義,且自動擴充程式將不會針對該指標採取任何動作。請參閱下方的演算法詳細資訊章節,以取得有關自動擴充演算法如何運作的更多資訊。

  • 對於每個 Pod 的自訂指標,控制器的運作方式與每個 Pod 的資源指標類似,不同之處在於它使用原始值,而不是使用率值。

  • 對於物件指標和外部指標,會擷取單一指標,用於描述相關物件。此指標會與目標值進行比較,以產生如上的比率。在 autoscaling/v2 API 版本中,此值可以選擇性地在進行比較之前除以 Pod 數量。

HorizontalPodAutoscaler 常見的用途是將其配置為從彙總的 APImetrics.k8s.iocustom.metrics.k8s.ioexternal.metrics.k8s.io)中提取指標。metrics.k8s.io API 通常由名為 Metrics Server 的附加元件提供,需要單獨啟動。有關資源指標的更多資訊,請參閱Metrics Server

對指標 API 的支援說明了這些不同 API 的穩定性保證和支援狀態。

HorizontalPodAutoscaler 控制器存取支援擴充的相應工作負載資源(例如 Deployments 和 StatefulSet)。這些資源各自都有一個名為 scale 的子資源,這是一個介面,可讓您動態設定副本數並檢查它們各自的目前狀態。有關 Kubernetes API 中子資源的一般資訊,請參閱Kubernetes API 概念

演算法詳情

從最基本的角度來看,HorizontalPodAutoscaler 控制器根據所需指標值與目前指標值之間的比例運作

desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]

例如,如果目前的指標值為 200m,而所需值為 100m,則副本數將加倍,因為 200.0 / 100.0 == 2.0。如果目前值反而為 50m,則副本數將減半,因為 50.0 / 100.0 == 0.5。如果比例與 1.0 非常接近(在全域可配置的容錯範圍內,預設為 0.1),則控制平面會跳過任何擴充動作。

當指定 targetAverageValuetargetAverageUtilization 時,currentMetricValue 的計算方式是取 HorizontalPodAutoscaler 擴充目標中所有 Pod 的給定指標的平均值。

在檢查容錯並決定最終值之前,控制平面也會考量是否有任何指標遺失,以及有多少 Pod 處於Ready狀態。所有設定了刪除時間戳記的 Pod(具有刪除時間戳記的物件正在關閉/移除過程中)都會被忽略,並且所有失敗的 Pod 都會被捨棄。

如果特定 Pod 遺失指標,則會將其擱置稍後處理;遺失指標的 Pod 將用於調整最終的擴充量。

當根據 CPU 進行擴充時,如果任何 Pod 尚未準備就緒(仍在初始化中,或可能不健康)該 Pod 最新的指標點是在其準備就緒之前,則該 Pod 也會被擱置。

由於技術限制,HorizontalPodAutoscaler 控制器在判斷是否擱置某些 CPU 指標時,無法準確判斷 Pod 首次準備就緒的時間。相反地,如果 Pod 未準備就緒,並且自啟動以來在短時間的可配置時間視窗內轉換為準備就緒,則控制器會將該 Pod 視為「尚未準備就緒」。此值透過 --horizontal-pod-autoscaler-initial-readiness-delay 標誌配置,預設值為 30 秒。一旦 Pod 準備就緒,如果任何轉換為準備就緒的情況發生在自啟動以來較長的可配置時間內,控制器會將其視為第一次轉換。此值透過 --horizontal-pod-autoscaler-cpu-initialization-period 標誌配置,預設值為 5 分鐘。

然後,使用未擱置或從上方捨棄的剩餘 Pod 計算 currentMetricValue / desiredMetricValue 的基本擴充比例。

如果存在任何遺失的指標,控制平面會更保守地重新計算平均值,假設這些 Pod 在縮減規模的情況下消耗了所需值的 100%,而在擴大規模的情況下則為 0%。這會減弱任何潛在擴充的幅度。

此外,如果存在任何尚未準備就緒的 Pod,並且工作負載會在未考慮遺失指標或尚未準備就緒的 Pod 的情況下擴大規模,則控制器會保守地假設尚未準備就緒的 Pod 消耗了所需指標的 0%,進一步減弱了擴大規模的幅度。

在考慮尚未準備就緒的 Pod 和遺失指標後,控制器會重新計算使用率。如果新比例反轉了擴充方向,或在容錯範圍內,則控制器不會採取任何擴充動作。在其他情況下,新比例將用於決定 Pod 數量的任何變更。

請注意,平均使用率的原始值會透過 HorizontalPodAutoscaler 狀態回報,即使使用新的使用率,也不會考慮尚未準備就緒的 Pod 或遺失指標。

如果在 HorizontalPodAutoscaler 中指定了多個指標,則會針對每個指標執行此計算,然後選擇所需副本計數中最大的值。如果這些指標中的任何一個都無法轉換為所需的副本計數(例如,由於從指標 API 提取指標時發生錯誤),並且可以提取的指標建議縮減規模,則會跳過擴充。這表示如果一個或多個指標給出的 desiredReplicas 大於目前值,則 HPA 仍然能夠擴大規模。

最後,在 HPA 擴充目標之前,會記錄擴充建議。控制器會考量可配置時間視窗內的所有建議,並選擇該視窗內的最高建議。此值可以使用 --horizontal-pod-autoscaler-downscale-stabilization 標誌配置,預設值為 5 分鐘。這表示縮減規模將逐步發生,從而平滑快速波動的指標值的影響。

API 物件

Horizontal Pod Autoscaler 是 Kubernetes autoscaling API 群組中的 API 資源。目前的穩定版本可在 autoscaling/v2 API 版本中找到,其中包括對根據記憶體和自訂指標進行擴充的支援。使用 autoscaling/v1 時,autoscaling/v2 中引入的新欄位會保留為註解。

當您建立 HorizontalPodAutoscaler API 物件時,請確保指定的名稱是有效的DNS 子網域名稱。有關 API 物件的更多詳細資訊,請參閱HorizontalPodAutoscaler 物件

工作負載擴充的穩定性

當使用 HorizontalPodAutoscaler 管理一組副本的擴充時,由於評估指標的動態特性,副本數量可能會持續頻繁波動。這有時被稱為抖動擺盪。它類似於控制論中的遲滯概念。

在滾動更新期間自動擴充

Kubernetes 可讓您對 Deployment 執行滾動更新。在這種情況下,Deployment 會為您管理底層的 ReplicaSet。當您為 Deployment 配置自動擴充時,您可以將 HorizontalPodAutoscaler 繫結到單個 Deployment。HorizontalPodAutoscaler 管理 Deployment 的 replicas 欄位。deployment 控制器負責設定底層 ReplicaSet 的 replicas,以便它們在部署期間和之後加總到合適的數量。

如果您對具有自動擴充副本數量的 StatefulSet 執行滾動更新,則 StatefulSet 會直接管理其 Pod 集(沒有類似於 ReplicaSet 的中間資源)。

對資源指標的支援

任何 HPA 目標都可以根據擴充目標中 Pod 的資源使用量進行擴充。定義 Pod 規格時,應指定 cpumemory 等資源請求。這用於判斷資源使用率,並由 HPA 控制器用於向上或向下擴充目標。若要使用基於資源使用率的擴充,請指定如下的指標來源

type: Resource
resource:
  name: cpu
  target:
    type: Utilization
    averageUtilization: 60

透過此指標,HPA 控制器將使擴充目標中 Pod 的平均使用率保持在 60%。使用率是目前資源使用量與 Pod 的請求資源之間的比率。請參閱演算法,以取得有關如何計算和平均使用率的更多詳細資訊。

容器資源指標

功能狀態: Kubernetes v1.30 [stable](預設啟用:true)

HorizontalPodAutoscaler API 也支援容器指標來源,HPA 可以追蹤一組 Pod 中個別容器的資源使用量,以便擴充目標資源。這可讓您為特定 Pod 中最重要的容器配置擴充閾值。例如,如果您有一個 Web 應用程式和一個提供記錄的 Sidecar 容器,您可以根據 Web 應用程式的資源使用量進行擴充,而忽略 Sidecar 容器及其資源使用量。

如果您修改目標資源以使其具有一組不同容器的新 Pod 規格,則如果新加入的容器也應使用於擴充,則應修改 HPA 規格。如果指標來源中指定的容器不存在或僅存在於部分 Pod 中,則這些 Pod 會被忽略,並且重新計算建議。請參閱演算法,以取得有關計算的更多詳細資訊。若要使用容器資源進行自動擴充,請定義如下的指標來源

type: ContainerResource
containerResource:
  name: cpu
  container: application
  target:
    type: Utilization
    averageUtilization: 60

在上面的範例中,HPA 控制器會擴充目標,使所有 Pod 的 application 容器中 CPU 的平均使用率為 60%。

根據自訂指標進行擴充

功能狀態: Kubernetes v1.23 [stable]

autoscaling/v2beta2 API 版本先前以 beta 功能形式提供此功能)

如果您使用 autoscaling/v2 API 版本,您可以將 HorizontalPodAutoscaler 配置為根據自訂指標(未內建於 Kubernetes 或任何 Kubernetes 元件中)進行擴充。然後,HorizontalPodAutoscaler 控制器會從 Kubernetes API 查詢這些自訂指標。

請參閱對指標 API 的支援以瞭解需求。

根據多個指標進行擴充

功能狀態: Kubernetes v1.23 [stable]

autoscaling/v2beta2 API 版本先前以 beta 功能形式提供此功能)

如果您使用 autoscaling/v2 API 版本,您可以為 HorizontalPodAutoscaler 指定多個要根據其進行擴充的指標。然後,HorizontalPodAutoscaler 控制器會評估每個指標,並根據該指標提出新的擴充規模。HorizontalPodAutoscaler 會採用針對每個指標建議的最大規模,並將工作負載設定為該大小(前提是這不大於您配置的整體最大值)。

對指標 API 的支援

預設情況下,HorizontalPodAutoscaler 控制器會從一系列 API 擷取指標。為了使其能夠存取這些 API,叢集管理員必須確保

  • API 彙總層已啟用。

  • 已註冊相應的 API

    • 對於資源指標,這是 metrics.k8s.io API,通常由 metrics-server 提供。它可以作為叢集附加元件啟動。

    • 對於自訂指標,這是 custom.metrics.k8s.io API。它由指標解決方案供應商提供的「配接器」API 伺服器提供。請諮詢您的指標管線,以查看是否有可用的 Kubernetes 指標配接器。

    • 對於外部指標,這是 external.metrics.k8s.io API。它可能由上面提供的自訂指標配接器提供。

有關這些不同指標路徑以及它們之間差異的更多資訊,請參閱 HPA V2custom.metrics.k8s.ioexternal.metrics.k8s.io 的相關設計提案。

有關如何使用它們的範例,請參閱使用自訂指標的逐步解說使用外部指標的逐步解說

可配置的擴充行為

功能狀態: Kubernetes v1.23 [stable]

autoscaling/v2beta2 API 版本先前以 beta 功能形式提供此功能)

如果您使用 v2 HorizontalPodAutoscaler API,您可以使用 behavior 欄位(請參閱 API 參考)來配置單獨的向上擴充和向下擴充行為。您可以透過在 behavior 欄位下設定 scaleUp 和/或 scaleDown 來指定這些行為。

您可以指定一個穩定視窗,以防止擴充目標的副本計數抖動。擴充策略還可讓您在擴充時控制副本的變更率。

擴充策略

可以在規格的 behavior 區段中指定一個或多個擴充策略。當指定多個策略時,預設情況下會選取允許最大變更量的策略。以下範例顯示了向下擴充時的此行為

behavior:
  scaleDown:
    policies:
    - type: Pods
      value: 4
      periodSeconds: 60
    - type: Percent
      value: 10
      periodSeconds: 60

periodSeconds 表示策略必須保持為真的過去時間長度。您可以為 periodSeconds 設定的最大值為 1800(半小時)。第一個策略(Pods)允許在一分鐘內最多縮減 4 個副本。第二個策略(Percent)允許在一分鐘內最多縮減目前副本的 10%。

由於預設情況下會選取允許最大變更量的策略,因此只有當 Pod 副本數量超過 40 時才會使用第二個策略。當副本數量為 40 或更少時,將套用第一個策略。例如,如果存在 80 個副本,並且目標必須縮減到 10 個副本,則在第一步中將減少 8 個副本。在下一次迭代中,當副本數量為 72 時,Pod 的 10% 為 7.2,但該數字會四捨五入為 8。在自動擴充控制器的每個迴圈中,要變更的 Pod 數量都會根據目前副本的數量重新計算。當副本數量降至 40 個以下時,將套用第一個策略(Pods),並且一次將減少 4 個副本。

可以透過為擴充方向指定 selectPolicy 欄位來變更策略選取。將值設定為 Min 將選取允許副本計數中最小變更的策略。將值設定為 Disabled 會完全停用該方向的擴充。

穩定視窗

當用於擴充的指標持續波動時,穩定視窗用於限制副本計數的抖動。自動擴充演算法使用此視窗來推斷先前的所需狀態,並避免對工作負載擴充進行不必要的變更。

例如,在以下範例程式碼片段中,為 scaleDown 指定了穩定視窗。

behavior:
  scaleDown:
    stabilizationWindowSeconds: 300

當指標指示應縮減目標規模時,演算法會查看先前計算的所需狀態,並使用指定間隔中的最高值。在上面的範例中,將考量過去 5 分鐘內的所有所需狀態。

這近似於滾動最大值,並避免擴充演算法頻繁地移除 Pod,而僅僅在稍後觸發重新建立等效的 Pod。

預設行為

若要使用自訂擴充,並非所有欄位都必須指定。只能指定需要自訂的值。這些自訂值會與預設值合併。預設值與 HPA 演算法中的現有行為相符。

behavior:
  scaleDown:
    stabilizationWindowSeconds: 300
    policies:
    - type: Percent
      value: 100
      periodSeconds: 15
  scaleUp:
    stabilizationWindowSeconds: 0
    policies:
    - type: Percent
      value: 100
      periodSeconds: 15
    - type: Pods
      value: 4
      periodSeconds: 15
    selectPolicy: Max

對於向下擴充,穩定視窗為 300 秒(或 --horizontal-pod-autoscaler-downscale-stabilization 標誌的值,如果提供)。向下擴充只有一個策略,該策略允許移除目前執行副本的 100%,這表示擴充目標可以縮減到允許的最小副本數。對於向上擴充,沒有穩定視窗。當指標指示應向上擴充目標時,目標會立即向上擴充。有 2 個策略,其中最多可以每 15 秒新增 4 個 Pod 或目前執行副本的 100%,直到 HPA 達到其穩定狀態。

範例:變更向下擴充穩定視窗

若要提供 1 分鐘的自訂向下擴充穩定視窗,應將以下行為新增至 HPA

behavior:
  scaleDown:
    stabilizationWindowSeconds: 60

範例:限制向下擴充速率

若要將 HPA 移除 Pod 的速率限制為每分鐘 10%,應將以下行為新增至 HPA

behavior:
  scaleDown:
    policies:
    - type: Percent
      value: 10
      periodSeconds: 60

若要確保每分鐘移除的 Pod 不超過 5 個,您可以新增第二個固定大小為 5 的向下擴充策略,並將 selectPolicy 設定為最小值。將 selectPolicy 設定為 Min 表示自動擴充器會選擇影響 Pod 數量最少的策略

behavior:
  scaleDown:
    policies:
    - type: Percent
      value: 10
      periodSeconds: 60
    - type: Pods
      value: 5
      periodSeconds: 60
    selectPolicy: Min

範例:停用向下擴充

DisabledselectPolicy 值會關閉給定方向的擴充。因此,若要防止向下擴充,將使用以下策略

behavior:
  scaleDown:
    selectPolicy: Disabled

kubectl 中對 HorizontalPodAutoscaler 的支援

HorizontalPodAutoscaler 與每個 API 資源一樣,以標準方式受到 kubectl 的支援。您可以使用 kubectl create 命令建立新的自動擴充器。您可以使用 kubectl get hpa 列出自動擴充器,或使用 kubectl describe hpa 取得詳細描述。最後,您可以使用 kubectl delete hpa 刪除自動擴充器。

此外,還有一個特殊的 kubectl autoscale 命令用於建立 HorizontalPodAutoscaler 物件。例如,執行 kubectl autoscale rs foo --min=2 --max=5 --cpu-percent=80 將為 ReplicaSet foo 建立一個自動擴充器,目標 CPU 使用率設定為 80%,副本數量介於 2 到 5 之間。

隱式維護模式停用

您可以隱式停用目標的 HPA,而無需變更 HPA 配置本身。如果目標的所需副本計數設定為 0,並且 HPA 的最小副本計數大於 0,則 HPA 會停止調整目標(並將自身的 ScalingActive 條件設定為 false),直到您透過手動調整目標的所需副本計數或 HPA 的最小副本計數來重新啟用它。

將 Deployment 和 StatefulSet 移轉到水平自動擴充

啟用 HPA 後,建議從 Deployment 和/或 StatefulSet 的資訊清單中移除 spec.replicas 的值。如果未執行此操作,則每次套用對該物件的變更時(例如透過 kubectl apply -f deployment.yaml),這都會指示 Kubernetes 將目前的 Pod 數量擴充到 spec.replicas 鍵的值。當 HPA 處於活動狀態時,這可能不是所需的,並且可能會很麻煩,從而導致抖動或擺盪行為。

請記住,移除 spec.replicas 可能會導致 Pod 數量的一次性降級,因為此鍵的預設值為 1(請參閱Deployment 副本)。更新後,除 1 個 Pod 外的所有 Pod 都將開始其終止程序。之後的任何部署應用程式都將正常運作,並根據需要遵循滾動更新配置。您可以根據您修改部署的方式,選擇以下兩種方法之一來避免此降級

  1. kubectl apply edit-last-applied deployment/<deployment_name>
  2. 在編輯器中,移除 spec.replicas。當您儲存並退出編輯器時,kubectl 會套用更新。在此步驟中不會發生 Pod 數量的變更。
  3. 您現在可以從資訊清單中移除 spec.replicas。如果您使用原始碼管理,也請提交您的變更或採取任何其他適合您追蹤更新方式的原始碼修訂步驟。
  4. 從此以後,您可以執行 kubectl apply -f deployment.yaml

當使用伺服器端套用時,您可以遵循轉移所有權指南,其中涵蓋了這個確切的使用案例。

下一步

如果您在叢集中配置了自動擴充,您可能還需要考慮使用叢集自動擴充,以確保您執行了正確數量的節點。

有關 HorizontalPodAutoscaler 的更多資訊

上次修改時間:2024 年 10 月 03 日 早上 7:54 PST:使用其他關鍵字更新 horizontal-pod-autoscale.md (39b49dfbf0)