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指定主机
podAffinityPodIn,NotIn,Exists,DoesNotExistspod与指定pod在一拓扑域
podAnitAffinityPodIn,NotIn,Exists,DoesNotExistspod与指定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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值