简介
前面的 nodeSelector 调度略显生硬,如果场景是:某个 Pod 最好调度到磁盘大的节点上,如果暂时没有,小点也行,比方说数据库;
如果场景是:某个 Pod,坚决不能调度到某类节点上,其余无所谓,比如说负载均衡不能调度到不对外开放端口的节点上;
诸如此类…
关于这些,nodeSelector 就不太行了。
nodeAffinity 节点亲和性
目前有两种亲和性表达:
- RequiredDuringScheduleIgnoreDuringExecution:调度时要求,执行时忽略。
- PreferedDuringScheduleIgnoreDuringExecution:调度时最好有,执行时忽略。
这什么意思呢,以第一个为例,就是调度的时候必须要有我需要的标签,调度完运行时有没有无所谓了。
第二个就是在调度的时候最好有我要的标签,没有那退而求其次吧。
动手验证:那么 nodeSelector 的 Pod 所在的 Node 在 pod 调度完成之后被删除了标签会怎么样呢?
apiVersion: v1
kind: pod
metadate:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringScheduleIgnoreDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- ["amd64","arm"]
preferedDuringScheduleIgnoreDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: disk-type
operator: In
values:
- ssd
containers:
- name: with-node-affinity
image: mysql
operator 的可选操作:
In: label的值在某个列表中
NotIn:label的值不在某个列表中
Exists:某个label存在
DoesNotExist:某个label不存在
Gt:label的值大于某个值(字符串比较)
Lt:label的值小于某个值(字符串比较)
equal:label存在且值等于指定的值
注意事项:
- 如果同时定义了nodeSelector和nodeAffinity,name必须两个条件都得到满足,pod才能最终运行在指定的node上。
- 如果nodeAffinity指定了多个nodeSelectorTerms,那么其中一个能够匹配成功即可。
- 如果在nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足所有matchExpressions才能运行该pod。
此外,我还发现了一个有趣的现象(因为这里没有一套模板,那么什么情况下字段能重复出现,什么情况下字段只有一次出现呢?在数组里可以重复出现,在字典里就出现一次。)
podAffinity
Pod 的亲和与互斥调度策略,从 1.4 版本开始引入,目的在于相关联的两种或多种 Pod 是否可以在同一个 拓扑域中共存或互斥,前者被称为 podAffinity,后者被称为 podAntiAffinity。
一个拓扑域由一些 Node 节点组成,这些 Node 节点通常有相同的地理空间坐标,在极端情况下,我们也可以认为一个 node 就是一个拓扑域。
k8s 内置了以下一些常用的默认拓扑域:
- kubernetes.io/hostname
- topology.kubernetes.io/region
- topology.kubernetes.io/zone
pod 亲和性的具体做法是通过在 Pod 上定义增加 topylogyKey 属性,来声明对应的目标拓扑域内几种相关联的 Pod 要在一起或不在一起。
亲和性调度实例
apiVersion: v1
metadate:
name: pod-flag
labels:
security: "s1"
app: "nginx"
spec:
containers:
- name: nginx
image: nginx
apiVersion: v1
metadate:
name: pod-anffinity
spec:
affinity:
podAnffinity:
requiredDuringSchedulingIgnoreDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- s1
topologyKey: kubernetes.io/hostname
containers:
- name: nginx2
image: nginx
创建 pod 之后,可以看到两个 pod 在同一个 Node 上运行。
互斥性调度实例
apiVersion: v1
metadate:
name: pod-flag
labels:
security: "s1"
app: "nginx"
spec:
containers:
- name: nginx
image: nginx
apiVersion: v1
metadate:
name: pod-anffinity
spec:
affinity:
podAnffinity:
requiredDuringSchedulingIgnoreDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- s1
topologyKey: topologyKey.kubernetes.io/zone
podAntiAnffinity:
requiredDuringSchedulingIgnoreDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: kubernetes.io/hostname
containers:
- name: nginx3
image: nginx
这里要求这个 pod 和 security=s1 的 pod 在同一个 zone,但是和 app 为 nginx 的 pod 不为同一个 node,然后就会发现它没地方去了,因为我就一个 node hhhhh。。