共计 3403 个字符,预计需要花费 9 分钟才能阅读完成。
Kubernetes 是目前最受欢迎的⾃动化容器治理平台,它提供了灵便的申明式容器编排、主动部署、资源调度等性能。Kube-Scheduler 作为 Kubernetes 的外围组件之一,次要负责整个集群资源的调度性能,依据特定的调度算法和策略,将 Pod 调度到最优的工作节点下面去,从而更加正当、充沛地利用集群资源。
然而随着 Kubernetes 部署的工作类型越来越多,原生 Kube-Scheduler 曾经不能应答多样的调度需要:比方机器学习、深度学习训练任务对于协同调度性能的需要;高性能计算作业,基因计算工作流对于一些动静资源 GPU、网络、存储卷的动静资源绑定需要等。因而自定义 Kubernetes 调度器的需要愈发迫切,本文探讨了扩大 Kubernetes 调度程序的各种办法,而后应用目前最佳的扩大形式 Scheduling Framework,演示如何扩大 Scheduler。
01 自定义调度器的形式
02 Scheduling Framework 解析
如下图所示,调度框架提供了丰盛的扩大点,在这幅图中,Filter 相当于之前 Predicate 预选模块, Score 相当于 Priority 优选模块,每一个扩大点模块都提供了接口,咱们能够实现扩大点定义的接口来实现本人的调度逻辑,并将实现的插件注册到扩大点。
Scheduling Framework 在执行调度流程时,当运行到扩大点时,会调用咱们注册的插件,通过执行自定义插件的策略,满足调度需要。此外,一个插件能够在多个扩大点注册,用以执行更简单或有状态的工作。
Scheduling Framework 每次调度一个 Pod,都分为调度周期和绑定周期两局部来执行,调度周期为 Pod 抉择一个节点,绑定周期则调用 Apiserver,用选好的 Node,更新 Pod 的 spec.nodeName 字段。调度周期和绑定周期统称为“Scheduling Context”(调度上下文)。调度周期是串行运行的,同一时间只能有一个 Pod 被调度,是线程平安的;而绑定周期因为须要拜访 Apiserver 的接口,耗时较长,为了进步调度的效率,须要异步执行,即同一时间,可执行多个 bind 操作,是非线程平安的。
如果 Pod 被确定为不可调度或远程桌面存在外部谬误,那么调度周期或绑定周期将被停止。Pod 将返回队列并期待下一次重试。如果一个绑定周期被终止,它将触发 Reserve 插件中的 UnReserve 办法。
Scheduling Cycle 的扩大点
QueueSort
用于给调度队列排序,默认状况下,所有的 Pod 都会被放到一个队列中,此扩大用于对 Pod 的待调度队列进行排序,以决定先调度哪个 Pod,QueueSort 扩大实质上只须要实现一个办法 Less(Pod1, Pod2) 用于比拟两个 Pod 谁更优先取得调度,同一时间点只能有一个 QueueSort 插件失效。
PreFilter
用于对 Pod 的信息进行预处理,或者查看一些集群或 Pod 必须满足的前提条件,比方 Pod 是否蕴含指定的 annotations 或 labels,如果 PreFilter 返回了 error,则调度过程终止。
Filter
用于排除那些不能运行该 Pod 的节点,对于每一个节点,调度器将按程序执行 Filter 扩大,如果任何一个 Filter 将节点标记为不可选,则余下的 Filter 扩大将不会被执行。如果对默认调度器提供的预选规定不称心,能够在配置中禁用默认调度器的预选算法,在这个扩大点只执行本人自定义的过滤逻辑。Node 节点执行 Filter 策略是并发执行的,所以在同一调度周期中屡次调用过滤器。
PostFilter
实现此扩大的插件是在 Filter 阶段之后被调用,仅当没有为 Pod 找到可行的节点时才调用。如果有任何 PostFilter 插件将节点标记为可调度节点,则前面的 PostFilter 插件就不会被调用了。一个典型的 PostFilter 实现是抢占,它试图通过抢占其余 Pod 来使 Pod 可调度。
PreScore
在预选后被调用,通常用来在 Score 之前进行一些信息生成或者记录日志和监控信息
Score
实现此扩大的插件为已通过过滤阶段的所有节点进行打分,调度器将针对每一个节点调用 Score 扩大。
NormalizeScore
在 NormalizeScore 阶段,调度器将会把每个 Score 扩大对具体某个节点的评分后果和该扩大的权重合并起来,作为最终评分后果,评分后果是一个范畴内的整数。如果 Score 或 NormalizeScore 返回谬误,则调度周期将停止。
Reserve
此扩大点为 Pod 预留的在要运行节点上的资源,目标是防止调度器在期待 Pod 与节点绑定的过程中调度新的 Pod 到节点上时,产生理论应用资源超出可用资源的状况。(因为绑定 Pod 到节点上是异步产生的)。这是调度过程的最初一个步骤,Pod 进入 Reserved 状态当前,要么在绑定失败时,触发 Unreserve 扩大,要么在绑定胜利时,由 PostBind 扩大完结绑定过程。
Permit
Permit 扩大,产生在 Pod 应用 Reserve 插件预留资源之后, Bind 扩大点 bind 之前,次要有三种策略,批准、回绝、期待。
1)approve(批准):当所有的 Permit 扩大都批准了 Pod 与节点的绑定,调度器将继续执行绑定过程
2)deny(回绝):如果任何一个 Permit 扩大 deny 了 Pod 与节点的绑定,Pod 将被放回到待调度队列,此时将触发 Unreserve 扩大
3)wait(期待):如果一个 Permit 扩大返回了 wait,则 Pod 将放弃在 Permit 阶段,直到被其余扩大 approve,如果超时事件产生,wait 状态变成 deny,Pod 将被放回到待调度队列,此时将触发 UnReserve 扩大
Binding Cycle 的扩大点
PreBind
扩大用于在 Pod 绑定之前执行某些逻辑。这个插件引入的起因,是有一些资源,是在不在调度 Pod 时,立刻确定可用的节点的资源,所以调度程序须要确保,这些资源曾经胜利绑定到选定的节点后,能力将 Pod 调度到此节点。例如,PreBind 扩大能够将一个基于网络的数据卷挂载到节点上,以 Pod 能够应用。如果任何一个 PreBind 扩大返回谬误,Pod 将被放回到待调度队列,此时将触发 Unreserve 扩大。
Bind
Bind 扩大会调用 apiserver 提供的接口,将 Pod 绑定到对应的节点上。
PostBind
PostBind 是一个信息扩大点。胜利绑定 Pod 后,将调用 PostBind 插件,可用于清理关联的资源。
UnReserve
是一个告诉性质的扩大,如果为 Pod 预留了资源,Pod 又在被绑定过程中被回绝绑定,则 Unreserve 扩大将被调用。Unreserve 扩大应该开释曾经为 Pod 预留的节点上的计算资源。在一个插件中,Reserve 扩大和 UnReserve 扩大应该成对呈现。
03 应用 Scheduling Framework 自定义 Scheduler
自定义插件须要两个步骤:
1)实现插件的接口
2)注册插件并配置插件
3.1 实现插件的接口
这里咱们实现 QueueSort 扩大点,先看看 QueueSort 扩大点定义的接口:
// QueueSortPlugin is an interface that must be implemented by “QueueSort” plugins.// These plugins are used to sort pods in the scheduling queue. Only one queue sort// plugin may be enabled at a time.type QueueSortPlugin interface {Plugin // Less are used to sort pods in the scheduling queue. Less(QueuedPodInfo, QueuedPodInfo) bool}
默认的调度器会优先调度优先级较高的 Pod , 其具体实现的形式是应用 QueueSort 这个插件,默认的实现,是对 Pod 的 Priority 值进行排序,但当优先级雷同时,再比拟 Pod 的 timestamp , timestamp 是 Pod 退出 queue 的工夫。咱们当初想先依据 Pod 的 Priority 值进行排序,当 Priority 值雷同,再依据 Pod 的 QoS 类型进行排序,最初再依据 Pod 的 timestamp 排序。