什么是topology key
pod親和性調度需要各個相關的pod對象運行於"同一位置", 而反親和性調度則要求他們不能運行於"同一位置",
這里指定“同一位置” 是通過 topologyKey 來定義的,topologyKey 對應的值是 node 上的一個標簽名稱,比如各別節點zone=A標簽,各別節點有zone=B標簽,pod affinity topologyKey定義為zone,那么調度pod的時候就會圍繞着A拓撲,B拓撲來調度,而相同拓撲下的node就為“同一位置”。
如果基於各個節點kubernetes.io/hostname標簽作為評判標准,那么很明顯“同一位置”意味着同一節點,不同節點既為不同位置,
一般用於:
1. 我啟動一個pod,希望(親和性)或不希望(反親和性)調度一台node上,並且這台node上有service=nginx標簽的pod
2. 我啟動一個2個副本控制器,pod標簽為service=tomcat,可以調度到任意node上,不希望兩個pod調度到同一個node上
個人理解:pod affinity的調度范圍為topology
官方解釋:
如果該X已經在運行一個或多個滿足規則Y的Pod,則該Pod應該(或者在非親和性的情況下不應該)在X中運行
Y表示為LabelSelector規則
X是一個拓撲域,例如節點,機架,雲提供者區域,雲提供者區域等。您可以使用topologyKey這是系統用來表示這種拓撲域的節點標簽的密鑰
例子:
需求:當前有兩個機房( beijing,shanghai),需要部署一個nginx產品,副本為兩個,為了保證機房容災高可用場景,需要在兩個機房分別部署一個副本
apiVersion: apps/v1 kind: StatefulSet metadata: name: nginx-affinity-test spec: serviceName: nginx-service replicas: 2 selector: matchLabels: service: nginx template: metadata: name: nginx labels: service: nginx spec: affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: service operator: In values: - nginx topologyKey: zone containers: - name: nginx image: contos7:latest command: - sleep - "360000000"
解釋:兩個node上分別有zone標簽,來標注自己屬於哪個機房,topologyKey定義為zone,pod所以在調度的時候,會根據node上zone標簽來區分拓撲域,當前用的上 反親和性調度 根據拓撲緯度調度,beijing機房調度完一個pod后,然后控制器判斷beijing 拓撲域已經有server=nginx標簽的pod,就在下一個拓撲域的node上調度了.
Pod親和性與反親和性
Pod 間的親和性與反親和性根據已經在 Node 上運行的 Pod 的標簽來調度新的 Pod 到哪個 Node 上,這些規則的形式是:
如果 X 已經運行一個或多個符合規則 Y 的 Pod,那么這個 Pod 應該(如果是反親和性,則不應該)運行在 X 上。
和 Node不同,由於 Pod 都是有命名空間的,所以基於 Pod 標簽的標簽選擇器(Label Selector)必須指定命名空間。可以通過 namespaces
(與 labelSelector
和 topologyKey
同一級) 指定,默認情況下為擁有親和性(或反親和性)的 Pod 所屬的命名空間,如果定義了 namespaces
但值是空的,則表示使用 all
命名空間。
那么,我需要 Pod 親和性或反親和性的同時,又能指定 Pod 調度到某個 Node 該如何處理呢?這就要用到接下來講的 topologyKey
了。
什么是topologyKey
顧名思義,topology
就是 拓撲
的意思,這里指的是一個 拓撲域
,是指一個范圍的概念,比如一個 Node、一個機櫃、一個機房或者是一個地區(如杭州、上海)等,實際上對應的還是 Node 上的標簽。這里的 topologyKey
對應的是 Node 上的標簽的 Key(沒有Value),可以看出,其實 topologyKey
就是用於篩選 Node 的。通過這種方式,我們就可以將各個 Pod 進行跨集群、跨機房、跨地區的調度了。
如何使用topologyKey
看下面的例子:
-
apiVersion: v1
-
kind: Pod
-
metadata:
-
name: with-pod-affinity
-
spec:
-
affinity:
-
podAffinity:
-
requiredDuringSchedulingIgnoredDuringExecution:
-
- labelSelector:
-
matchExpressions:
-
- key: security
-
operator: In
-
values:
-
- S1
-
topologyKey: failure-domain.beta.kubernetes.io/zone
-
podAntiAffinity:
-
preferredDuringSchedulingIgnoredDuringExecution:
-
- weight: 100
-
podAffinityTerm:
-
labelSelector:
-
matchExpressions:
-
- key: security
-
operator: In
-
values:
-
- S2
-
topologyKey: kubernetes.io/hostname
-
containers:
-
- name: with-pod-affinity
-
image: k8s.gcr.io/pause:2.0
這里 Pod 的親和性規則是:這個 Pod 要調度到的 Node 必須有一個標簽為 security: S1
的 Pod,且該 Node 必須有一個 Key 為 failure-domain.beta.kubernetes.io/zone
的 標簽,即 Node 必須屬於 failure-domain.beta.kubernetes.io/zone
拓撲域。
Pod 的反親和性規則是:這個 Pod 盡量不要調度到這樣的 Node,其包含一個 Key 為 kubernetes.io/hostname
的標簽,且該 Node 上有標簽為 security: S2
的 Pod。
topologyKey詳解
既然 topologyKey
是拓撲域,那 Pod 之間怎樣才是屬於同一個拓撲域?
如果使用 k8s.io/hostname
,則表示拓撲域為 Node 范圍,那么 k8s.io/hostname
對應的值不一樣就是不同的拓撲域。比如 Pod1 在 k8s.io/hostname=node1
的 Node 上,Pod2 在 k8s.io/hostname=node2
的 Node 上,Pod3 在 k8s.io/hostname=node1
的 Node 上,則 Pod2 和 Pod1、Pod3 不在同一個拓撲域,而Pod1 和 Pod3在同一個拓撲域。
如果使用 failure-domain.k8s.io/zone
,則表示拓撲域為一個區域。同樣,Node 的標簽 failure-domain.k8s.io/zone
對應的值不一樣也不是同一個拓撲域,比如 Pod1 在 failure-domain.k8s.io/zone=beijing
的 Node 上,Pod2 在 failure-domain.k8s.io/zone=hangzhou
的 Node 上,則 Pod1 和 Pod2 不屬於同一個拓撲域。
當然,topologyKey 也可以使用自定義標簽。比如可以給一組 Node 打上標簽 custom_topology
,那么拓撲域就是針對這個標簽了,則該標簽相同的 Node 上的 Pod 屬於同一個拓撲域。
注意事項
原則上,topologyKey 可以是任何合法的標簽 Key。但是出於性能和安全原因,對 topologyKey 有一些限制:
- 對於親和性和
requiredDuringSchedulingIgnoredDuringExecution
的 Pod 反親和性,topologyKey 不能為空。 - 對於
requiredDuringSchedulingIgnoredDuringExecution
的 Pod 反親和性,引入LimitPodHardAntiAffinityTopology
准入控制器來限制 topologyKey 只能是kubernetes.io/hostname
。如果要使用自定義拓撲域,則可以修改准入控制器,或者直接禁用它。 - 對於
preferredDuringSchedulingIgnoredDuringExecution
的 Pod 反親和性,空的 topologyKey 表示所有拓撲域。截止v1.12
版本,所有拓撲域還只能是kubernetes.io/hostname
、failure-domain.beta.kubernetes.io/zone
和failure-domain.beta.kubernetes.io/region
的組合。 - 除上述情況外,topologyKey 可以是任何合法的標簽 key。