Framework是kubernetes扩展的第二种实现,相比SchedulerExtender基于远程独立Service的扩展,Framework核心则实现了一种基于扩展点的本地化的规范流程管理机制
1. 扩展实现目标
Framework的设计在官方文档中已经有明确的描述,当前还没有Stable, 本文目前基于1.18版本聊一聊除了官方描述外的实现的上的一些细节
1.1 阶段扩展点
目前官方主要是围绕着之前的预选和优选阶段进行扩展,提供了更多的扩展点,其中每个扩展点都是一类插件,我们可以根据我们的需要在对应的阶段来进行扩展插件的编写,实现调度增强
在当前版本中优先级插件已经抽取到了framework中,后续应该会继续将预选插件来进行抽取,这块应该还得一段时间才能稳定
1.2 context与CycleState
在Framework的实现中,每个插件扩展阶段调用都会传递context和CycleState两个对象,其中context与我们在大多数go编程中的用法类似,这里主要是用于多阶段并行处理的时候的统一退出操作,而CycleState则存储当前这一个调度周期内的所有数据,这是一个并发安全的结构,内部包含一个读写锁
1.3 Bind Permit
Permit是在进行Bind绑定操作之前进行的一项操作,其主要设计目标是在进行bind之前,进行最后一道决策,即当前pod是否准许进行最终的Bind操作,具有一票否决权,如果里面的插件拒绝,则对应的pod会重新进行调度
2. 核心源码实现
2.1 Framework核心数据结构
Framework的核心数据结构简单的来说分为三部分:插件集合(针对每个扩展阶段都会有自己的集合)、元数据获取接口(集群和快照数据的获取)、等待Pod集合
2.1.1 插件集合
插件集合中会根据不同的插件类型,来进行分类保存, 其中还有一个插件的优先级存储map,目前只有在优选阶段使用,后续可能会加入预选的优先级
pluginNameToWeightMap map[string]int
queueSortPlugins []QueueSortPlugin
preFilterPlugins []PreFilterPlugin
filterPlugins []FilterPlugin
postFilterPlugins []PostFilterPlugin
scorePlugins []ScorePlugin
reservePlugins []ReservePlugin
preBindPlugins []PreBindPlugin
bindPlugins []BindPlugin
postBindPlugins []PostBindPlugin
unreservePlugins []UnreservePlugin
permitPlugins []PermitPlugin
2.1.2 集群数据获取
主要是集群中的一些数据获取接口的实现,主要是为了实现FrameworkHandle, 该接口主要是提供一些数据的获取的接口和集群操作的接口给插件使用
clientSet clientset.Interface
informerFactory informers.SharedInformerFactory
volumeBinder *volumebinder.VolumeBinder
snapshotSharedLister schedulerlisters.SharedLister
2.1.3 等待pod集合
等待pod集合主要是存储在Permit阶段进行等待的pod,如果在等待周期中pod被删除,则会直接拒绝
waitingPods *waitingPodsMap
2.1.4 插件工厂注册表
通过插件工厂来存储所有注册的插件工厂,然后通过插件工厂构建具体的插件
registry Registry
2.2 插件工厂注册表

2.2.1 插件工厂函数
工厂函数即传入对应的参数,构建一个Plugin,其中FrameworkHandle主要是用于获取快照和集群的其他数据
type PluginFactory = func(configuration *runtime.Unknown, f FrameworkHandle) (Plugin, error)
2.2.2 插件工厂的实现
在go里面大多数插件工厂的实现都是通过map来实现这里也是一样,对外暴露Register和UnRegister接口
type Registry map[string]PluginFactory
// Register adds a new plugin to the registry. If a plugin with the same name
// exists, it returns an error.
func (r Registry) Register(name string, factory PluginFactory) error {
if _, ok := r[name]; ok {
return fmt.Errorf("a plugin named %v already exists", name)
}
r[name] = factory
return nil
}
// Unregister removes an existing plugin from the registry. If no plugin with
// the provided name exists, it returns an error.
func (r Registry) Unregister(name string) error {
if _, ok := r[name]; !ok {
return fmt.Errorf("no plugin named %v exists", name)
}
delete(r, name)
return nil
}
// Merge merges the provided registry to the current one.
func (r Registry) Merge(in Registry) error {
for name, factory := range in {
if err := r.Register(name, factory); err != nil {
return err
}
}
return nil
}
2.3 插件注册实现
这里以preFilterPlugins为例展示整个流程的

本文探讨了kubernetes调度器Framework的核心实现,包括扩展点、上下文、CycleState、Permit机制以及核心数据结构如插件集合、等待Pod集合等。详细介绍了插件工厂注册、注册实现和插件调用方法,揭示了调度流程中的数据管理和并发控制策略。
最低0.47元/天 解锁文章
1023

被折叠的 条评论
为什么被折叠?



