kuburnetes的Taints与Tolerations
Taints(污点)与tolerations(容忍度)一起工作确保Pod不会被调度到不合适的节点上。单个节点可以应用多个taint(污点),node不接受无法容忍taint(污点)的pod调度。Toleration(容忍度)是pod的属性,允许(非强制)pod调度到taints(污点)相匹配的node上去。(注意taints是node的属性,affinity是pod的属性。)
概念:
1 |
|
为node节点 node1增加一条taint(污点)。Taint(污点)的关键字为key,值为value,taint(污点)影响NoSchedule。意味着没有pod会被调度到node1上,除非Pod它有匹配的toleration(容忍度)。
1 |
|
可以为pod指定toleration(容忍度)。以下的两种toleration(容忍度)都与上文中创建的taint(污点)匹配,因此这个pod有可能被调试到node1上。
1 |
|
Toleration(容忍度)与taint(污点)匹配的条件是key相同、effect相同,并且:
- Operator的值是Exists(无需指定values的值)
- Operator是Equal,并且values的值相等
如果不指定,operator默认是Equal。
注意:两种特殊情况。
1 |
|
1 |
|
上例中用到了NoSchedule的effect。另外,可以使用PreferNoSchedule的effect,这是NoSchedule的“偏好”或者“软“版本。系统尽量避免非tolerate的pod调度到taint node上,但非强制要求。第三种可用的effect是NoExecute,后文描述。
可以为单个node指定多条taint(污点),也可以为单个pod指定多条toleration(容忍度)。系统采用过滤的方式处理这种情况:首先从node的所有taint(污点)开始,然后将与pod中的toleration(容忍度)相匹配的taint(污点)删除,余下的taint(污点)对部署进来的pod产生影响。特别地:
- 如果余下的taint(污点)中至少有一条的effect是NoSchedule,kubernetes将不会高度这个pod到的node上。
- 如果余下的taint(污点)中没有effect为NoSchedule的taint(污点),但至少有一条effect为PreferNoSchedule,则系统尝试着不将pod部署在node上(也就是有可能还是会部署到这个node上)。
- 如果余下的taint(污点)中至少有一条的effect是NoExecute,那么不旦新的pod不会被调度到这个node上,而且已经运行在这个node上的pod还会被驱逐出去。
例如,假如像这样taint一个node:
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule
pod有两个toleration:
1 |
|
这种情况下,pod不能调度到node上。因为pod没有toleration(容忍度)与node的第三条taint(污点)匹配。但是在添加taint(污点)之前已经运行在node上的pod不受影响(这里之前运行的pod指添加了toleration(容忍度)的pod),可能将pod排除出node的noExecute因为被过滤而没有生效。
一般情况下,如果一个effect为NoExecute的taint(污点)应用于node,运行在node上的所有不能容忍这条taint(污点)的pod都会被排挤出node,能容忍这种taint(污点)的pod则不会被排挤。然而,如果effect为NoExecute的toleration(容忍度)指定给pod,同时添加可选的tolerationSeconds字段,则表示pod被排挤出node之前,以taint(污点)的添加时间为起点,允许此pod在此node上的生存时间。
1 |
|
使用案例:
Taints与tolerations可以灵活的控制pod远离node,或者将不应该运行的pod从node上排挤出去。以下是几个使用案例:
- 专用node:如果打算指定特定node集合供特定用户专用,那么可以给这些node添加一条taint(kubectl taint nodes nodename dedicated=groupName:NoSchedule),然后在相应的pod上添加匹配的toleration(容忍度)。拥有toleration的pod被允许像使用集群中的其它node一样使用拥有taint的node。如果打算让pod只使用taint性质的node,并且只能使用taint的node的话,可以对这些taint的node再额外增加标签(例如:dedicated=groupName),然后再通过入口控制器为这些pod额外再增加亲和性要求它们只能部署到拥有dedicated=groupName的node上。总结就是通过标签的亲和性控制pod部署到特定的node上,通过为node增加taint并且为pod增加toleration抵制其它pod部署到这些node上,从而实现node专用。
- 拥有特殊硬件的node:在集群中,有少数node拥有特殊的硬件配置(例如 GPUs),希望那些不使用特殊的硬件的pod尽量不要部署到这些拥有特殊硬件的node上,为后续到达的需要使用特殊硬件的pod预留出空间。通过如下方法达到这个目的。首先为node添加taint,taint表示node拥有特殊硬件(例如: kubectl taint nodes nodename special=true:NoSchedule 或者 kubectl taint nodes nodename special=true:PreferNoSchedule),然后为需要使用特殊硬件的pod添加相应的toleration。像专用node的例子一样,通过入口控制器很容易为pod添加对应的toleration。例如:推荐使用“扩展资源”代表特殊硬件,使用“扩展资源”的名称为拥有特殊硬件的node添加taint,当提交的pod被配置为需要使用特殊硬件时,扩展资源入口控制器自动为其加上正确的toleration。
- 基于taint的驱逐(测试特性):一种当node出现问题时per-pod-configurable的驱逐行为,下节介绍。
基于taint的驱逐:
先前提到的effect为NoExecute的taint,它对已经运行在node上的pod的影响如下:
- 如果pod没有toleration这个taint的话,pod立即被驱逐。
- 如果toleration了这个taint,并且没有指定tolerationSeconds的值,则一直不会驱逐
- 如果toleration了这个taint,但是指定tolerationSeconds限定了容忍的时间,则到期后驱逐
此外,Kubernetes用taint代表node出了问题(1.13beta版)。换句话说,当Node某些条件为
True
时,节点控制器自动为Node节点添加污点,而在状态为Ready的Node上,之前设置过的普通的驱逐逻辑将会被禁用。内置以下污点:
node.kubernetes.io/not-ready
:节点尚未就绪。这对应于NodeCondition Ready为“ False”。node.kubernetes.io/unreachable
:Node controlloer无法访问节点。这对应于NodeCondition Ready为“ Unknown”。node.kubernetes.io/out-of-disk
:节点变得磁盘不足。node.kubernetes.io/memory-pressure
:节点有内存压力。node.kubernetes.io/disk-pressure
:节点有磁盘压力。node.kubernetes.io/network-unavailable
:节点的网络不可用。node.kubernetes.io/unschedulable
:节点是不可调度的。node.cloudprovider.kubernetes.io/uninitialized
:当使用“外部”云提供程序启动kubelet时,会在节点上设置此污点以将其标记为不可用。在cloud-controller-manager的控制器初始化此节点后,kubelet将删除此污点。
注意:在节点故障的情况下,为了保持现存的Pod驱逐的限速设置,系统将会以限速的模式逐步给Node设置Taint,这就能避免在一些特定情况下(比如Master暂时失联)大量的Pod被驱逐。这一功能兼容于
tolerationSeconds
允许Pod定义节点故障时持续多久才被逐出。
例如:一个包含很多本地状态的应用可能需要在网络发生故障时,还能持续在节点上运行,期望网络能够快速恢复,从而避免被从这个节点上驱逐。Pod的toleration可以这样定义:
1 |
|
- 对于Node未就绪状态,可以把Key设置为
node.kubernetes.io/not-ready
如果没有为Pod指定node.kubernetes.io/not-ready
的Tolerations
,那么Kubernetes会自动为Pod加入tolerationSeconds= 300
的node.kubernetes.io/not-ready
类型的Tolerations
- 同样如果Pod没有定义
node.kubernetes.io/unreachable
的Tolerations
那么系统会自动为其加入tolerationSeconds=300
的node.kubernetes.io/unreachable
类型的Tolerations
这些系统自动设置的
Tolerations
在Node发现问题时,能够为Pod确保驱逐前再运行5min。
其阈值由kubelet如下参数控制:
--eviction-hard
:驱逐阈值(例如memory.available<1Gi),如果满足这些阈值,就会触发pod驱逐。(默认imagefs.available < 15%, memory.available < 100 mi, nodefs.available < 10%, nodefs.inodesFree < 5%)
--eviction-soft
:驱逐阈值(例如memory.available<1.5Gi),如果在相应的宽限期内达到该阈值,就会触发pod驱逐。--eviction-minimum-reclaim
:最小回收(例如imagef .available=2Gi),描述kubelet在执行pod回收(如果该资源处于压力之下)时回收的最小资源量。--eviction-pressure-transition-period
:kubelet必须等待一段时间才能从驱逐压力状态过渡出来。(默认5m0)
编辑kubelet-conf.yml文件修改默认阈值来调整驱逐条件:
1 |
|