k8s调度器扩展(Scheduler Framework)、源码编译及部署

本文详细介绍了如何扩展K8S调度器,包括下载v1.23.1版本源码,理解调度框架的预选和优选阶段,以及实现Filter、Score等扩展点。还涵盖了编译二进制程序、制作镜像和部署到集群的步骤,并分享了在扩展过程中遇到的问题及解决策略。

因为研究的需要,需要对K8S的调度器进行扩展,本文主要讲解了k8s调度器扩展的一个流程,其中包含源码修改、源码编译、调度器配置以及部署和本人所踩的一些坑,使用的k8s的版本为1.23.1

1.下载源码,在此选择v1.23.1版本:

git clone --branch v1.23.1 https://github.com/kubernetes/kubernetes.git

2. 扩展调度器

2.1 调度器的源码位置

调度器的源码在kubernetes/pkg/schedulerkubernetes/cmd/kube-scheduler目录下,第一个路径是调度器的主要功能实现的代码,第二个是调度器的main文件所在位置
在这里插入图片描述

2.2 调度框架

调度器中的调度框架定义了一组扩展点,用户可以实现扩展点定义的接口来实现自己的调度逻辑,并将扩展注册到扩展点上。
如下图所示,有下面几个扩展点:
在这里插入图片描述
主要讲解几个重要的扩展点:
QueueSort:该扩展点用于对调度队列中的Pod进行排序,以决定优先调度哪个Pod
Filter:对节点进行过滤,排除那些不满足Pod运行的节点,比如Pod需要2G的内存,如果节点的可用内存小于2G那么就会被过滤掉。
Score:对过滤后的节点进行打分,最终选择一个得分最高的节点来运行该Pod
Bind:用于将Pod绑定到选择的节点上。

2.3 预选和优先阶段

k8s调度器的调度框架是基于预选优选两个阶段的框架。

- 预选阶段:在该阶段,调度器将根据Pod的资源需求和节点的资源容量等信息,筛选出所有可行的节点,将它们标记为“可调度节点”。该阶段中,调度器将对各个节点依次执行注册的各个Filter插件(Filter插件可以有很多),只要有一个Filter插件不满足,就会排除掉该节点。
优选阶段:在该阶段,调度器将针对每个“可调度节点”,计算出一个得分,选取最高得分的节点,并将Pod绑定到该节点上。该阶段中,调度器将对经过过滤的各个阶段执行注册的各个Score插件(Score插件可以有很多)来对节点进行打分,最终对各个插件的打分进行聚合,最终选择得分最高的节点来运行Pod。

整个调度框架是可以扩展的,可以在预选和优选阶段之间添加过滤器和扩展器,以定制化地满足用户的需求。

源码分析:代码在kubernetes/pkg/scheduler/schedule_one.go
        预选阶段:

在这里插入图片描述
        优选阶段:
在这里插入图片描述

2.4 扩展点的源码定义

如下图为QueueSortPlugin、FilterPlugin以及ScorePlugin,还有很多其它的插件,在这里就不介绍了
在这里插入图片描述
 

2.5 调度器扩展以及注册

k8s scheduler为我们提供了很多调度插件扩展点,我们可以实现这些插件来实现特定的一些功能。
如果要自己实现一个打分插件,那么需要下面的步骤:

  1. kubernetes/pkg/scheduler/framework/plugins目录下创建自己的目录,编写代码实现插件定义的接口,比如Filter插件需要实现Filter这个方法,Score插件需要实现一个打分的方法Score
    实现后,需要将我们的方法注册进去,我们需要提供一个构造函数,类似于K8s中内置的插件
    下面为一个示例:在这里插入图片描述 3. 然后在kubernetes/cmd/kube-scheduler/scheduler.go中注册插件:在这里插入图片描述
    之后,就需要将源码进行编译然后部署到集群中了。
     

3. 编译二进制程序

k8s官方已经为我们提供了编译脚本,也就是Makefile
下面的命令可以将源码编译成二进制程序(执行下面的命令前需要在kubernetes目录下):

make all WHAT=cmd/kube-scheduler GOFLAGS=-v

使用make all可以编译所有的二进制程序,使用WHAT可以选择单独编译某个程序,GOFLAGS用于给go编译器传递参数,-v表示在编译时显示正在编译的文件

在这里插入图片描述

编译成功后的二进制程序在_output/bin/文件夹下:

在这里插入图片描述
 

4.编译为镜像

使用下面的命令可以将程序编译为镜像:

注意:编译为docker镜像时依赖其它的镜像,比如kube-cross镜像,这些镜像需要科学上网才能下载,而且镜像很大,kube-cross有六点几个G

在这里插入图片描述

make quick-release-images 

使用该命令只会编译linux/amd64平台下的docker镜像,而且无法指定单独编译某个组件

编译完成后的镜像在_output/release-images/amd64目录下,为tar包

在这里插入图片描述

将tar包导入docker镜像:


                
### Kubernetes Scheduler Framework 使用指南 Kubernetes Scheduler Framework 是一种用于增强 Kubernetes 默认调度器的功能模块化框架。通过该框架,用户能够自定义调度逻辑并将其集成到默认调度器中[^1]。 #### 1. 调度框架的工作原理 调度框架允许开发者在调度的不同阶段插入自定义插件。这些阶段包括 `Filter`(过滤)、`PreScore`(预评分)、`Score`(打分)、`Reserve`(预留)以及 `Bind`(绑定)。每个阶段都可以由一个或多个插件来处理特定的任务[^4]。 #### 2. 开发调度插件的关键步骤 为了开发一个新的调度插件,通常需要完成以下几个方面: - **注册插件** 插件需要被注册到调度框架中以便于调度器识别和加载。这可以通过实现 `NewPlugin` 函数并将其实现返回给调度框架完成[^5]。 - **配置插件** 插件的行为可能依赖某些外部参数或者配置项。因此,在初始化过程中,应提供相应的配置支持。例如,使用 `config.PluginConfig` 来传递必要的选项。 - **实现接口方法** 不同类型的插件需实现对应的接口函数。比如,`Filter` 类型的插件要实现 `Filter` 方法;而 `Score` 类型则需要实现 `Score` 和 `NormalizeScore` 方法[^4]。 #### 3. 替换 kube-scheduler 镜像 如果希望部署带有定制化插件的新版调度器,则需要替换官方提供的 kube-scheduler 容器镜像,并指定新的配置文件路径。具体操作如下所示[^2]: ```yaml apiVersion: kubescheduler.config.k8s.io/v1beta1 kind: KubeSchedulerConfiguration profiles: - schedulerName: default-scheduler pluginConfig: - name: MyCustomPlugin args: myKey: "myValue" ``` 随后启动命令行时加入参数 `--config=/path/to/config.yaml` 即可生效[^2]。 #### 4. 性能优化建议 当涉及大规模集群场景下频繁触发复杂业务逻辑时,可能会面临性能瓶颈问题。此时可以从减少不必要的计算开销入手调整算法效率,同时也可以考虑引入缓存机制降低重复查询数据库带来的延迟影响[^3]。 --- ### 示例代码:简单 Filter Plugin 实现 下面展示了一个基础版本 filter 插件样例供参考学习如何判断 pod 是否满足条件运行在一个 node 上面: ```go package main import ( "fmt" schedulingv1 "k8s.io/api/core/v1" framework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1" ) type ExampleFilter struct{} func (e *ExampleFilter) Name() string { return "example-filter" } // Filter checks whether the given pod can be scheduled onto the specified node. func (e *ExampleFilter) Filter(ctx context.Context, state *framework.CycleState, pod *schedulingv1.Pod, nodeInfo *framework.NodeInfo) (*framework.Status, error) { if !nodeInfo.FitsPod(pod) { // FitsPod is a helper function that determines if the pod fits on this node based on resource availability and other constraints. return framework.NewStatus(framework.UnschedulableAndUnresolvable), nil } return framework.NewStatus(framework.Success), nil } func NewExampleFilter() (framework.FilterPlugin, error) { return &ExampleFilter{}, nil } ``` ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值