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

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

搭建Kafka+zookeeper集群调度

前言 硬件环境 172.18.0.5        kafkazk1        Kafka+zookeeper                Kafka Broker集群 172.18.0.6        kafkazk2        Kafka+zookeeper                Kafka Broker集群 172.18.0.7        kafkazk3

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

dp算法练习题【8】

不同二叉搜索树 96. 不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n = 3输出:5 示例 2: 输入:n = 1输出:1 class Solution {public int numTrees(int n) {int[] dp = new int