kube-scheduler调度策略之优选算法(四)

2024-09-02 07:04

本文主要是介绍kube-scheduler调度策略之优选算法(四),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、概述

摘要: 本文我们继续从源码层面分析kube-scheduler调度策略中的优选调度算法,分析优选算法如何对Node节点进行打分的。

二、正文

说明:基于 kubernetes v1.12.0 源码分析

上文我们说的(g *genericScheduler) Schedule()函数调用了PrioritizeNodes()执行优选策略(打分),接下来我们就具体展开分析。

2.1 PrioritizeNodes对节点打分


// PrioritizeNodes prioritizes the nodes by running the individual priority functions in parallel.
// Each priority function is expected to set a score of 0-10
// 0 is the lowest priority score (least preferred node) and 10 is the highest
// The node scores returned by the priority function are multiplied by the weights to get weighted scores
// All scores are finally combined (added) to get the total weighted scores of all nodes
func PrioritizeNodes(pod *v1.Pod,nodeNameToInfo map[string]*schedulercache.NodeInfo,meta interface{},priorityConfigs []algorithm.PriorityConfig,nodes []*v1.Node,extenders []algorithm.SchedulerExtender,
) (schedulerapi.HostPriorityList, error) {// If no priority configs are provided, then the EqualPriority function is applied// This is required to generate the priority list in the required format// 如果没有配置优选调度算法,则使用 EqualPriorityMap 函数对每个节点打分,这样每个节点的分数都一样,都是1分。if len(priorityConfigs) == 0 && len(extenders) == 0 {result := make(schedulerapi.HostPriorityList, 0, len(nodes))for i := range nodes {hostPriority, err := EqualPriorityMap(pod, meta, nodeNameToInfo[nodes[i].Name])if err != nil {return nil, err}result = append(result, hostPriority)}return result, nil}var (mu   = sync.Mutex{}wg   = sync.WaitGroup{}errs []error)appendError := func(err error) {mu.Lock()defer mu.Unlock()errs = append(errs, err)}// 定义results列表,记录每个节点用优选算法打分后的结果results := make([]schedulerapi.HostPriorityList, len(priorityConfigs), len(priorityConfigs))// 遍历出所有预选调度算法for i, priorityConfig := range priorityConfigs {if priorityConfig.Function != nil {// DEPRECATEDwg.Add(1)go func(index int, config algorithm.PriorityConfig) {defer wg.Done()var err error// 使用具体的某个调度算法中的 PriorityFunction,为节点打分。打分的结果放到results列表中results[index], err = config.Function(pod, nodeNameToInfo, nodes)if err != nil {appendError(err)}}(i, priorityConfig)} else {results[i] = make(schedulerapi.HostPriorityList, len(nodes))}}processNode := func(index int) {nodeInfo := nodeNameToInfo[nodes[index].Name]var err errorfor i := range priorityConfigs {if priorityConfigs[i].Function != nil {continue}// 使用具体的某个调度算法中的 PriorityMapFunction,为节点打分。打分的结果放到results列表中results[i][index], err = priorityConfigs[i].Map(pod, meta, nodeInfo)if err != nil {appendError(err)results[i][index].Host = nodes[index].Name}}}workqueue.Parallelize(16, len(nodes), processNode)for i, priorityConfig := range priorityConfigs {if priorityConfig.Reduce == nil {continue}wg.Add(1)go func(index int, config algorithm.PriorityConfig) {defer wg.Done()// 使用具体的某个调度算法中的 PriorityReduceFunction,为节点打分。打分的结果放到results列表中if err := config.Reduce(pod, meta, nodeNameToInfo, results[index]); err != nil {appendError(err)}if glog.V(10) {for _, hostPriority := range results[index] {glog.Infof("%v -> %v: %v, Score: (%d)", pod.Name, hostPriority.Host, config.Name, hostPriority.Score)}}}(i, priorityConfig)}// Wait for all computations to be finished.wg.Wait()if len(errs) != 0 {return schedulerapi.HostPriorityList{}, errors.NewAggregate(errs)}// Summarize all scores.result := make(schedulerapi.HostPriorityList, 0, len(nodes))for i := range nodes {result = append(result, schedulerapi.HostPriority{Host: nodes[i].Name, Score: 0})for j := range priorityConfigs {// 对分数进行加权后累加result[i].Score += results[j][i].Score * priorityConfigs[j].Weight}}// 如果使用了 SchedulerExtender ,使用扩展的打分策略继续计算。一般不需要考虑,除非用户自定逻辑来实现更复杂的逻辑if len(extenders) != 0 && nodes != nil {combinedScores := make(map[string]int, len(nodeNameToInfo))for _, extender := range extenders {if !extender.IsInterested(pod) {continue}wg.Add(1)go func(ext algorithm.SchedulerExtender) {defer wg.Done()prioritizedList, weight, err := ext.Prioritize(pod, nodes)if err != nil {// Prioritization errors from extender can be ignored, let k8s/other extenders determine the prioritiesreturn}mu.Lock()for i := range *prioritizedList {host, score := (*prioritizedList)[i].Host, (*prioritizedList)[i].ScorecombinedScores[host] += score * weight}mu.Unlock()}(extender)}// wait for all go routines to finishwg.Wait()for i := range result {result[i].Score += combinedScores[result[i].Host]}}if glog.V(10) {for i := range result {glog.V(10).Infof("Host %s => Score %d", result[i].Host, result[i].Score)}}return result, nil
}
  • 依次遍历PriorityConfig中注册的优选算法对节点进行打分
  • 再对各个优选算法的打分结果,进行加权后累加得到最终的分数
  • 对某个host的打分的计算公式总结:host1最终得分= 优选算法1 * weight1 + 优选算法2 * weight2 + 优选算法3 * weight3 + …

优选算法进行打分的过程示意图

在这里插入图片描述

2.2 优选算法有哪些

接下来我们看下默认的调度器加载的优选调度算法有哪些

源码位置k8s.io/kubernetes/pkg/scheduler/algorithmprovider/defaults/defaults.go`

经整理统计优选算法包括如下这些。可以看到除了算法"NodePreferAvoidPodsPriority"之外,其他优选算法的weight都是1.


factory.RegisterPriorityFunction2("EqualPriority", core.EqualPriorityMap, nil, 1)
factory.RegisterPriorityFunction2("MostRequestedPriority", priorities.MostRequestedPriorityMap, nil, 1)
factory.RegisterPriorityFunction2("RequestedToCapacityRatioPriority",priorities.RequestedToCapacityRatioResourceAllocationPriorityDefault().PriorityMap,nil,1)factory.RegisterPriorityConfigFactory("ServiceSpreadingPriority",factory.PriorityConfigFactory{MapReduceFunction: func(args factory.PluginFactoryArgs) (algorithm.PriorityMapFunction, algorithm.PriorityReduceFunction) {return priorities.NewSelectorSpreadPriority(args.ServiceLister, algorithm.EmptyControllerLister{}, algorithm.EmptyReplicaSetLister{}, algorithm.EmptyStatefulSetLister{})},Weight: 1,},)
factory.RegisterPriorityFunction2("ResourceLimitsPriority", priorities.ResourceLimitsPriorityMap, nil, 1)
factory.RegisterPriorityConfigFactory("SelectorSpreadPriority",factory.PriorityConfigFactory{MapReduceFunction: func(args factory.PluginFactoryArgs) (algorithm.PriorityMapFunction, algorithm.PriorityReduceFunction) {return priorities.NewSelectorSpreadPriority(args.ServiceLister, args.ControllerLister, args.ReplicaSetLister, args.StatefulSetLister)},Weight: 1,},),factory.RegisterPriorityConfigFactory("InterPodAffinityPriority",factory.PriorityConfigFactory{Function: func(args factory.PluginFactoryArgs) algorithm.PriorityFunction {return priorities.NewInterPodAffinityPriority(args.NodeInfo, args.NodeLister, args.PodLister, args.HardPodAffinitySymmetricWeight)},Weight: 1,},),factory.RegisterPriorityFunction2("LeastRequestedPriority", priorities.LeastRequestedPriorityMap, nil, 1),factory.RegisterPriorityFunction2("BalancedResourceAllocation", priorities.BalancedResourceAllocationMap, nil, 1),factory.RegisterPriorityFunction2("NodePreferAvoidPodsPriority", priorities.CalculateNodePreferAvoidPodsPriorityMap, nil, 10000),factory.RegisterPriorityFunction2("NodeAffinityPriority", priorities.CalculateNodeAffinityPriorityMap, priorities.CalculateNodeAffinityPriorityReduce, 1),factory.RegisterPriorityFunction2("TaintTolerationPriority", priorities.ComputeTaintTolerationPriorityMap, priorities.ComputeTaintTolerationPriorityReduce, 1),factory.RegisterPriorityFunction2("ImageLocalityPriority", priorities.ImageLocalityPriorityMap, nil, 1),)

2.3 预选算法的控制

有时候我们想对集群的默认调度策略进行干预和控制,比如这个常见需求:集群中分配pod时,我们希望尽快能的平衡Pod到不同的node节点,因为我们的cpu通常超分,"分散布局"Pod,有利于宿主的CPU充分利用

我们有2中方法控制干预kubernetes的默认调度策略。

  • 通过--policy-config-file 配置文件的方式调整调度算法(包括预选与优选算法)
  • 通过--policy-configmap 也就是k8s中的configmap方式,调整调度算法。

下面通过指定配置文件的方式来设置修改某个打分接口的比重。

  1. 先创建 kube-scheduler.yaml 文件

    在这里插入图片描述

  2. 在Kube-scheduler进程的启动命令中中添加 - --policy-config-file=/etc/kubernetes/policy.cfg指定配置文件。

  3. 重启Kube-scheduler进程
    在这里插入图片描述

如果想了解更多,请查看文档Controlling pod placement onto nodes

三、总结

本文分析了优选算法的执行过程并通过阅读源码总结出了打分(预选策略)的计算公式。之后我们整理了默认的调度器中的优选算法有哪些,对应的weight值是多少。最后我们讲述了如何通过修改调度配置策略文件,来控制和干预kubernetes的调度过程。

四、参考文献

  • Controlling pod placement onto nodes

  • kubernetes_scheduler_code

这篇关于kube-scheduler调度策略之优选算法(四)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1129326

相关文章

Redis过期删除机制与内存淘汰策略的解析指南

《Redis过期删除机制与内存淘汰策略的解析指南》在使用Redis构建缓存系统时,很多开发者只设置了EXPIRE但却忽略了背后Redis的过期删除机制与内存淘汰策略,下面小编就来和大家详细介绍一下... 目录1、简述2、Redis http://www.chinasem.cn的过期删除策略(Key Expir

利用Python实现时间序列动量策略

《利用Python实现时间序列动量策略》时间序列动量策略作为量化交易领域中最为持久且被深入研究的策略类型之一,其核心理念相对简明:对于显示上升趋势的资产建立多头头寸,对于呈现下降趋势的资产建立空头头寸... 目录引言传统策略面临的风险管理挑战波动率调整机制:实现风险标准化策略实施的技术细节波动率调整的战略价

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

Springboot实现推荐系统的协同过滤算法

《Springboot实现推荐系统的协同过滤算法》协同过滤算法是一种在推荐系统中广泛使用的算法,用于预测用户对物品(如商品、电影、音乐等)的偏好,从而实现个性化推荐,下面给大家介绍Springboot... 目录前言基本原理 算法分类 计算方法应用场景 代码实现 前言协同过滤算法(Collaborativ

Redis中6种缓存更新策略详解

《Redis中6种缓存更新策略详解》Redis作为一款高性能的内存数据库,已经成为缓存层的首选解决方案,然而,使用缓存时最大的挑战在于保证缓存数据与底层数据源的一致性,本文将介绍Redis中6种缓存更... 目录引言策略一:Cache-Aside(旁路缓存)策略工作原理代码示例优缺点分析适用场景策略二:Re

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾

redis过期key的删除策略介绍

《redis过期key的删除策略介绍》:本文主要介绍redis过期key的删除策略,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录第一种策略:被动删除第二种策略:定期删除第三种策略:强制删除关于big key的清理UNLINK命令FLUSHALL/FLUSHDB命

Linux之计划任务和调度命令at/cron详解

《Linux之计划任务和调度命令at/cron详解》:本文主要介绍Linux之计划任务和调度命令at/cron的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux计划任务和调度命令at/cron一、计划任务二、命令{at}介绍三、命令语法及功能 :at

SpringRetry重试机制之@Retryable注解与重试策略详解

《SpringRetry重试机制之@Retryable注解与重试策略详解》本文将详细介绍SpringRetry的重试机制,特别是@Retryable注解的使用及各种重试策略的配置,帮助开发者构建更加健... 目录引言一、SpringRetry基础知识二、启用SpringRetry三、@Retryable注解

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各