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

news2025/1/6 20:06:06

因为研究的需要,需要对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镜像:

docker load < kube-scheduler.tar

在这里插入图片描述
 

5.将生成的调度器镜像部署到集群

5.1 生成scheduler配置文件

        我们对调度器的源码进行了扩展,实现了里面规定的插件,并且注册了插件。
        调度器会生成一个默认的调度方案,名称为default-scheduler,这个调度方案中包含了一系列的原生插件,
        通过下面的配置文件我们可以对各个扩展点进行启用或禁用,profiles是一个切片,一个profile就是一个调度器,可以通过profiles来指定多个包含不同扩展点的调度器。

apiVersion: kubescheduler.config.k8s.io/v1beta3
kind: KubeSchedulerConfiguration
leaderElection:
  leaderElect: true
profiles:
- schedulerName: my-scheduler
  plugins:
    score: 
      enabled: 
      - name: MyScorePlugin
      disabled: 
      - name: "*"

这个配置文件对应的go结构体在kubernetes/pkg/scheduler/apis/config/types.go中
在这里插入图片描述
注意:默认情况下,调度器会生成一个default-scheduler的profile,如果使用我们自己编写的config文件,如果没有配置default-scheduler,默认的好像是不会生成的。但是看别人的博客中说是会自己生成的,但是我的就没有生成,在没有指定调度器的时候,提交的pod不会被调度。

 

5.2 使配置生效

5.1节中生成的配置需要在scheduler启动的时候使用--config参数来指定,因此需要重启scheduler。

注意:kubeadm搭建的集群中,kubernetes中的组件(除了kubelet)是以静态Pod的方式运行的。
注意:不能通过kubectl edit kube-scheduler-master的方式来修改,因为scheduler是静态pod,无法通过ApiServer来进行管理

5.2.1 静态Pod的概念

静态Pod是由kubelet进行管理并且仅存于特点Node上的Pod,因此它们不能通过ApiServer进行管理。

静态Pod的配置文件可以从kubelet的配置文件中获取:

在这里插入图片描述

kubelet的配置文件为/var/lib/kubelet/config.yaml,查看配置文件:

在这里插入图片描述

可以获取到静态Pod所在的配置文件路径为/etc/kubernetes/manifests
在这里插入图片描述
在/etc/kubernetes/manifests有一些Pod资源的yaml文件,kubelet会负责启动该目录下的所有pod,当我们对这些配置文件进行了修改后,kubelet会重新启动修改的pod。
 

5.2.2 配置scheduler扩展

要重启scheduler,并且指定配置文件,我们需要修改/etc/kubernetes/manifests目录下的kube-scheduler.yaml文件,我们只需要修改kube-scheduler.yaml,kubelet就会根据这个文件重启scheduler,

注意:经过测试,如果镜像没有修改,scheduler应该是不会重启的
我们需要将调度器的配置文件挂载到Pod中,并且指定Pod启动的命令行参数,同时指定我们构建的镜像的名称

修改kube-scheduler.yaml文件,需要修改的地方有四个,分别是:scheduler启动参数镜像名volumesvolumeMounts
1添加--config参数指定配置文件 2.修改镜像:
在这里插入图片描述
3 挂载配置文件到/etc/kubernetes/目录下:
在这里插入图片描述

之后kubelet会重启scheduler,如果没有可以尝试重启主机

6 测试

部署了修改的调度器后,就需要对我们的调度器进行一个测试,可以在集群中部署Pod来测试调度情况。
在部署Pod的时候,需要指定调度器的名称,比如我们在配置文件中的profiles下配置了一个名称为my-scheduler的调度器,因此在创建pod类的资源时要指定调度器名称:

apiVersion: v1
kind: Pod
metadata: 
  name: nginx-pod
spec:
  schedulerName: my-scheduler
  containers:
  - image: nginx:1.17.1
    imagePullPolicy: IfNotPresent
    name: pod
    ports:
    - name: nginx-port
      containerPort: 80
      protocol: TCP

 

踩坑记录:

1、源码无法编译

在windows上克隆了源码,对scheduler进行了扩展,然后将代码上传到了Linux上进行编译,出现下面的错误:

在这里插入图片描述

后来才发现,kubernetes根目录下的Makefile是一个链接文件,链接到buidl/root/Makefile,但是克隆到windows上之后,这个链接就没有了,上传到Linux后,没有这个链接因此无法编译

windows上克隆后上传到linux的文件:缺少链接

在这里插入图片描述
在linux上直接克隆的源码:
在这里插入图片描述
 

2、k8s组件编译为镜像

要将k8s中的组件编译为镜像,需要依赖其它的镜像,比如:kube-cross、go-runner等,

这些镜像需要去外网下载,而且镜像文件很大,导致频繁失败。

在这里插入图片描述

  • 解决方案1:科学上网
  • 解决方案2:如果没有科学上网,可以租赁阿里云国外服务器(按量使用),使用docker拉下来,再下载到本地。但是镜像很大,下载速度很慢
  • 解决方案3:租赁阿里云国外服务器,直接在服务器上编译,编译完成后再下载到本地,但是如果代码出了问题,修改后就需要重新编译,很麻烦

 

3、使用kubeadm搭建集群时节点没有就绪

安装完集群并且安装了网络插件后,依然显示所有节点NotReady:

在这里插入图片描述

查看日志:

发现日志出现 failed to find plugin “flannel” in path [/opt/cni/bin]

[root@node2 ~]# journalctl -f -u kubelet
-- Logs begin at 四 2023-04-06 15:59:04 CST. --
4月 06 16:25:31 node2 kubelet[2046]: I0406 16:25:31.045873    2046 cni.go:240] "Unable to update cni config" err="no valid networks found in /etc/cni/net.d"
4月 06 16:25:34 node2 kubelet[2046]: E0406 16:25:34.788414    2046 kubelet.go:2347] "Container runtime network not ready" networkReady="NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized"
4月 06 16:25:36 node2 kubelet[2046]: I0406 16:25:36.049721    2046 cni.go:205] "Error validating CNI config list" configList="{\n  \"name\": \"cbr0\",\n  \"cniVersion\": \"0.3.1\",\n  \"plugins\": [\n    {\n      \"type\": \"flannel\",\n      \"delegate\": {\n        \"hairpinMode\": true,\n        \"isDefaultGateway\": true\n      }\n    },\n    {\n      \"type\": \"portmap\",\n      \"capabilities\": {\n        \"portMappings\": true\n      }\n    }\n  ]\n}\n" err="[failed to find plugin \"flannel\" in path [/opt/cni/bin]]"
4月 06 16:25:36 node2 kubelet[2046]: I0406 16:25:36.049741    2046 cni.go:240] "Unable to update cni config" err="no valid networks found in /etc/cni/net.d"
4月 06 16:25:39 node2 kubelet[2046]: E0406 16:25:39.804414    2046 kubelet.go:2347] "Container runtime network not ready" networkReady="NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized"
4月 06 16:25:41 node2 kubelet[2046]: I0406 16:25:41.053032    2046 cni.go:205] "Error validating CNI config list" configList="{\n  \"name\": \"cbr0\",\n  \"cniVersion\": \"0.3.1\",\n  \"plugins\": [\n    {\n      \"type\": \"flannel\",\n      \"delegate\": {\n        \"hairpinMode\": true,\n        \"isDefaultGateway\": true\n      }\n    },\n    {\n      \"type\": \"portmap\",\n      \"capabilities\": {\n        \"portMappings\": true\n      }\n    }\n  ]\n}\n" err="[failed to find plugin \"flannel\" in path [/opt/cni/bin]]"

查看/opt/cni/bin 缺少 flannel

解决方案:

下载CNI插件:https://github.com/containernetworking/plugins/releases/tag/v0.8.6

解压后放入/opt/cni/bin/目录下:

tar zxvf cni-plugins-linux-amd64-v0.8.6.tgz
cp flannel /opt/cni/bin/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/421659.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据之Spark部署模式

文章目录前言一、Spark的部署模式&#xff08;一&#xff09;Client模式1. Standalone集群下的Client模式2. Spark On Yarn集群下的Client模式&#xff08;二&#xff09;Cluster模式1. Standalone集群下的Cluster模式2. Spark On Yarn集群下的Cluster模式总结前言 #博学谷IT学…

c++头文件、namespace 的理解、#include、 编译模式

namespace C 命名空间 | 菜鸟教程 C命名空间&#xff08;名字空间&#xff09;详解 作用&#xff1a;多写在头文件中&#xff0c;用于多个头文件的变量函数出现重命名。 namespace中可以定义变量&#xff0c;函数&#xff0c;类等等&#xff0c;也可以写声明&#xff0c;来…

牛客网 HJ28 素数伴侣【二分图匹配,匈牙利算法】困难

描述 若两个正整数的和为素数&#xff0c;则这两个正整数称之为“素数伴侣”&#xff0c;如2和5、6和13&#xff0c;它们能应用于通信加密。现在密码学会请你设计一个程序&#xff0c;从已有的 N &#xff08; N 为偶数&#xff09;个正整数中挑选出若干对组成“素数伴侣”&am…

一种用于水位量测的浮子水位计

简介 浮子式水位传感器&#xff08;带水位显示&#xff09;是集机、电技术于一体的数字化传感器。通过输出轴的角度位移量转换成相应的数字量&#xff0c;可以高精度测量被测液位高度&#xff0c;能确认准确位置。具有断电记忆功能。 其工作原理就是&#xff1a;水位传感器测轮…

二叉搜索树(BSTree)

目录 一、二叉搜索树 二、二叉搜索树的接口及实现 1、二叉搜索树的查找 2、二叉搜索树的插入 3、二叉搜索树的删除 三、二叉搜索树的递归版本 本期博客主要分享二叉搜索树的底层实现。(主要是笔记&#xff0c;供自己复习使用&#x1f602;) 一、二叉搜索树 二叉搜索树(B…

Github创建组织(organization)

目录 前言 Github上创建组织的详细步骤 前言 创建 Github 组织&#xff08;Organization&#xff09;可以让你和你的团队共享代码&#xff0c;更好地管理和协作开发项目。Github 组织&#xff08;Organization&#xff09;是一个非常有用的工具&#xff0c;可以让开发者协同…

stm32cubemx IAP升级(一)

stm32cubemx IAP升级- Bootloader的制作 板卡&#xff1a;Nucleo-L412 平台&#xff1a;macbook pro 工具&#xff1a;vscode stm32cubemx stm32cubeProgramer cmake toolchain 分区 L412 自带128K的flash&#xff0c;所以我们可以这样分区&#xff0c; printf(“| flash pr…

crypto-js AES-CTR 实现密文前缀式局部解密细节 踩坑点

项目有需求&#xff0c;长明文经过AES-CTR模式加密后&#xff0c;在解密的时候&#xff0c;密文不能直接得到&#xff0c;每次通过某些方法尝试后&#xff0c;只能得到一块密文&#xff08;按顺序&#xff09;&#xff0c;所以只能一块一块的拼接解密。在使用crypto-js这个库的…

WooCommerce可扩展性:如何扩大您的WooCommerce商店

有了合适的人和技术&#xff0c;WooCommerce可扩展性绝对是很大的&#xff01; 事实上&#xff0c;使用WooCommerce作为您的电子商务平台&#xff0c;您的在线商店的规模可以与您的目标和愿望一样大&#xff01; 根据自定义模板开发高性能品牌电子商务网站 全球超500万个电商…

高效办公——Excel表格-02篇(if函数常见用法 + 条件格式的使用)

高效办公——Excel表格-02篇&#xff08;if函数常见用法 条件格式的使用&#xff09;1. if单条件简单用法1.1 简单需求1.2 实现方法2. if多条件使用(if-else的情况)3. if多条件使用(if(A && B)的情况)3.1 简单需求3.2 实现需求4. if多条件使用(if(A || B)的情况)5. 条…

亚马逊云科技“三步走”,实现区块链应用的快速开发

作为数字技术的代表之一&#xff0c;区块链技术正在被越来越多的企业所重视&#xff0c;并被引入到各行业的数字化转型中。根据中国通信院数据显示&#xff0c;目前中国区块链应用场景主要以金融和互联网为主&#xff0c;但应用范围呈现不断拓展的态势&#xff0c;政务数据共享…

day10_oop

今日内容 零、 复习昨日 一、面向对象的概念 二、面向对象编程 三、内存图 零、 复习昨日 晨考复习… 一、作业 package com.qf.homework;import java.util.Arrays;/*** --- 天道酬勤 ---** author QiuShiju* desc* ----------------* 引用数据类型的默认初始值null*/ public …

Nginx 正向代理、方向代理、端口转发

正向代理就是客户端代理&#xff0c;代理客户端&#xff0c;服务端不知道实际发起请求的客户端 正向代理中&#xff0c;proxy和client一般同一个lan或者网络可达&#xff0c;server与client一般不可达&#xff08;缓存场景除外&#xff09; 正向代理类似一个跳板机&#xff0c…

下一个“AI王炸”,别只盯着OpenAI,DeepMind也在憋大招

过去几个月&#xff0c;OpenAI风头无两&#xff0c;各大科技公司争先恐后地跟进大语言模型&#xff08;LLM&#xff09;这一技术路线。 对比之下&#xff0c;OpenAI的老对手DeepMind&#xff0c;显得有些低调和沉默。微软靠OpenAI打了一场胜仗&#xff0c;而谷歌推出的Bard翻了…

【c++初阶】命名空间的定义

命名空间的定义一.缺陷二.namespace和::三.访问namespace四.一些注意1.工程里标准库的展开2.命名域的小技巧一.缺陷 在c语言中&#xff0c;如果我们同时定义一个全局变量和一个局部变量并且使用同一个名称的话&#xff0c;是可以编过的&#xff08;因为全局和局部是属于两个不同…

云原生_kubernetes(k8s)_pod介绍以及配置信息说明

目录 一、Pod介绍 1、Pod结构 2、Pod定义 二、Pod配置 1、基本配置 2、镜像拉取 3、启动命令 4、环境变量 5、端口设置 6、资源配额 一、Pod介绍 1、Pod结构 每个Pod中都可以包含一个或者多个容器&#xff0c;这些容器可以分为两类&#xff1a; 用户程序所在的容器&…

网络编程(第二章: TCPUDP基础模型)

TCP/UDP&#xff08;服务器、客户端源码&#xff09; [(12条消息) 网络编程(4.7作业)(TCP/UDP源代码)_m0_37565374的博客-CSDN博客]: 一. 套接字 socket 1.概念 最早的socket和消息队列、共享内存&#xff0c;管道一致只能实现一台主机中的多个进程间通信。后期加入了TCP/I…

云日记个人中心项目思路

验证昵称的唯一性 前台&#xff1a; 昵称文本框的失焦事件 blur 1. 获取昵称文本框的值 2. 判断值是否为空 如果为空&#xff0c;提示用户&#xff0c;禁用按钮&#xff0c;并return 3. 判断昵称是否做了修改…

一文详解:linux部署jenkins,一键构建并部署springboot至第三方服务器

目录 1、下载jenkins 2、 启动jenkins 3、访问jenkins 4、在当前Linux上安装maven 4.1、更新wget命令&#xff0c;支持https请求 4.2、下载maven 4.3、解压安装maven 4.4、配置maven环境变量 4.5、maven配置阿里云镜像 4.6、配置maven依赖下载的位置 5、Linux安装Gi…

Redis的使用【Redis】

一、缓存简介 缓存简介 二、缓存分类 缓存分类 三、常见缓存 常见缓存 四、Redis使用 Redis 有 5 ⼤基础数据类型&#xff1a; String——字符串类型Hash——字典类型List——列表类型Set——集合类型ZSet——有序集合类型 其中最常⽤的是字符串和字典类型。 1.字符…