四、kubernetes之pod的调度(二)

能够影响Pod调度的资源属性主要有如下5种:

  1. NodeSelector (工作节点选择器)
  2. NodeAffinity (工作节点级亲和性)
  3. PodAffinity (Pod级的亲和性)
  4. Taints和Tolerations(污点和容忍)
  5. pod的资源限制和要求

NodeSelector(硬性要求)

根据node上的标签,指定Pod可以调度到哪些node工作节点上。如果所有的node节点上都没有符合标签,则Pod不会被创建。

使用方式如下:
template.spec.nodeselector:键值对(k:v,标签)

NodeAffinity

Affinity的优点:

  • 匹配有更多的逻辑组合,不只是字符串的完全相等
  • 调度分成软策略(soft)和硬策略(hard),在软策略下,如果没有满足调度条件的节点,pod会忽略这条规则,继续完成调度。

目前主要的node affinity:

  • requiredDuringSchedulingIgnoredDuringExecution表示pod必须部署到满足条件的节点上,如果没有满足条件的节点,就不停重试。其中IgnoreDuringExecution表示pod部署之后运行的时候,如果节点标签发生了变化,不再满足pod指定的条件,pod也会继续运行。
  • requiredDuringSchedulingRequiredDuringExecution表示pod必须部署到满足条件的节点上,如果没有满足条件的节点,就不停重试。其中RequiredDuringExecution表示pod部署之后运行的时候,如果节点标签发生了变化,不再满足pod指定的条件,则重新选择符合要求的节点。
  • preferredDuringSchedulingIgnoredDuringExecution表示优先部署到满足条件的节点上,如果没有满足条件的节点,就忽略这些条件,按照正常逻辑部署。
  • preferredDuringSchedulingRequiredDuringExecution表示优先部署到满足条件的节点上,如果没有满足条件的节点,就忽略这些条件,按照正常逻辑部署。其中RequiredDuringExecution表示如果后面节点标签发生了变化,满足了条件,则重新调度到满足条件的节点。

对于软策略还可以为其设置权重weight

一个官方实例:

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/e2e-az-name
            operator: In
            values:
            - e2e-az1
            - e2e-az2
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
 - name: with-node-affinity
    image: gcr.io/google_containers/pause:2.0

这里的匹配逻辑是label在某个列表中,可选的操作符有:

  • In: label的值在某个列表中
  • NotIn:label的值不在某个列表中
  • Exists:某个label存在
  • DoesNotExist:某个label不存在
  • Gt:label的值大于某个值(字符串比较)
  • Lt:label的值小于某个值(字符串比较)
    可利用NotIn和DoesNotExist来实现对node排斥的功能

特别注意
如果同时定义了nodeselector和NodeAffinity,则需要两者同时满足
如果定义了多个nodeselectorTerms,则只需要有一个满足
如果定义了多个matchExpressions,只需要满足所有的matchExpressions

PodAffinity

实现能够考虑pod之间的关系,而不只是pod与node的关系来进行调度。情况1(亲和):有两个应用pod交互的比较多,希望在同一node;情况2(互斥):有两个Pod都有大读写,希望不要调度在同一个node上。

通过topologyKey来表达对node节点的选择,topologyKey指向node节点内置标签的KEY;意为表达节点所属的topology范围:

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

和node affinity相似,pod affinity 也有requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution,意义也和之前一样。如果使用亲和性,在 affinity 下面添加 podAffinity 字段,如果要使用互斥性,在 affinity 下面添加 podAntiAffinity 字段。

先定义一个参照目标pod:

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

Pod亲和性调度
下面是一个亲和性调度的示例

apiVersion: v1
kind: Pod
metadata:
  name: pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          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与上面那个参照的pod位于同一个node上,另外,如果将这个node上的kubernetes.io/hostname标签干掉,将会发现pod会一直处于pending状态,这是因为找不到满足条件的node了。

pod互斥性调度
下面是一个互斥性调度的示例:

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: "failure-domain.beta.kubernetes.io/zone"
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: kubernetes.io/hostname
  containers:
  - name: with-pod-affinity
    image: gcr.io/google_containers/pause:2.0

这个例子要求这个新pod与security=S1的pod为同一个zone,但是不与security=S2的pod为同一个node。

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

  1. 在pod亲和性和RequiredDuringScheduling的pod互斥性的定义中,不允许使用空的topologyKey
  2. 如果admissioncontroller包含了LimitPodHardAntiAffinityTopology,那么针对RequiredDuringScheduling的pod互斥性定义就被限制为kubernetes.io/hostname,要使用自定义的topologyKey,就要改写或禁用该控制器
  3. 在PerferredDuringScheduling类型的Pod互斥性定义中,空的topologyKey会被解释为kubernetes.io/hostname、failure-domain.beta.kubernetes.io/zone及failure-domain.beta.kubernetes.io/region的组合

podAffinity规则设置的注意事项:

在labelSelector和topologyKey同级,还可以定义namespaces列表,表示匹配哪些namespace里面的pod,默认情况下,会匹配定义的pod所在的namespace,如果定义了这个字段,但是它的值为空,则匹配所有的namespaces。
所有关联requiredDuringSchedulingIgnoredDuringExecution的matchExpressions全都满足之后,系统才能将pod调度到某个node上。

Taint(污点)和Toleration(容忍)

Taint需要与Toleration配合使用,让pod避开那些不合适的node。在node上设置一个或多个Taint后,除非pod明确声明能够容忍这些“污点”,否则无法在这些node上运行。Toleration是pod的属性,让pod能够(注意,只是能够,而非必须)运行在标注了Taint的node上。

举例说明
设置node的污点

kubectl taint nodes node1  key=value:NoSchedule

Taint污点的组成有KEY表示键名,VALUE表示KEY的值,NoSchedule表示效果。
效果一共有三种:

  • NoSchedule:Pod除非设置容忍这个属性,否则无法调度到此node
  • PreferNoSchedule:Pod除非设置容忍这个属性,否则避免调度到此node
  • NoExecute:pod的驱逐行为,以应对节点故障。NoExecute这个Taint效果对节点上正在运行的pod有以下影响:
  1. 没有设置Toleration的Pod会被立刻驱逐
  2. 配置了对应Toleration的pod,如果没有为tolerationSeconds赋值,则会一直留在这一节点中
  3. 配置了对应Toleration的pod且指定了tolerationSeconds值,则会在指定时间后驱逐

设置pod的容忍

apiVersion: v1
kind: Pod
metadata:
  name: pod-taints
spec:
  tolerations:
 - key: "key"
    operator: "Equal"
    value: "value"
    effect: "NoSchedule"
  containers:
    - name: pod-taints
      image: busybox:latest

也可以写成如下:

tolerations:
 - key: "key"
  operator: "Exists"
  effect: "NoSchedule"

pod的Toleration中的key和effect需要与Taint的设置保持一致,并且满足以下条件之一

  • operator的值为Exists,这时无需指定value
  • operator的值为Equal并且value相等(默认)

多污点和多容忍
Kubernetes调度器处理Toleration对Taint进行匹配,剩下的没有匹配掉的Taint就是对Pod的效果了。下面是几种特殊情况:

  1. 如果剩余的Taint中存在effect=NoSchedule,则调度器不会把该pod调度到这一节点上。
  2. 如果剩余的Taint中没有NoSchedule的效果,但是有PreferNoSchedule效果,则调度器会尝试不会pod指派给这个节点
  3. 如果剩余Taint的效果有NoExecute的,并且这个pod已经在该节点运行,则会被驱逐;如果没有在该节点运行,也不会再被调度到该节点上。
发布了40 篇原创文章 · 获赞 2 · 访问量 2053

猜你喜欢

转载自blog.csdn.net/weixin_42155272/article/details/100518318