kubernetes 调度之 Taints 和 Tolerations
[](https://github.com/jolestar/kubernetes-complete-course/blob/master/chapter-5-kubernetes-pod-allocation-and-application-example.md)
为什么要有 Taints 和 Tolerations
Taints 隔离 Node
上线新 Node 验证
下线 Node 维护
专用 Node
Tolerations Pod 对 Taints Node 的容忍
验证 Taints Node 是否工作正常
表明 Pod 有资格使用专用 Node
每个节点必须运行的基础 Pod
Kubernetes 中的调度策略比较多,每个策略都有其比较适用的需求场景。
Taints(污点),Tolerations(容忍)
本文主要介绍 kubernetes 的中调度算法中的 Taints 和 Tolerations 用法,实际上是对 PodToleratesNodeTaints 策略和 TaintTolerationPriority 策略的具体应用。先从中文字面意思上理解下这两个词语:Taints(污点),Tolerations(容忍)。
1 Dashboard 与 Master 那些事
部署 kube-dashboard 的时候,在 yaml 文件中有这样一段定义:
# Comment the following annotation if Dashboard must not be deployed on master
annotations:
scheduler.alpha.kubernetes.io/tolerations: |
[
{
"key": "dedicated",
"operator": "Equal",
"value": "master",
"effect": "NoSchedule"
}
]
注释 Comment the following annotation if Dashboard must not be deployed on master 说的很清楚:如果 Dashboard 不想部署在 master 节点上,那就注释掉下下边的这段 annotations 定义。
有的同学在部署 Dashboard 的时候就疑惑了,说注释写的怎么跟 annotations 定义是相反的,annotations 的定义中说的是:如果 Node 节点上定义有 key 为 dedicated,并且 value 为 master 的 annotations,那就不调度 Pod,如果注释掉这段代码,那岂不是把这个约束去掉了?
单从 annotations 定义的字面意思来理解,似乎的确是这种说法,但是事实上,这是忽略一件事情,那就是 Taints 和 Tolerations。
来看下 Master 节点上的 taints 定义:
#v1.6 以前的的版本
annotations:
scheduler.alpha.kubernetes.io/taints: '[{"key":"dedicated","value":"master","effect":"NoSchedule"}]'
volumes.kubernetes.io/controller-managed-attach-detach: "true"
#v1.6 + 版本
spec:
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
timeAdded: null
可见,Master 节点上定义了 Taints,Taints 是用来干什么的?它表达的是一个含义:此节点已被 key=value 污染,Pod 调度不允许(PodToleratesNodeTaints 策略)或尽量不(TaintTolerationPriority 策略)调度到此节点,除非是能够容忍(Tolerations)key=value 污点的 Pod。
Master 节点上定义了 Taints,声明:如果不是带有 Tolerations 定义为 [{"key":"dedicated","value":"master","effect":"NoSchedule"}] 的 Pod,不允许调度到 Master 节点,PS:operator 的默认值为 Equal,所以可以不必显示声明。
这下明白了,Master 上定义一个污点 A(Taints)禁止 Pod 调度,Dashboard 的 yaml 里定义一个容忍(Tolerations)允许 A 污点,所以可以调度到 Master 节点上。
2 Taints 和 Tolerations
如上所述,Taints 和 Tolerations 和搭配使用的,Taints 定义在 Node 节点上,声明污点及标准行为,Tolerations 定义在 Pod,声明可接受得污点。
可以在命令行为 Node 节点添加 Taints:
kubectl taint nodes node1 key=value:NoSchedule
也可以直接在 node 的定义中修改 Taints:
#v1.6 以前的的版本
annotations:
scheduler.alpha.kubernetes.io/taints: '[{"key":"xxx","operator":"Equal","value":"yyy","effect":"NoSchedule"}]'
#v1.6 + 版本
spec:
taints:
- effect: NoSchedule
value: yyy
key: xxx
operator(v1.6 + 的定义中无此属性) 可以定义为:
Equal 表示 key 是否等于 value,默认
Exists 表示 key 是否存在,此时无需定义 value
effect 可以定义为:
NoSchedule 表示不允许调度,已调度的不影响
PreferNoSchedule 表示尽量不调度
NoExecute 表示不允许调度,已调度的在 tolerationSeconds(定义在 Tolerations 上)后删除
Node 和 Pod 上都可以定义多个 Taints 和 Tolerations,Scheduler 会根据具体定义进行筛选,Node 筛选 Pod 列表的时候,会保留 Tolerations 定义匹配的,过滤掉没有 Tolerations 定义的,过滤的过程是这样的:
如果 Node 中存在一个或多个影响策略为 NoSchedule 的 Taint,该 Pod 不会被调度到该 Node
如果 Node 中不存在影响策略为 NoSchedule 的 Taint,但是存在一个或多个影响策略为 PreferNoSchedule 的 Taint,该 Pod 会尽量不调度到该 Node
如果 Node 中存在一个或多个影响策略为 NoExecute 的 Taint,该 Pod 不会被调度到该 Node,并且会驱逐已经调度到该 Node 的 Pod 实例
Pod 上的 Tolerations 定义类似这样:
#v1.6 以前的的版本
annotations:
scheduler.alpha.kubernetes.io/tolerations: |
[
{
"key": "xxx",
"operator": "Equal",
"value": "yyy",
"effect": "NoSchedule"
}
]
#v1.6 + 版本
tolerations:
- key: xxx
value: yyy
effect: NoSchedule
污点和容忍 (Taints and Tolerations)
此功能允许您标记一个 Node(“受污染”,“有污点”),以便没有 Pod 可以被调度到此节点上,除非 Pod 明确地 “容忍” 污点。标记的是 Node 而不是 Pod(如节点的亲和性和反亲和性),对于集群中大多数 Pod 应该避免调度到特定的节点上的功能特别有用,例如,您可能希望主节点(Master)标记为仅可调度 Kubernetes 系统组件,或将一组节点专用于特定的用户组,或者让常规的 Pod 远离具有特殊硬件的 Node,以便为有特殊硬件需求的 Pod 留出空间。
使用 kubectl 命令可以设置节点的 “污点”,例如:
kubectl taint nodes node1 key=value:NoSchedule
创建一个污点并标记到 Node,那些没有设置容忍的 Pod(通过 key-value 方式设置 NoSchedule,这是其中一个选项)不能调度到该 Node 上。其他污点的选项是 PerferredNoSchedule,这是 NoSchedule 首选版本;还有 NoExecute,这个选项意味着在当 Node 被标记有污点时,该 Node 上运行的任何没有设置容忍的 Pod 都将被驱逐。容忍将被添加到 PodSpec 中,看起来像这样:
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
除了将污点和容忍 (Taints and Tolerations) 特性在 Kubernetes 1.6 中移至 Beta 版外,我们还引入了一个使用污点和容忍的 Alpha 的特性:允许用户自定义一个 Pod 被绑定到 Node 上后遇到了诸如网络分区的问题时的行为(可能 Pod 希望长时间允许在这个 Node 上,或者网络分区会很快恢复),而不是现在默认的等待五分钟超时。更详细的信息,请参阅文档。