原文出處:http://ju.outofmemory.cn/entry/278349
背景
Kubernetes中的調度策略可以大致分爲兩種,一種是全局的調度策略,要在啓動調度器時配置,包括kubernetes調度器自帶的各種predicates和priorities算法,具體可以參看文章《Kubernetes調度詳解》;另一種是運行時調度策略,包括nodeAffinity(主機親和性),podAffinity(POD親和性)以及podAntiAffinity(POD反親和性)。
nodeAffinity 主要解決POD要部署在哪些主機,以及POD不能部署在哪些主機上的問題,處理的是POD和主機之間的關係。
podAffinity 主要解決POD可以和哪些POD部署在同一個拓撲域中的問題(拓撲域用主機標籤實現,可以是單個主機,也可以是多個主機組成的cluster、zone等。),podAntiAffinity主要解決POD不能和哪些POD部署在同一個拓撲域中的問題。它們處理的是Kubernetes集羣內部POD和POD之間的關係。
三種親和性和反親和性策略的比較如下表所示:
策略名稱 | 匹配目標 | 支持的操作符 | 支持拓撲域 | 設計目標 |
nodeAffinity | 主機標籤 | In,NotIn,Exists,DoesNotExist,Gt,Lt | 不支持 | 決定Pod可以部署在哪些主機上 |
podAffinity | Pod標籤 | In,NotIn,Exists,DoesNotExist | 支持 | 決定Pod可以和哪些Pod部署在同一拓撲域 |
PodAntiAffinity | Pod標籤 | In,NotIn,Exists,DoesNotExist | 支持 | 決定Pod不可以和哪些Pod部署在同一拓撲域 |
本文主要介紹如何使用親和性和反親和性做資源調度。
使用場景
nodeAffinity使用場景 :
將S1服務的所有Pod部署到指定的符合標籤規則的主機上。
將S1服務的所有Pod部署到除部分主機外的其他主機上。
podAffinity使用場景 :
將某一特定服務的pod部署在同一拓撲域中,不用指定具體的拓撲域。
如果S1服務使用S2服務,爲了減少它們之間的網絡延遲(或其它原因),把S1服務的POD和S2服務的pod部署在同一拓撲域中。
podAntiAffinity使用場 景:
將一個服務的POD分散在不同的主機或者拓撲域中,提高服務本身的穩定性。
給POD對於一個節點的獨佔訪問權限來保證資源隔離,保證不會有其它pod來分享節點資源。
把可能會相互影響的服務的POD分散在不同的主機上。
對於親和性和反親和性,每種都有三種規則可以設置:
RequiredDuringSchedulingRequiredDuringExecution :在調度期間要求滿足親和性或者反親和性規則,如果不能滿足規則,則POD不能被調度到對應的主機上。在之後的運行過程中,如果因爲某些原因(比如修改label)導致規則不能滿足,系統會嘗試把POD從主機上刪除(現在版本還不支持)。
RequiredDuringSchedulingIgnoredDuringExecution :在調度期間要求滿足親和性或者反親和性規則,如果不能滿足規則,則POD不能被調度到對應的主機上。在之後的運行過程中,系統不會再檢查這些規則是否滿足。
PreferredDuringSchedulingIgnoredDuringExecution :在調度期間儘量滿足親和性或者反親和性規則,如果不能滿足規則,POD也有可能被調度到對應的主機上。在之後的運行過程中,系統不會再檢查這些規則是否滿足。
使用示例
使用POD親和性調度時要先開啓Kubernetes調度器的MatchInterPodAffinity篩選功能,具體的操作方式是修改調度器的配置文件,在predicates中增加如下內容:
1 | {"name": "MatchInterPodAffinity"} |
測試環境的主機信息如下:
其中每個主機上都有 beta.kubernetes.io/arch、beta.kubernetes.io/os、kubernetes.io/hostname這幾個標籤,在測試過程中把這些標籤當做拓撲域使用。
nodeAffinity 使用示例:
使用nodeAffinity把POD部署到主機mesos-slave1和mesos-slave2上,yaml定義如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | { "nodeAffinity": { "requiredDuringSchedulingIgnoredDuringExecution": { "nodeSelectorTerms": [ { "matchExpressions": [ { "key": "kubernetes.io/hostname", "operator": "In", "values": [ "mesos-slave1", "mesos-slave2" ] } ] } ] } } } |
創建一個有6個POD的RC,結果如下:
從結果可以看出POD被部署到了mesos-slave1和mesos-slave2上,mesos-slave3上沒有部署POD。
podAffinity使用示例 :
使用kubernetes.io/hostname作爲拓撲域,把pod創建在同一主機上。其中matchExpressions中填寫內容對應到RC中POD自身的標籤。可以通過修改需要匹配的標籤內容來控制把一個服務中的POD和其它服務的POD部署在同一主機上。
yaml中的定義如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | { "podAffinity": { "requiredDuringSchedulingIgnoredDuringExecution": [ { "labelSelector": { "matchExpressions": [ { "key": "name", "operator": "In", "values": [ "node-rc" ] } ] }, "topologyKey": "kubernetes.io/hostname" } ] } } |
創建一個有3個POD的RC,結果如下:
所有創建的POD集中在同一個主機上,具體的主機是哪個不需要指定。
podAntiAffinity 使用示例:
使用kubernetes.io/hostname作爲拓撲域,把pod創建在不同主機上,每個主機上最多隻有一個同類型的POD(同類型用標籤區分)。其中matchExpressions中填寫內容對應到RC中POD自身的標籤。可以通過修改需要匹配的標籤內容來控制把一個服務中的POD和其它服務的POD部署在不同主機上。
yaml中的定義如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | { "podAntiAffinity": { "requiredDuringSchedulingIgnoredDuringExecution": [ { "labelSelector": { "matchExpressions": [ { "key": "name", "operator": "In", "values": [ "node-rc" ] } ] }, "topologyKey": "kubernetes.io/hostname" } ] } } |
創建一個有4個POD的RC,結果如下:
三個主機上都有一個POD運行,因爲每個主機上最多隻能運行一個這種類型的POD,所以有一個POD一直處於Pending狀態,不能調度到任何節點。
上邊的例子中可以通過修改topologyKey來限制拓撲域的範圍,實現把相關服務部署在不同的容災域等其它功能。
總結
Kubernetes提供了豐富的調度策略,包括靜態的全局調度策略,以及動態的運行時調度策略,用戶可以根據需要自由組合使用這些策略來實現自己的需求。在調度過程中,使用nodeAffnity決定資源可以部署在哪些主機上,使用podAffinity和podAntiAffinity決定哪些資源需要部署在同一主機(拓撲域)或者不能部署在同一主機。