Kubernetes调度之Taints以及Tolerations

一般情况下我们部署的 Pod 是通过集群自动调度选择某个节点的,默认情况下调度器考虑的是资源足够,并且负载尽量平均,但是有的时候我们需要能够更加细粒度的去控制 POD 的调度。这就需要用到 Kubernetes 里面的一个概念:亲和性,亲和性主要分为两类:nodeAffinitypodAffinity

一、概述

Kubernetes 支持限制 Pod 在指定的 Node 上运行,或者指定更倾向于在某些特定 Node 上运行。

有几种方式可以实现这个功能:

NodeName: 最简单的节点选择方式,直接指定节点,跳过调度器。
NodeSelector: 早期的简单控制方式,直接通过键—值对将 Pod 调度到具有特定 label 的 Node 上。
NodeAffinity: NodeSelector 的升级版,支持更丰富的配置规则,使用更灵活。(NodeSelector 将被淘汰)
PodAffinity: 根据已在节点上运行的 Pod 标签来约束 Pod 可以调度到哪些节点,而不是根据 node label。

二、指定调度节点

1. NodeName

Pod.spec.nodeNamePod 直接调度到指定的 Node 节点上,会跳过 Scheduler 的调度策略,该规则是强制匹配。如果选择的节点不存在则 Pod 处于 Pending 状态。

apiVersion: v1
kind: Pod
metadata:
  name: nginx-nodename
spec:
  containers:
  - name: nginx
    image: nginx:1.7.9
  nodeName: loc-node36

2. NodeSelector

通过 kuberneteslabel-selector 机制选择节点,由调度器策略匹配 label,而后调度 Pod 到目标节点,该规则属于强制约束。如果选择的节点不存在则 Pod 处于 Pending 状态。

设置标签到 node 上:

# kubectl label nodes loc-node36  zone=guangzhou

示例如下:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  nodeSelector:
    zone: guangzhou

三、亲和性

1. 节点亲和性

pod.spec.affinity.nodeAffinity

  • requiredDuringSchedulingIgnoredDuringExecution # 硬策略

     硬策略是必须(不)落在指定的节点上,如果不符合条件,则一直处于Pending状态
    
  • preferredDuringSchedulingIgnoredDuringExecution # 软策略

    软策略是偏向于,更想(不)落在某个节点上,但如果实在没有,落在其他节点也可以    
    

软硬结合达到一个更为准确的 node 选择,以下配置意思为此 Pod 必须不存在 loc-node36 节点中,其他的节点都可以,但最好落在 labelapp 的值为 loc-node37 的节点中。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-node-affinity
  labels:
    app: nginx-node-affinity
spec:
  replicas: 2
  selector:
    matchLabels:
      app: node-affinity         # 这个lable需要对应下面metadata lables
  template:
    metadata:
      labels:
        app: node-affinity
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
          name: nginx-web
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略
            nodeSelectorTerms:   # 在nodeAffinity下面,如果是required,则需要使用nodeSelectorTerms   #多个nodeSelectorTerms是或的关系,满足一个即可
            - matchExpressions:  # 多个matchExpressions是与的关系,全部满足才会调度
              - key: kubernetes.io/hostname
                operator: NotIn
                values:
                - loc-node36
          preferredDuringSchedulingIgnoredDuringExecution:  # 软策略
          - weight: 1
            preference:
              matchExpressions:
              - key: app
                operator: In
                values:
                - loc-node37
# 节点存在默认的 label
# kubectl get nodes --show-labels
NAME           STATUS   ROLES    AGE    VERSION   LABELS
loc-master35   Ready    master   5d7h   v1.18.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=loc-master35,kubernetes.io/os=linux,node-role.kubernetes.io/master=
loc-node36     Ready    <none>   5d5h   v1.18.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=loc-node36,kubernetes.io/os=linux
loc-node37     Ready    <none>   5d4h   v1.18.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=loc-node37,kubernetes.io/os=linux
# kubectl get pods -o wide 
NAME                                   READY   STATUS    RESTARTS   AGE     IP               NODE         NOMINATED NODE   READINESS GATES
nginx-node-affinity-7fcff98c5c-8whzf   1/1     Running   0          7h58m   172.16.100.209   loc-node37   <none>           <none>
nginx-node-affinity-7fcff98c5c-nnwgr   1/1     Running   0          7h58m   172.16.100.210   loc-node37   <none>           <none>

键值运算关系

  • In:label 的值在某个列表中
  • NotIn:label 的值不在某个列表中
  • Gt:label 的值小于某个值
  • Exists:某个 label 存在
  • DoesNotExist:某个 label 不存在

2. Pod 亲和性

上面两种方式都是让 Pod 去选择节点的,有的时候我们也希望能够根据 Pod 之间的关系进行调度,Kubernetes 在1.4版本引入的 podAffinity 概念就可以实现我们这个需求。

nodeAffinity 类似,podAffinity 也有如下两种两种调度策略,唯一不同的是如果使用互斥性,我们需要使用 podAntiAffinity 字段。

pod.spec.affinity.podAffinity/podAntiAffinity

  • requiredDuringSchedulingIgnoredDuringExecution # 硬策略
  • preferredDuringSchedulingIgnoredDuringExecution # 软策略

以下策略表示 pod-affinity-podlabelapp 值为 nginx 在同一个拓扑域部署,最好不和 labelapp 值为 nginx2Pod 不在同一个拓扑域下。

如何理解拓扑域? 当前是以 kubernetes.io/hostname 基本上表示一个主机是一个拓扑域,我们也可以在主机上打上新的标签 kubernetes.io/zone = gz, 那 Pod 可以随意部署在该拓扑域下的一台 Node 上,并不需要与匹配的一定要在同一个 Node

apiVersion: v1
kind: Pod
metadata:
  name: pod-affinity-pod
  labels:
    app: nginx-affinity-pod
spec:
  containers:
  - name: pod-affinity-pod
    image: nginx:1.7.9
    imagePullPolicy: IfNotPresent
    ports:
    - name: web
      containerPort: 80
  affinity:
      podAffinity:                 # 在同一域下
        requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app           # 标签key
                operator: In
                values:
                - nginx            # 标签value
            topologyKey: kubernetes.io/hostname  # 域的标准为node节点的名称
      podAntiAffinity:
        preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 1
          podAffinityTerm:
            labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - nginx2
            topologyKey: kubernetes.io/hostname
# kubectl get pods --show-labels -o wide
NAME               READY   STATUS    RESTARTS   AGE     IP               NODE         NOMINATED NODE   READINESS GATES   LABELS
nginx              1/1     Running   0          5m30s   172.16.100.235   loc-node37   <none>           <none>            app=nginx
pod-affinity-pod   1/1     Running   0          5m26s   172.16.100.236   loc-node37   <none>           <none>            app=nginx-affinity-pod

亲和性/反亲和性调度策略如下:

调度策略 匹配标签 操作符 拓扑域支持 调度目标
nodeAffinity 主机 In,NotIn,Exists,DoesNotExists,Gt,Lt 指定主机
podAffinity Pod In,NotIn,Exists,DoesNotExists pod与指定pod在一拓扑域
podAnitAffinity Pod In,NotIn,Exists,DoesNotExists pod与指定pod不在一拓扑域

四、污点

节点亲和性,是 Pod 的一种属性(偏好或硬性要求),它使 Pod 被吸引到一类特定的节点。Trint 则相反,它使节点能够排斥一类特定的 Pod

TaintToleration 相互配合,可以用来避免 Pod 被分配到不合适的节点上。每个节点上都可以应用一个或多个 Taint, 这表示对于那些不能容忍这些 TaintPod ,是不会被节点接受的。如果 Toleration 应用于 Pod 上,则表示这些 Pod 可以(但不要求)被调度到具有匹配 Taint 的节点上。

1. 污点组成

每个污点的组成:

key=value:effect

每个污点有一个 key 和 value 作为污点的标签,其中 vlaue 可以为空,effect 描述污点的作用。当前 taint effect 支持如下三个选项:

  • Noscedule: 表示 k8s 将不会将 Pod 调度到具有该污点的 Node
  • PreferNoSchedule: 表示 k8s 将尽量避免将 Pod 调度到具有该污点的 Node
  • NoExecute: 表示 k8s 将不会将 Pod 调度到具有该污点的 Node 上,同时会将 Node 上已经存在的 Pod 驱逐出去

2. 污点设置

使用 kubectl taint 命令可以给某个 Node 节点设置污点,Node 将设置上污点之后就和 Pod 之间存在了一种相斥的关系,可以让 Node 拒绝 Pod 的调度执行,甚至将 Node 已经存在的 Pod 驱逐出去。

# 设置污点
kubectl taint nodes loc-node36 key1=value:Noscedule

# 节点说明中,查找 Taints 字段
kubectl describe node loc-master35

# 去除污点
kubectl taint nodes loc-node36 key1:Noscedule-

五、容忍

设置了污点的 Node 将要根据 tainteffect: Noscedule、PreferNoScheduleNoExecutePod 之间产生互斥的关系,Pod 将在一定程度上不会被调度到 Node 上,但我们可以在 Pod 上设置容忍(Toleration),意思是设置了容忍的 Pod 将可以容忍污点的存在,可以被调度到存在污点的 Node 上。

pod.spec.tolerations

tolerations:
- key: "key1"
  operator: "Equal"
  value: "Value"
  effect: "NoSchedule"
  tolerationSeconds: 3600
- key: "key1"
  operator: "Equal"
  value: "Value"
  effect: "NoExecute"
- key: "key2"
  operator: "Exists"
  effect: "NoSchedule" 
  • 其中 keyvalueeffect 要与 Node 上设置的 taint 保持一致
  • operator 的值为 Exists 将会忽略 value
  • tolerationsSeconds 用于描述当 Pod 需要被驱逐时可以在 Pod 上继续保留运行的时间

1、当不指定 key 值时,表示容忍所有的污点 key:

tolerations:
- operator: "Exists"

2、当不指定 effect 值试,表示容忍所有的污点作用

tolerations:
- key: "key"
  operator: "Exists"

3、当有多个 Master 存在时,为防止资源浪费,可以如下设置

kubectl taint nodes master-nodename node-role.kubernetes.io/master:PreferNoSchedule


Reference:
https://segmentfault.com/a/1190000018446833

猜你喜欢

转载自blog.csdn.net/qq_25854057/article/details/124303796