k8s中,什么是pod亲和性、反亲和性,以及如何在k8s中进行应用?
1、概述
我们在现实的环境中,会有这些的场景,比如,需要根据节点上运行的pod来决定,这个pod是否要被调度到该节点上。
这,就涉及到了k8s中的一个概念,pod亲和性、pod反亲和性,这个和节点亲和性很相似,就是根据节点上运行的标签,而部是节点的标签进行判断和调度。
更重要的是,pod亲和性,主要是在调度的时候的一个作用。
同时,也实现了一个功能:就是通过另外的一种方式来限制pod所能运行的节点。
接下来,我们通过一个实际的例子,看下,如何在k8s中使用pod亲和性、反亲和性,这个特性。
2、pod亲和性调度策略
那,我们知道,所谓的亲和也好、互斥也好,都是针对于某个目标来说的,那,我们就先创建一个参照的pod
- 创建一个参照的pod
通过以下的yaml配置文件,创建参考pod
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-flag
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
security: S1
app: nginx
spec:
containers:
- image: 172.20.58.152/middleware/nginx:1.21.4
name: nginx
查看创建好的pod
[root@nccztsjb-node-23 ~]# kubectl get pod -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
pod-flag-7d4d89f9c9-whf22 1/1 Running 0 3m19s 172.39.157.244 nccztsjb-node-24 app=nginx,pod-template-hash=7d4d89f9c9,security=S1
[root@nccztsjb-node-23 ~]#
已经创建好了这个pod,运行在节点nccztsjb-node-24上,并且都带上了对应的标签。
OK,我们已经创建好了这个参照pod,后续的例子,将使用这个pod作为亲和与互斥的目标pod.
- pod的亲和性调度
现在创建第2个pod,通过亲和性标签,security=S1来定位之前的参考pod
kubectl apply -f - <
查看创建的pod
[root@nccztsjb-node-23 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-affinity-64b7774db8-vjgs5 1/1 Running 0 8s 172.39.157.247 nccztsjb-node-24
pod-flag-7d4d89f9c9-whf22 1/1 Running 0 22h 172.39.157.244 nccztsjb-node-24
[root@nccztsjb-node-23 ~]#
发现,这次发的pod已经和参考pod在一个节点上了。
这里面有个参数:topologyKey。这个参数主要是用来选择节点的,通过节点上的key来表示,也就是说,在节点上有这个标签,然后这个在包含这个key的节点上,有pod包含security=S1这样的标签的时候,是要将pod调度到这个节点上来的。
OK,这样就达到了一个限制pod运行节点上的一个效果。
- 删除掉节点的kubernetes.io/hostname,看调度情况
[root@nccztsjb-node-23 ~]# kubectl label node nccztsjb-node-24 kubernetes.io/hostname-
node/nccztsjb-node-24 unlabeled
再次进行pod发布
kubectl apply -f - <
[root@nccztsjb-node-23 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-affinity-7d8598689d-2cg5z 0/1 Pending 0 3s
pod-flag-7d4d89f9c9-whf22 1/1 Running 0 23h 172.39.157.244 nccztsjb-node-24
[root@nccztsjb-node-23 ~]#
发现,pod是处于pending状态,也就是说,不满足topologykey中指定的节点的条件。
即亲和性、反亲和性,首先是找到满足key的节点,然后再是上面的符合标签的pod.
3、pod反亲和性(互斥性)调度策略
接下来,我们要创建的这个pod,我们不希望它与参考pod运行在同一个主机上。
通过以下的pod创建pod,指定podAntiAffinity
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-antiaffinity
spec:
selector:
matchLabels:
app: pod-antiaffinity
replicas: 1
template:
metadata:
labels:
app: pod-antiaffinity
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: kubernetes.io/hostname
containers:
- image: 172.20.58.152/middleware/nginx:1.21.4
name: pod-antiaffinity
查看创建的pod
[root@nccztsjb-node-23 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-antiaffinity-d57996c54-w67tx 1/1 Running 0 84s 172.39.21.69 nccztsjb-node-25
pod-flag-7d4d89f9c9-whf22 1/1 Running 0 26h 172.39.157.244 nccztsjb-node-24
[root@nccztsjb-node-23 ~]#
发现先建的pod没有和参考pod在一个节点上。
那么,我们多创建些实例(副本数改成5),看看结果:
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-antiaffinity
spec:
selector:
matchLabels:
app: pod-antiaffinity
replicas: 5
template:
metadata:
labels:
app: pod-antiaffinity
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: kubernetes.io/hostname
containers:
- image: 172.20.58.152/middleware/nginx:1.21.4
name: pod-antiaffinity
发现,5个副本,没有一个副本和参考pod在一个节点上的。
OK,这样通过pod的反亲和性设置,就将pod定向的调度到某些的节点上了。