Kubernetes Scheduler 调度器
kube-scheduler 给一个 Pod 做调度选择时包含两个步骤
- Kubernetes 调度器默认为 kube-scheduler
- 过滤
- 执行一组过滤函数(Predicates / Filter Plugins)筛选出所有满足 Pod 调度需求的候选节点
- 打分
- 对每个可调度节点应用一组打分规则(Priorities / Score Plugins),从可调度节点中选出最合适的节点(总分最高的节点)
- 如果存在多个得分最高的节点,kube-scheduler 会从中随机选取一个
部署自定义调度器
- 参考资料
KubernetesKubernetes 调度器
Kubernetes 调度器
在 Kubernetes 中,调度是指将 Pod 放置到合适的节点上,以便对应节点上的 Kubelet 能够运行这些 Pod。 调度概览 调度器通过 Kubernetes 的监测(Watch)机制来发现集群中新创建且尚未被调度到节点上的 Pod。 调度器会将所发现的每一个未调度的 Pod 调度到一个合适的节点上来运行。 调度器会依据下文的调度原则来做出调度选择。 如果你想要理解 Pod 为什么会被调度到特定的节点上, 或者你想要尝试实现一个自定义的调度器,这篇文章将帮助你了解调度。 kube-scheduler kube-scheduler 是 Kubernetes 集群的默认调度器,并且是集群 控制面 的一部分。 如果你真的希望或者有这方面的需求,kube-scheduler 在设计上允许你自己编写一个调度组件并替换原有的 kube-scheduler。 Kube-scheduler 选择一个最佳节点来运行新创建的或尚未调度(unscheduled)的 Pod。 由于 Pod 中的容器和 Pod 本身可能有不同的要求,调度程序会过滤掉任何不满足 Pod 特定调度需求的节点。 或者,API 允许你在创建 Pod 时为它指定一个节点,但这并不常见,并且仅在特殊情况下才会这样做。 在一个集群中,满足一个 Pod 调度请求的所有节点称之为可调度节点。 如果没有任何一个节点能满足 Pod 的资源请求, 那么这个 Pod 将一直停留在未调度状态直到调度器能够找到合适的 Node。 调度器先在集群中找到一个 Pod 的所有可调度节点,然后根据一系列函数对这些可调度节点打分, 选出其中得分最高的节点来运行 Pod。之后,调度器将这个调度决定通知给 kube-apiserver,这个过程叫做绑定。 在做调度决定时需要考虑的因素包括:单独和整体的资源请求、硬件/软件/策略限制、 亲和以及反亲和要求、数据局部性、负载间的干扰等等。 kube-scheduler 中的节点选择 kube-scheduler 给一个 Pod 做调度选择时包含两个步骤:
Kubernetes配置多个调度器
配置多个调度器
Kubernetes 自带了一个默认调度器,其详细描述请查阅 这里。 如果默认调度器不适合你的需求,你可以实现自己的调度器。 而且,你甚至可以和默认调度器一起同时运行多个调度器,并告诉 Kubernetes 为每个 Pod 使用哪个调度器。 让我们通过一个例子讲述如何在 Kubernetes 中运行多个调度器。 关于实现调度器的具体细节描述超出了本文范围。 请参考 kube-scheduler 的实现,规范示例代码位于 pkg/scheduler。 准备开始 你必须拥有一个 Kubernetes 的集群,且必须配置 kubectl 命令行工具让其与你的集群通信。 建议运行本教程的集群至少有两个节点,且这两个节点不能作为控制平面主机。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面的 Kubernetes 练习环境之一: iximiuz Labs Killercoda KodeKloud 玩转 Kubernetes 要获知版本信息,请输入 kubectl version. 打包调度器 将调度器可执行文件打包到容器镜像中。出于示例目的,可以使用默认调度器 (kube-scheduler)作为第二个调度器。 克隆 GitHub 上 Kubernetes 源代码, 并编译构建源代码。 git clone https://github.com/kubernetes/kubernetes.git cd kubernetes make 创建一个包含 kube-scheduler 二进制文件的容器镜像。用于构建镜像的 Dockerfile 内容如下: FROM busybox ADD ./_output/local/bin/linux/amd64/kube-scheduler /usr/local/bin/kube-scheduler 将文件保存为 Dockerfile,构建镜像并将其推送到镜像仓库。 此示例将镜像推送到 Google 容器镜像仓库(GCR)。 有关详细信息,请阅读 GCR 文档。 或者,你也可以使用 Docker Hub。 有关更多详细信息,请参阅 Docker Hub 文档。
Kubernetes调度器配置
调度器配置
特性状态: Kubernetes v1.25 [stable] 你可以通过编写配置文件,并将其路径传给 kube-scheduler 的命令行参数,定制 kube-scheduler 的行为。 调度模板(Profile)允许你配置 kube-scheduler 中的不同调度阶段。每个阶段都暴露于某个扩展点中。插件通过实现一个或多个扩展点来提供调度行为。 你可以通过运行 kube-scheduler --config <filename> 来设置调度模板, 使用 KubeSchedulerConfiguration v1 结构体。 最简单的配置如下: apiVersion: kubescheduler.config.k8s.io/v1 kind: KubeSchedulerConfiguration clientConnection: kubeconfig: /etc/srv/kubernetes/kube-scheduler/kubeconfig 说明: KubeSchedulerConfiguration v1beta3 在 v1.26 中已被弃用, 并将在 v1.29 中被移除。请将 KubeSchedulerConfiguration 迁移到 v1。 配置文件 通过调度配置文件,你可以配置 kube-scheduler 在不同阶段的调度行为。 每个阶段都在一个扩展点中公开。 调度插件通过实现一个或多个扩展点,来提供调度行为。 你可以配置同一 kube-scheduler 实例使用多个配置文件。 扩展点 调度行为发生在一系列阶段中,这些阶段是通过以下扩展点公开的: queueSort:这些插件对调度队列中的悬决的 Pod 排序。 一次只能启用一个队列排序插件。 preFilter:这些插件用于在过滤之前预处理或检查 Pod 或集群的信息。 它们可以将 Pod 标记为不可调度。 filter:这些插件相当于调度策略中的断言(Predicates),用于过滤不能运行 Pod 的节点。 过滤器的调用顺序是可配置的。 如果没有一个节点通过所有过滤器的筛选,Pod 将会被标记为不可调度。 postFilter:当无法为 Pod 找到可用节点时,按照这些插件的配置顺序调用他们。 如果任何 postFilter 插件将 Pod 标记为可调度,则不会调用其余插件。 preScore:这是一个信息扩展点,可用于预打分工作。 score:这些插件给通过筛选阶段的节点打分。调度器会选择得分最高的节点。 reserve:这是一个信息扩展点,当资源已经预留给 Pod 时,会通知插件。 这些插件还实现了 Unreserve 接口,在 Reserve 期间或之后出现故障时调用。 permit:这些插件可以阻止或延迟 Pod 绑定。 preBind:这些插件在 Pod 绑定节点之前执行。 bind:这个插件将 Pod 与节点绑定。bind 插件是按顺序调用的,只要有一个插件完成了绑定, 其余插件都会跳过。bind 插件至少需要一个。 postBind:这是一个信息扩展点,在 Pod 绑定了节点之后调用。 multiPoint:这是一个仅配置字段,允许同时为所有适用的扩展点启用或禁用插件。 对每个扩展点,你可以禁用默认插件或者是启用自己的插件,例如:
- k8s 可以同时部署多种 scheduler
- 也可以仅配置多个 scheduler profile 来定义同一 Scheduler 实例的不同表现
- 部署 pod 时通过 spec.schedulerName 来指定调度器
使用 kube-scheduler 镜像并传递自定义配置来创建新的调度器
vim admin/sched/RBAC.yaml
vim admin/sched/my-custom-scheduler.yaml
在启用了 leader 选举的情况下运行多调度器需要进一步修改 Configmap 文件配置
kubectl get leases -n kube-system- 锁本质是一个 Lease 资源
- Kubernetes 中多个调度器实例不能同时进行调度,否则会导致冲突
leaderElection.leaderElecttotrueleaderElection.resourceNamespaceto<lock-object-namespace>- 默认为
kube-system leaderElection.resourceNameto<lock-object-name>- 应该和 schedulerName 字段对应值相似或一致
kubectl apply -f ./admin/sched/
为 pod 指定调度器
- 没有设置
spec.schedulerName则默认为 default-scheduler
spec.schedulerName与KubeSchedulerProfile的对应 schedulerName 字段一致
vim admin/sched/pod3.yaml
kubectl apply -f ./admin/sched/pod3.yaml
通过调度策略和调度配置来配置调度器的过滤和打分行为
- 调度策略允许你配置过滤所用的断言(Predicates)和打分所用的优先级(Priorities)
- 调度配置允许你配置实现不同调度阶段的插件,也可以配置 kube-scheduler 运行不同的配置文件
调度阶段的扩展点包括:QueueSort、Filter、Score、Bind 等等
QueueSort作用于 Pod 进入调度队列时
PreFilter,Filter,PostFilter对每个候选节点逐一检查,过滤掉不满足条件的节点
preScore,Score对通过 Filter 的节点进行打分
Reserve在调度器内部预留资源,防止其他 Pod 同时调度到同一节点导致冲突- 非持久化的占位操作(仅存在于调度器内存中)
- 如果后续 Bind 失败,会调用
Unreserve回滚
Permit允许插件延迟或拒绝 Pod 的绑定- 常见于等待外部系统就绪(如存储卷准备完毕)或实现批调度(等待同一批所有 Pod 都可调度后再放行)
PreBind,Bind,PostBind将 Pod 绑定到节点
Kubernetes Pod 资源保障和抢占、驱逐机制
参考资料
KubernetesPod Quality of Service Classes
Pod Quality of Service Classes
This page introduces Quality of Service (QoS) classes in Kubernetes, and explains how Kubernetes assigns a QoS class to each Pod as a consequence of the resource constraints that you specify for the containers in that Pod. Kubernetes relies on this classification to make decisions about which Pods to evict when there are not enough available resources on a Node. Quality of Service classes Kubernetes classifies the Pods that you run and allocates each Pod into a specific quality of service (QoS) class.
QoS 等级由 Pod 的 resources 自动生成,决定在资源不足时 Pod 被驱逐的优先级
- BestEffort(最低优先级,最先被驱逐)
- 容器没有设置
requests和limits
- Burstable(中等优先级)
- 至少有一个容器的
requests和limits不相等,或者只设置了requests
- Guaranteed(最高优先级,最后被驱逐)
- 每个容器都设置了
limits,且requests和limits相等且不为 0
干扰(Disruption)和干扰预算(PodDisruptionBudget, PDB)
- 参考资料
干扰分为自愿干扰和非自愿干扰
类型 | 说明 | 是否受 PDB 限制 |
自愿(Voluntary)中断 | 由集群管理员或控制器主动触发的操作 | ✅ 受 PDB 限制 |
非自愿(Involuntary)中断 | 节点宕机、内核 panic、硬件故障等意外事件 | ❌ 不受 PDB 限制 |
减轻非自愿干扰的一些方法
- 确保 Pod 在请求中给出 requests
- 设置 replicas 实现 Pod 的高可用性
- 设置 PodAntiAffinity 和 topologySpreadConstraints 来实现副本集的高可用性
健康 Pod 定义:status.conditions[] 中有 item 为 type="Ready" 且 status="True"
- 健康 Pod 始终受 PDB 保护
- 健康的 Pod 总是根据 PDB 进行驱逐
正在运行但不健康的 Pod 的驱逐行为由策略 spec.unhealthyPodEvictionPolicy 决定
- 正在运行但尚未达到健康状态的 Pod
status.phase="Running"
- 默认为
IfHealthyBudget - 仅当
status.currentHealthy >= status.desiredHealthy(即未违反 PDB)时,才允许驱逐正在运行但不健康的 Pod status特指PodDisruptionBudgetStatus,即PodDisruptionBudget对象本身的 status
AlwaysAllow总是允许驱逐正在运行但尚未达到健康状态的 Pod
Pod 设置 status.conditions[] 特定 item 的 type 为 DisruptionTarget 表示当前受到干扰
status.conditions[].type: DisruptionTarget
status.conditions[].reason可能的情况PreemptionByScheduler:被高优先级 Pod 抢占DeletionByTaintManager:无法容忍NoExecute污点而被驱逐EvictionByEvictionAPI:通过 Eviction API 主动驱逐(如kubectl drain)DeletionByPodGC:所属节点已不存在,被 Pod 垃圾回收器清理TerminationByKubelet:因节点压力、优雅关机或系统 Pod 抢占被 kubelet 终止
PDB 保障应用的高可用性和最小可用实例数
- PDB 不能防止非自愿干扰,但非自愿干扰造成的影响仍会计入 PDB 计算
- deploy, sts 进行滚动升级时不受 PDB 的限制
PDB 规范 selector, minAvailable, maxUnavailable, unhealthyPodEvictionPolicy
KubernetesPodDisruptionBudget
PodDisruptionBudget
PodDisruptionBudget 是一个对象,用于定义可能对一组 Pod 造成的最大干扰。
- 一个 PDB 对象同时只能够指定
maxUnavailable和minAvailable中的一个
spec.selector用于指定其所作用的 Pod 集合policy/v1中,空的选择算符{}会匹配名字空间中所有 Pod- 属于 LabelSelector 对象
matchExpressionsmatchLabels
spec.minAvailable表示驱逐后仍须保证可用的 Pod 数量- 可以是绝对值或是百分比
spec.maxUnavailable表示驱逐后允许不可用的 Pod 的最大数量- 可以是绝对值或是百分比
spec.unhealthyPodEvictionPolicy定义不健康的 Pod 应被考虑驱逐时的标准- 可用策略,默认为
IfHealthyBudget IfHealthyBudget仅当status.currentHealthy >= status.desiredHealthy(即未违反 PDB)时,才允许驱逐正在运行但不健康的 Podstatus特指PodDisruptionBudgetStatus,即PodDisruptionBudget对象本身的 statusAlwaysAllow总是允许驱逐正在运行但不健康的 Pod
- 针对 CRD 使用 PDB 时只能使用
.spec.minAvailable且只能指定整数值
kubectl drain --force忽略 PDB 清空节点
PDB 样例
minAvailable
maxUnavailable
基于 PriorityClass 的 Pod 优先级
- PriorityClass 是集群级资源,定义了从优先级类名称到优先级整数值的映射
PriorityClass 规范
value:整数,表示优先级的数值- 数值越大,优先级越高
- 用户可以设置任何小于或等于 10 亿的 32 位整数值,从 -2,147,483,648 到 1,000,000,000(含)
globalDefault:(可选)是否为默认优先级,布尔值- 若设为
true,则未显式指定 PriorityClass 的 Pod 将自动使用该 PriorityClass
description:(可选)描述信息
preemptionPolicy用于控制是否允许该优先级的 Pod 抢占其他 Pod- 可选值,默认为
PreemptLowerPriority PreemptLowerPriority- 允许该 PriorityClass 的 Pod 抢占较低优先级的 Pod
Never- 被放置在调度队列中较低优先级 Pod 之前,直到有足够的可用资源, 它才可以被调度
仅限系统可用的最高优先级 PriorityClass
system-cluster-critical- value 为 2,000,000,000,还要用户可定义的最大值 1,000,000,000 大一倍
system-node-critical- value 为 2,000,000,000
- 比
system-cluster-critical优先
PriorityClass 示例
抢占(Preemption)和驱逐(evict)
- 触发条件:当一个 Pod 创建后无法被调度(即没有节点满足其资源或约束要求)时,调度器会尝试抢占
- 调度器查找可以通过驱逐(evict)低于当前 Pod 优先级的低优先级 Pod 来腾出资源的节点,并对这些 Pod 执行驱逐后将 Pod 调度到该节点上
抢占过程
- 调度器识别出高优先级 Pod 无法调度
- 查找具有可以被抢占的低优先级 Pod 且可释放足够资源的节点
- 优先级需要低于当前 Pod
- 删除(优雅终止)这些低优先级 Pod
- 高优先级 Pod 被调度到腾出资源的节点上
将 Pod 指派给 Node
通过 spec.nodeName 手动调度 Pod 到某个 Node
- 不设置
schedulerName(或设为默认但确保调度器未运行),Kubernetes 将跳过调度阶段,直接绑定
- 手动调度 Pod 跳过调度阶段的影响
- 不检查资源可用性
- 不应用调度策略
- 如亲和性(affinity)、污点容忍(tolerations)、Pod 拓扑分布等全部失效
- 不检查节点存在性
- DaemonSet 不适用
spec.nodeName 样例
vim pods/pod-nginx-specific-node.yaml
通过 spec.nodeSeletor 指派 pod 给特定标签的 Node
- 参考资料
- 查看现有标签
kubectl get nodes --show-labels
- 添加与撤销标签
kubectl label nodes <your-node-name> key=valuekubectl label nodes <your-node-name> key=value-
spec.nodeSeletor 样例
vim pods/pod-nginx.yaml
taint 和 toleration 限制 pod 是否可以调度到特定节点
- 污点(taint)使节点能够排斥一类特定的 Pod
- 其中
NoExecute还会驱逐不具备对应 toleration 的已运行 Pod
taint 规范
key
value- 可选
effect:污点的效果,有三种:NoSchedule:不允许新 Pod 调度到该节点(已运行的不受影响)- 如
key=value:NoSchedule PreferNoSchedule:尽量避免调度(软性约束,调度器会尽量避开)NoExecute:不仅禁止调度,还会驱逐节点上已运行的、不满足容忍的 Pod
toleration 规范
key
operator- 必填,两种可选值,默认为 Equal
- Equal
- Exists
value- 可选,仅当
operator为 Equal 时可用
effect:可选,可容忍的 taint effect- NoSchedule
- PreferNoSchedule
- NoExecute
添加和移除 taint
kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoSchedule-- 移除污点
kubectl 查看当前 nodes taint
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.taints}{"\n"}{end}'
toleration 允许调度器调度 Pod 到带有对应污点的 Node
affinity (nodeaffinity, podAffinity, podAntiAffinity) 控制 Pod 调度位置
- taint, toleration 限制调度时的可用节点,affinity 控制 Pod 调度的节点选择
- 可用不代表会调度到对应节点,因为可能存在其他可用节点
- 使用
.spec.affinity.nodeAffinity字段来设置节点亲和性 - 影响 pod 调度时选择的节点
- 使用
.spec.affinity.podAffinity字段来设置 pod 间亲和性 - 让 Pod 尽量/必须和某些已存在的 Pod 跑在一起,实现微服务同机部署、降低延迟
- 使用
.spec.affinity.podAntiAffinity字段来设置 pod 间反亲和性 - 让 Pod 避开某些已存在的 Pod,实现高可用,避免单点故障
node 间亲和性字段规范
preferredDuringSchedulingIgnoredDuringExecutionweight,范围 1-100preferencematchExpressionsmatchFields- 用于匹配资源的字段(fields),而非标签(labels)
- 仅用于系统内部,不推荐用户使用
requiredDuringSchedulingIgnoredDuringExecutionnodeSelectorTermsmatchExpressionsmatchFields
pod 间亲和性字段规范
preferredDuringSchedulingIgnoredDuringExecutionweight,范围 1-100podAffinityTermlabelSelectortopologyKeynamespaces,可选namespaceSelector,可选
requiredDuringSchedulingIgnoredDuringExecution- 每个可用字段均为
PodAffinityTerm的键值 labelSelectortopologyKeynamespaces,可选namespaceSelector,可选
podAffinityTerm 的 topologyKey 指定在哪个拓扑域内进行 Pod 的亲和性/反亲和性计算
众所周知的常用 topologyKey 值
kubernetes.io/hostname:表示节点级别- 这是最细粒度的拓扑域,意味着规则会在单个节点上生效
topology.kubernetes.io/zone:表示可用区级别- 规则会在可用区这一层级上生效
- 可以将新 Pod 调度到与特定 Pod 在同一可用区的节点上,以减少网络延迟
topology.kubernetes.io/region:表示区域级别- 规则会在区域这一层级上生效
- 自定义
topologyKey:可以使用任何在节点上定义的标签作为topologyKey - 例如
rack、floor、building等,只要节点上存在对应的标签
一些限制
- 对于 Pod 亲和性而言,在
requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution中,topologyKey不允许为空
- 对于
requiredDuringSchedulingIgnoredDuringExecution要求的 Pod 反亲和性, 准入控制器LimitPodHardAntiAffinityTopology要求topologyKey只能是kubernetes.io/hostname
Pod 亲和性/反亲和性 topologyKey 示例
可用的亲和性类型
可以拆分为两部分来理解
requiredDuringScheduling/preferredDuringScheduling- 调度是否必须满足亲和性要求
IgnoredDuringExecution/RequiredDuringExecution- 是否驱逐已经部署但不满足条件的 pod
requiredDuringSchedulingIgnoredDuringExecution
- 必须满足
preferredDuringSchedulingIgnoredDuringExecution
- 最好满足
- 通过 weight 字段来设置权重,取值范围是 1 到 100
- 不同 label 的 weight 加总求和,优先取总分最高的节点
requiredDuringSchedulingRequiredDuringExecution
- 必须满足并驱逐当前不满足的节点
- 目前还没实现该功能
其中 matchExpressions.operator 设置要使用的逻辑操作符
In、NotIn、Exists、DoesNotExist、Gt和LtNotIn和DoesNotExist可以用来实现节点反亲和
nodeAffinity 带亲和性权重的样例
vim pods/pod-with-affinity-preferred-weight.yaml
podAffinity 带反亲和性权重的样例
vim pods/pod-with-pod-affinity.yaml
topologySpreadConstraints 控制 Pod 在集群内拓扑域之间的分布
参考资料
KubernetesPod 拓扑分布约束
Pod 拓扑分布约束
你可以使用 拓扑分布约束(Topology Spread Constraints) 来控制 Pod 在集群内故障域之间的分布, 例如区域(Region)、可用区(Zone)、节点和其他用户自定义拓扑域。 这样做有助于实现高可用并提升资源利用率。 你可以将集群级约束设为默认值, 或为个别工作负载配置拓扑分布约束。 动机 假设你有一个最多包含二十个节点的集群,你想要运行一个自动扩缩的 工作负载,请问要使用多少个副本? 答案可能是最少 2 个 Pod,最多 15 个 Pod。 当只有 2 个 Pod 时,你倾向于这 2 个 Pod 不要同时在同一个节点上运行: 你所遭遇的风险是如果放在同一个节点上且单节点出现故障,可能会让你的工作负载下线。 除了这个基本的用法之外,还有一些高级的使用案例,能够让你的工作负载受益于高可用性并提高集群利用率。 随着你的工作负载扩容,运行的 Pod 变多,将需要考虑另一个重要问题。 假设你有 3 个节点,每个节点运行 5 个 Pod。这些节点有足够的容量能够运行许多副本; 但与这个工作负载互动的客户端分散在三个不同的数据中心(或基础设施可用区)。 现在你可能不太关注单节点故障问题,但你会注意到延迟高于自己的预期, 在不同的可用区之间发送网络流量会产生一些网络成本。 你决定在正常运营时倾向于将类似数量的副本调度 到每个基础设施可用区,且你想要该集群在遇到问题时能够自愈。 Pod 拓扑分布约束使你能够以声明的方式进行配置。 topologySpreadConstraints 字段 Pod API 包括一个 spec.topologySpreadConstraints 字段。这个字段的用法如下所示: --- apiVersion: v1 kind: Pod metadata: name: example-pod spec: # 配置一个拓扑分布约束 topologySpreadConstraints: - maxSkew: <integer> minDomains: <integer> # 可选 topologyKey: <string> whenUnsatisfiable: <string> labelSelector: <object> matchLabelKeys: <list> # 可选;从 v1.
- topologySpreadConstraints 依赖于节点标签来标识每个节点所在的拓扑域
- 一些众所周知的标签键
topology.kubernetes.io/zonetopology.kubernetes.io/region
topologySpreadConstraints 规范
minDomains 参与计算的最小拓扑域数量(必须 >0)
- 未指定时默认为 1
- 若实际域数 <
minDomains,则全局最小值(符合条件的域中匹配的最小 Pod 数量)视为 0
maxSkew允许各拓扑域中匹配 Pod 数量的最大偏差(必须 >0)
topologyKey 节点标签键,如 topology.kubernetes.io/zone
- 众所周知的标签键
topology.kubernetes.io/zonetopology.kubernetes.io/region
whenUnsatisfiable 约束不满足时的行为
whenUnsatisfiable: DoNotSchedule硬限制偏差- 目标拓扑中匹配 Pod 的数量与全局最小值之间的最大允许差值
whenUnsatisfiable: ScheduleAnyway软策略- 更为偏向能够降低偏差值的拓扑域
labelSelector选择用于计算分布的已有 Pod(通过标签匹配)
matchLabelKeys Pod 标签键的列表
- 便于按版本分组分布
- 如Deployment 控制器自动添加的一个标签
pod-template-hash
- 创建 Pod 时,动态从新 Pod 标签中提取对应键值,自动合并到
labelSelector - 必须先设置
labelSelector - 相同的键不允许同时出现在
matchLabelKeys和labelSelector中 - 如果键在 Pod 标签中不存在,则会被忽略
- 不建议将
matchLabelKeys与可能直接在 Pod 上更新的标签一起使用 - kube-apiserver 不会将标签更新反映到合并的
labelSelector上
nodeAffinityPolicy 是否考虑 Pod 的 nodeAffinity/nodeSelector
- Honor:默认,只包含匹配节点
- Ignore:忽略 nodeAffinity/nodeSelector ,所有节点均包括到计算中
nodeTaintsPolicy 是否考虑节点污点
- Ignore:默认,忽略节点污点,所有节点均包括到计算中
- Honor:仅包含无污点或可容忍污点的节点
集群级别的默认约束和内置默认约束
- 集群级别的默认拓扑分布约束在且仅在以下条件满足时才会被应用到 Pod 上:
- Pod 没有在其
.spec.topologySpreadConstraints中定义任何约束 - Pod 隶属于某个 Service、ReplicaSet、StatefulSet 或 ReplicationController
通过调度方案中配置 PodTopologySpread 插件来设置集群级别的默认拓扑分布约束
- 规范同上,只是不能设置
labelSelector - 由 Pod 所属的 Service、ReplicaSet、StatefulSet 或 ReplicationController 来设置
- 样例
没有手动修改则默认采用以下内置默认约束
配置 PodTopologySpread 插件禁用内置默认约束
defaultingType改为 List
defaultConstraints改为空列表[]
一些隐式约定
- 命名空间隔离:调度器仅考虑与新 Pod 同一命名空间中的现有 Pod 作为分布计算的匹配对象
- 节点必须包含所有
topologyKey标签
labelSelector应匹配新 Pod 自身标签- 如果新 Pod 的标签不满足
topologySpreadConstraints.labelSelector,它仍可被调度(只要约束条件在已有 Pod 上成立),但不会被计入后续的分布统计,从而导致分布失衡
topologySpreadConstraints 均匀分布样例
- 假设有 zoneA 和 zoneB,node1~4
topologySpreadConstraints 多约束样例
- 假设有 zoneA 和 zoneB,node1~4
- Author:白鸟3
- URL:https://blog.kun2peng.top/operation/k8s_schedule
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
