news 2026/7/8 14:44:03

K8s 调度器扩展:自定义优先级与亲和性策略深度解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
K8s 调度器扩展:自定义优先级与亲和性策略深度解析

K8s 调度器扩展:自定义优先级与亲和性策略深度解析

一、默认调度器的能力天花板

K8s 默认调度器足够应付 80% 的场景。但当你的 Pod 对 GPU 型号敏感、需要跨可用区严格反亲和、或要求基于实时负载动态调度时,默认的nodeSelector+affinity组合就力不从心了。

典型痛点:集群里有 A100 和 V100 两种 GPU 节点,默认调度器只能按 label 匹配,无法感知哪个节点的 GPU 显存碎片率更低、当前温度更优。你要的是"优先 A100,但 A100 负载 > 80% 时 fallback 到 V100"——这种带有优先级的降级链

还有更棘手的:多个 Deployment 之间的跨 Pod 反亲和。默认的podAntiAffinity基于 label selector,但如果你希望"同一个拓扑域内最多 2 个同类 Pod",直接用requiredDuringScheduling会导致集群碎片化,用preferredDuringScheduling权重又不够精确。

flowchart TD A[Pod 创建事件] --> B[Scheduler 监听] B --> C{默认调度阶段} C -->|Filter| D[节点过滤] C -->|Score| E[节点打分] D --> F[Scheduler Extender] E --> F F --> G[自定义 Filter 插件] F --> H[自定义 Score 插件] G --> I{通过?} I -->|否| J[节点剔除] I -->|是| H H --> K[最终排序] K --> L[Bind Pod 到 Node]

二、Scheduler Extender 与 Scheduling Framework 的选型

两种扩展方式:

Scheduler Extender(HTTP Webhook 模式):调度器在 Filter/Score 阶段通过 HTTP 调用外部服务。优点是解耦,任意语言实现。缺点是每次调度都要额外 HTTP 调用,延迟高;Webhook 不可用时调度整体阻塞。

Scheduling Framework(插件模式):Go 语言写的编译时插件,和调度器同进程运行。延迟几乎为零,能访问调度器的内部状态。缺点是只能用 Go,且调度器升级时需要重新编译。

生产环境建议:Filter 阶段用 Framework 插件(高吞吐低延迟),Score 阶段用 Extender(业务逻辑灵活变更)。

三、自定义 Scoring 插件实现

package main import ( "context" "fmt" "math" "sync" "time" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/kubernetes/pkg/scheduler/framework" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/names" ) const PluginName = "GPUWearLevel" // GPUWearLevel 基于 GPU 利用率漂移节点打分。 // 设计决策:不使用实时指标(Prometheus 查询有延迟抖动), // 而是读取 Node 上的 annotation,由外部 DaemonSet 定期写入。 // 这样调度器内部无 IO,保持确定性。 type GPUWearLevel struct { handle framework.Handle mu sync.RWMutex } var _ framework.ScorePlugin = &GPUWearLevel{} func (p *GPUWearLevel) Name() string { return PluginName } // Score 为节点打分。 // 分数 = (1 - GPU利用率) * 100,确保低负载节点获高分。 // 没有 GPU annotation 的节点给 0 分——不参与 GPU 工作负载调度。 func (p *GPUWearLevel) Score( ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string, ) (int64, *framework.Status) { nodeInfo, err := p.handle.SnapshotSharedLister().NodeInfos().Get(nodeName) if err != nil { return 0, framework.NewStatus(framework.Error, fmt.Sprintf("node not found: %s", nodeName)) } node := nodeInfo.Node() if node == nil { return 0, framework.NewStatus(framework.Error, "node object is nil") } // 读取外部 DaemonSet 写入的 annotation gpuUtilStr, ok := node.Annotations["gpu-scheduler.example.com/utilization"] if !ok { return 0, framework.NewStatus(framework.Success, "no gpu annotation, skip") } var gpuUtil float64 if _, err := fmt.Sscanf(gpuUtilStr, "%f", &gpuUtil); err != nil { return 0, framework.NewStatus(framework.Error, fmt.Sprintf("invalid gpu annotation: %v", err)) } // 利用率越低的节点分越高,上限 100 score := int64((1.0 - gpuUtil) * 100) if score < 0 { score = 0 } return score, framework.NewStatus(framework.Success, "") } // ScoreExtensions 返回空——NormalizeScore 不做归一化,保持原始分。 func (p *GPUWearLevel) ScoreExtensions() framework.ScoreExtensions { return nil }

四、边界分析与架构权衡

自定义调度的隐性成本

  1. 调试复杂度:Pod 为什么没调度到预期节点?默认调度器有 Events。自定义插件需要自己实现诊断日志。
  2. 升级风险:K8s 版本升级时,Framework 插件的 API 可能 breaking change。需要每次升级时重新编译。
  3. annotation 滞后:Node annotation 更新有延迟(取决于 DaemonSet 的采集间隔),可能导致"过时的调度决策"。采集间隔取 5-10s,太短则 etcd 写压力大。

禁用场景

  • 集群规模 < 10 节点,自定义调度纯属过度设计
  • 对延迟要求 > 99.9% 可用性的场景,HTTP Extender 的单点风险太高
  • 业务调度逻辑频繁变更的场景(改一次插件就要重启调度器)

五、结语

自定义调度不是炫技。只有当你明确知道默认调度器哪里不够用时才动手。优先用 Scheduling Framework 做 Filter/Sort,用 Node annotation 传指标——把复杂计算放在调度器外面,保持核心链路轻量。记住一件事:调度决策越快越好,100ms 的延迟放大到千级 Pod 就是 100 秒。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/8 14:43:40

Windows系统文件capisp.dll丢失找不到问题解决

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/7/8 14:42:39

Windows系统文件CaptureService.dll丢失找不到问题解决

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/7/8 14:41:18

5分钟魔法:零基础创建专业级法线贴图的终极指南

5分钟魔法&#xff1a;零基础创建专业级法线贴图的终极指南 【免费下载链接】NormalMap-Online NormalMap Generator Online 项目地址: https://gitcode.com/gh_mirrors/no/NormalMap-Online 你是否曾经为3D模型表面缺乏真实感而苦恼&#xff1f;是否觉得专业3D软件操作…

作者头像 李华
网站建设 2026/7/8 14:38:36

Windows安卓应用安装器:跨平台应用运行新方案探索

Windows安卓应用安装器&#xff1a;跨平台应用运行新方案探索 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 你是否曾想在Windows电脑上直接运行安卓应用&#xff0c;…

作者头像 李华
网站建设 2026/7/8 14:37:42

边缘AI部署:模型量化与推理引擎选型指南

边缘AI部署&#xff1a;模型量化与推理引擎选型指南将AI模型从云端GPU迁移到边缘设备&#xff08;手机、IoT、车载芯片&#xff09;是实现低延迟、低成本、隐私保护的必经之路。然而&#xff0c;边缘设备算力受限、内存紧张、功耗敏感&#xff0c;要求模型必须大幅压缩。本文系…

作者头像 李华