Skip to content

扩展Kubernetes Scheduler By 泽东

小傅哥 edited this page May 19, 2020 · 1 revision

转载请注明出处即可。 所使用源码k8s源码为release-1.18

如果对K8s的Scheduler不是很了解,可以先看下Kubernetes Scheduler简介这篇文章

零、Scheduler扩展简介

Scheduler的扩展有两种方式,一种是修改Scheduler的源码,编写调度和绑定两个过程的插件。然后将插件注册。 k8s目录

还有一种是通过Extender来进行扩展, 可以通过http请求调用自己编写的extender项目来处理自定义调度。 image.png

第一种的话,需要修改源码,但可以修改的阶段比较灵活,而第二种方法,处理的阶段比较宽泛。 本文主要是通过第二种方式, 首先先构建k8s集群,然后构建一个用于模拟调度扩展的项目。

一、环境准备

需要准备一个多节点的k8s集群,如果手上没有现成的测试集群或者云服务。那么可以看kubernetes部署-基于vmware+centos7虚拟机3个节点这篇文章来搭建一个简单的集群。 需要注意的是,本文使用的k8s版本为1.18,之前那篇文章上为1.17.4,需要升级。

generic_scheduler.go

需要多节点的原因如上图,仅仅是一个节点的话,也就无需考虑到底放到哪里了^_^

二、构建项目

所使用的环境为 Go 1.14版本,并且配置了go mod。通过go mod来安装相关包。框架主要使用gin,toml, k8s client等。

# 配置到.bash_profile中或者.zshrc中
export GOPROXY="https://goproxy.cn"
export GO111MODULE=on

因为考虑到大部分开发都在用Java,所以在这里多啰嗦几句。 首先创建一个项目文件夹 scheduler-extender 然后进入到文件夹内部执行go mod init scheduler-extender创建go.mod 然后安装相关的包

go get github.com/BurntSushi/toml
go get github.com/gin-gonic/gin
go get k8s.io/kube-scheduler

如果安装成功的话 go.mod如下图所示,当然版本可能会有所不同 go.mod

然后简单封装下https://gitee.com/VincentWang/scheduler-extender,具体extender实现都在这个项目中

项目封装后,在看下需要如何接收与返回参数,然后在考虑如果编写相关逻辑。 extender.go 首先看下HTTPExtender的 send 方法, 发现使用的json格式,并且args参数会序列化成json后发送到自定义的extender服务中。

send方法有四处调用,分别对应着,

  • Filter: 在调度过程中,过滤掉不部署pod的node
  • Preempt: 在资源不足时候,抢占低优先级的pod资源,优先保证高优先级pod运行
  • Prioritize: node排序,在资源充足时,选择"最佳"的node
  • Bind: 绑定阶段

在看下具体调用send方法的地方,这里只看下Filter v1/types.go 其实在上面的四个扩展都有对应的传参和返回值(ExtenderArgs是filter和prioritize两个阶段在共用),在scheduler-extender项目实现时,需要分别进行处理。

我这里的nodes环境如下。

ip host node role
192.168.179.137 ceph1 master
192.168.179.138 ceph2 master
192.168.179.139 ceph3 master

然后我们来模拟实现一个调度,filter阶段过滤掉cehp3,prioritize阶段, cehp1的优先级高于ceph2, preempt, bind先不实现。实现后,理论上部署的pod会部署到ceph1中。 filter.go prioritize.go

具体实现逻辑完成后,在ceph3中进行项目部署,生产环境中可以部署到k8s中。

三、Scheduler配置

首先先关注下如何进行配置,才能让Scheduler去调用scheduler-extender。 register.go 首先不稳当的api版本才会用internal

const (
	// APIVersionInternal may be used if you are registering a type that should not
	// be considered stable or serialized - it is a convention only and has no
	// special behavior in this package.
	APIVersionInternal = "__internal"
)

然后在看下v1alpha2版本的api,发现也可以使用Extenders配置。 register.go

保存以下配置到sched.yaml中, 这个配置可以参考源码中的KubeSchedulerConfiguration struct,在官网没有搜索到具体的配置项,注意不要使用json的配置,k8s的这个api解析json有些bug。 KubeSchedulerConfiguration

apiVersion: kubescheduler.config.k8s.io/v1alpha2
kind: KubeSchedulerConfiguration
extenders:
  - urlPrefix: http://192.168.179.139/scheduler-extender
    filterVerb: filter
    prioritizeVerb: prioritize
    nodeCacheCapable: true
    enableHttps: false
    weight: 100000
leaderElection:
	leaderElect: true
clientConnection:
	kubeconfig: /etc/kubernetes/scheduler.conf

并将sched.yaml 放到/etc/kubernetesf中,然后修改/etc/kubernetes/manifests下的kube-scheduler.yaml文件

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    component: kube-scheduler
    tier: control-plane
  name: kube-scheduler
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-scheduler
    - --authentication-kubeconfig=/etc/kubernetes/scheduler.conf
    - --authorization-kubeconfig=/etc/kubernetes/scheduler.conf
    - --bind-address=127.0.0.1
    - --kubeconfig=/etc/kubernetes/scheduler.conf
    - --leader-elect=true
    - --config=/etc/kubernetes/sched.yaml
    image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.18.2
    imagePullPolicy: IfNotPresent
    livenessProbe:
      failureThreshold: 8
      httpGet:
        host: 127.0.0.1
        path: /healthz
        port: 10259
        scheme: HTTPS
      initialDelaySeconds: 15
      timeoutSeconds: 15
    name: kube-scheduler
    resources:
      requests:
        cpu: 100m
    volumeMounts:
    - mountPath: /etc/kubernetes/scheduler.conf
      name: kubeconfig
      readOnly: true
    - mountPath: /etc/kubernetes/sched.yaml
      name: schedconfig
      readOnly: true
  hostNetwork: true
  priorityClassName: system-cluster-critical
  volumes:
  - hostPath:
      path: /etc/kubernetes/scheduler.conf
      type: FileOrCreate
    name: kubeconfig
  - hostPath:
      path: /etc/kubernetes/sched.yaml
      type: FileOrCreate
    name: schedconfig
status: {}

主要增加了--config配置以及通过hostPath挂载sched.yaml 可以查看下是否存在配置错误

k logs -f kube-scheduler-ceph1 -n kube-system

log 修改过kube-scheduler.yaml后,k8s会自动重启pod,但是需要将3个节点的配置都修改下才行

四、验证自定义调度是否有效

上面小节的步骤都完成后,尝试部署一个简单的pod。 在执行指令前,一定要确保scheduler-extender程序是在运行的。 scheduler-extender

kubectl run kubia --image=luksa/kubia --port=8080

在执行后, 查看po的状态

kubectl get po

kubia

这里我们也可以看到scheduler-extender也存在对应的请求 scheduler-extender请求

最后看下是否部署到了ceph1节点

kubectl descibe po kubia

descibe po

DONE,大功告成。

📝 首页

🌏 知识星球码农会锁

实战项目:「DDD+RPC分布式抽奖系统」、专属小册、问题解答、简历指导、架构图稿、视频课程

🐲 头条

⛳ 目录

  1. 源码 - :octocat: 公众号:bugstack虫洞栈 文章所涉及到的全部开源代码
  2. Java
  3. Spring
  4. 面向对象
  5. 中间件
  6. Netty 4.x
  7. 字节码编程
  8. 💯实战项目
  9. 部署 Dev-Ops
  10. 📚PDF 下载
  11. 关于

💋 精选

🐾 友链

建立本开源项目的初衷是基于个人学习与工作中对 Java 相关技术栈的总结记录,在这里也希望能帮助一些在学习 Java 过程中遇到问题的小伙伴,如果您需要转载本仓库的一些文章到自己的博客,请按照以下格式注明出处,谢谢合作。

作者:小傅哥
链接:https://bugstack.cn
来源:bugstack虫洞栈

2021年10月24日,小傅哥 的文章全部开源到代码库 CodeGuide 中,与同好同行,一起进步,共同维护。

这里我提供 3 种方式:

  1. 提出 Issue :在 Issue 中指出你觉得需要改进/完善的地方(能够独立解决的话,可以在提出 Issue 后再提交 PR )。
  2. 处理 Issue : 帮忙处理一些待处理的 Issue
  3. 提交 PR: 对于错别字/笔误这类问题可以直接提交PR,无需提交Issue 确认。

详细参考:CodeGuide 贡献指南 - 非常感谢你的支持,这里会留下你的足迹

  • 加群交流 本群的宗旨是给大家提供一个良好的技术学习交流平台,所以杜绝一切广告!由于微信群人满 100 之后无法加入,请扫描下方二维码先添加作者 “小傅哥” 微信(fustack),备注:加群。
微信:fustack

  • 公众号(bugstack虫洞栈) - 沉淀、分享、成长,专注于原创专题案例,以最易学习编程的方式分享知识,让自己和他人都能有所收获。
公众号:bugstack虫洞栈

感谢以下人员对本仓库做出的贡献或者对小傅哥的赞赏,当然不仅仅只有这些贡献者,这里就不一一列举了。如果你希望被添加到这个名单中,并且提交过 Issue 或者 PR,请与我联系。

Clone this wiki locally