命令记不住

登陆

k8s 亲和性 / 反亲和性 / 污点 / 容忍

亲和性 反亲和性 污点 容忍

1.nodeSelector

nodeSelector:用于将Pod调度到匹配Label的Node上,如果没有匹配的标签会调度失败

作用:

  • 约束Pod到特定的节点运行
  • 完全匹配节点标签

应用场景:

  • 专用节点:根据业务线将Node分组管理
  • 配备特殊硬件:部分Node配有SSD硬盘、GPU

需求

确保Pod分配到具有SSD硬盘的节点

查看标签

# kubectl get node --show-labels

给节点打上标签

# kubectl label node cka-node1 disktype=ssd

添加nodeSelector字段到Pod配置中

# kubectl run pod1 --image=nginx --dry-run=client -o yaml > /tmp/pod1.yaml

#cat  pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: pod1
  name: pod1
spec:
  nodeSelector:
    disktype: "ssd"
  containers:
  - image: nginx
    name: pod1
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

验证

# kubectl get pods -o wide

排错

# kubectl describe pod pod2
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  16s   default-scheduler  0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector.
  Warning  FailedScheduling  14s   default-scheduler  0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector.

删除Node标签

# kubectl label node cka-node1 disktype-

2.亲和性调度

nodeAffinity:节点亲和性

podAffinity:pod 亲和性

podAntiAffinity:pod 反亲和性

preferredDuringSchedulingIgnoredDuringExecution:软策略

requiredDuringSchedulingIgnoredDuringExecution:硬策略

在默认的K8S调度中,一般经过预选和优选即可完成调度,但是生产的实际使用中,考虑到部分业务的特殊性,一般会手动进行一些"指定", K8S 把这些"指定"分为nodeAffinity(节点亲和性)、podAffinity(pod 亲和性) 以及 podAntiAffinity(pod 反亲和性), 这在调度过程中,称之为亲和性调度
亲和性调度可以分成软策略(preferredDuringSchedulingIgnoredDuringExecution )和硬策略(requiredDuringSchedulingIgnoredDuringExecution)两种方式,软策略意思是如果现在没有满足调度要求要求的话,那就跳过这条策略,继续调度,总结起来就是"有则用之,无则跳过", 而硬策略相对就强硬很多,如果不满足调度策略,则不停重试,直到满足策略。

3.nodeAffinity

nodeAffinity: 节点亲和类似于nodeSelector,可以根据节点上的标签来约束Pod可以调度到哪些节点

pod 有podAffinity和podAntiAffinity,但是node 却只有nodeAffinity,这是因为operator , operator 是匹配表达式的操作符,nodeAffinity支持In, NotIn, Exists, DoesNotExist, Gt和Lt,所以想支持"nodeAntiAffinity"只要operator使用NotIn或者DoesNotExist就可以实现了。

相比nodeSelector:

  • 匹配有更多的逻辑组合,不只是字符串的完全相等,支持的操作符有:In、NotIn、Exists、DoesNotExist、Gt、Lt
  • 调度分为软策略和硬策略,而不是硬性要求
    • 硬(required):必须满足
    • 软(preferred):尝试满足,但不保证

可以添加多个策略

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: k8s.gcr.io/pause:2.0

.

4.pod亲和性和反亲和性

podAffinity和podAntiAffinity:

1.podAffinity

  • topologyKey

podAffinity的operator支持In, NotIn, Exists, DoseNotExit。

相对nodeAffinity,podAffinity多了一个topologyKey,topologyKey可以理解为拓扑域,在yaml里的意思是调度需要对应的node有对应的标签,而不关心这个label对应的值。

假设反topologykey是idc的维度,公司有北京上海2个idc,pod的副本数量为2,那么pod在完成了topologykey-idc=beijing之后,根据podAntiAffinity的策略,则不会在同样个zone的topologykey在创建了,而会创建在shanghai,从而做到了IDC的均衡部署。

2.podAntiAffinity

Pod 反亲和性(podAntiAffinity)则是反着来的,比如一个节点上运行了某个 Pod,那么我们的模板 Pod 则不希望被调度到这个节点上面去了。

5.污点和容忍

亲和性和反亲和性的作用是为了让pod可以根据需要调度到自己像分配的一个或者一组node上,污点的作用其实就是反过来,就是给node打上一个特殊的标签,让该node不再被分配pod,除非该pod容忍了该污点。假设有服务器硬件发生了预告警,或者服务器维保到期需要预下线,那么从服务器等待维护/预下线到真正服务器不在提供服务的周期里,该node不会被调度。

taints:避免Pod调度到特定Node上

effect 支持以下3种:
  • NoSchedule //不会将 Pod 调度到有污点的 Node
  • PreferNoSchedule //避免将 Pod 调度到有污点的 Node
  • NoExecute //不会将 Pod 调度到有污点的 Node, 将已经存在的 Pod 驱逐出去
添加污点

格式:

kubectl taint node [node] key=value:[effect]

示例:

#kubectl taint node cka-node2 memtype=samsung:NoSchedule
node/cka-node2 tainted

验证:

#kubectl describe node cka-node2   |  grep  Taint
Taints:             memtype=samsung:NoSchedule
去掉污点
#kubectl taint  node  cka-node2  memtype:NoSchedule-
node/cka-node2 untainted

tolerations:允许Pod调度到持有Taints的Node上

假设NodeA存在"node-role.kubernetes.io/maintenance"的标签,该pod可以容忍NoSchedule的污点。容忍存在以下默认场景:

  • 如果不指定 operator 属性,则operator默认值为 Equal
  • 空的 key 如果再配合 Exists 就能匹配所有的 key 与 value,也就是能容忍所有节点的所有 Taints
  • 空的 effect 匹配所有的 effect
  • 如果需要容忍多个污点,就写多个-key:–effect的过滤策略即可。
#cat  tolrations.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: tolrations
  name: tolrations
spec:
  tolerations:
  - key: memtype
    operator: "Equal"
    value: "samsung"
    effect: "NoSchedule"
  containers:
  - image: nginx
    name: tolrations
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

应用场景:

  • 专用节点,根据业务线将Node分组管理,希望在默认情况下不调度该节点,只有配置了污点容忍才允许分配
  • 配备特殊硬件,部分Node配有SSD硬盘、GPU、希望在默认情况下不调度该节点,只有配置了污点容忍才允许分配
  • 基于Taint的驱逐

6.调度失败原因分析

查看调度结果:

kubectl  get  pod  <NAME>  -o   wide

查看调度失败原因

kubect  describe  pod  <NAME>
  • 节点CPU/内存不足
  • 有污点,没容忍
  • 没有匹配到节点标签
推荐阅读