1. 程式人生 > >影響K8S Pod分配和排程策略的兩大關鍵特性

影響K8S Pod分配和排程策略的兩大關鍵特性

在Kubernetes中有一個最複雜的排程器可以處理pod的分配策略。基於在pod規範中所提及的資源需求,Kubernetes排程器會自動選擇最合適的節點來執行pod。

但在許多實際場景下,我們必須干預排程過程才能在pod和一個節點或兩個特定pod之間進行匹配。因此,Kubernetes中有一種十分強大的機制來管理及控制pod的分配邏輯。

那麼,本文將探索影響Kubernetes中預設排程決定的關鍵特性。

節點親和性/反親和性

Kubernetes一向以來都是依賴label和selector來對資源進行分組。例如,某服務使用selector來過濾具有特定label的pod,這些label可以選擇性地接收流量。Label和selector可以使用簡單的基於等式的條件(=and!=)來評估規則。通過nodeSelector的特性(即強制將pod排程到特定節點上),可以將這一技術擴充套件到節點中。

此外,label和selector開始支援基於集合的query,它帶來了基於in、notin和exist運算子的高階過濾技術。與基於等式的需求相結合,基於集合的需求提供了複雜的技術來過濾Kubernetes中的資源。

節點親和性/反親和性使用label和annotation的基於表達集的過濾技術來定義特定節點上的pod的分配邏輯。Annotation可以提供不會暴露到selector的其他元資料,這意味著用於annotation的鍵不會包含在query和過濾資源中。但是節點親和性可以在表示式中使用annotation。反親和性可以確保pod不會被強制排程到與規則匹配的節點上。

除了能夠在query中使用複雜的邏輯之外,節點親和性/反親和效能夠為分配邏輯強制施加硬性和軟性規則。硬性規則將會執行嚴格的策略,可能會阻止將pod分配到不符合條件的節點上。而軟性規則則會首先確認節點是否與特定的條件相匹配,如果它們不匹配,它將使用預設的排程模式來分配Pod。表示式requiredDuringSchedulingIgnoredDuringExecution

preferredDuringSchedulingIgnoredDuringExecution將會分別執行硬性規則和軟性規則。

以下是在硬性和軟性規則下使用節點親和性/反親和性的示例:

affinity:
  nodeAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
          - key: "failure-domain.beta.kubernetes.io/zone"
            operator: In
            values: ["asia-south1-a"]

以上規則將指示Kubernetes排程器嘗試將Pod分配到在GKE叢集的asia-south1-a區域中執行的節點上。如果沒有可用的節點,則排程器將會直接應用標準的分配邏輯。

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
          - key: "failure-domain.beta.kubernetes.io/zone"
            operator: NotIn
            values: ["asia-south1-a"]

以上規則通過使用NotIn運算子來強制執行反親和性。這是一個硬性規則,它能夠確保沒有pod被分配到執行在asia-south1-a空間中的GKE節點。

Pod親和性/反親和性

儘管節點親和性/反親和效能夠處理pod和節點之間的匹配,但是有些場景下我們需要確保pod在一起執行或在相同的節點上不執行2個pod。Pod親和性/反親和性將幫助我們應用強制實施粒度分配邏輯。

與節點親和性/反親和性中的表示式類似,pod親和性/反親和性也能夠通過requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecution強制實施硬性以及軟性規則。還可以將節點親和性與pod親和性進行混合和匹配,以定義複雜的分配邏輯。

為了能夠更好地理解概念,想象一下我們有一個web和快取deployment,其中三個副本在一個3節點的叢集中執行。為了確保在web和快取pod之間低延遲,我們想要在用一個節點上執行它們。與此同時,我們不想在相同的節點上執行超過1個快取pod。基於此情況,我們需要實施以下策略:每個節點僅執行1個且只有1個快取Pod的web pod。

首先,我們將使用反親和性規則來部署快取,它將阻止超過1個pod執行在1個節點上:

      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - redis
            topologyKey: "kubernetes.io/hostname"

topoloyKey使用附加到節點的預設label動態過濾節點的名稱。請注意,我們使用podAntiAffinity表示式和in運算子來應用規則的方式。

假設在叢集的某個節點上安排了3個pod快取,那麼現在我們想要在與快取Pod相同的節點上部署web pod。我們將使用podAffinity來實施這一邏輯:

        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - redis
            topologyKey: "kubernetes.io/hostname"

以上程式碼表明Kubernetes排程器要尋找有快取Pod的節點並部署web pod。

除了節點和pod的親和性/反親和性之外,我們還能使用taints和tolerations來定義自定義分配邏輯。此外,我們還能寫自定義排程程式,它可以從預設的排程程式中接管排程邏輯