1.前言

k8s的亲和性和反亲和性都是通过标签来影响pod的调度,在此基础上亲和性又分为硬亲和性和软亲和性,required为硬亲和性即标签内容必须要符合才能调度,preferred为软亲和性即标签内容不一定要符合也能调度,除此之外还有node亲和性和pod亲和性,接下来都使用一下这些亲和性的功能

2.node亲和性

2.1node软亲和性

先编辑一个yaml文件

vi deployment-nginx.yaml 

apiVersion: apps/v1
kind: Deployment
metadata: 
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 5
  progressDeadlineSeconds: 600
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec: 
      containers:
      - name: nginx
        image: nginx:1.21
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
      affinity:       #亲和性配置项
        nodeAffinity:       #node亲和性配置项
          preferredDuringSchedulingIgnoredDuringExecution:  #软亲和性配置项
            - weight: 70         #配置权重
              preference:
                matchExpressions:
                - key: key1      #配置标签key的值
                  operator: In    #配置操作符
                  values:        #配置标签values的值
                    - value1
            - weight: 30         #配置权重
              preference:
                matchExpressions:
                - key: key2
                  operator: In
                  values:
                    - value2

配置一下node节点的标签,给node01节点打上权重高的标签,node02节点打上权重低的标签

kubectl label node k8s-node01 key1=value1

kubectl label node k8s-node02 key2=value2

执行yaml文件

kubectl create -f deployment-nginx.yaml

查看一下pod再node上的分配情况

kubectl get pod -o wide -n default -l app=nginx

kubernetes pod亲和性和节点亲和性优先级_云原生

 可以看到node01上分配的pod比node02节点多,这就是权重导致的,软亲和性是不强制要求调度到特定节点的,可以把node节点的label标签删掉,再重新创建delpoyment,pod依然能正常调度,我这里只贴一下效果,就不展示过程了

kubernetes pod亲和性和节点亲和性优先级_容器_02

2.2node硬亲和性

 编辑一下yaml文件

vi deployment-nginx.yaml 

apiVersion: apps/v1
kind: Deployment
metadata: 
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 5
  progressDeadlineSeconds: 600
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec: 
      containers:
      - name: nginx
        image: nginx:1.21
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
      affinity:  
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:   #硬亲和性配置项
            nodeSelectorTerms:   #通过 nodeSelectorTerms,可以指定多个节点标签的匹配规则,从而更加灵活地控制 Pod 的调度,再有多个nodeSelectorTerms时,他们的关系为或,即node节点满足任意一个nodeSelectorTerms中的规则时,就可以把pod调度到该节点上
            - matchExpressions:    #通过 matchExpressions,可以精确地指定一个节点标签的匹配规则,从而更加精细地控制 Pod 的调度,在使用多个matchExpressions的情况下,他们的关系为且,即node节点需要满足所有matchExpressions项的规则才可以把pod调度到该节点上
              - key: key1
                operator: In
                values:   #这里配置了两个values值,因为控制项使用的是In,只要node满足其中一个即可调度
                - value1
                - value2

我现在的node节点上是没有标签的,先来测试一下pod的调度情况

kubernetes pod亲和性和节点亲和性优先级_容器_03

可以看到因为设置了硬亲和性的原因pod调度不到任何一个node节点上,状态为pending,接下来我们给node01打上符合yaml文件硬亲和性的标签看看效果

kubectl label node k8s-node01 key1=value1 

kubernetes pod亲和性和节点亲和性优先级_容器_04

 可以看到给node01节点打上标签后,所有pod都调度到了node01节点上了

3.pod亲和性和反亲和性

 3.1pod软亲和性

 编辑一下yaml文件

vi deployment-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata: 
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 5
  progressDeadlineSeconds: 600
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec: 
      containers:
      - name: nginx
        image: nginx:1.21
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
      affinity:
        podAffinity:   #pod亲和性配置项
          preferredDuringSchedulingIgnoredDuringExecution:  #软亲和性配置项
          - weight: 70    #配置权重
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: key1
                  operator: In
                  values:
                  - value1
              topologyKey: zone   #在 PodAffinity 中,topologyKey 配置项用于指定 Pod 应该调度到哪些节点上。例如,可以将 topologyKey 设置为 kubernetes.io/hostname,这样 Pod 将调度到与它在同一主机上的节点上
          - weight: 30
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: key2
                  operator: In
                  values:
                  - value2
              topologyKey: zone

执行以下yaml文件看一下效果

kubectl create -f  deployment-nginx.yaml

kubernetes pod亲和性和节点亲和性优先级_容器_05

 pod软亲和性表示Pod将尽可能被调度到与它们亲和的pod所在的节点上,但如果没有符合条件的pod,Pod仍然可以被调度到其他节点上

 3.2pod硬亲和性

编辑一下yaml文件

vi deployment-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata: 
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 5
  progressDeadlineSeconds: 600
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec: 
      containers:
      - name: nginx
        image: nginx:1.21
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution: #硬亲和性配置项
          - labelSelector:
              matchExpressions:
              - key: key1
                operator: In
                values:
                - value1
            topologyKey: kubernetes.io/hostname

执行以下yaml文件看一下效果

kubectl create -f  deployment-nginx.yaml

kubernetes pod亲和性和节点亲和性优先级_容器_06

现在集群中是没有pod的,没有可以满足pod硬性亲和条件的pod,所以pod无法调度,现在创建两个不符合以上条件标签的pod看看效果

vi web1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web
  name: web1
spec:
  replicas: 2
  selector:
    matchLabels:
      key3: value3
  template:
    metadata:
      labels:
        key3: value3  #这里pod使用的标签和上面亲和性的标签不一致
    spec:
      containers:
      - image: nginx:1.19
        name: nginx1

kubectl create -f web1.yaml

kubectl get pod -o wide

kubernetes pod亲和性和节点亲和性优先级_nginx_07

可以看到依旧没有满足硬亲和性调度的条件,pod还是pending状态,接下来创建一个符合以上条件标签的pod看看效果

vi web.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: web
  name: web
spec:
  replicas: 1
  selector:
    matchLabels:
      key1: value1
  template:
    metadata:
      labels:
        key1: value1   #此处使用与硬亲和性条件一样的label
    spec:
      containers:
      - image: nginx:1.19
        name: nginx

kubectl create -f web.yaml

kubectl get pod -o wide

kubernetes pod亲和性和节点亲和性优先级_kubernetes_08

可以看到有满足硬亲和性条件标签的pod后,所有pod都调度到了与该pod相同的节点上

pod硬亲和性表示Pod必须被调度到与它们亲和的pod的节点上,否则它们将无法被调度

3.3pod硬反亲和性

编辑一下yaml文件

vi deployment-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata: 
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 5
  progressDeadlineSeconds: 600
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec: 
      containers:
      - name: nginx
        image: nginx:1.21
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
      affinity:
        podAntiAffinity:  #反亲和性配置项
          requiredDuringSchedulingIgnoredDuringExecution:   #硬反亲和性配置项
          - labelSelector:
              matchExpressions:
              - key: key1
                operator: In
                values:
                - value1
            topologyKey: zone   #避免pod调度到故障节点上

上一个试验创建的web和web1的pod还没删除,使用他们来验证一下硬反亲和性,web使用的标签是符合硬反亲和性的条件,执行一下这个yaml看看效果

kubectl create -f deployment-nginx.yaml

kubectl get pod -o wide

kubernetes pod亲和性和节点亲和性优先级_云原生_09

可以看到因为硬反亲和性的原因,所有创建的nginx pod都和web pod不在同一个节点上

3.4pod软反亲和性

编辑一下yaml文件

vi deployment-nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata: 
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 5
  progressDeadlineSeconds: 600
  minReadySeconds: 10
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec: 
      containers:
      - name: nginx
        image: nginx:1.21
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
      affinity:
        podAntiAffinity:  #反亲和性配置项
          preferredDuringSchedulingIgnoredDuringExecution:   #软反亲和性配置项
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: key1
                  operator: In
                  values:
                  - value1
              topologyKey: zone

 依然使用带有符合反亲和性条件的web pod,执行一下yaml看看效果

kubectl create -f deployment-nginx.yaml

kubectl get pod -o wide

kubernetes pod亲和性和节点亲和性优先级_nginx_10

 可以看到因为软反亲和性的原因,有一些nginx pod调度到了和web pod相同的节点上

亲和性和反亲和性的使用展示就这么多,接来下所以下上面使用到的配置项的补充

operator:用于指定匹配规则的操作符,operator参数可以设置为In、NotIn、Exists、DoesNotExist、Gt、Lt、Gte、Lte、DoubleEqual、NotEqual等值中的一种

In:表示标签的值必须包含在给定的值列表中

NotIn:表示标签的值不能包含在给定的值列表中

Exists:表示标签必须存在

DoesNotExist:表示标签必须不存在

Gt:表示标签的值必须大于给定的值

Lt:表示标签的值必须小于给定的值

Gte:表示标签的值必须大于或等于给定的值

Lte:表示标签的值必须小于或等于给定的值

DoubleEqual:表示标签的值必须等于给定的值

NotEqual:表示标签的值不能等于给定的值