topology key
什么是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。