摘要:換句話說,親和性選擇節點僅在調度時起作用。先創建集群反親和性打散各個副本再部署服務,需要打散并且與服務共存,配置如下注意需要進行大量處理,所以會明顯減慢大型集群的調度時間,不建議在大于幾百個節點的集群中使用該功能。
一、概述
前一篇文章 Kubernetes 調度器淺析,大致講述了調度器的工作原理及相關調度策略。這一章會繼續深入調度器,介紹下“親和性調度”。
Kubernetes 支持限制 Pod 在指定的 Node 上運行,或者指定更傾向于在某些特定 Node 上運行。
有幾種方式可以實現這個功能:
NodeName: 最簡單的節點選擇方式,直接指定節點,跳過調度器。
NodeSelector: 早期的簡單控制方式,直接通過鍵—值對將 Pod 調度到具有特定 label 的 Node 上。
NodeAffinity: NodeSelector 的升級版,支持更豐富的配置規則,使用更靈活。(NodeSelector 將被淘汰.)
PodAffinity: 根據已在節點上運行的 Pod 標簽來約束 Pod 可以調度到哪些節點,而不是根據 node label。
二、NodeNamenodeName 是 PodSpec 的一個字段,用于直接指定調度節點,并運行該 pod。調度器在工作時,實際選擇的是 nodeName 為空的 pod 并進行調度然后再回填該 nodeName,所以直接指定 nodeName 實際是直接跳過了調度器。換句話說,指定 nodeName 的方式是優于其他節點選擇方法。
方法很簡單,直接來個官方示例:
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx nodeName: kube-01
當然如果選擇的節點不存在,或者資源不足,那該 pod 必然就會運行失敗。
三、NodeSelectornodeSelector 也是 PodSpec 中的一個字段,指定鍵—值對的映射。
如果想要將 pod 運行到對應的 node 上,需要先給這些 node 打上 label,然后在 podSpec.NodeSelector 指定對應 node labels 即可。
步驟如下:
設置標簽到 node 上:
kubectl label nodes kubernetes-node type=gpu
pod 配置添加 nodeSelector 字段:
apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx nodeSelector: type: gpu內置 Node 標簽
Kubernetes 內置了一些節點標簽:
kubernetes.io/hostname
beta.kubernetes.io/instance-type
beta.kubernetes.io/os
beta.kubernetes.io/arch
failure-domain.beta.kubernetes.io/zone
failure-domain.beta.kubernetes.io/region
有些標簽是對云提供商使用。
還有些表示 node role 的 labels(可以指定 master、lb 等):
kubernetes.io/role
node-role.kubernetes.io
四、NodeAffinitynodeSelector 通過 k-v 的方式非常簡單的支持了 pod 調度限制到具有特定標簽的節點上。而 nodeAffinity 根據親和力 & 反親和力極大地擴展了能夠表達的約束信息。
nodeAffinity 特性的設計初衷就是為了替代 nodeSelector。
nodeAffinity 當前支持的匹配符號包括:In、NotIn、Exists、DoesNotExists、Gt、Lt 。
nodeAffinity 當前支持兩種調度模式:
requiredDuringSchedulingIgnoredDuringExecution: 一定要滿足的條件,如果沒有找到滿足條件的節點,則 Pod 創建失敗。所有也稱為hard 模式。
preferredDuringSchedulingIgnoredDuringExecution: 優先選擇滿足條件的節點,如果沒有找到滿足條件的節點,則在其他節點中擇優創建 Pod。所有也稱為 soft 模式。
兩種模式的名字特長,這是 k8s 的命名風格。其中IgnoredDuringExecution的意義就跟 nodeSelector 的實現一樣,即使 node label 發生變更,也不會影響之前已經部署且又不滿足 affinity rules 的 pods,這些 pods 還會繼續在該 node 上運行。換句話說,親和性選擇節點僅在調度 Pod 時起作用。
k8s 社區正在計劃提供 requiredDuringSchedulingRequiredDuringExecution 模式,便于驅逐 node 上不滿足 affinity rules 的 pods。
來個官方示例,看下怎么玩:
apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: # 必須選擇 node label key 為 kubernetes.io/e2e-az-name, # value 為 e2e-az1 或 e2e-az2. requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/e2e-az-name operator: In values: - e2e-az1 - e2e-az2 # 過濾掉上面的必選項后,再優先選擇 node label key 為 another-node-label-key # value 為 another-node-label-value. preferredDuringSchedulingIgnoredDuringExecution: # 如果滿足節點親和,積分加權重(優選算法,會對 nodes 打分) # weight: 0 - 100 - weight: 1 preference: matchExpressions: - key: another-node-label-key operator: In values: - another-node-label-value containers: - name: with-node-affinity image: k8s.gcr.io/pause:2.0
簡單看下 NodeAffinity 的結構體,下面介紹注意事項時會涉及:
type NodeAffinity struct { RequiredDuringSchedulingIgnoredDuringExecution *NodeSelector PreferredDuringSchedulingIgnoredDuringExecution []PreferredSchedulingTerm } type NodeSelector struct { NodeSelectorTerms []NodeSelectorTerm } type NodeSelectorTerm struct { MatchExpressions []NodeSelectorRequirement MatchFields []NodeSelectorRequirement }
配置相關的注意點:
如果 nodeSelector 和 nodeAffinity 兩者都指定,那 node 需要兩個條件都滿足,pod 才能調度。
如果指定了多個 NodeSelectorTerms,那 node 只要滿足其中一個條件,pod 就可以進行調度。
如果指定了多個 MatchExpressions,那必須要滿足所有條件,才能將 pod 調度到該 node。
五、PodAffinitynodeSelector & nodeAffinity 都是基于 node label 進行調度。而有時候我們希望調度的時候能考慮 pod 之間的關系,而不只是 pod 和 node 的關系。
舉個例子,會有需求希望服務 A 和 B 部署在同一個機房、機架或機器上,因為這些服務可能會對網路延遲比較敏感,需要低延時;再比如,希望服務 C 和 D 又希望盡量分開部署,即使一臺主機甚至一個機房出了問題,也不會導致兩個服務一起掛而影響服務可用性,提升故障容災的能力。
podAffinity 會基于節點上已經運行的 pod label 來約束新 pod 的調度。
其規則就是“如果 X 已經運行了一個或者多個符合規則 Y 的 Pod,那么這個 Pod 應該(如果是反親和性,則是不應該)調度到 X 上”。
這里的 Y 是關聯 namespace 的 labelSelector,當然 namespace 也可以是 all。和 node 不同,pod 是隸屬于 namespace 下的資源,所以基于 pod labelSelector 必須指定具體的 namespace;而 X 則可以理解為一個拓撲域,類似于 node、rack、zone、cloud region 等等,就是前面提到的 內置 Node 標簽 ,當然也可以自定義。
看下 pod affinity 涉及的結構體,便于進行功能介紹:
type Affinity struct { // NodeAffinity 前面介紹了 NodeAffinity *NodeAffinity // pod 親和性 PodAffinity *PodAffinity // pod 反親和性 PodAntiAffinity *PodAntiAffinity } type PodAffinity struct { // hard 模式, 必選項 RequiredDuringSchedulingIgnoredDuringExecution []PodAffinityTerm // soft 模式, 進行 node 優先 PreferredDuringSchedulingIgnoredDuringExecution []WeightedPodAffinityTerm } type PodAffinityTerm struct { LabelSelector *metav1.LabelSelector Namespaces []string TopologyKey string } type WeightedPodAffinityTerm struct { Weight int32 PodAffinityTerm PodAffinityTerm }
podAffinity 和 nodeAffinity 有相似的地方,使用了 labelSelector 進行匹配,支持的匹配符號包括:In、NotIn、Exists、DoesNotExists;
也支持兩種調度模式 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution, 功能和 nodeAffinity 一樣,這里就不在累述。
podAffinity 和 nodeAffinity 也有較大的差異,前面講了 pod 是 namespace 資源,所以必然會需要配置 namespaces,支持配置多個 namespace。如果省略的話,默認為待調度 pod 所屬的 namespace;如果定義了但是值為空,則表示使用 “all” namespaces。
還有一個較大的差別 TopologyKey, 便于理解進行多帶帶介紹。
TopologyKeyTopologyKey 用于定義 in the same place,前面也介紹了是拓撲域的概念。
看下面的圖,這兩個 pod 到底該如何算在一個拓撲域?
如果我們使用k8s.io/hostname,in the same place 則意味著在同一個 node,那下圖的 pods 就不在一個 place:
如果我們使用failure-domain.k8s.io/zone 來表示一個 place,那下圖的 pods 就表示在一個 zone:
當然我們也可以自定義 node labels 作為 TopologyKey。比如我們可以給一組 node 打上 rack 標簽,那下圖的 pods 表示在同一個 place:
原則上,topologyKey 可以是任何合法的 label key。但是出于性能和安全考慮,topologyKey 存在一些限制:
對于親和性和反親和性的 requiredDuringSchedulingIgnoredDuringExecution 模式,topologyKey 不能為空
pod 反親和性 requiredDuringSchedulingIgnoredDuringExecution 模式下,LimitPodHardAntiAffinityTopology 權限控制器會限制 topologyKey 只能設置為 kubernetes.io/hostname。當然如果你想要使用自定義 topology,那可以簡單禁用即可。
pod 反親和性 preferredDuringSchedulingIgnoredDuringExecution 模式下,topologyKey 為空則表示所有的拓撲域。截止 v1.12 版本,所有的拓撲域還只能是 kubernetes.io/hostname, failure-domain.beta.kubernetes.io/zone 和 failure-domain.beta.kubernetes.io/region 的組合。
除此之外,topologyKey 可以是任何合法的 label key。
示例來個官方示例,有三節點集群,需要分別部署 3 份 web 和 redis 服務。希望 web 與 redis 服務共存,但需要保證各個服務的副本分散部署。
先創建 redis 集群:
apiVersion: apps/v1 kind: Deployment metadata: name: redis-cache spec: selector: matchLabels: app: store replicas: 3 template: metadata: labels: app: store spec: affinity: // pod 反親和性, 打散 redis 各個副本 podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - store topologyKey: "kubernetes.io/hostname" containers: - name: redis-server image: redis:3.2-alpine
再部署 web 服務,需要打散并且與 redis 服務共存,配置如下:
apiVersion: apps/v1 kind: Deployment metadata: name: web-server spec: selector: matchLabels: app: web-store replicas: 3 template: metadata: labels: app: web-store spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - web-store topologyKey: "kubernetes.io/hostname" podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - store topologyKey: "kubernetes.io/hostname" containers: - name: web-app image: nginx:1.12-alpine
注意1: pod affinity 需要進行大量處理,所以會明顯減慢大型集群的調度時間,不建議在大于幾百個節點的集群中使用該功能。六、參考資料 官方
注意2: pod antiAffinity 要求對節點進行一致標志,即集群中的所有節點都必須具有適當的標簽用于配置給 topologyKey,如果節點缺少指定的 topologyKey 指定的標簽,則可能會導致意外行為。
Assigning Pods to Nodes - Kubernetes
node affinity
pod affinity
性能優化: Improve performance of affinity/anti-affinity predicate by 20x in large clusters by bsalamat
blogK8S 的調度 (一) 抽象優雅的 Affinity
Scheduling in Kubernetes, Part 2: Pod Affinity – Koki – Medium
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/32907.html
摘要:的調度機制組件調度器會將調度到資源滿足要求并且評分最高的上。這個特性的設計初衷是為了替代,并擴展更強大的調度策略。和完全相同,以進行強制的約束。軟規則除了,,還有一條軟規則配置后,沒有相關污點策略的會盡量避免調度到該上。 k8s的調度機制 scheduler組件 k8s調度器會將pod調度到資源滿足要求并且評分最高的node上。我們可以使用多種規則比如:1.設置cpu、內存的使用要求;...
摘要:下面通過該文章來簡述的基礎信息并詳述的生命周期。聲明周期鉤子函數為容器提供了兩種生命周期鉤子于容器創建完成之后立即運行的鉤子程序。向容器指定發起請求,響應碼為或者是為成功,否則失敗。 簡述 Kubernetes 是一種用于在一組主機上運行和協同容器化應用程序的系統,提供應用部署、規劃、更新維護的機制。應用運行在 kubernetes 集群之上,實現服務的擴容、縮容,執行滾動更新以及在不...
摘要:與已運行相關的過濾規則負責檢查待調度與上已有之間的親和性關系。并且每個打分函數都可以配置對應的權重值,下面介紹調度器策略配置時,也會涉及權重值的配置。默認權重值是,如果覺得某個打分函數特別重要,便可以加大該權重值。 一、概述 Kubernetes 是 Google 開源的容器集群管理系統(谷歌內部:Borg),而今天要介紹的 kube-scheduler 是 k8s 系統的核心組件之一...
摘要:作為一個開源的分布式數據庫產品,具有多副本強一致性的同時能夠根據業務需求非常方便的進行彈性伸縮,并且擴縮容期間對上層業務無感知。另外本身維護了數據多副本,這點和分布式文件系統的多副本是有重復的。 作者:鄧栓來源:細說云計算 作為一款定位在 Cloud-native 的數據庫,現如今 TiDB 在云整合上已取得了階段性的進展。日前 Cloud TiDB 產品在 UCloud 平臺正式開啟...
摘要:在這種情況下,以防干擾其他集群租戶,調度器可能會考慮將作為驅逐的候選對象。其結果是負載均衡和調度之間交互作用。 每當談及Kubernetes,我們經常聽到諸如資源管理、調度和負載均衡等術語。雖然Kubernetes提供了許多功能,但更關鍵的還是要了解這些概念,只有這樣才能更好地理解如何放置、管理并恢復工作負載。在這篇文章中,我提供了每個功能的概述,并解釋了它們是如何在Kubernete...
閱讀 885·2021-10-27 14:19
閱讀 1102·2021-10-15 09:42
閱讀 1526·2021-09-14 18:02
閱讀 738·2019-08-30 13:09
閱讀 2981·2019-08-29 15:08
閱讀 2084·2019-08-28 18:05
閱讀 948·2019-08-26 10:25
閱讀 2777·2019-08-23 16:28