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定向的调度到某些的节点上了。