在Kubernetes中有一個最複雜的調度器能夠處理pod的分配策略。基於在pod規範中所說起的資源需求,Kubernetes調度器會自動選擇最合適的節點來運行pod。node
但在許多實際場景下,咱們必須干預調度過程才能在pod和一個節點或兩個特定pod之間進行匹配。所以,Kubernetes中有一種十分強大的機制來管理及控制pod的分配邏輯。web
那麼,本文將探索影響Kubernetes中默認調度決定的關鍵特性。redis
Kubernetes一貫以來都是依賴label和selector來對資源進行分組。例如,某服務使用selector來過濾具備特定label的pod,這些label能夠選擇性地接收流量。Label和selector可使用簡單的基於等式的條件(=and!=)來評估規則。經過nodeSelector的特性(即強制將pod調度到特定節點上),能夠將這一技術擴展到節點中。緩存
此外,label和selector開始支持基於集合的query,它帶來了基於in、notin和exist運算符的高級過濾技術。與基於等式的需求相結合,基於集合的需求提供了複雜的技術來過濾Kubernetes中的資源。app
節點親和性/反親和性使用label和annotation的基於表達集的過濾技術來定義特定節點上的pod的分配邏輯。Annotation能夠提供不會暴露到selector的其餘元數據,這意味着用於annotation的鍵不會包含在query和過濾資源中。可是節點親和性能夠在表達式中使用annotation。反親和性能夠確保pod不會被強制調度到與規則匹配的節點上。dom
除了可以在query中使用複雜的邏輯以外,節點親和性/反親和性可以爲分配邏輯強制施加硬性和軟性規則。硬性規則將會執行嚴格的策略,可能會阻止將pod分配到不符合條件的節點上。而軟性規則則會首先確認節點是否與特定的條件相匹配,若是它們不匹配,它將使用默認的調度模式來分配Pod。表達式requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution將會分別執行硬性規則和軟性規則。性能
如下是在硬性和軟性規則下使用節點親和性/反親和性的示例:ui
affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: "failure-domain.beta.kubernetes.io/zone" operator: In values: ["asia-south1-a"]
以上規則將指示Kubernetes調度器嘗試將Pod分配到在GKE集羣的asia-south1-a區域中運行的節點上。若是沒有可用的節點,則調度器將會直接應用標準的分配邏輯。code
affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: "failure-domain.beta.kubernetes.io/zone" operator: NotIn values: ["asia-south1-a"]
以上規則經過使用NotIn運算符來強制執行反親和性。這是一個硬性規則,它可以確保沒有pod被分配到運行在asia-south1-a空間中的GKE節點。blog
儘管節點親和性/反親和性可以處理pod和節點之間的匹配,可是有些場景下咱們須要確保pod在一塊兒運行或在相同的節點上不運行2個pod。Pod親和性/反親和性將幫助咱們應用強制實施粒度分配邏輯。
與節點親和性/反親和性中的表達式相似,pod親和性/反親和性也可以經過requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution強制實施硬性以及軟性規則。還能夠將節點親和性與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來定義自定義分配邏輯。此外,咱們還能寫自定義調度程序,它能夠從默認的調度程序中接管調度邏輯。