污点(Taint)和容忍(Toleration)是从Kubernetes 1.6开始提供的高级调度功能。 在Kubernetes的文档中Taints and Tolerations的介绍已经十分详细。 本文将从简单理解的角度看一下Taint和Toleration。

污点(Taint)

污点(Taint)的组成

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

每个污点的组成如下:

1key=value:effect

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

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

污点的设置和去除

使用kubectl设置和去除污点的命令示例如下:

1# 设置污点
2kubectl taint nodes node1 key1=value1:NoSchedule
3
4# 去除污点
5kubectl taint nodes node1 key1:NoSchedule-

接下来看一个具体的例子,使用kubeadm部署和初始化的Kubernetes集群,master节点被设置了一个node-role.kubernetes.io/master:NoSchedule的污点,可以使用kubectl describe node <node-name>命令查看。这个污点表示默认情况下master节点将不会调度运行Pod,即不运行工作负载。对于使用二进制手动部署的集群设置和移除这个污点的命令如下:

1kubectl taint nodes <node-name> node-role.kubernetes.io/master=:NoSchedule
2
3kubectl taint nodes <node-name> node-role.kubernetes.io/master:NoSchedule-

注意:kubeadm初始化的Kubernetes集群,master节点也被打上了一个node-role.kubernetes.io/master=的label,标识这个节点的角色为master。给Node设置Label和设置污点是两个不同的操作。设置Label和移除Label的操作命令如下

 1# 设置Label
 2kubectl label node node1 node-role.kubernetes.io/master=
 3# 移除Label
 4kubectl label node node1 node-role.kubernetes.io/master-
 5
 6kubectl get node
 7NAME      STATUS    ROLES     AGE       VERSION
 8node1    Ready     master    10d       v1.9.8
 9node2    Ready     master    10d       v1.9.8
10node3    Ready     master    10d       v1.9.8
11node4    Ready     <none>    10d       v1.9.8
12node5    Ready     <none>    10d       v1.9.8

容忍(Tolerations)

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

通过在Pod的spec中设置tolerations字段,给Pod设置上容忍点Toleration:

 1tolerations:
 2- key: "key1"
 3  operator: "Equal"
 4  value: "value1"
 5  effect: "NoSchedule"
 6  tolerationSeconds: 3600
 7- key: "key1"
 8  operator: "Equal"
 9  value: "value1"
10  effect: "NoExecute"
11- key: "key2"
12  operator: "Exists"
13  effect: "NoSchedule"
  • 其中key, vaule, effect要与Node上设置的taint保持一致
  • operator的值为Exists将会忽略value值
  • tolerationSeconds用于描述当Pod需要被驱逐时可以在Pod上继续保留运行的时间

下面看一下在Pod上设置容忍的两个特例:

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

1tolerations:
2- operator: "Exists"

示例2:当不指定effect值时,表示容忍所有的污点作用:

1tolerations:
2- key: "key"
3  operator: "Exists"

实践:Kubernetes master节点不运行工作负载

Kubernetes集群的Master节点是十分重要的,一个高可用的Kubernetes集群一般会存在3个以上的master节点,为了保证master节点的稳定性,一般不推荐将业务的Pod调度到master节点上。 下面将介绍一下我们使用Kubernetes调度的Taints和和Tolerations特性确保Kubernetes的Master节点不执行工作负载的实践。

我们的Kubernetes集群中总共有3个master节点,节点的名称分别为k8s-01k8s-02k8s-03。 为了保证集群的稳定性,同时提高master节点的利用率,我们将其中一个节点设置为node-role.kubernetes.io/master:NoSchedule,另外两个节点设置为node-role.kubernetes.io/master:PreferNoSchedule,这样保证3个节点中的1个无论在任何情况下都将不运行业务Pod,而另外2个载集群资源充足的情况下尽量不运行业务Pod。

1kubectl taint nodes k8s-01 node-role.kubernetes.io/master=:NoSchedule
2
3kubectl taint nodes k8s-02 node-role.kubernetes.io/master=:PreferNoSchedule
4
5kubectl taint nodes k8s-03 node-role.kubernetes.io/master=:PreferNoSchedule

另外对于我们部署在集群中的一些非业务组件,例如Kubernetes Dashboardjaeger-collectorjaeger-queryPrometheuskube-state-metrics等组件,通过设置Tolerations和Pod Affinity(亲和性)将这些组件运行在master节点上,而其他的业务Pod运行在普通的Node节点上。

参考