☰
k8s调度机制2
2026/10/26 18:21:31 网站建设 项目流程

k8s调度机制2

节点污点和pod容忍

污点taint和容忍tolerations

  • 污点(Taint) ——它使节点能够排斥一类特定的 Pod,是定义在节点的属性

  • 容忍度(Toleration)是应用于 Pod 上的属性。容忍度允许调度器调度 Pod到有污点的节点上。 容忍度允许调度但并不保证调度:作为其功能的一部分, 调度器也会评估其他参数。

  • 内置污点功能

    • Kubernetes自1.6起支持使用污点自动标识问题节点,它通过节点控制器在特定条件下自动为节点添加污点信息实现。它们都使用NoExecute效用标识,因此非能容忍此类污点的现在Pod对象也会遭到驱逐。
    • 节点状态相关的某种条件为真时,节点控制器会自动给节点添加一个污点
node.kubernetes.io/not-ready:节点进入NotReady状态时被自动添加的污点。 node.alpha.kubernetes.io/unreachable:节点进入NotReachable状态时被自动添加的污点。 node.kubernetes.io/out-of-disk:节点进入OutOfDisk状态时被自动添加的污点。 node.kubernetes.io/memory-pressure:节点内存资源面临压力。 node.kubernetes.io/disk-pressure:节点磁盘资源面临压力 node.kubernetes.io/pid-pressure:节点PID资源紧张 node.kubernetes.io/network-unavailable:节点网络不可用 node.kubernetes.io/unschedulable:节点不可用于调度 node.cloudprovider.kubernetes.io/uninitialized:kubelet由外部的云环境程序启动时,它自动 为节点添加此污点,待到云控制器管理器中的控制器初始化此节点时再将其删除。

属性解析

  • taint是节点上的属性
kubectl explain node.spec.taints(对象列表) key#定义一个key=value:effectvalue#定义一个值,这是一个可选项effect#pod不能容忍这个污点时,有三个行为值:NoSchedule、PreferNoSchedule、NoExecutetimeAdded#记录污点被添加的具体时间,此属性仅与NoExecute类型的污点相关,在使用kubectl taint命令添加或删除污点时,Kubernetes会自动处理TimeAdded属性的更新或移除,此字段由系统自动添加,无需人为管理
  • 污点处理方式effect的属性值(优先级从低到高)

  • 范例:查看属性

#查看节点上的污点kubectl describenodemaster1.hajimi.org|grepTaint kubectl getnodemaster1.hajimi.org-oyaml... taints:#污点- effect: NoSchedule#效用标识key: node-role.kubernetes.io/master...#查看pod上的污点容忍度kubectl describe pod pod名|grep-A3Tolerations: Tolerations: node.kubernetes.io/not-ready:NoExecuteop=Existsfor300s
  • tolerations容忍度属性
    • 这是pod上的属性
kubectl explain pod.spec.tolerations key#被容忍的keyvalue#被容忍key的值,当operator为exists时,此value无需定义operator#Equal(等值比较)表示key对应的value值以及effect三者必须要和tains的值相同才能容忍,此为默认值#Exists 表示只要存在key和effect二者相同,但不关注value就可容忍,必须不能定义value, 即可以调度Pod,如果没有定义key和effect,表示容忍所有污点effect#可以容忍的节点的行为值,必须和Traint中的effect值相同或高于才能容忍tolerationSeconds#被驱逐的宽限时间,默认是0就是立即被驱逐
  • 容忍度的判断方式
    • 在pod对象上定义容忍度时,支持两种操作符——一种是等值比较Equal,表示容忍度与污点必须在key、value和effect三者之上完全匹配,此为默认值;一种是存在性判断Exists,表示keyeffect 二者必须完全匹配,而容忍度tolerations中的value字段无需定义。
    • 特殊情况——operator为Exists,且容忍度的key为空,表示其可以容忍任意污点;若effect为空,则可以匹配所有键名相同的污点
  • 容忍度匹配原则
    • 一个节点可以配置使用多个污点,而一个Pod对象也可以有多个容忍度
    • 遍历该节点的所有污点,并过滤掉容忍度可匹配到的污点
    • 余下未被过滤掉的污点,则由污点的effect来判定其满足状态
      • 对于剩余的不能匹配到容忍度的所有污点中,若存在至少一个污点使用了NoSchedule效用标识,则拒绝调度当前Pod至该节点
      • 对于不能匹配到容忍度的所有污点,若都不具有NoSchedule效用标识,但至少有一个污点使用了PreferNoScheduler效用标准,则调度器会尽量避免将当前Pod对象调度至该节点
      • 如果至少有一个不能匹配容忍度的污点使用了NoExecute效用标识,节点将立即驱逐当前Pod对象,或者不允许该Pod调度至给定的节点;而且,即便容忍度可以匹配到使用了NoExecute效用标识的污点,若在Pod上定义容忍度时同时使用tolerationSeconds属性定义了容忍时限,则在超出时限后当前Pod也将会被节点所驱逐

污点管理命令

#查看污点Kubectl getnode<nodename>-ogo-template{{.spec.taints}}kubectl describe nodes|grep-itaint#添加污点#指定节点添加污点kubectl taintnode<node-name><key>=<value>:<effect>...#所有节点添加污点kubectl taintnode-all<key>=<value>:<effect>...#删除污点kubectl taintnode<node-name><key>[:<effect]- kubectl patch nodes<node-name>-p'{"spec":{"taints":[]}}'#cordon封锁节点,即添加污点node.kubernetes.io/unschedulable:NoSchedule,只影响新Podkubectl cordon<node-name>#删除污点node.kubernetes.io/unschedulable:NoSchedulekubectl uncordon<node-name>#强制驱逐节点上pod#方法1:drain 排空节点上面的 Pod,同时添加污点node.kubernetes.io/unschedulable:NoSchedule#注意:要删除node.kubernetes.io/unschedulable:NoSchedule污点,需要执行kubectl uncordon<node-name>#--ignore-daemonsets 默认kubectl drain删除daemonset资源会报错,加此项可以忽略错误提示kubectl drain<nodename>--ignore-daemonsets --delete-emptydir-data--force#取消强制驱逐节点上Podkubectl uncordon<node-name>#方法2:使用污点NoExecute实现kubectl taint nodes node3.wang.orgname=wang:NoExecute

拓扑调度

拓扑分布约束可以控制pod的调度实现平均分布的程度

  • 在定义pod亲和性和反亲和时,有一个 topologyKey的属性,但是默认情况下,pod的亲和性调度,仅仅针对单一的拓扑场景,也就是说,要么所有的pod都在这里,要么所有的pod都不要在这里,这样会导致应用过于集中,反而导致物理资源的浪费。

  • 如果希望在进行正常pod亲和性调度的时候,能够自动识别多个不同的调度节点,然后均匀的分散到多个节点中,从而实现资源的有效利用。通过拓扑调度来实现的功能

  • 敏置偏差Skew

    • 偏差Skew 是当前每一个拓扑域Pod数量和Pod数量最少的拓扑域之间的Pod数量的差值
    • 公式:当前i拓扑域 skew[i] = 拓扑域[i]中匹配的 Pod 个数 - min{拓扑域[*]中匹配的 Pod 个数}
  • Pod分散约束策略基于允许的最大偏差(maxSkew)来定义Pod在拓扑域中的分散逻辑

  • 当无法满足最大偏差约束时,whenUnsatisfable则用于定义妥协策略

    • 当无法满足最大偏差约束时,whenUnsatisfable则用于定义妥协策略
    • ScheduleAnyway:根据每个节点的skew值打分排序后进行调度,即软限制
  • 就是让pod分配的均匀一点,不让资源分配过于极端。具体分配多少可以用公式来算

  • 属性解析

kubectl explain pod.spec.topologySpreadConstraints labelSelector#根据 LabelSelector来计算出匹配的pod的数量maxSkew#描述了 pod 可能不均匀分布的程度,不同拓扑域之间的各节点pod数量比例的最大限制topologyKey#用于指定带有此标签的值相同的节点在同一拓扑中。whenUnsatisfiable#指示如果 Pod 不满足扩展约束,如何处理它。默认值是DoNotSchedule#maxSkew 默认值是1,即各个不同的拓扑中的Pod总数量之差最大不能超过1,如果这个值越大,则pod的分布可能会是不均匀的。
  • 案例分析
    • labelSelector用于查找匹配的 Pod。对于每个拓扑,我们计算 与此标签选择器匹配的 Pod 数量。在上面的例子中,给定 labelSelector为“app: foo”,“zone1”中的匹配数字为2;而 “Zone2”中的数字为 0。
    • topologyKey是在节点标签中定义拓扑的键。如果两个 Node 的 label 同时具有该 key 并且 label 值相同,就说它们在同一个拓扑域。在上图中,指定 topologyKey 为 zone, 具有 “zone=zone1” 标签的 Node 被分在一个拓扑域,具有"zone=zone2" 标签的 Node 被分在另一个拓扑域。
    • maxSkew描述了 Pod 在不同拓扑域中Skew不均匀分布的最大程度,maxSkew 的取值必须大于0。每个拓扑域都有一个 skew,计算的公式是:skew[i] = 拓扑域[i]中匹配的 Pod 个数 - min{拓扑域[*]中匹配的 Pod 个数}。skew 不能大于maxSkew ,在上图中,我们新建一个带有 “app=foo” label 的 Pod:
      • 如果将传入的 Pod 放在 “zone1”,则 “zone1” 上的偏斜 skew 值将变为 3 ( 在“zone1”中匹配的 Pod为3个;在“zone2”上匹配的全局最小值为 0 个 Pod),违反了“maxSkew: 1”约束。
      • 如果将传入的 Pod 放置在 “zone2”,则 “zone1“ 中 的 skew 值变为 1, “zone2” 上的偏斜skew 值为 0 (zone2 有 1 个匹配的 Pod,拥有全局最小匹配 Pod 数的拓扑域正是 zone2 自己), 则满足“maxSkew: 1”约束

优先级调度

  • 背景:集群资源不够用时候怎么办

    • 先到先得策略(FIFO):简单、相对公平、上手快
    • 优先级策略(Priority): 符合日常公司业务特点, 优先级值越大,优先级越高
  • 优先级调度过程(发生在Pending Pod出队列开始调度):

    • Pod2(低优先级)和Pod1(高优先级)先后进入调度队列,但均未被调度
    • 当进行一轮调度时,PriorityQueue会优先将优先级更大的Pod1弹出队列进行调度
    • 调度成功后,对此Pod1进行Bind,并开始下一轮调度Pod2
  • 优先级抢占过程(发生在调度失败):

    • Pod2先进行调度,调度成功后分配至Node1上运行
    • 之后Pod1再进行调度,由于Node1资源不足出现了调度失败,此时进入抢占流程
    • 在经过抢占算法计算后,选中了Pod2作为Pod1的承让者
    • 驱逐了Node1上运行的Pod2,并将Pod1调度至Node1

节点压力驱逐

节点压力驱逐是 kubelet 主动终止 Pod 以回收节点上资源的过程

  • 当这些资源中的一个或者多个达到特定的消耗水平,kubelet 可以主动驱逐节点上一个或者多个 Pod,以回收资源防止出现资源饥饿。
    kubelet 会主动给节点打上一个或者多个污点标记,这些标记的 effect 为 NoExecute

    • 内存比较紧张,会打上 node.kubernetes.io/memory-pressure
    • 磁盘比较紧张,会打上 node.kubernetes.io/disk-pressure
    • pid 比较紧张,会打上 node.kubernetes.io/pid-pressure
  • 而如果该节点上,已有一些 Pod 在运行,并且这些 Pod 没有配置以上三种对应的容忍度,则 kubelet 会开始驱逐的流程,一个一个的驱逐,直到节点不再有存在资源压力为止,才会清除污点,结束驱逐。

  • 在节点压力驱逐期间,kubelet 将所选 Pod 的 PodPhase 设置为 Failed。这将终止 Pod。

  • 通常还会带上一个 tolerationSeconds ,它意思是在污点出现后,Pod 还可以正常工作多少时间,也就是延迟多久再进行驱逐。

驱逐信号

驱逐信号是特定资源在特定时间点的当前状态。 kubelet 使用驱逐信号,通过将信号与驱逐条件进行比较来做出驱逐决定, 驱逐条件是节点上应该可用资源的最小量。

  • 软驱逐条件

    软驱逐条件将驱逐条件与管理员所必须指定的宽限期配对。 在超过宽限期之前,kubelet 不会驱逐Pod。 如果没有指定的宽限期,kubelet 会在启动时返回错误。

  • 硬驱逐条件

    硬驱逐条件没有宽限期。当达到硬驱逐条件时, kubelet 会立即杀死 pod,而不会正常终止以回收紧缺的资源

  • 驱逐pod时的选择

    1. 首先考虑资源使用量超过其请求的 BestEffort 或 Burstable Pod。 这些 Pod 会根据它们的优先级以及它们的资源使用级别超过其请求的程度被逐出。
      指定的宽限期,kubelet 会在启动时返回错误。
  • 硬驱逐条件

    硬驱逐条件没有宽限期。当达到硬驱逐条件时, kubelet 会立即杀死 pod,而不会正常终止以回收紧缺的资源

  • 驱逐pod时的选择

    1. 首先考虑资源使用量超过其请求的 BestEffort 或 Burstable Pod。 这些 Pod 会根据它们的优先级以及它们的资源使用级别超过其请求的程度被逐出。
    2. 资源使用量少于请求量的 Guaranteed Pod 和 Burstable Pod 根据其优先级被最后驱逐

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询