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

Kubernetes 1.27:更細粒度的 Pod 拓撲分佈策略達到 Beta

在 Kubernetes v1.19 中,Pod 拓撲分佈約束功能正式釋出(GA)。

隨著時間的推移,我們 SIG Scheduling 收到了使用者的反饋,因此,我們正透過三個 KEP 積極改進拓撲分佈功能。所有這些功能在 Kubernetes v1.27 中已達到 Beta 階段,並預設啟用。

這篇博文將介紹每個功能及其背後的用例。

KEP-3022:Pod 拓撲分佈中的 minDomains

Pod 拓撲分佈具有 maxSkew 引數,用於定義 Pod 可能不均勻分佈的程度。

但是,過去沒有辦法控制我們應該分佈的域的數量。一些使用者希望強制將 Pod 分佈到最少數量的域上,如果當前域數量不足,則讓叢集自動伸縮器(cluster-autoscaler)來供應新的域。

Kubernetes v1.24 引入了 minDomains 引數作為 Pod 拓撲分佈約束的 Alpha 功能。透過 minDomains 引數,你可以定義最小的域數量。

例如,假設有 3 個具有足夠容量的節點,一個新建立的 ReplicaSet 在其 Pod 模板中具有以下 topologySpreadConstraints

...
topologySpreadConstraints:
- maxSkew: 1
  minDomains: 5 # requires 5 Nodes at least (because each Node has a unique hostname).
  whenUnsatisfiable: DoNotSchedule # minDomains is valid only when DoNotSchedule is used.
  topologyKey: kubernetes.io/hostname
  labelSelector:
    matchLabels:
        foo: bar

在這種情況下,3 個 Pod 將被排程到這 3 個節點上,但該 ReplicaSet 的另外 2 個 Pod 將處於不可排程狀態,直到更多節點加入叢集。

你可以想象叢集自動伸縮器會根據這些不可排程的 Pod 來供應新節點,最終,副本將被分佈在 5 個節點上。

KEP-3094:在計算 podTopologySpread 傾斜度時考慮汙點/容忍度

在此增強之前,當你部署一個配置了 podTopologySpread 的 Pod 時,kube-scheduler 會在過濾和評分時考慮滿足 Pod 的 nodeAffinity 和 nodeSelector 的節點,但不會關心節點汙點是否被傳入的 Pod 所容忍。這可能導致一個帶有無法容忍的汙點的節點成為分佈的唯一候選者,結果,如果 Pod 不容忍該汙點,它將卡在 Pending 狀態。

為了在計算分佈傾斜度時對考慮哪些節點做出更細粒度的決策,Kubernetes 1.25 在 topologySpreadConstraints 中引入了兩個新欄位來定義節點包含策略:nodeAffinityPolicynodeTaintPolicy

應用這些策略的清單(manifest)如下所示:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  # Configure a topology spread constraint
  topologySpreadConstraints:
    - maxSkew: <integer>
      # ...
      nodeAffinityPolicy: [Honor|Ignore]
      nodeTaintsPolicy: [Honor|Ignore]
  # other Pod fields go here

nodeAffinityPolicy 欄位指示 Kubernetes 如何處理 Pod 的 nodeAffinitynodeSelector 以進行 Pod 拓撲分佈。如果設定為 Honor,kube-scheduler 在計算分佈傾斜度時會過濾掉不匹配 nodeAffinity/nodeSelector 的節點。如果設定為 Ignore,則會包含所有節點,無論它們是否匹配 Pod 的 nodeAffinity/nodeSelector

為了向後相容,nodeAffinityPolicy 預設為 Honor

nodeTaintsPolicy 欄位定義了 Kubernetes 如何考慮節點汙點以進行 Pod 拓撲分佈。如果設定為 Honor,只有傳入 Pod 具有容忍度的被汙染節點才會被包含在分佈傾斜度的計算中。如果設定為 Ignore,kube-scheduler 在計算分佈傾斜度時將完全不考慮節點汙點,因此,帶有 Pod 無法容忍的汙點的節點也將被包含在內。

為了向後相容,nodeTaintsPolicy 預設為 Ignore

該功能在 v1.25 中作為 Alpha 功能引入。預設情況下,它是停用的,所以如果你想在 v1.25 中使用此功能,你必須顯式啟用 NodeInclusionPolicyInPodTopologySpread 特性門控。在接下來的 v1.26 版本中,該相關功能升級為 Beta 版並預設啟用。

KEP-3243:滾動升級後遵循 Pod 拓撲分佈

Pod 拓撲分佈使用 labelSelector 欄位來識別將要計算分佈的 Pod 組。在與 Deployment 一起使用拓撲分佈時,通常的做法是使用 Deployment 的 labelSelector 作為拓撲分佈約束中的 labelSelector。然而,這意味著 Deployment 的所有 Pod 都是分佈計算的一部分,無論它們是否屬於不同的修訂版本。因此,當推出新修訂版本時,分佈將應用於新舊 ReplicaSet 的 Pod,所以當新 ReplicaSet 完全推出而舊的 ReplicaSet 被縮減後,我們最終得到的實際分佈可能不符合預期,因為舊 ReplicaSet 中被刪除的 Pod 會導致剩餘 Pod 的分佈傾斜。為了避免這個問題,過去使用者需要在每次滾動升級時向 Deployment 新增一個修訂標籤,並手動更新它(包括 Pod 模板上的標籤和 topologySpreadConstraints 中的 labelSelector)。

為了用更簡單的 API 解決這個問題,Kubernetes v1.25 在 topologySpreadConstraints 中引入了一個名為 matchLabelKeys 的新欄位。matchLabelKeys 是一個 Pod 標籤鍵的列表,用於選擇將要計算分佈的 Pod。這些鍵用於從正在排程的 Pod 的標籤中查詢值,這些鍵值標籤與 labelSelector 進行“與”運算,以選擇將為傳入 Pod 計算分佈的現有 Pod 組。

有了 matchLabelKeys,你就不需要在不同修訂版本之間更新 pod.spec。管理釋出的控制器或操作員只需為不同修訂版本設定相同標籤鍵的不同值即可。排程器將根據 matchLabelKeys 自動假定這些值。例如,如果你正在配置一個 Deployment,你可以使用由 Deployment 控制器自動新增的、鍵為 pod-template-hash 的標籤來區分單個 Deployment 中的不同修訂版本。

topologySpreadConstraints:
    - maxSkew: 1
      topologyKey: kubernetes.io/hostname
      whenUnsatisfiable: DoNotSchedule
      labelSelector:
        matchLabels:
          app: foo
      matchLabelKeys:
        - pod-template-hash

參與進來

這些功能由 Kubernetes SIG Scheduling 管理。

請加入我們並分享您的反饋。我們期待您的來信!

我如何瞭解更多資訊?