如何在k8s中定义多个筛选条件

47 阅读3分钟

定义单个筛选条件

定义单个筛选条件,大家用的最多的应该是 nodeSelector,即节点选择器,nodeSelector可以定义到kind为pod的资源中,也可以定义到kind为deployment的资源中

例如,如果想要求k8s分配的pod运行在amd64架构的节点上,可以这样定义

nodeSelector:
  beta.kubernetes.io/arch: amd64

但是nodeSelector的定义具有局限性,一个是要求节点具有相应的标签,不然无法被条件筛选到;另一个是只能使用一个标签,且一个标签只能拥有一个值,这意味着不能筛选同时满足多个条件的节点,也无法筛选只满足其中某个条件的节点。换句话说,就是无法做到定义与条件(多个条件满足即为满足)以及或条件(满足多个条件中的任一条件即为满足)。

定义多个筛选条件

nodeAffinity和podAffinity

为了解决上述问题,k8s提供了affinity(亲和性)机制。affinity机制提供了两种affinity的定义,一种是podAffinity(用于定义pod的筛选条件),另一种是nodeAffinity(用于定义node的筛选条件),两者的属性相同,只是作用的资源不同。

下面以nodeAffinity为例进行介绍

requiredDuringSchedulingIgnoredDuringExecution

使用requiredDuringSchedulingIgnoredDuringExecution可以标记必须满足的条件,比如以下例子要求具备标签topology.kubernetes.io/zone ,且标签的值必须为antarctica-east1或antarctica-west1,同时需要具备kubernetes.io/arch标签 ,且标签的值必须是amd64

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - antarctica-east1
            - antarctica-west1
          - key: kubernetes.io/arch
            operator: In
            values:
            - amd64

  containers:
  - name: with-node-affinity
    image: registry.k8s.io/pause:2.0

实际上requiredDuringSchedulingIgnoredDuringExecution可以匹配label,也可以匹配非label字段,匹配非label字段时,需要使用matchFields字段,与matchExpressions字段的定义相似

另外在多个nodeSelectorTerm之间只要满足其中之一 即可,因为它们之间是逻辑或的关系

preferredDuringSchedulingIgnoredDuringExecution

使用requiredDuringSchedulingIgnoredDuringExecution可以标记倾向于满足的条件,增加一个weight值(要求为Integer类型,数字越大表示权重越高,其取值范围是 1 到 100),如下所示,one-node-label-key的匹配权重为1,another-node-label-key的匹配权重为5,则分发pod时,会按照此权重进行加权分配。

apiVersion: v1
kind: Node
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: one-node-label-key
            operator: In
            values:
            - one-node-label-value
      - weight: 5
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: registry.k8s.io/pause:2.0

定义反向筛选条件(podAntiAffinity)

定义反向筛选条件可以使用podAntiAffinity,在下面的例子中,要求不能分配在app标签值为web-store的节点上

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  selector:
    matchLabels:
      app: web-store
  replicas: 3
  template:
    metadata:
      labels:
        app: web-store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web-store
            topologyKey: "kubernetes.io/hostname"
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - store
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: web-app
        image: nginx:1.16-alpine

更复杂的条件

将上面的筛选条件结合起来使用,理论上可以满足所有复杂的筛选条件