亲和性调度功能包括节点亲和性(NodeAffinity)和Pod亲和性(PodAffinity)两个维度的设置。

NodeAffinity:Node亲和性调度

NodeAffinity意为Node亲和性的调度策略,是用于替换NodeSelector的全新调度策略,目前有两种节点亲和性表达。

  • RequireDuringSchedulingIgnoredDuringExecution:必须满足指定的规则才可以调度Pod到Node上(功能与NodeSelector很像,但是使用的是不同的语法),相当于硬限制。
  • PrefeeredDuringSchedulingIgonredDuringExecution:强调优先满足指定规则,调度器会尝试调度Pod到Node上,但并不强求,相当于软限制。多个优先级规则还可以设置权重(weight)值,以定义执行的先后顺序。

IgnoredDuringExecution的意思是:如果一个Pod所在的节点在Pod运行期间标签发生了变更,不再符合该Pod的节点亲和性需求,则系统将忽略Node上Label的变化,该Pod能继续在该节点运行。

下面的例子设置了NodeAffinity调度的如下规则。

  • requiredDuringSchedulingIgnoredDuringExecution 要求只运行在amd64的节点上(beta.kubernetes.io/arch In amd64)
  • preferredDuringSchedulingIgnoreDuringExecution 的要求是尽量运行在磁盘类型为ssd(disk-type In ssd)的节点上

代码如下:

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: beta.kubernetes.io/arch
            operator: In
            values:
            - amd64
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: disk-type
            operator: In
            values:
            - ssd
  containers:
  - name: with-node-affinity
    image:gcr.io/google_containers/pause:2.0

NodeAffinity语法支持的操作符包括In、NotIn、Exists、DoesNotExist、Gt、Lt。
虽然没有节点排斥功能,但是NotIn和DoesNotExist就可以实现排斥的功能了。

NodeAffinity 规则设置的注意事项如下:

  • 如果同时定义了nodeSelector和nodeAffinity,那么必须两个条件都得到满足,Pod才能最终运行在指定Node上。
  • 如果nodeAffinity指定了多个nodeSelectorTerms,那么其中一个能够匹配成功即可。
  • 如果在nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足所有matchExpressions才能运行该Pod。

PodAffinity: Pod亲和性与互斥调度策略

根据在节点上正在运行的Pod的标签而不是节点的标签进行判断和调度,要求对节点和Pod两个条件进行匹配。这种规则可以描述为:如果在具有标签X的Node上运行了一个或多个符合条件Y的Pod,那么Pod应该(如果是互斥的情况,那么就变成拒绝)运行在这个Node上。

这里X指的是一个集群中的节点、机架、区域等概念,通过k8s内置节点标签中的key来进行声明。这个key的名字为topologyKey,意为表达节点所属的topology范围。

  • kubernetes.io/hostname
  • failure-domain.beta.kubernetes.io/zone
  • failuer-domain.beta.kubernetes.io/region

与节点不同的是,Pod是属于某个命名空间的,所以条件Y表达的是一个或者全部命名空间中的一个LabelSelector。

和节点亲和性相同,Pod亲和性与互斥的条件设置也是requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingInnoredDuringExecution。

Pod的亲和性被定义为PodSpec的affinity字段下的podAffinity子字段中。

Pod间的互斥性则被定义于同一层次的podAntiAffinity子字段中。

Pod的亲和性调度

下面通过实例来说明Pod间的亲和性和互斥性策略设置。

1.参照目标Pod

首先,创建一个名为pod-flag的Pod,带有标签security=S1和app=nginx,后面的例子将使用pod-flag作为Pod亲和性与互斥的目标Pod:

apiVersion: v1
kind: Pod
metadata:
  name: pod-flag
  labels:
    security: "S1"
    app: "nginx"
spec:
  containers:
  - name: nginx
    image: nginx

2.Pod的亲和性调度

下面创建第二个Pod来说明Pod的亲和性调度,这里定义的亲和标签是security=S1,对应上面的Pod ”pod-flag“,topologyKey的值被设置为”kubernetes.io/hostname“:

apiVersion: v1
kind: Pod
metadata:
  name: pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelectors:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: kubernetes.io/hostname
  containers:
  - name: with-pod-affinity
    image: gcr.io/google_containers/pause:2.0

创建Pod之后,使用kubectl get pods -o wide 命令可以看到,这两个Pod在同一个Node上运行。
查看node labels命令:kubectl get nodes --show-labels

3.Pod的互斥性调度

创建第3个Pod,我们希望它不与目标Pod运行在同一个Node上:

apiVersion: v1
kind: Pod
metadata:
  name: anti-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operation: In
            values:
            - S1
        topologyKey: failure-domain.beta.kubernetes.io/zone
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
        matchExpressions:
        - key: app
          operation: In
          values:
          - nginx
        topologyKey: kubernetes.io/hostname
   containers:
   - name: anti-affinity
     image: gcr.io/google_containers/pause:2.0

这里要求这个新Pod与security=S1的Pod为同一个zone,但是不与app=nginx的Pod为同一个Node。创建Pod之后,同样用kubectl get pods -o wide来查看,会看到新的Pod被调度到了同一zone内的不同Node上。

与节点亲和性类似,Pod亲和性的操作符也包括In、NotIn、Exists、DoesNotExist、Gt、Lt。

原则上,topologyKey可以使用任何合法的标签Key赋值,但是出于性能和安全方面的考虑,对topologyKey有如下限制。

  • 在Pod亲和性和RequiredDuringScheduling的Pod互斥性的定义中,不允许使用空的topologyKey。
  • 如果Admission controlloer 包含了LimitPodHardAntiAffinityTopology,那么针对RequiredDuringScheduling的Pod互斥性定义就被限制为kubernetes.io/hostname,要使用自定义的topologyKey,就要改写或禁用该控制器。
  • 在preferredDuringScheduling类型的Pod互斥性定义中,空的topologyKey会被解释为kebernetes.io/hostname、failure-domain.beat.kubernetes.io/zone及failure-domain.beta.kubernetes.io/region的组合。
  • 如果不是上述情况,就可以采用任意合法的topologyKey了。

PodAffinity规则设置的注意事项如下。

  • 除了设置Label Selector和topologyKey,用户还可以指定Namespace列表来进行限制,同样,使用Label Selector对Namespace进行选择。Namespace的定义和Label Selector及topologyKey同级。省略Namespace的设置,表示使用定义了affinity/anti-affinity的Pod所在的Namespace。如果Namespace被设置为空值(”“),则表示所有Namespace。
  • 在所有关联requiredDuringSchedulingIgnoredDuringExecution的matchExpressions全部满足之后,系统才能将Pod调度到某个Node上。

 

 

 

 

 

 

 

 

 

 

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐