kube-scheduler基于scheduler-framework拓展默认调度器

举报
可以交个朋友 发表于 2023/12/11 21:57:44 2023/12/11
【摘要】 kube-scheduler基于scheduler-framework拓展默认调度器

一、背景

    由于scheduler-extender方式性能较差且支持的扩展接口有限(Filter、Prioritize和Bind),开源K8S在1.19版本增加了调度器新特性scheduler-framework(支持PreFilter、Filter、PostFilter、PreScore、Score、Reserve、Permit、PreBind、Bind和PostBind),并且后续版本主推这种方式实现调度器的扩展。

二、framwork开发示例

     本示例sample-scheduler将指定名称的Pod调度到指定label节点上

2.1 代码结构

2.2 main.go代码示例

package main

import (
   "fmt"
   "github.com/cnych/sample-scheduler-framework/pkg/plugins"
   "k8s.io/component-base/logs"
   "k8s.io/kubernetes/cmd/kube-scheduler/app"
   "math/rand"
   "os"
   "time"
)
func main() {
   rand.Seed(time.Now().UTC().UnixNano())
   //使用k8s提供的sdk注册自定义调度插件
   command := app.NewSchedulerCommand(
      app.WithPlugin(plugins.Name, plugins.New),
   )
   logs.InitLogs()
   defer logs.FlushLogs()
   if err := command.Execute(); err != nil {
      _, _ = fmt.Fprintf(os.Stderr, "%v\n", err)
      os.Exit(1)
   }
}

2.3 plugin代码示例 

package plugins

import (
   "context"
   "fmt"
   v1 "k8s.io/api/core/v1"
   "k8s.io/apimachinery/pkg/runtime"
   "k8s.io/klog/v2"
   "k8s.io/kubernetes/pkg/scheduler/framework"
   runtime2 "k8s.io/kubernetes/pkg/scheduler/framework/runtime"
   "strings"
)
// 插件名称
const Name = "sample-plugin"

type Sample struct {
   handle framework.Handle
   args samplePluginArg
}
type samplePluginArg struct {
   NodeLabel string `json:"node_label,omitempty"`
   WorkloadName string `json:"workload_name,omitempty"`
}
func (s *Sample) Name() string {
   return Name
}

func (s *Sample) PreFilter(ctx context.Context, state  *framework.CycleState, pod *v1.Pod) *framework.Status {
   klog.V(3).Infof("prefilter pod: %v", pod.Name)
   return framework.NewStatus(framework.Success, "")
}
func (s *Sample) PreFilterExtensions() framework.PreFilterExtensions {
   return nil
}

func SplicingKeyValue(k, v string) string {
   return k + "/" + v
}
func (s *Sample) Filter(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeInfo *framework.NodeInfo) *framework.Status {
   klog.V(3).Infof("filter pod: %v, node: %v", pod.Name, nodeInfo.Node().Name)
   #将指定工作负载的pod与带有特定标签的节点进行绑定
   if strings.Contains(pod.Name, s.args.WorkloadName) {
      match := false
      for k, v := range nodeInfo.Node().Labels {
         if s.args.NodeLabel == SplicingKeyValue(k, v) {
            match = true
         }
      }
      if !match {
         return framework.NewStatus(framework.UnschedulableAndUnresolvable, "no match label")
      }
   }
   return framework.NewStatus(framework.Success, "")
}

func (s *Sample) PreBind(ctx context.Context, state  *framework.CycleState, pod *v1.Pod, nodeName string) *framework.Status {
   return framework.NewStatus(framework.Success, fmt.Sprintf("prebind get node : %+v", nodeName))
}

#用于在main函数中调用进行注册
func New(configuration runtime.Object, f framework.Handle) (framework.Plugin, error) {
   args := &samplePluginArg{}
   runtime2.DecodeInto(configuration, args)
   klog.V(3).Infof("Starting: %v plugin, args: %v", Name, args)
   return &Sample{
      handle: f,
      args: *args,
   }, nil
}

2.4 编译组件并构建镜像

GOOS=linux GOARCH=amd64 go build -o sample-scheduler-framework ./main.go 

将二进制文件上传至Node节点,并使用如下dockerfile文件制作镜像;docker build -t sample-scheduler:v1 .

FROM centos:7.6.1810

WORKDIR /

COPY sample-scheduler-framework /usr/local/bin

CMD ["sample-scheduler-framework"]

三、部署调度器

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: sample-scheduler-clusterrole
rules:
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - pods
    verbs:
      - get
      - list
      - watch
      - update
  - apiGroups:
      - ""
    resources:
      - bindings
      - pods/binding
    verbs:
      - create
  - apiGroups:
      - ""
    resources:
      - pods/status
    verbs:
      - patch
      - update
  - apiGroups:
      - ""
    resources:
      - persistentvolumeclaims
      - persistentvolumes
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "storage.k8s.io"
    resources:
      - storageclasses
      - csinodes
      - csistoragecapacities
      - csidrivers
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "coordination.k8s.io"
    resources:
      - leases
    verbs:
      - create
      - get
      - list
      - update
  - apiGroups:
      - "events.k8s.io"
    resources:
      - events
    verbs:
      - create
      - patch
      - update
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: sample-scheduler-sa
  namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: sample-scheduler-clusterrolebinding
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: sample-scheduler-clusterrole
subjects:
  - kind: ServiceAccount
    name: sample-scheduler-sa
    namespace: kube-system

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: sample-scheduler-config   #挂载到sample-scheduler容器
  namespace: kube-system
data:
  scheduler-config.yaml: |
    apiVersion: kubescheduler.config.k8s.io/v1beta1
    kind: KubeSchedulerConfiguration
    leaderElection:
      leaderElect: true
      leaseDuration: 15s
      renewDeadline: 10s
      resourceLock: leases
      resourceName: sample-scheduler
      resourceNamespace: kube-system
      retryPeriod: 2s
    profiles:
    - schedulerName: default-scheduler #如果使用其他名称,则需要在工作负载的schedulerName字段中指明该名称
      pluginConfig:
      - name: sample-plugin
        args:
          node_label: test/test         #业务相关联配置,用于指定节点标签,格式为key/value
          workload_name: nginx     #业务相关联配置,用于指定工作负载名称
      plugins:     #在已实现的阶段开启自己的插件
         filter:
           enabled:
           - name: "sample-plugin"
         preFilter:
           enabled:
           - name: "sample-plugin"
         preBind:
           enabled:
           - name: "sample-plugin"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-scheduler
  namespace: kube-system
  labels:
    component: sample-scheduler
spec:
  replicas: 1
  selector:
    matchLabels:
      component: sample-scheduler
  template:
    metadata:
      labels:
        component: sample-scheduler
    spec:
      serviceAccount: sample-scheduler-sa
      priorityClassName: system-cluster-critical
      volumes:
        - name: scheduler-config
          configMap:
            name: sample-scheduler-config
      containers:
        - name: scheduler-ctrl
          image: sample-scheduler:v1
          imagePullPolicy: IfNotPresent
          args:
            - sample-scheduler-framework
            - --config=/etc/kubernetes/scheduler-config.yaml
            - --v=3
          volumeMounts:
            - name: scheduler-config
              mountPath: /etc/kubernetes

创建nginx工作负载时只能调度至带有test=test标签的节点上,其他工作负载不受影响,调度插件工作


qrcode_for_gh_0412fa5a12f4_344 (5).jpg

订阅本文作者或关注容器魔方

获取更多云原生技术资讯

本文评论区回复“云原生”,即可添加小助手微信k8s2222

领取应季云原生资料一份

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。