调度
概述
1、在 Kubernetes 中,调度是指将 Pod 放置到合适的节点上,以便对应节点上的 Kubelet 能够运行这些 Pod
2、调度器通过 Kubernetes 的监测(Watch)机制来发现集群中新创建且尚未被调度到节点上的 Pod
(1)调度器会将所发现的每一个未调度的 Pod 调度到一个合适的节点上来运行
(2)调度器会依据下文的调度原则来做出调度选择
kube-scheduler
1、kube-scheduler 是 Kubernetes 集群的默认调度器,并且是集群控制面的一部分
(1)kube-scheduler 在设计上允许你自己编写一个调度组件并替换原有的 kube-scheduler
(2)Kube-scheduler 选择一个最佳节点来运行新创建的或尚未调度(unscheduled)的 Pod
(3)由于 Pod 中的容器和 Pod 本身可能有不同的要求,调度程序会过滤掉任何不满足 Pod 特定调度需求的节点,或者,API 允许在创建 Pod 时为它指定一个节点,但这并不常见,并且仅在特殊情况下才会这样做
2、在一个集群中,满足一个 Pod 调度请求的所有节点称之为可调度节点
(1)如果没有任何一个节点能满足 Pod 的资源请求,那么这个 Pod 将一直停留在未调度状态,直到调度器能够找到合适的 Node
(2)调度器先在集群中找到一个 Pod 的所有可调度节点,然后根据一系列函数对这些可调度节点打分,选出其中得分最高的节点来运行 Pod。之后,调度器将这个调度决定通知给 kube-apiserver,这个过程叫做绑定
(3)在做调度决定时需要考虑的因素包括:单独和整体的资源请求、硬件 / 软件 / 策略限制、 亲和以及反亲和要求、数据局部性、负载间的干扰等等
3、调度方式
(1)自动调度:运行在哪个节点上完全由 scheduler 经过一系列的算法计算得出
(2)定向调度:NodeName、NodeSelector
(3)亲和性调度:NodeAffinity、PodAffinity、PodAntiAffinity
(4)污点(容忍)调度:Taints、Toleration
将 Pod 指派给节点
1、可以约束一个 Pod 以便限制其只能在特定的节点上运行,或优先在特定的节点上运行
(1)有几种方法可以实现这点,推荐的方法都是用标签选择算符来进行选择
(2)通常这样的约束不是必须的,因为调度器将自动进行合理的放置,比如:将 Pod 分散到节点上,而不是将 Pod 放置在可用资源不足的节点上等等
(3)但在某些情况下,你可能需要进一步控制 Pod 被部署到哪个节点
2、可以使用下列方法中的任何一种来选择 Kubernetes 对特定 Pod 的调度
(1)与节点标签匹配的 nodeSelector
(2)亲和性与反亲和性
(3)nodeName 字段
(4)Pod 拓扑分布约束
节点标签
1、与很多其他 Kubernetes 对象类似,节点也有标签
2、可以手动地添加标签。 Kubernetes 也会为集群中所有节点添加一些标准的标签
3、这些标签的取值是取决于云提供商的,并且是无法在可靠性上给出承诺的,例如:kubernetes.io/hostname 的取值在某些环境中可能与节点名称相同, 而在其他环境中会取不同的值
节点隔离 / 限制
1、通过为节点添加标签,可以准备让 Pod 调度到特定节点或节点组上,来确保特定的 Pod 只能运行在具有一定隔离性,安全性或监管属性的节点上
2、如果使用标签来实现节点隔离,建议选择节点上的 kubelet 无法修改的标签键,这可以防止受感染的节点在自身上设置这些标签,进而影响调度器将工作负载调度到受感染的节点
nodeSelector
1、nodeSelector 是节点选择约束的最简单推荐形式
2、可以将 nodeSelector 字段添加到 Pod 的规约中设置你希望目标节点所具有的节点标签,Kubernetes 只会将 Pod 调度到拥有你所指定的每个标签的节点上
亲和性与反亲和性
1、nodeSelector 提供了一种最简单的方法来将 Pod 约束到具有特定标签的节点上,亲和性和反亲和性扩展了你可以定义的约束类型
2、使用亲和性与反亲和性的优点
(1)亲和性、反亲和性语言的表达能力更强。nodeSelector 只能选择拥有所有指定标签的节点。 亲和性、反亲和性为你提供对选择逻辑的更强控制能力
(2)你可以标明某规则是“软需求”或者“偏好”,这样调度器在无法找到匹配节点时仍然调度该 Pod
(3)你可以使用节点上(或其他拓扑域中)运行的其他 Pod 的标签来实施调度约束,而不是只能使用节点本身的标签。这个能力让你能够定义规则允许哪些 Pod 可以被放置在一起
3、亲和性功能由两种类型的亲和性组成
(1)节点亲和性功能类似于 nodeSelector 字段,但它的表达能力更强,并且允许你指定软规则
(2)Pod 间亲和性 / 反亲和性允许你根据其他 Pod 的标签来约束 Pod
节点亲和性
1、节点亲和性概念上类似于 nodeSelector, 它使你可以根据节点上的标签来约束 Pod 可以调度到哪些节点上
2、节点亲和性有两种
(1)requiredDuringSchedulingIgnoredDuringExecution:调度器只有在规则被满足的时候才能执行调度。此功能类似于 nodeSelector,但其语法表达能力更强
(2)preferredDuringSchedulingIgnoredDuringExecution:调度器会尝试寻找满足对应规则的节点。如果找不到匹配的节点,调度器仍然会调度该 Pod
(3)说明:在上述类型中,IgnoredDuringExecution 意味着如果节点标签在 Kubernetes 调度 Pod 后发生了变更,Pod 仍将继续运行
3、可以使用 Pod 规约中的 .spec.affinity.nodeAffinity 字段来设置节点亲和性
4、可以使用 operator 字段来为 Kubernetes 设置在解释规则时要使用的逻辑操作符
(1)可以使用 In、NotIn、Exists、DoesNotExist、Gt、Lt 之一作为操作符
(2)NotIn 和 DoesNotExist 可用来实现节点反亲和性行为,也可以使用节点污点将 Pod 从特定节点上驱逐
5、说明
(1)如果同时指定 nodeSelector 和 nodeAffinity,两者必须都要满足,才能将 Pod 调度到候选节点上
(2)如果与 nodeAffinity 类型关联的 nodeSelectorTerms 中指定多个条件,只要其中一个 nodeSelectorTerms 满足(各个条件按逻辑或操作组合)的话,Pod 就可以被调度到节点上
(3)如果与 nodeSelectorTerms 中的条件相关联的单个 matchExpressions 字段中指定多个表达式,则只有当所有表达式都满足(各表达式按逻辑与操作组合)时,Pod 才能被调度到节点上
6、节点亲和性权重
(1)可以为 preferredDuringSchedulingIgnoredDuringExecution 亲和性类型的每个实例设置 weight 字段,其取值范围是 1 到 100
(2)当调度器找到能够满足 Pod 的其他调度请求的节点时,调度器会遍历节点满足的所有的偏好性规则,并将对应表达式的 weight 值加和,最终的加和值会添加到该节点的其他优先级函数的评分之上
(3)在调度器为 Pod 作出调度决定时,总分最高的节点的优先级也最高
Pod 间亲和性与反亲和性
1、Pod 间亲和性与反亲和性使你可以基于已经在节点上运行的 Pod 的标签来约束 Pod 可以调度到的节点,而不是基于节点上的标签
2、Pod 间亲和性与反亲和性的规则格式为“如果 X 上已经运行了一个或多个满足规则 Y 的 Pod,则这个 Pod 应该(或者在反亲和性的情况下不应该)运行在 X 上”
(1)这里的 X 可以是节点、机架、云提供商可用区或地理区域或类似的拓扑域
(2)Y 则是 Kubernetes 尝试满足的规则
(3)通过标签选择算符的形式来表达规则(Y),并可根据需要指定选关联的命名空间列表,Pod 在 Kubernetes 中是命名空间作用域的对象,因此 Pod 的标签也隐式地具有命名空间属性,针对 Pod 标签的所有标签选择算符都要指定命名空间,Kubernetes 会在指定的命名空间内寻找标签
(4)通过 topologyKey 来表达拓扑域(X)的概念,其取值是系统用来标示域的节点标签键
3、说明
(1)Pod 间亲和性和反亲和性都需要相当的计算量,因此会在大规模集群中显著降低调度速度,不建议在包含数百个节点的集群中使用这类设置
(2)Pod 反亲和性需要节点上存在一致性的标签。换言之, 集群中每个节点都必须拥有与 topologyKey 匹配的标签。如果某些或者所有节点上不存在所指定的 topologyKey 标签,调度行为可能与预期的不同
4、Pod 间亲和性与反亲和性的类型
(1)requiredDuringSchedulingIgnoredDuringExecution:告诉调度器, 将两个服务的 Pod 放到同一个云提供商可用区内,因为它们彼此之间通信非常频繁
(2)preferredDuringSchedulingIgnoredDuringExecution:将同一服务的多个 Pod 分布到多个云提供商可用区中
(3)要使用 Pod 间亲和性,可以使用 Pod 规约中的 .affinity.podAffinity 字段
(4)对于 Pod 间反亲和性,可以使用 Pod 规约中的 .affinity.podAntiAffinity 字段
5、可以针对 Pod 间亲和性与反亲和性为其 operator 字段使用 In、NotIn、Exists、 DoesNotExist 等值
6、原则上,topologyKey 可以是任何合法的标签键,出于性能和安全原因,topologyKey 有一些限制
(1)对于 Pod 亲和性而言,在 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution 中,topologyKey 不允许为空
(2)对于 requiredDuringSchedulingIgnoredDuringExecution 要求的 Pod 反亲和性, 准入控制器 LimitPodHardAntiAffinityTopology 要求 topologyKey 只能是 kubernetes.io/hostname,如果你希望使用其他定制拓扑逻辑, 你可以更改准入控制器或者禁用之
(3)除了 labelSelector 和 topologyKey,你也可以指定 labelSelector 要匹配的命名空间列表,方法是在 labelSelector 和 topologyKey 所在层同一层次上设置 namespaces,如果 namespaces 被忽略或者为空,则默认为 Pod 亲和性 / 反亲和性的定义所在的命名空间
nodeName
1、nodeName 是比亲和性或者 nodeSelector 更为直接的形式
(1)nodeName 是 Pod 规约中的一个字段
(2)如果 nodeName 字段不为空,调度器会忽略该 Pod,而指定节点上的 kubelet 会尝试将 Pod 放到该节点上
(3)使用 nodeName 规则的优先级会高于使用 nodeSelector 或亲和性与非亲和性的规则
2、使用 nodeName 来选择节点的方式有一些局限性
(1)如果所指代的节点不存在,则 Pod 无法运行,而且在某些情况下可能会被自动删除
(2)如果所指代的节点无法提供用来运行 Pod 所需的资源,Pod 会失败, 而其失败原因中会给出是否因为内存或 CPU 不足而造成无法运行
(3)在云环境中的节点名称并不总是可预测的,也不总是稳定的
Pod 拓扑分布约束
1、可以使用拓扑分布约束(Topology Spread Constraints)来控制 Pod 在集群内故障域之间的分布
2、故障域的示例有区域(Region)、可用区(Zone)、节点、其他用户自定义的拓扑域
3、这样做有助于提升性能、实现高可用或提升资源利用率
污点和容忍度
1、污点(Taint)使节点能够排斥一类特定的 Pod
2、容忍度(Toleration)是应用于 Pod 上的
(1)容忍度允许调度器调度带有对应污点的 Pod
(2)容忍度允许调度但并不保证调度:作为其功能的一部分, 调度器也会评估其他参数
3、污点和容忍度(Toleration)相互配合,可以用来避免 Pod 被分配到不合适的节点上,每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的 Pod, 是不会被该节点接受的
使用例
1、命令 kubectl taint 给节点增加一个污点,比如:
#给节点 node1 增加一个污点,它的键名是 key1,键值是 value1,效果是 NoSchedule
#表示只有拥有和这个污点相匹配的容忍度的 Pod 才能够被分配到 node1 这个节点
kubectl taint nodes node1 key1=value1:NoSchedule
2、移除上述命令所添加的污点
kubectl taint nodes node1 key1=value1:NoSchedule-
3、可以在 Pod 规约中为 Pod 设置容忍度
(1)下面两个容忍度均与上面例子中使用 kubectl taint 命令创建的污点相匹配, 因此如果一个 Pod 拥有其中的任何一个容忍度,都能够被调度到 node1
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
tolerations:
- key: "key1"
operator: "Exists"
effect: "NoSchedule"
4、operator
(1)默认值是 Equal
(2)一个容忍度和一个污点相“匹配”是指它们有一样的键名和效果,如果 operator 是 Exists (此时容忍度不能指定 value),或者如果 operator 是 Equal ,则它们的 value 应该相等
5、两种特殊情况
(1)如果一个容忍度的 key 为空且 operator 为 Exists,表示这个容忍度与任意的 key、value 和 effect 都匹配,即这个容忍度能容忍任何污点
(2)如果 effect 为空,则可以与所有键名 key1 的效果相匹配
6、PreferNoSchedule
(1)这是“优化”或“软”版本的 NoSchedule
(2)系统会尽量避免将 Pod 调度到存在其不能容忍污点的节点上,但这不是强制的
7、可以给一个节点添加多个污点,也可以给一个 Pod 添加多个容忍度设置
(1)Kubernetes 处理多个污点和容忍度的过程就像一个过滤器:从一个节点的所有污点开始遍历,过滤掉那些 Pod 中存在与之相匹配的容忍度的污点,余下未被过滤的污点的 effect 值决定了 Pod 是否会被分配到该节点
(2)需要注意以下情况
(3)如果未被忽略的污点中存在至少一个 effect 值为 NoSchedule 的污点, 则 Kubernetes 不会将 Pod 调度到该节点
(4)如果未被忽略的污点中不存在 effect 值为 NoSchedule 的污点,但是存在至少一个 effect 值为 PreferNoSchedule 的污点,则 Kubernetes 会尝试不将 Pod 调度到该节点
(5)如果未被忽略的污点中存在至少一个 effect 值为 NoExecute 的污点,则 Kubernetes 不会将 Pod 调度到该节点(如果 Pod 还未在节点上运行),或者将 Pod 从该节点驱逐(如果 Pod 已经在节点上运行)
基于污点的驱逐
1、NoExecute 会影响已经在节点上运行的 Pod
(1)如果 Pod 不能忍受这类污点,Pod 会马上被驱逐
(2)如果 Pod 能够忍受这类污点,但是在容忍度定义中没有指定 tolerationSeconds, 则 Pod 还会一直在这个节点上运行
(3)如果 Pod 能够忍受这类污点,而且指定了 tolerationSeconds,则 Pod 还能在这个节点上继续运行这个指定的时间长度
2、当某种条件为真时,节点控制器会自动给节点添加一个污点。当前内置的污点包括
(1)node.kubernetes.io/not-ready:节点未准备好。这相当于节点状况 Ready 的值为 "False"
(2)node.kubernetes.io/unreachable:节点控制器访问不到节点,这相当于节点状况 Ready 的值为 "Unknown"
(3)node.kubernetes.io/memory-pressure:节点存在内存压力
(4)node.kubernetes.io/disk-pressure:节点存在磁盘压力
(5)node.kubernetes.io/pid-pressure:节点的 PID 压力
(6)node.kubernetes.io/network-unavailable:节点网络不可用
(7)node.kubernetes.io/unschedulable:节点不可调度
(8)node.cloudprovider.kubernetes.io/uninitialized:如果 kubelet 启动时指定了一个“外部”云平台驱动, 它将给当前节点添加一个污点将其标志为不可用。在 cloud-controller-manager 的一个控制器初始化这个节点后,kubelet 将删除这个污点
3、在节点被驱逐时,节点控制器或者 kubelet 会添加带有 NoExecute 效果的相关污点,如果异常状态恢复正常,kubelet 或节点控制器能够移除相关的污点
4、控制面会限制向节点添加新污点的速率。这一速率限制可以管理多个节点同时不可达时 (例如出现网络中断的情况),可能触发的驱逐的数量
5、可以为 Pod 设置 tolerationSeconds,以指定当节点失效或者不响应时,Pod 维系与该节点间绑定关系的时长
(1)Kubernetes 会自动给 Pod 添加针对 node.kubernetes.io/not-ready 和 node.kubernetes.io/unreachable 的容忍度,且配置 tolerationSeconds=300,除非用户自身或者某控制器显式设置此容忍度
(2)这些自动添加的容忍度意味着 Pod 可以在检测到对应的问题之一时,在 5 分钟内保持绑定在该节点上
6、DaemonSet 中的 Pod 被创建时,针对以下污点自动添加的 NoExecute 的容忍度将不会指定 tolerationSeconds
(1)node.kubernetes.io/unreachable
(2)node.kubernetes.io/not-ready
(3)这保证了出现上述问题时 DaemonSet 中的 Pod 永远不会被驱逐
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战