K8S调度之Taints and Tolerations

一、污点和容忍概述

1、概念

K8S官方关于Taints and Tolerations概述
Taints和Tolerations和搭配使用的,Taints定义在Node节点上,声明污点及标准行为,Tolerations定义在Pod,声明可接受得污点。
在《K8S之节点亲和性》中,我们说到的的NodeAffinity节点亲和性,是在pod上定义的一种属性,使得Pod能够被调度到某些node上运行。Taint刚好相反,它让Node拒绝Pod的运行。
Taint需要与Toleration配合使用,让pod避开那些不合适的node。在node上设置一个或多个Taint后,除非pod明确声明能够容忍这些“污点”,否则无法在这些node上运行。Toleration是pod的属性,让pod能够(注意,只是能够,而非必须)运行在标注了Taint的node上。

污点
更新一个或多个节点上的污点。
污点由键、值和效果组成。作为这里的参数,它表示为 key=value:effect。
密钥必须以字母或数字开头,并且可以包含字母、数字、连字符、点和下划线,最多 253 个字符。
或者,密钥可以以 DNS 子域前缀和单个“/”开头,例如 example.com/my-app。
该值是可选的。如果给出,它必须以字母或数字开头,并且可以包含字母、数字、连字符、点和下划线,最多 63 个字符。
效果必须是 NoSchedule、PreferNoSchedule 或 NoExecute。
目前污点只能应用于节点。

2、基本用法

设置污点:

    kubectl taint node [node] key=value[effect]   
          其中[effect] 可取值: [ NoSchedule | PreferNoSchedule | NoExecute ]
           NoSchedule :一定不能被调度。
           PreferNoSchedule:尽量不要调度。
           NoExecute:不仅不会调度,还会驱逐Node上已有的Pod。
    #示例:
      kubectl taint node 10.3.1.16 test=16:NoSchedule  

去除污点:

    #比如设置污点:
     kubectl taint node 10.3.1.16 test=16:NoSchedule
     kubectl taint node 10.3.1.16 test=16:NoExecute
     
    #去除指定key及其effect:
     kubectl taint nodes node_name key:[effect]-    #(这里的key不用指定value)
                
    #去除指定key所有的effect: 
     kubectl taint nodes node_name key-
    
    #示例:
     kubectl taint node 10.3.1.16 test:NoSchedule-
     kubectl taint node 10.3.1.16 test:NoExecute-
     kubectl taint node 10.3.1.16 test-

下面是一个简单的示例:

在node1上加一个Taint,该Taint的键为key,值为value,Taint的效果是NoSchedule。这意味着除非pod明确声明可以容忍这个Taint,否则就不会被调度到node1上:

kubectl taint nodes node1  key=value:NoSchedule

然后需要在pod上声明Toleration。下面的Toleration设置为可以容忍具有该Taint的Node,使得pod能够被调度到node1上:

apiVersion: v1
kind: Pod
metadata:
  name: pod-taints
spec:
  tolerations:
  - key: "key"
    operator: "Equal"
    value: "value"
    effect: "NoSchedule"
  containers:
    - name: pod-taints
      image: busybox:latest

也可以写成如下:
tolerations:
- key: "key"
  operator: "Exists"
  effect: "NoSchedule"

pod的Toleration声明中的key和effect需要与Taint的设置保持一致,并且满足以下条件之一:
operator的值为Exists,这时无需指定value
operator的值为Equal并且value相等
如果不指定operator,则默认值为Equal。
另外还有如下两个特例:
空的key配合Exists操作符能够匹配所有的键和值
空的effect匹配所有的effect

Update node 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule' # 如果已经存在具有该键和效果的污点,则按指定替换其值

kubectl taint nodes foo dedicated=special-user:NoSchedule
从节点 'foo' 中删除键为 'dedicated' 的污点,如果存在则影响 'NoSchedule'

kubectl taint nodes foo dedicated:NoSchedule-
从节点 'foo' 中删除所有带有键 'dedicated' 的污点

kubectl taint nodes foo dedicated-
在标签为 mylabel=X 的节点上添加带有键 'dedicated' 的污点

kubectl taint node -l myLabel=X  dedicated=foo:PreferNoSchedule
向节点 'foo' 添加一个带有键 'bar' 且没有值的污点

kubectl taint nodes foo bar:NoSchedule

3、effect说明

上面的例子中effect的取值为NoSchedule,下面对effect的值作下简单说明:
NoSchedule: 如果一个pod没有声明容忍这个Taint,则系统不会把该Pod调度到有这个Taint的node上
PreferNoSchedule:NoSchedule的软限制版本,如果一个Pod没有声明容忍这个Taint,则系统会尽量避免把这个pod调度到这一节点上去,但不是强制的。
NoExecute:定义pod的驱逐行为,以应对节点故障。NoExecute这个Taint效果对节点上正在运行的pod有以下影响:
没有设置Toleration的Pod会被立刻驱逐
配置了对应Toleration的pod,如果没有为tolerationSeconds赋值,则会一直留在这一节点中
配置了对应Toleration的pod且指定了tolerationSeconds值,则会在指定时间后驱逐
从kubernetes 1.6版本开始引入了一个alpha版本的功能,即把节点故障标记为Taint(目前只针对node unreachable及node not ready,相应的NodeCondition "Ready"的值为Unknown和False)。激活TaintBasedEvictions功能后(在–feature-gates参数中加入TaintBasedEvictions=true),NodeController会自动为Node设置Taint,而状态为"Ready"的Node上之前设置过的普通驱逐逻辑将会被禁用。注意,在节点故障情况下,为了保持现存的pod驱逐的限速设置,系统将会以限速的模式逐步给node设置Taint,这就能防止在一些特定情况下(比如master暂时失联)造成的大量pod被驱逐的后果。这一功能兼容于tolerationSeconds,允许pod定义节点故障时持续多久才被逐出。

4、配置

多污点与多容忍配置
系统允许在同一个node上设置多个taint,也可以在pod上设置多个Toleration。Kubernetes调度器处理多个Taint和Toleration能够匹配的部分,剩下的没有忽略掉的Taint就是对Pod的效果了。下面是几种特殊情况:
如果剩余的Taint中存在effect=NoSchedule,则调度器不会把该pod调度到这一节点上。
如果剩余的Taint中没有NoSchedule的效果,但是有PreferNoSchedule效果,则调度器会尝试不会pod指派给这个节点
如果剩余Taint的效果有NoExecute的,并且这个pod已经在该节点运行,则会被驱逐;如果没有在该节点运行,也不会再被调度到该节点上。

kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule

5、示例

诊断报错
NODE_WITH_INTOLERABLE_TAINT/所有满足nodeSelector的节点均存在pod无法容忍的污点
查看pod处于pending状态
查看events事件报错没有合适的node可以调度

kubectl get pod
kubectl get nodes -o=custom-columns=NodeName:.metadata.name,TaintKey:.spec.taints[*].key,TaintValue:.spec.taints[*].value,TaintEffect:.spec.taints[*].effect

在这里插入图片描述
在这里插入图片描述

kubectl describe po {pod_name}

在这里插入图片描述

kubectl get node
kubectl get node {node_name} -o go-template --template='{{.spec.taints}}'
kubectl taint node {node_name} {key}:{effect}-

在这里插入图片描述
再次查看pod
在这里插入图片描述

二、节点亲和

1、概念

Node Affinity
Affinity 翻译成中文是“亲和性”,它对应的是 Anti-Affinity,我们翻译成“互斥”。这两个词比较形象,可以把 pod 选择 node 的过程类比成磁铁的吸引和互斥,不同的是除了简单的正负极之外,pod 和 node 的吸引和互斥是可以灵活配置的。
Affinity的优点:
匹配有更多的逻辑组合,不只是字符串的完全相等
调度分成软策略(soft)和硬策略(hard),在软策略下,如果没有满足调度条件的节点,pod会忽略这条规则,继续完成调度。
目前主要的node affinity:
requiredDuringSchedulingIgnoredDuringExecution
表示pod必须部署到满足条件的节点上,如果没有满足条件的节点,就不停重试。其中IgnoreDuringExecution表示pod部署之后运行的时候,如果节点标签发生了变化,不再满足pod指定的条件,pod也会继续运行。
requiredDuringSchedulingRequiredDuringExecution
表示pod必须部署到满足条件的节点上,如果没有满足条件的节点,就不停重试。其中RequiredDuringExecution表示pod部署之后运行的时候,如果节点标签发生了变化,不再满足pod指定的条件,则重新选择符合要求的节点。
preferredDuringSchedulingIgnoredDuringExecution
表示优先部署到满足条件的节点上,如果没有满足条件的节点,就忽略这些条件,按照正常逻辑部署。
preferredDuringSchedulingRequiredDuringExecution
表示优先部署到满足条件的节点上,如果没有满足条件的节点,就忽略这些条件,按照正常逻辑部署。其中RequiredDuringExecution表示如果后面节点标签发生了变化,满足了条件,则重新调度到满足条件的节点
软策略和硬策略的区分是有用处的,硬策略适用于 pod 必须运行在某种节点,否则会出现问题的情况,比如集群中节点的架构不同,而运行的服务必须依赖某种架构提供的功能;软策略不同,它适用于满不满足条件都能工作,但是满足条件更好的情况,比如服务最好运行在某个区域,减少网络传输等。这种区分是用户的具体需求决定的,并没有绝对的技术依赖。

2、官网案例

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/e2e-az-name
            operator: In
            values:
            - e2e-az1
            - e2e-az2
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: gcr.io/google_containers/pause:2.0

这个 pod 同时定义了 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution 两种 nodeAffinity。第一个要求 pod 运行在特定 AZ 的节点上,第二个希望节点最好有对应的 another-node-label-key:another-node-label-value 标签。

这里的匹配逻辑是label在某个列表中,可选的操作符有:
In: label的值在某个列表中
NotIn:label的值不在某个列表中
Exists:某个label存在
DoesNotExist:某个label不存在
Gt:label的值大于某个值(字符串比较)
Lt:label的值小于某个值(字符串比较)
如果nodeAffinity中nodeSelector有多个选项,节点满足任何一个条件即可;如果matchExpressions有多个选项,则节点必须同时满足这些选项才能运行pod 。
需要说明的是,node并没有anti-affinity这种东西,因为NotIn和DoesNotExist能提供类似的功能。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要设置 k8s 节点不可调度,可以通过以下两种方式实现: 1. 使用 kubectl 命令设置节点不可调度: ``` kubectl cordon <node-name> ``` 这个命令会在节点上设置一个 taint ,使得 k8s 调度器不会将新的 Pod 调度到该节点上。 2. 在节点上设置 taint: 在要设置不可调度的节点上运行以下命令: ``` kubectl taint nodes <node-name> node-role.kubernetes.io/master:NoSchedule ``` 这个命令会在该节点上设置一个 taint,使得 k8s 调度器不会将新的 Pod 调度到该节点上。 这两种方式都可以实现节点不可调度的目的,但是第二种方式可以设置更多的 taints,例如可以设置 Pod 必需的节点标签,从而限制 Pod 的调度。 ### 回答2: 在Kubernetes(简称K8s)中,可以通过设置节点的调度状态来控制其可调度性。要将节点设置为不可调度,可以使用以下步骤: 1. 首先,可以使用以下命令查看当前集群中的所有节点:`kubectl get nodes` 2. 选择要将其设置为不可调度的节点,并使用以下命令标记该节点为不可调度的状态:`kubectl cordon <节点名称>` 3. 当节点被标记为不可调度后,新的Pod将不会被调度到该节点上,而已经运行在该节点上的Pod将继续运行。 4. 如果要将节点重新设置为可调度状态,可以使用以下命令:`kubectl uncordon <节点名称>` 5. 再次将节点设置为可调度后,K8s调度器将重新考虑该节点上的Pod的分布,并在需要时在该节点上调度新的Pod。 通过设置节点的调度状态,可以灵活地控制K8s集群中Pod的调度行为,确保节点的资源被有效利用,并实现负载均衡和高可用性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值