深圳幻海软件技术有限公司 欢迎您!

如何自定义 Kube-Scheduler 插件

2023-02-28

  k8s的发展越来越像是一个框架,然后把各种扩展的能力留给开发者。开发者可以基于这些接口结合自己的业务场景,实现自己的场景化需求。其中kubescheduler就是充分体现了这个特质,关于kubescheduler本身的介绍参加之前的文章,今天我想介绍如何给scheduler添

 

 k8s的发展越来越像是一个框架,然后把各种扩展的能力留给开发者。开发者可以基于这些接口结合自己的业务场景,实现自己的场景化需求。其中kube scheduler 就是充分体现了这个特质,关于kube scheduler 本身的介绍参加之前的文章,今天我想介绍如何给scheduler 添加一个调度plugin。

 

我们首先通过yaml定义这个plugin

apiVersion: kubescheduler.config.k8s.io/v1beta1 
kind: KubeSchedulerConfiguration 
clientConnection: 
  kubeconfig: "/etc/kubernetes/scheduler.conf" 
profiles: 
- schedulerName: default-scheduler 
  plugins: 
    score: 
      enabled: 
      - name: HelloWorldPlugin 
      disabled: 
      - name"*" 
  pluginConfig: 
  - name: HelloWorldPlugin 
    args: 
      xxx: "xxx" 
      yyy: "123" 
      zzz: 3 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

我们定义了一个 HelloWorldPlugin 的插件,并且定义了这个插件的启动参数。然后需要修改kube scheduler启动参数通过 --config 指定上面的配置文件。

接下来我们就需要实现这个插件,scheduler是通过每个插件的打分的方式确定调度的主机。所以我们需要实现一个打分的接口

type ScorePlugin interface { 
  Plugin 
  // 打分 
  Score(ctx context.Context, state *CycleState, p *v1.Pod, nodeName string) (int64, *Status) 
   
  ScoreExtensions() ScoreExtensions 
} 
 
type ScoreExtensions interface { 
  // 打分归一化,保证每个插件的公平性 
  NormalizeScore(ctx context.Context, state *CycleState, p *v1.Pod, scores NodeScoreList) *Status 
} 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

我们根据自己的业务需求实现这个接口,譬如下面这个例子,基于主机网络带宽的调度:首先通过promethues获取主机的网络流量,打分依据网络流量大小。

func (n *HelloWorldPlugin) Score(ctx context.Context, state *framework.CycleState, p *v1.Pod, nodeName string) (int64, *framework.Status) { 
    nodeBandwidth, err := n.prometheus.GetNodeBandwidthMeasure(nodeName) 
    if err != nil { 
        return 0, framework.NewStatus(framework.Error, fmt.Sprintf("error getting node bandwidth measure: %s", err)) 
    } 
 
    klog.Infof("[NetworkTraffic] node '%s' bandwidth: %s", nodeName, nodeBandwidth.Value) 
    return int64(nodeBandwidth.Value), nil 
} 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

我们希望网络流量越大,得分越少,于是在归一化处理的时候,我们通过下面简单公式转化成最终的分数。

func (n *HelloWorldPlugin) NormalizeScore(ctx context.Context, state *framework.CycleState, pod *v1.Pod, scores framework.NodeScoreList) *framework.Status { 
    for i, node := range scores { 
        scores[i].Score = framework.MaxNodeScore - (node.Score * framework.MaxNodeScore / higherScore) 
    } 
 
    klog.Infof("[NetworkTraffic] Nodes final score: %v", scores) 
    return nil 
} 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

这样一个简单的,基于网络流量调度的插件就实现了。