如何利用shell脚本和client-go实现自己的k8s调度器

调度器介绍

scheduler 是k8s master的一部分,作为插件存在于k8s生态体系。

自定义调度器方式

  • 添加功能重新编译
  • 实现自己的调度器(multi-scheduler)
  • scheduler调用扩展程序实现最终调度(Kubernetes scheduler extender)

添加调度功能

k8s中的调度算法介绍

预选 优选

实现自己的调度器(配置多个scheduler)

scheduler以插件形式存在,集群中可以存在多个scheduler,可以显式指定scheduler

配置pod使用自己的调度器

下面pod显式指定使用my-scheduler调度器

apiVersion: v1
kind: Pod
metadata:name: nginxlabels:app: nginx
spec:schedulerName: my-schedulercontainers:- name: nginximage: nginx:1.10

官方给出的shell版本scheduler示例

#!/bin/bash
SERVER='localhost:8001'
while true;
dofor PODNAME in $(kubectl --server $SERVER get pods -o json | jq '.items[] | select(.spec.schedulerName == "my-scheduler") | select(.spec.nodeName == null) | .metadata.name' | tr -d '"')
;doNODES=($(kubectl --server $SERVER get nodes -o json | jq '.items[].metadata.name' | tr -d '"'))NUMNODES=${#NODES[@]}CHOSEN=${NODES[$[ $RANDOM % $NUMNODES ]]}curl --header "Content-Type:application/json" --request POST --data '{"apiVersion":"v1", "kind": "Binding", "metadata": {"name": "'$PODNAME'"}, "target": {"apiVersion": "v1", "kind"
: "Node", "name": "'$CHOSEN'"}}' http://$SERVER/api/v1/namespaces/default/pods/$PODNAME/binding/echo "Assigned $PODNAME to $CHOSEN"donesleep 1
done

影响pod调度的因素

https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/

预选

过滤不符合运行条件的node

优选

对node进行打分

抢占

Kubernetes 1.8 及其以后的版本中可以指定 Pod 的优先级。优先级表明了一个 Pod 相对于其它 Pod 的重要性。
当 Pod 无法被调度时,scheduler 会尝试抢占(驱逐)低优先级的 Pod,使得这些挂起的 pod 可以被调度。
在 Kubernetes 未来的发布版本中,优先级也会影响节点上资源回收的排序。

1.9+支持pdb,优先支持PDB策略,但在无法抢占其他pod的情况下,配置pdb策略的pod依旧会被抢占

Kubernetes scheduler extender

scheduler策略配置

{"kind" : "Policy","apiVersion" : "v1","predicates" : [{"name" : "PodFitsHostPorts"},{"name" : "PodFitsResources"},{"name" : "NoDiskConflict"},{"name" : "MatchNodeSelector"},{"name" : "HostName"}],"priorities" : [{"name" : "LeastRequestedPriority", "weight" : 1},{"name" : "BalancedResourceAllocation", "weight" : 1},{"name" : "ServiceSpreadingPriority", "weight" : 1},{"name" : "EqualPriority", "weight" : 1}],"extenders" : [{"urlPrefix": "http://localhost/scheduler","apiVersion": "v1beta1","filterVerb": "predicates/always_true","bindVerb": "","prioritizeVerb": "priorities/zero_score","weight": 1,"enableHttps": false,"nodeCacheCapable": false"httpTimeout": 10000000000}],"hardPodAffinitySymmetricWeight" : 10}

包含extender的配置

// ExtenderConfig保存用于与扩展器通信的参数。如果动词是未指定/空的即认为该扩展器选择不提供该扩展。
type ExtenderConfig struct {// 访问该extender的url前缀URLPrefix string `json:"urlPrefix"`//过滤器调用的动词,如果不支持则为空。当向扩展程序发出过滤器调用时,此谓词将附加到URLPrefixFilterVerb string `json:"filterVerb,omitempty"`//prioritize调用的动词,如果不支持则为空。当向扩展程序发出优先级调用时,此谓词被附加到URLPrefix。PrioritizeVerb string `json:"prioritizeVerb,omitempty"`//优先级调用生成的节点分数的数字乘数,权重应该是一个正整数Weight int `json:"weight,omitempty"`//绑定调用的动词,如果不支持则为空。在向扩展器发出绑定调用时,此谓词会附加到URLPrefix。//如果此方法由扩展器实现,则将pod绑定动作将由扩展器返回给apiserver。只有一个扩展可以实现这个功能BindVerb string// EnableHTTPS指定是否应使用https与扩展器进行通信EnableHTTPS bool `json:"enableHttps,omitempty"`// TLSConfig指定传输层安全配置TLSConfig *restclient.TLSClientConfig `json:"tlsConfig,omitempty"`// HTTPTimeout指定对扩展器的调用的超时持续时间,过滤器超时无法调度pod。Prioritize超时被忽略//k8s或其他扩展器优先级被用来选择节点HTTPTimeout time.Duration `json:"httpTimeout,omitempty"`//NodeCacheCapable指定扩展器能够缓存节点信息//所以调度器应该只发送关于合格节点的最少信息//假定扩展器已经缓存了群集中所有节点的完整详细信息NodeCacheCapable bool `json:"nodeCacheCapable,omitempty"`// ManagedResources是由扩展器管理的扩展资源列表.// - 如果pod请求此列表中的至少一个扩展资源,则将在Filter,Prioritize和Bind(如果扩展程序是活页夹)//阶段将一个窗格发送到扩展程序。如果空或未指定,所有pod将被发送到这个扩展器。// 如果pod请求此列表中的至少一个扩展资源,则将在Filter,Prioritize和Bind(如果扩展程序是活页夹)阶段将一个pod发送到扩展程序。如果空或未指定,所有pod将被发送到这个扩展器。ManagedResources []ExtenderManagedResource `json:"managedResources,omitempty"`
}

通过k8s predicates和pod过滤的节点集传递给扩展器上的FilterVerb端点的参数。
通过k8s predicates和扩展predicates以及pod过滤的节点集传递给扩展器上的PrioritizeVerb端点的参数。

// ExtenderArgs代表被扩展器用于为pod filter/prioritize node所需要的参数
type ExtenderArgs struct {// 被调度的podPod   api.Pod      `json:"pod"`// 可被调度的候选列表Nodes api.NodeList `json:"nodes"`
}

"filter"被调用时返回节点列表(schedulerapi.ExtenderFilterResult),
"prioritize"返回节点的优先级(schedulerapi.HostPriorityList).

"filter"可以根据对应动作对节点列表进行剪裁,"prioritize"返回的分数将添加到k8s最终分数(通过其优先函数进行计算),用于最终宿主选择。

“bind”调用用于将pod绑定到节点的代理绑定到扩展器。它可以选择由扩展器实现。当它被实现时,
它是向apiserver发出绑定调用的扩展器的响应。 Pod名称,名称空间,UID和节点名称被传递给扩展器

ExtenderBindingArgs表示将pod绑定到节点的扩展器的参数

type ExtenderBindingArgs struct {// 将被绑定的podPodName string// 将被绑定的namespacePodNamespace string// poduidPodUID types.UID// 最终调度到的podNode string
}

实现

package mainimport ("bytes""encoding/json""io""k8s.io/api/core/v1"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd"schedulerapi "k8s.io/kubernetes/pkg/scheduler/api/v1""log""net/http"
)var (kubeconfig string = "xxx"
)func main() {http.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {w.Write([]byte("hellowrold"))})http.HandleFunc("/predicates/test", testPredicateHandler)http.HandleFunc("/prioritize/test", testPrioritizeHandler)http.HandleFunc("/bind/test", BindHandler)http.ListenAndServe(":8880", nil)
}func testPredicateHandler(w http.ResponseWriter, r *http.Request) {var buf bytes.Bufferbody := io.TeeReader(r.Body, &buf)log.Println(buf.String())var extenderArgs schedulerapi.ExtenderArgsvar extenderFilterResult *schedulerapi.ExtenderFilterResultif err := json.NewDecoder(body).Decode(&extenderArgs); err != nil {extenderFilterResult = &schedulerapi.ExtenderFilterResult{Nodes:       nil,FailedNodes: nil,Error:       err.Error(),}} else {extenderFilterResult = predicateFunc(extenderArgs)}if resultBody, err := json.Marshal(extenderFilterResult); err != nil {panic(err)} else {w.Header().Set("Content-Type", "application/json")w.WriteHeader(http.StatusOK)w.Write(resultBody)}}func testPrioritizeHandler(w http.ResponseWriter, r *http.Request) {var buf bytes.Bufferbody := io.TeeReader(r.Body, &buf)var extenderArgs schedulerapi.ExtenderArgsvar hostPriorityList *schedulerapi.HostPriorityListif err := json.NewDecoder(body).Decode(&extenderArgs); err != nil {panic(err)}if list, err := prioritizeFunc(extenderArgs); err != nil {panic(err)} else {hostPriorityList = list}if resultBody, err := json.Marshal(hostPriorityList); err != nil {panic(err)} else {w.Header().Set("Content-Type", "application/json")w.WriteHeader(http.StatusOK)w.Write(resultBody)}
}func predicateFunc(args schedulerapi.ExtenderArgs) *schedulerapi.ExtenderFilterResult {pod := args.PodcanSchedule := make([]v1.Node, 0, len(args.Nodes.Items))canNotSchedule := make(map[string]string)for _, node := range args.Nodes.Items {result, err := func(pod v1.Pod, node v1.Node) (bool, error) {return true, nil}(pod, node)if err != nil {canNotSchedule[node.Name] = err.Error()} else {if result {canSchedule = append(canSchedule, node)}}}result := schedulerapi.ExtenderFilterResult{Nodes: &v1.NodeList{Items: canSchedule,},FailedNodes: canNotSchedule,Error:       "",}return &result
}func prioritizeFunc(args schedulerapi.ExtenderArgs) (*schedulerapi.HostPriorityList, error) {nodes := args.Nodes.Itemsvar priorityList schedulerapi.HostPriorityListpriorityList = make([]schedulerapi.HostPriority, len(nodes))for i, node := range nodes {priorityList[i] = schedulerapi.HostPriority{Host:  node.Name,Score: 0,}}return &priorityList, nil
}func BindHandler(w http.ResponseWriter, r *http.Request) {var buf bytes.Bufferbody := io.TeeReader(r.Body, &buf)var extenderBindingArgs schedulerapi.ExtenderBindingArgsif err := json.NewDecoder(body).Decode(&extenderBindingArgs); err != nil {panic(err)}b := &v1.Binding{ObjectMeta: metav1.ObjectMeta{Namespace: extenderBindingArgs.PodNamespace, Name: extenderBindingArgs.PodName, UID: extenderBindingArgs.PodUID},Target: v1.ObjectReference{Kind: "Node",Name: extenderBindingArgs.Node,},}bind(b)}func bind(b *v1.Binding) error {config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)if err != nil {panic(err)}clientset, err := kubernetes.NewForConfig(config)if err != nil {panic(err)}return clientset.CoreV1().Pods(b.Namespace).Bind(b)
}

参考:
https://github.com/kubernetes/community/blob/master/contributors/devel/scheduler.md

https://github.com/kubernetes/community/blob/master/contributors/design-proposals/scheduling/scheduler_extender.md

https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/

https://github.com/kubernetes/kubernetes-docs-cn/blob/master/docs/concepts/overview/extending.md

欢迎加入QQ群:k8s开发与实践

任何程序错误,以及技术疑问或需要解答的,请添加

 

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

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

相关文章

Linux ubuntu安装搜狗输入法

1.下载搜狗输入法的安装包 下载地址为:http://pinyin.sogou.com/linux/,如下图,要选择与自己系统位数一致的安装包, 我的系统是 64 位,所以我下载 64 位的安装包 sogoupinyin_2.2.0.0108_amd64.deb 安装方法: 1.打开命令终端,输入: sudo apt-get install xxx.deb 路径 2.重启电…

React Native顶|底部导航使用小技巧

导航一直是App开发中比较重要的一个组件,ReactNative提供了两种导航组件供我们使用,分别是:NavigatorIOS和Navigator,但是前者只能用于iOS平台,后者在ReactNative0.44版本以后已经被移除了。 好在有人提供了更好的导航…

Linux QT5.12 一种整体界面字体设置的方法及设置PlainTextEdit组件的字体大小方法

1.在Linux QT5.12开发界面时,经常会涉及到界面字体大小的设置,默认字体一般比较小,解决方法如下: 在main函数中添加代码: // // 一种整体界面字体设置的方法: QFont font a.font(); font.setPointSize(14); a.setFont(font); // 2.在L…

Win7电脑,无法把文件保存到桌面上?

今天有用户反映重装了Win7后&#xff0c;文件无法另存到桌面上&#xff0c;解决方法如下&#xff1a;1、在任何地方打开资源管理器&#xff0c;按<Alt><F>键打开资源管理器的菜单&#xff1b;2、选择“工具”的“文件夹选项”&#xff0c;在“导航窗格”里选上“显…

ReactNative常用组件汇总

导航组件react-navigation: https://github.com/react-community/react-navigation 网络请求asios: https://github.com/mzabriskie/axios 设备信息react-native-device-info: https://github.com/rebeccahughes/react-native-device-info 缓存使用react-native-storage: https…

Yolov5训练自己的数据集之制作数据集

在VOC 2018文件夹下有五个文件夹&#xff0c;搜集好的图片放在JPEGImages文件夹下&#xff1b;标注后数据保存在Annotations文件夹下&#xff1b;labels文件夹在数据集的训练时用到&#xff1b;在ImageSets文件夹下有下面三个文件夹&#xff0c;在Main文件夹中有一个train.txt文…

ReactNative布局样式总结

flex number 用于设置或检索弹性盒模型对象的子元素如何分配空间 flexDirection enum(row, row-reverse ,column,column-reverse) flexDirection属性决定主轴的方向&#xff0c;默认是“column”&#xff1a; row&#xff1a;主轴为水平方向&#xff0c;起点在左端row-rev…

Android 线程池对象-ThreadPoolExecutor浅析

本人最近在已经在91&#xff0c;百度应用等渠道上线的个人应用——铃声酷的代码里用到了ThreadPoolExecutor这一线程池对象去处理并发&#xff0c;个人感觉相当的给力啊&#xff01;它是并发实用程序开放源码库 util.concurrent&#xff0c;它包括互斥、信号量、诸如在并发访问…

Linux kubuntu x64系统下解决QT5.12编辑菜单和工具栏不显示图标问题

Linux kubuntu x64系统下发现QT5.12在设计视图下编辑菜单和工具栏显示图标,但是编译运行后发现菜单和工具栏不显示图标,如下图: 我的解决办法是: 1.在QT项目中,菜单和工具栏图标一定要添加到项目资源文件中(在资源编辑器中Add Prefix后,再添加文件,关闭资源编辑器后自动将图标…

PyTorch系列 (二): pytorch数据读取自制数据集并

PyTorch系列 (二): pytorch数据读取 PyTorch 1: How to use data in pytorch Posted by WangW on February 1, 2019 参考&#xff1a; PyTorch documentationPyTorch 码源 本文首先介绍了有关预处理包的源码&#xff0c;接着介绍了在数据处理中的具体应用&#xff1b; 1 P…

nodejs+nginx获取真实ip

nodejs nginx获取真实ip分为两部分&#xff1a; 第一、配置nginx&#xff1b;第二、通过nodejs代码获取&#xff1b; 其他语言也是一样的&#xff0c;都是配置nginx之后&#xff0c;在http头里面获取“x-forwarded-for”. 第一、配置nginx location / {proxy_set_header Ho…

【OSChina-MoPaaS应用开发大赛】豪美创新后台业务管理系统

2019独角兽企业重金招聘Python工程师标准>>> 应用名称&#xff1a;豪美创新后台业务管理系统 应用URL地址&#xff1a;http://tyz.sturgeon.mopaas.com/admin/index.html 登录&#xff1a;admin/admin 投票地址&#xff1a;http://www.oschina.net/mopaas-app-co…

QT5更改应用程序图标

1.准备好.ico的图片放在工程目录下&#xff0c;并添加到项目的资源文件中 2.在项目配置.pro文件中添加一下内容 RC_ICONS AppIcon.icoAppIcon为你的ico图片名字 3.在可视化设计文件.ui中选择主窗口&#xff0c;将其属性中的windowIcon一项右侧下三角单击&#xff0c;从“选择…

python List中元素两两组合

python List中元素两两组合 import itertools aa [a, b, c] bb list(itertools.permutations(aa, 2)) print(bb) print("######################") cc list(itertools.combinations(aa, 2)) print(cc) 话不多说&#xff0c;运行结果解释一些 任何程序错误&…

xcode编译报错unknown error -1=ffffffffffffffff Command /bin/sh failed with exit code 1

升级完xcode9.1之后&#xff0c;编译项目出现如下错误&#xff1a; CI今日构建时报出如下错误&#xff1a; /Users/xxx/Library/Developer/Xcode/DerivedData/Snowball-ebllohyukujrncbaldsfojfjxwep/Build/Intermediates.noindex/ArchiveIntermediates/ProjectName/Installat…

android button的selector

实现按钮的selector <?xml version"1.0" encoding"utf-8"?><selector xmlns:android"http://schemas.android.com/apk/res/android"><item android:drawable"drawable/common_topbar_route_bus_pressed" android:sta…

Windows Qt5下用QAxObject快速读写Excel指南

Qt Windows 下快速读写Excel指南 很多人搜如何读写excel都会看到用QAxObject来进行操作&#xff0c;很多人试了之后都会发现一个问题&#xff0c;就是慢&#xff0c;非常缓慢&#xff01;因此很多人得出结论是QAxObject读写excel方法不可取&#xff0c;效率低。 后来我曾试过…

python opencv过滤红色

OpenCV简易视频处理框架OpenCV主要色彩空间OpenCV的位操作方法 找出视频中红色物体 import cv2 import numpy as npdef filter_out_black(src_frame):if src_frame is not None:hsv cv2.cvtColor(src_frame, cv2.COLOR_BGR2HSV)lower_red np.array([0, 0, 0])upper_red np.…

#39;boost/iterator/iterator_adaptor.hpp#39; file not found之xcode生成时报错的解决方案

xcode生成rn&#xff08;0.49.3&#xff09;项目的时候出现“boost/iterator/iterator_adaptor.hpp file not found之xcode”报错。 原因&#xff1a; /Users/xxx/.rncache 中 boost_1_63_0.tar.gz&#xff0c; double-conversion-1.1.5.tar.gz&#xff0c; folly-2016.09.26.…