惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Exploit Database - CXSecurity.com
F
Fortinet All Blogs
U
Unit 42
F
Full Disclosure
雷峰网
雷峰网
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
The Cloudflare Blog
Last Week in AI
Last Week in AI
罗磊的独立博客
D
DataBreaches.Net
C
Check Point Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
O
OpenAI News
C
CXSECURITY Database RSS Feed - CXSecurity.com
aimingoo的专栏
aimingoo的专栏
S
Security @ Cisco Blogs
大猫的无限游戏
大猫的无限游戏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
SegmentFault 最新的问题
NISL@THU
NISL@THU
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Hacker News
The Hacker News
Webroot Blog
Webroot Blog
Security Latest
Security Latest
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Google DeepMind News
Google DeepMind News
酷 壳 – CoolShell
酷 壳 – CoolShell
N
News | PayPal Newsroom
P
Proofpoint News Feed
B
Blog RSS Feed
MongoDB | Blog
MongoDB | Blog
C
Cybersecurity and Infrastructure Security Agency CISA
N
News and Events Feed by Topic
Google Online Security Blog
Google Online Security Blog
H
Help Net Security
Spread Privacy
Spread Privacy
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
I
Intezer
Application and Cybersecurity Blog
Application and Cybersecurity Blog
M
MIT News - Artificial intelligence
Vercel News
Vercel News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
IT之家
IT之家
MyScale Blog
MyScale Blog
腾讯CDC

博客园 - 左扬

VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— VictoriaLogs 协同:Metrics 到 Logs 的一体化监控 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 源码阅读路线图:如何高效阅读 VM 源码 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 开源生态:VM 在 CNCF 生态中的位置 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 与其他 TSDB 对比:Prometheus/InfluxDB/Thanos/VM VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 写入吞吐/查询延迟/内存占用的数学模型 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 模块依赖图——从 import 语句看组件关系 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— Goroutine 池/atomic/零拷贝/sync.Pool VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 多租户架构——accountID/projectID 与 tenant 隔离 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 版本演进:1.146.0 LTS 重大更新解析 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 整体数据流:一条监控数据的完整生命周期 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— 架构演进:从 TSDB 到 MergeSet 的设计取舍 VictoriaMetrics 1.146.0 源码专题【左扬精讲】—— Single-Node vs Cluster 模式本质区别 VictoriaMetrics 1.146.0 源码【左扬精讲】—— 开篇总览 Rust 专题【左扬精讲】—— 从语法到灵魂:Ownership、Borrowing 与多语言对比 kubernetes 源码【左扬精讲】—— kube-scheduler 启动流程源码分析 Rust 专题【左扬精讲】—— 选择控制语句、运算符与格式化输出 Rust 专题【左扬精讲】—— 所有权详解 Rust 专题【左扬精讲】—— 作用域详解 Rust 专题【左扬精讲】—— 变量、常量与标量数据类型 kubernetes 源码 / Operator 专题【左扬精讲】—— Deployment Controller 源码分析:从对象创建到滚动更新 kubernetes 源码 / Operator 专题【左扬精讲】—— Operator 开发中的 Webhook:从准入控制到生产部署 Kubernetes源码 / Operator 专题【左扬精讲】—— 实现 Application Controller:从零构建生产级控制器 Kubernetes 编程 / Operator 专题【左扬精讲】—— 定义 Application 资源 + 添加自定义新 API 完整指南 Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 八):内部架构与核心组件 Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 八): —— 从入口到调度的全链路源码剖析(k8s v1.36.1) DeepSeek-R1 多模态 R1 / VLM-GRPO【左扬精讲】—— Qwen2-VL 微调与视觉推理强化学习实战 DeepSeek-R1 工业 RAG + 微调混合系统【左扬精讲】—— R1 系列收官之作:从 Prompt → RAG → 微调 选型决策树 DeepSeek-R1 推理时扩展【左扬精讲】—— o1 / R1 慢思考机制:Self-Consistency + ToT + PRM 详解 DeepSeek-R1 端侧 LLM 工程【左扬精讲】—— llama.cpp 调参与 Apple Silicon / 国产 NPU / Android 端侧落地全攻略 DeepSeek-R1 vLLM + k8s 生产部署【左扬精讲】—— 从单卡 7B 到 100 卡 671B MoE 集群的工业化部署实战 DeepSeek-R1 评估与系统(Evaluation & Systems)【左扬精讲】—— 从 GSM8K/MMLU 到 LLM-as-Judge 的工业级评估方法论 DeepSeek-R1 模型训练与算法【左扬精讲】—— GRPO 进阶算法:DAPO / PRIME / RLVR / PRM 四大 2025 前沿改进 DeepSeek-R1 模型训练与算法【左扬精讲】—— 数据蒸馏:用 DeepSeek-R1-671B 生成 800K 高质量 CoT 样本的完整流水线 DeepSeek-R1 优化与微调实战【左扬精讲】—— 从 R1 强化学习新范式到 GRPO 微调一站式入门 Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 七):自定义插件开发实战 —— 手写一个 Score 插件并注册到集群 Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 六):Scheduler Profile 与多调度器 —— 如何配置多个 profile 实现多租户、Coordinated LeaderElection Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 五):SchedulingQueue 与 QueueingHint —— 三段队列的细节、v1.36 新引入的 QueueingHint 工作机制 Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 四):抢占(Preemption)算法剖析 —— DefaultPreemption 如何选 victim、PodDisruptionBudget 如何约束 Kubernetes 源码【左扬精讲】—— kube-scheduler(调度专题 · 二):内置插件逐个精读 — NodeResourcesFit / NodeAffinity / TaintToleration / PodTopologySpread / VolumeBinding / InterPodAffinity Kubernetes 源码 / Operator 专题【左扬精讲】——kube-scheduler(调度专题):调度器内置插件 逐个精读 k8s 源码级精讲(二十六):调度器内置插件逐个精读 Kubernetes 源码 / Operator 专题【左扬精讲】——kube-scheduler(调度专题):调度器内置插件精读 — NodeResourcesFit / NodeAffinity / TaintToleration / PodTopologySpread / VolumeBinding / InterPodAffinity Kubernetes 源码 / Operator 专题【左扬精讲】——kube-scheduler(调度专题):Scheduling Framework 扩展点逐个源码拆解 Kubernetes 源码 / Operator 专题【左扬精讲】——kube-scheduler(调度专题):初识调度模型、内部架构与事件驱动机制 Kubernetes 编程 / client-go 专题【左扬精讲】—— 四种客户端:为什么、怎么选、怎么用 Kubernetes 编程 / Operator 专题【左扬精讲】—— controller-runtime、kubebuilder、operator-sdk 三大框架深度对比 Kubernetes 编程 / Operator 专题【左扬精讲】—— 深入理解 ManagedFields 字段冲突协调机制 Kubernetes 编程 / Operator 专题【左扬精讲】—— k8s Finalizers 深度解析:对象的生命周期与删除控制 Kubernetes 编程 / Operator 专题【左扬精讲】—— OwnerReference 字段与级联删除机制 Kubernetes 编程 / Operator 专题【左扬精讲】—— 深入学习 Server-Side Apply:managedFields 替代 last-applied-configuration 的演进方向 Kubernetes 编程 / Operator 专题【左扬精讲】—— k8s Annotations 与元数据体系(Operator 专题) Kubernetes 编程 / Operator 专题【左扬精讲】—— RESTMapper:把 Group / Version / Kind / Resource 四元组翻译成 REST 路径的"查字典"大师 Kubernetes 编程 / Operator 专题【左扬精讲】—— Converter 资源版本转换器 Kubernetes 编程 / Operator 专题【左扬精讲】—— Application 业务扩展:从单 Deployment 到多 Workload 的复合 Operator 演进 Kubernetes 编程 / Operator 专题【左扬精讲】—— OwnerReference / Finalizer / 准入控制:k8s 资源生命周期的三大支柱 Kubernetes 编程 / Operator 专题【左扬精讲】—— controller-runtime 框架内幕:从 Manager 到 Reconcile 的全栈拆解 Kubernetes 编程 / Operator 专题【左扬精讲】—— 生产级 Operator 最佳实践:并发安全、资源清理与高可用设计 Kubernetes 编程 / Operator 专题【左扬精讲】—— application-operator Reconcile 循环源码精讲:从 client-go Informer 到 workqueue 的全链路解剖 Kubernetes 编程 / Operator 专题【左扬精讲】—— 从零搭建一个 application-operator 新项目:脚手架、API 设计与基于原生 DeploymentStatus/ServiceStatus 的状态建模 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:生产级 Controller 实践:并发安全、资源清理与高可用设计 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析: Controller 调试与诊断工具:从日志分析到问题定位 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:DynamicClient 操作 CRD:无需代码生成的动态操作 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:控制器与 APIServer 完整交互流程:从 Watch 到缓存同步 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:错误处理与重试机制:WorkQueue 限速器详解 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:Leader 选举机制:高可用控制器的必备技能 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:Controller 开发模式完整实战 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:SharedInformerFactory 与等待缓存同步 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:从认证配置到 Deployment 操作 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:版本对应、架构组件与组件关系 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:Informer 源码深度解析:从底层原理到实战应用 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:Reflector 源码深度解析 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:ListWatcher 源码深度解析 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:Indexer 与 ThreadSafeStore 核心原理与源码深度剖析 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:DeltaFIFO 核心原理与源码深度剖析 Kubernetes 编程 / Operator 专题【左扬精讲】—— Client-go 源代码分析:workqueue 核心原理与实战 Kubernetes 编程 / Operator 专题【左扬精讲】—— runtime.Codec 资源编解码:serializer 与 codec 差异、编解码数据结构、codec 核心调用链路 Kubernetes 编程 / Operator 专题【左扬精讲】—— Scheme 资源注册机制全解 Kubernetes 编程 / Operator 专题【左扬精讲】—— Kubernetes 自定义资源的内部版本与外部版本:从源码看版本定义机制 Kubernetes 编程 / Operator 专题【左扬精讲】—— Kubernetes 1.36.1 核心 API 数据结构全解 Kubernetes 编程 / Operator 专题【左扬精讲】—— Kubernetes 构建过程 【AIOPS】一文读懂LLM【左扬精讲】:从诞生到普及,解锁大语言模型的核心密码 【AIOPS】AI Agent 专题【左扬精讲】核心功能篇:MCP-VictoriaMetrics Hooks 源码精讲:Hooks 可观测性的无侵入式实现 【AIOPS】AI Agent 专题【左扬精讲】核心功能篇:MCP-VictoriaMetrics Golang 配置解析源码精讲 ——SRE 自定义 Agent 核心技巧 【AIOPS】AI Agent 专题【左扬精讲】核心功能篇:MCP-VictoriaMetrics Golang 并发模型解析 ——SRE 应对高并发采集的调优思路 【AIOPS】AI Agent 专题【左扬精讲】基础架构篇:MCP-VictoriaMetrics Golang 源码整体架构拆解 ——SRE 必懂的核心模块与数据流 OpenTelemetry 开发实战【左扬精讲】—— 云原生可观测体系构建与分布式追踪二次开发 Kubernetes 编程 / Operator 专题【左扬精讲】—— Operator 开发实战项目 7 —— 基于流量预测模型的智能弹性扩缩容 Operator 实战(AIOps 模型训练与智能扩容(下篇)—— 预测式弹性扩缩容 Operator 落地实现) Kubernetes 编程 / Operator 专题【左扬精讲】—— Operator 开发实战项目 7 —— 基于流量预测模型的智能弹性扩缩容 Operator 实战(AIOps 模型训练与智能扩容(上篇)—— 时序预测模型构建与离线训练) Kubernetes 编程 / Operator 专题【左扬精讲】—— Operator 开发实战项目 6 —— 基于运维专家知识库的智能故障诊断与排查 Operator 实战 Kubernetes 编程 / Operator 专题【左扬精讲】—— Operator 开发实战项目 5 —— 基于大语言模型(LLM)的实时日志流智能监测 Operator 实现 Kubernetes 编程 / Operator 专题【左扬精讲】—— Operator 开发实战项目 4 —— 基于 Operator 实现大模型私有化部署与管理 Kubernetes编程 / Operator专题【左扬精讲】—— Operator 开发实战项目 2 —— 面向零售 / 电商潮汐流量难题:多云多集群数据中心级全链路弹性伸缩 DataCenter Scaler Operator 从 0 到 1 全链路开发 Kubernetes编程 / Operator专题【左扬精讲】—— 深入理解Kubebuilder注解:为什么Operator开发离不开这些特殊注释 Kubernetes编程 / Operator专题【左扬精讲】—— Operator 开发实战项目1 —— Applicaion Operator(通用应用生命周期管理 Operator 实战) Pod 镜像拉取失败?kubectl edit pods修改镜像地址的底层原理与实操 (该方法仅为临时应急方案,并非长期解决方案) Kubernetes编程/Operator专题精讲—— 理解控制器模式 —— 控制器模式的核心原理与实现逻辑(从原理到实践) 【AIOPS】AI Agent 专题【左扬精讲】模型微调实战:一站式平台 LLaMA-Factory 【AIOPS】AI Agent 专题【左扬精讲】基于 k8s+vLLM+Ray 分布式部署全指南:架构设计、资源调度与性能优化 【AIOPS】AI Agent专题【左扬精讲】非量化版DeepSeek分布式部署全指南:精度保障、显存规划与Ollama/vLLM选型 【AIOPS】AI Agent 专题【左扬精讲】零开发框架实现 ReAct Agent(Go SRE友好)
Kubernetes 编程 / Operator 专题【左扬精讲】—— Operator 开发实战项目 3(上篇)—— 面向 AI / 算力调度场景:GPU 竞价实例资源池统一调度管理 Operator 开发
左扬 · 2026-02-17 · via 博客园 - 左扬

Tencent 什么是竞价实例(波动型):https://cloud.tencent.com/document/product/213/17816?from=console_top_search

Aliyun 什么是抢占式实例:https://help.aliyun.com/zh/ecs/user-guide/what-is-a-spot-instance?spm=5176.ecsnewbuy.customBuy_chargeTypeNewTooltip.1.3c413675JxeQbT

华为云 什么是竞价实例:https://support.huaweicloud.com/usermanual-ecs/ecs_03_0188.html#section0

AWS 什么是竞价实例:https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-spot-instances.html

       在 AI 大模型训练、分布式深度学习、科学计算等算力密集型场景下,GPU 计算资源的成本占比已成为企业 AI 基础设施建设的核心痛点 —— 传统包年包月的 GPU 实例采购模式灵活性差,无法适配 AI 任务波峰波谷的算力需求;按量计费模式虽灵活但单价高昂,长期运行会带来巨额成本支出。而云厂商推出的竞价 / 抢占式 GPU 实例,以 按量计费 1-2 折的价格 提供同等性能的算力,成为降本的核心选择,却因资源中断回收、跨云厂商规格不统一、调度管控复杂等问题,难以直接在生产级 AI 算力调度中落地。

       Kubernetes Operator 基于 CRD(自定义资源定义)实现集群能力扩展,可将多云竞价实例运维逻辑、AI 算力调度规则转化为自动化工作流,是解决上述问题的最佳技术方案。本实战项目聚焦GPU 竞价实例资源池统一调度管理 Operator的从 0 到 1 开发,正是基于这一行业痛点与技术趋势,通过 CRD 定义算力调度的核心资源模型,联动腾讯云、阿里云、华为云、AWS 等主流云厂商的竞价实例 OpenAPI,打造集动态扩缩容、成本最优调度、故障自愈、资源池化管控于一体的生产级能力,实现 AI 算力调度的成本最小化、资源利用率最大化、业务稳定性高保障。

 二、整体架构

GPU 竞价实例统一调度管理 Operator 架构分四层,各层单向依赖、职责隔离: 

架构层级 核心模块 核心职责
资源抽象层(CRD) GPUSpotPool、GPUSpotStrategy、GPUWorkloadProfile 作为整个 Operator 的核心数据模型底座,通过 k8s 自定义资源定义,统一封装 GPU 竞价实例资源池、算力调度策略、工作负载配置等核心对象,标准化定义资源规格、调度规则、成本约束等核心参数,彻底屏蔽底层云厂商的资源差异,为上层调度控制提供统一的资源抽象入口。
控制调度层(Controller) Pool Controller、Interrupt Controller、Scheduler Controller、CloudSync Controller

作为 Operator 的核心控制中枢,实现「状态感知→规则判断→动作执行」的全闭环自动化逻辑;

各控制器分责协同,分别负责资源池全生命周期管理、实例中断事件实时感知与应急处理、成本最优的算力调度决策、多云资源状态与价格数据的实时同步,是整个系统的核心调度与控制引擎。

多云适配执行层(Provider) TencentCloud、AliCloud、HuaweiCloud、AWS 作为底层云厂商的标准化适配执行层,封装各主流云厂商竞价实例的官方 OpenAPI/SDK,实现实例创建 / 销毁、状态查询、实时价格获取、中断事件监听等核心执行能力的标准化封装,彻底屏蔽不同云厂商在 API 接口、定价规则、中断机制、状态定义上的差异,为上层控制调度层提供统一的多云资源执行接口。
执行 & 观测保障层 kube-scheduler 协同、Metrics、Events、Alert

实现与 k8s 原生调度体系的深度无缝协同,同时提供全链路的可观测性与生产级故障保障能力;

通过 Metrics 采集资源运行、调度决策、成本消耗全维度数据,通过 Events 记录资源全生命周期关键事件,通过 Alert 实现实例中断风险、资源异常、调度故障的实时告警,是整个系统生产级稳定运行的核心保障底座。

2.1、四层架构职责边界详解:单向依赖、职责隔离的设计思想

本 GPU 竞价实例调度 Operator 整体采用四层分层架构,层级之间严格遵循单向依赖、职责隔离原则,上层只依赖下层接口,各层级权责清晰、互不越界。

这种设计不仅让代码解耦、易于扩展维护,也完美适配多云场景、动态调度、策略迭代等生产级诉求,下面逐层拆解职责边界、运行逻辑与设计优势。

整套架构自上而下分为

  • 资源抽象层
  • 控制调度层
  • 多云适配执行层
  • 执行 & 观测保障层

层级单向流转:资源抽象层 → 控制调度层 → 多云适配执行层 → 执行 & 观测保障层。每层只聚焦自身核心能力,不侵入其他层级逻辑。

2.2、各层级详细职责与运行边界

2.2.1、资源抽象层(CRD):仅定义 "期望状态",无任何执行逻辑

资源抽象层(CRD)层基于 Kubernetes CRD 实现,包含三大自定义资源:GPUSpotPool、GPUSpotStrategy、GPUWorkloadProfile,核心定位是统一的配置与期望状态载体。
它只做一件事:面向用户暴露标准化配置入口,描述业务想要达到的最终资源状态,不包含任何调度、创建、销毁等执行代码。

        • GPUSpotPool:定义 GPU 竞价资源池基础规格,例如实例机型、GPU 卡型、数量、价格上限、可用区等;
        • GPUSpotStrategy:定义全局调度规则,例如成本优先、资源优先级、故障重试策略、扩缩容阈值等;
        • GPUWorkloadProfile:对接上层 AI 业务负载,描述训练 / 推理任务对 GPU 算力、显存、网络的资源诉求。

使用示例:用户在集群中提交一条 GPUSpotPool 自定义资源,声明期望状态:需要 10 台 V100 32G 竞价 GPU 实例,单台最高出价 5 元 / 小时。
配置提交完成后,资源抽象层的工作就彻底结束,后续所有资源落地、调度、异常处理全部交由下层组件完成。

2.2.、控制调度层(Controller):仅负责 "决策判断",不直接调用云厂商 API

控制调度层(Controller)是整个 Operator 的决策中枢,包含资源池控制器、中断控制器、调度控制器、云状态同步控制器等多个 Controller,依托 Kubernetes Reconcile 协调循环工作。
它只做一件事:只做状态对比、逻辑判断、指令生成,绝不直接对接任何云厂商 SDK/API。
运行逻辑:

    1. 持续监听资源抽象层的 CRD 期望状态,同时拉取多云资源的真实运行状态;
    2. 通过 Reconcile 循环对比 "期望状态" 与 "集群 + 云侧实际状态",发现偏差;
    3. 根据内置调度策略、中断规则、成本规则,生成标准化执行指令,例如:创建 3 台 GPU 竞价实例、删除 2 台闲置实例、替换 1 台被回收的中断实例;
    4. 将标准化指令统一下发至下层多云适配执行层。

简单来说,这一层 只关心“要做什么”不关心“具体怎么调用云接口实现”

2.3、多云适配执行层(Provider):仅负责 "指令执行",不参与业务决策

多云适配执行层(Provider)层 是对接各大公有云的适配底座,实现了腾讯云、阿里云、华为云、AWS 等多厂商 Provider 适配器,核心定位是纯执行单元。
它制作一件事:只接收上层下发的执行指令,调用对应云厂商官方 SDK/API 完成操作,不理解、不参与任何调度策略与业务逻辑。

运行逻辑:

      1. 接收控制调度层传来的标准化指令(创建、销毁、查询、重启实例等);
      2. 根据指令匹配对应云厂商 Provider,封装云平台专属请求参数,调用官方 API/SDK;
      3. 处理云侧 API 调用异常、限流、报错、返回结果等底层问题;
      4. 将执行结果、实例状态、价格信息、中断通知等原始数据回传给上层控制调度层。

这一层 只关心“怎么去做”不关心 "上层为什么要创建实例、为什么选择当前机型、为什么要替换中断节点"。

 2.4、执行 & 观测保障层:专注 "运行时观测与稳定性保障"

执行 & 观测保障层 作为整套系统的生产级底座,该层独立于业务调度与资源执行逻辑,聚焦 可观测性、集群协同、风险告警 三大能力,为全链路稳定运行保驾护航。

核心能力划分:

      1. 与 kube-scheduler 协同:对接 k8s 原生调度器,让集群原生调度感知 GPU 竞价实例状态、中断风险、资源标签,实现容器 Pod 与竞价实例节点的合理绑定;
      2. Metrics 指标采集:采集资源池数量、实例在线率、竞价价格、扩缩容次数、中断频次、任务运行时长等全维度监控指标;
      3. Events 事件记录:记录实例创建、销毁、中断、重建、调度决策、策略变更等全生命周期关键事件,方便问题溯源;
      4. Alert 告警通知:针对实例批量中断、资源池水位不足、价格超限、API 调用失败、调度异常等风险,主动触发告警,提前规避业务故障。

简单的来说,这一层 只关心 "状态监控、事件留痕、风险预警、集群协同",不关心  "调度决策与资源执行"。

三、核心 CRD 模型设计

3.1、GPUSpotPool——资源池

apiVersion: spotgpu.zuoyang.cn/v1alpha1
 kind: GPUSpotPool
 metadata:
   name: training-pool-a100
 spec:
   minInstances: 2          # 最少保活实例数
   maxInstances: 20         # 最大实例数
   gpuTypes:                # GPU 型号白名单
     - A100-40G
     - A100-80G
   maxPricePerHour: 8.0     # 单实例小时价格上限(元)
   providers:               # 允许使用的云厂商
     - name: tencent
       regions: [ap-guangzhou, ap-shanghai]
     - name: aliyun
       regions: [cn-shenzhen, cn-beijing]
   interruptStrategy:
     gracefulShutdownSeconds: 120   # 中断后给 Pod 的优雅退出时间
     checkpointRequired: true       # 要求 Pod 配合 checkpoint
     rebuildOnInterrupt: true       # 中断后自动重建
   scaleStrategy:
     scaleUpStep: 2                 # 单次扩容上限,防止抖动
     scaleDownStep: 1               # 单次缩容上限
     cooldownSeconds: 300           # 扩缩容冷却时间  
    

Status 子资源是实际运行状态的核心,必须设计清楚:

status:
   currentInstances: 8
   desiredInstances: 10
   instances:
     - id: ins-abc123
       provider: tencent
       region: ap-guangzhou
       gpuType: A100-40G
       status: Running              # Pending | Running | Interrupting | Terminated
       pricePerHour: 4.2
       createdAt: "2025-05-20T10:30:00Z"
       nodeName: gpu-spot-abc123     # 对应 k8s Node 名
     - id: ins-def456
       provider: aliyun
       region: cn-shenzhen
       gpuType: A100-80G
       status: Interrupting          # 正在被中断
       interruptNoticeAt: "2025-05-20T14:55:00Z"  # 收到中断通知的时间
       pricePerHour: 5.1
   interruptedInstances:
     - id: ins-def456
       interruptReason: "price_exceeded"
   totalCostThisMonth: 2150.6       # 当月累计成本(元)
   lastSyncTime: "2025-05-20T15:00:00Z"
   conditions:
     - type: Ready
       status: "True"
     - type: ScaleUpInProgress
       status: "True"
       message: "creating 2 instances on tencent ap-guangzhou"
    

几个设计注意点:

      • instances 里每个实例都关联了 k8s Node 名,这是跟 k8s 调度体系联动的关键
      • status 用状态机管理:Pending → Running → Interrupting → Terminated,每个状态有最小停留时间(比如 Pending 至少等 60s 再判断是否失败),避免 API 延迟导致误判
      • interruptedInstances 单独列出,因为中断实例的处理逻辑和正常实例完全不同
      • totalCostThisMonth 每轮 Reconcile 累加,是成本超限判断的数据源

3.2、GPUSpotStrategy——调度策略

apiVersion: spotgpu.zuoyang.cn/v1alpha1
  kind: GPUSpotStrategy
  metadata:
    name: cost-first-strategy
  spec:
    mode: CostFirst              # CostFirst | StableFirst | Balance
    costFirst:
      preferLowPrice: true
      priceTolerancePercent: 20  # 价格比最低价高 20% 以内都接受,避免只选最便宜的导致库存不足
      fallbackOnInsufficient: true  # 低价机型库存不足时,自动 fallback 到次低价
    stableFirst:
      preferLongUptime: true
      avoidHighInterruptRate: true
      minStableMinutes: 60       # 优先选择承诺稳定时长的机型(如阿里云首小时不中断)
    balance:
      costWeight: 0.6
      stabilityWeight: 0.4
    

策略不是排他选择,而是可以动态切换。实际情况是训练任务用 CostFirst推理服务用 StableFirst,同一个资源池在不同时段可能切换策略(比如白天推理为主用 StableFirst,夜间跑训练用 CostFirst)。

3.3、GPUWorkloadProfile——工作负载适配

apiVersion: spotgpu.zuoyang.cn/v1alpha1
kind: GPUWorkloadProfile
metadata:
  name: pytorch-ddp-training
spec:
  gpuRequirement:
    minCount: 4                # 最少 GPU 卡数
    minMemoryGB: 32            # 最少显存
    preferredTopology: NVLink  # 优先 NVLink 互联
  priority: high               # 配合 k8s PriorityClass
  interruptTolerance:
    maxInterruptPercent: 30    # 资源池内最多 30% 实例可同时中断
    checkpointEnabled: true    # 任务支持断点续算
    checkpointIntervalSeconds: 600  # 建议的 checkpoint 间隔
  poolRef: training-pool-a100  # 绑定到哪个资源池
    

四、核心 Controller 设计

用单 CRD 多协同 Controller 模式,4 个 Controller 各管一件事:

4.1、GPUSpotPool Controller——资源池主控

Reconcile 流程不是简单的 "对比差异→执行→更新",生产环境中大量异常分支:

Reconcile(pool) {
    1. 获取 pool 的 spec(期望状态)

    2. 通过 CloudSync 同步多云实例真实状态
       → 如果同步失败(API 超时/限流),不继续执行,直接返回 error
       → 原因:基于过时状态做决策比不做决策更危险

    3. 对比 desiredInstances vs currentInstances
       → 不足:触发扩容
       → 超出:触发缩容
       → 相等:检查是否有异常实例需要替换

    4. 扩容逻辑:
       a. 调度策略选机型+厂商+可用区
       b. 生成幂等 token(poolName + provider + region + instanceType)
       c. 检查是否已有同 token 的实例在创建中(防止重入)
       d. 调用 Provider.CreateInstances
       e. 如果返回 InsufficientInstanceCapacity:
          - fallback 到次优机型(需策略允许)
          - 如果所有 fallback 都失败,记录 event,等待下一轮
       f. 创建成功但状态为 Pending:
          - 不立即视为成功,设最小等待时间 60s
          - 60s 后如果仍为 Pending,视为创建失败,重试

    5. 缩容逻辑:
       a. 按策略选择要缩的实例(优先缩高价的、空闲的)
       b. 调用 Provider.TerminateInstances
       c. 等待实例状态变为 Terminated
       d. 清理对应 k8s Node

    6. 更新 pool.status
       → 包括 instances、conditions、totalCostThisMonth
}
    

生产踩坑1Reconcile 重入问题:创建实例的 API 调用发出去了但超时没返回,下一轮 Reconcile 又来了,不知道上一次创建成功了没有。如果直接再创建一次,就会出现重复实例。

解决办法:每次创建请求生成幂等 token,创建前查状态缓存里有没有同 token 的记录。各云厂商的幂等支持不同——阿里云的 ClientToken 参数原生支持幂等,腾讯云需要在应用层用 Redis 记录请求 ID 做 24 小时去重。

生产踩坑2CR 被删除但云实例还在。用户删了 GPUSpotPool CR,但 Finalizer 逻辑没跑完 Operator 就挂了重启,云实例变成孤儿。

解决办法:

  1. GPUSpotPool 加 Finalizer spotgpu.zuoyang.cn/cloud-instance-cleanup
  2. 删除时,Finalizer 逻辑遍历 status.instances,逐个调云厂商 Terminate
  3. 所有实例确认 Terminated 后,移除 Finalizer,让 k8s 完成 CR 删除
  4. Operator 启动时加孤儿实例回收逻辑:遍历所有 GPUSpotPool CR,对比 status.instances

和云厂商实际实例列表,不在任何 CR 管理中的实例标记为孤儿,根据策略决定是否回收

4.2、Interrupt Controller——中断感知与故障自愈

这是整个项目最核心也最容易出问题的模块。

中断检测方式因云厂商而异:

云厂商 中断通知方式 提前量 可靠性
AWS Spot Instance Metadata Service 的 spot/instance-action 端点 2 分钟 高,但只能轮询
阿里云抢占式 无主动通知 0 必须靠主动轮询实例状态
腾讯云波动型 无主动通知 0 同上
腾讯云计划型 站内信/事件总线 按计划时间 较可靠
华为云竞价 无主动通知 0 主动轮询

实际实现中,中断检测必须同时用两种机制:

    • 被动监听:在 Spot 节点上跑一个 DaemonSet,每 5s 轮询元数据服务(AWS)或云厂商事件接口
    • 主动轮询:CloudSync Controller 每 30s 拉一次所有实例状态,状态变更(Running→Stopping)视为中断信号

4.2.1、场景一:大模型长周期分布式训练,中断无感断点续训落地

适用生产情况千亿级基座模型预训练、长周期深度学习分布式训练,依托低价GPU竞价实例降本,核心诉求是 杜绝中断重跑、保障训练进度无损、实现全自动自愈续算,解决原生k8s无法适配竞价实例生命周期、中断无感知、进度不可控的核心难题。

      1. 集群节点侧部署的DaemonSet常驻监测,实时抓取云厂商竞价实例中断信号,同时通过CloudSync组件同步实例状态,一旦检测到实例进入Stopping回收状态,立即触发中断事件;
      2. 核心Interrupt Controller监听并接收全局中断事件,锁定待回收的GPU节点与节点上的训练业务Pod;
      3. Controller快速为故障节点打上污点 spotgpu.zuoyang.io/interrupting=true:NoSchedule,阻断新任务调度至该节点,规避二次业务冲突;
      4. 通过k8s API Server更新业务Pod注解,写入精准中断时间戳 spotgpu.zuoyang.io/interrupt-sent-at=2025-05-20T15:00:00Z,训练进程通过监听Pod注解变更、结合DownwardAPI完成中断信号感知;
      5. 业务层训练代码触发预设逻辑,自动执行模型Checkpoint权重、优化器参数、训练步数的全量保存,持久化至NAS/OSS共享存储,保存完成后回填 spotgpu.zuoyang.io/checkpoint-complete=true 注解;
      6. Operator按照预设gracefulShutdownSeconds(默认120s)优雅窗口等待任务落盘,优先响应Pod的 checkpoint完成确认信号;
      7. 超时未收到完成信号时,自动记录k8s事件,标记 checkpointStatus=incomplete 异常状态,留存运维追溯依据;
      8. 统一标记实例为Interrupting中断状态,触发等价GPU规格节点的自动重建流程,新节点就绪后,训练任务从最新断点无缝续跑。

大家要注意的关键点Operator仅承担 中断信号投递、优雅等待窗口管控、节点自愈重建、状态可观测 能力,不替代业务逻辑。训练任务必须自主实现 "定期自动快照+中断信号触发强制保存" 机制,二者配合才能实现生产级无损训练。

4.2.2、场景二:可用区批量竞价实例回收,大规模集群稳恢复治理

适用生产工况AI推理集群、大规模离线算力集群,单可用区部署数十台GPU竞价实例,突发云厂商区域级Spot资源回收,批量实例同步触发中断,极易引发API限流、重建拥堵、业务大面积抖动,核心诉求是 化解批量中断冲击、规避云厂商限流、保障集群快速平稳恢复

生产核心痛点以AWS为例,单地域 API 创建实例限流为2次/秒,若数十台故障实例集中向原可用区发起重建请求,会直接触发限流报错,导致重建任务排队积压、算力缺口持续扩大,推理服务超时飙升、离线训练任务长时间停滞。

实际的完整链路:

      1. 热点可用区规避:实时记录被批量回收的故障可用区信息,重建调度阶段自动规避风险AZ,优先选择同地域其他健康可用区分配资源,从源头规避区域级资源故障;
      2. 限流适配分批重建:深度适配各云厂商API限流阈值,自定义单批次最大创建实例数量,默认按2台/批执行,批次间间隔10s,有序消化重建需求,彻底杜绝API限流报错;
      3. 多云降级兜底机制:当单一云厂商全可用区无可用竞价资源、库存耗尽时,自动触发跨云Fallback策略,调度腾讯云、阿里云、华为云等价GPU资源兜底,保障业务不中断;
      4. 故障热点缓存规避:通过内存缓存+CRD状态持久化双机制,记录近期高频回收的故障可用区,调度器永久降低故障AZ优先级,避免反复调度至问题节点,规避重复故障。

落地效果彻底解决单AZ批量中断引发的集群雪崩、重建拥堵问题,大规模算力集群故障恢复有序可控,业务恢复时长缩短80%以上,保障推理、离线计算业务稳定性。

4.2.3、场景三:竞价实例动态重建,GPU拓扑感知性能最优调度

适用生产工况:8卡及以上多卡NVLink分布式训练场景,依赖全互联GPU拓扑保障NCCL通信效率,竞价实例随机重建易出现拓扑碎片化问题,核心诉求是 保障分布式训练通信性能稳定,杜绝重建后算力大幅衰减

生产核心痛点:标准 8卡 NVLink 全互联拓扑是大模型分布式训练的最优架构,一旦竞价实例回收重建,集群可能被分配 4+4 跨 NUMA 节点的碎片化拓扑,无全链路 NVLink 互联,直接导致 NCCL allreduce 通信效率下降 30% 以上,整体训练速度大幅降级,严重影响训练迭代效率。

实际的完整链路:

      1. 业务拓扑偏好自定义:通过 GPUWorkloadProfile 自定义资源,声明训练任务专属拓扑需求 preferredTopology: NVLink,明确优先使用全NVLink互联的多卡节点;
      2. 拓扑亲和智能打分调度:调度器新增GPU拓扑权重打分机制,对8卡全NVLink拓扑节点赋予最高调度优先级,跨NUMA、碎片化拓扑节点大幅降权,优先匹配最优算力资源;
      3. 智能降级与全链路可观测:当集群无完整最优拓扑资源时,自动降级适配次优4卡NVLink拓扑,同时生成k8s事件记录降级原因,方便运维追溯资源瓶颈,兼顾业务可用性与性能;
      4. 拓扑自适应环境适配:根据重建后实际GPU拓扑结构,自动更新 CUDA_VISIBLE_DEVICES、NCCL_TOPOLOGY 等核心环境变量,无需修改训练代码,即可适配当前拓扑完成通信优化。

落地效果彻底解决竞价实例重建后的拓扑碎片化、性能衰减问题,常规场景下保持100%最优训练性能,资源不足降级场景下,将性能损耗控制在5%以内,实现低成本竞价资源与高性能分布式训练的完美兼容。

4.3、Scheduler Controller——成本最优调度

打分函数需要考虑的实际约束,不是简单的价格排序:

type ScheduleScore struct {
    Provider       string
    Region         string
    InstanceType   string
    PriceScore     float64    // 价格越低分越高,满分 100
    InventoryScore float64    // 库存越充分越高,满分 100
    StabilityScore float64    // 历史中断率越低分越高,满分 100
    TopologyScore  float64    // GPU 拓扑亲和性,满分 100
}

// CostFirst 模式
func (s *CostFirstScorer) Score(candidates []ScheduleScore) []ScoredCandidate {
    for i := range candidates {
        c := &candidates[i]
        // 价格分:低于 maxPrice 的按比例打分
        c.PriceScore = (s.maxPrice - c.ActualPrice) / s.maxPrice * 100
        // 库存分:根据云厂商返回的库存状态,充足=100,紧张=50,极低=10
        c.InventoryScore = calcInventoryScore(c.InventoryStatus)
        // 综合分:CostFirst 模式价格权重 70%,库存权重 30%
        c.FinalScore = c.PriceScore*0.7 + c.InventoryScore*0.3
    }
    // 按综合分排序
    sort.Slice(candidates, func(i, j int) bool {
        return candidates[i].FinalScore > candidates[j].FinalScore
    })
    return candidates
}
    

4.3.1、场景四:竞价机型库存动态耗尽,多级自动降级兜底调度

适用生产工况:常态化AI算力调度场景,集群默认开启CostFirst成本优先调度策略,优先选用低价GPU竞价实例,日常高频遇到优选机型、指定可用区库存耗尽问题,核心诉求是资源不足时自动容错降级、不阻塞业务扩容、异常可观测可告警,适配云厂商竞价资源库存动态波动的生产特性。
生产核心痛点:竞价实例库存具备极强的随机性、时效性,是生产环境每日高频遇见的问题。传统固定机型、固定可用区调度模式下,首选低价机型一旦返回 InsufficientInstanceCapacity 库存不足错误,调度会直接失败,导致算力扩容停滞、训练/推理任务排队阻塞,原生k8s无多级降级、重试、告警机制,严重影响算力业务连续性。

实际的完整链路:

      1. 优选资源重试适配:调度器基于CostFirst策略选中最优低价GPU机型后,调用云厂商API创建实例,若返回库存不足异常,不直接失败,自动尝试同一厂商其他可用区的同规格机型,最大化利用同地域资源;
      2. 跨机型策略降级:当同一厂商所有可用区均无库存时,检测调度策略配置fallbackOnInsufficient: true,自动放弃首选机型,按价格排序切换为次低价、同算力等级的备选GPU机型,继续发起创建请求;
      3. 异常状态沉淀重试:当所有可用机型、可用区降级尝试均失败后,Operator记录k8s事件,同时为资源对象标记 ScaleUpFailed 异常状态,终止本次调度流程,等待下一轮Reconcile循环重新尝试调度,避免瞬时资源波动导致的误失败;
      4. 阶梯式告警自愈:持续统计调度失败次数,若连续3轮Reconcile均触发扩容失败,自动提升事件严重级别为Warning,主动推送运维告警,告知集群算力资源紧缺异常,人工可及时介入补充资源、调整调度策略。

落地效果:彻底解决竞价实例库存动态波动导致的调度失败、任务阻塞问题,实现 "同AZ重试→跨AZ重试→跨机型降级→重试告警" 的全链路容错,极大提升算力调度成功率,90%以上瞬时库存不足问题可通过自动降级自愈,无需人工干预,保障业务持续稳定运行。

4.3.2、场景五:多云算力精细化计费,全维度综合成本最优调度

适用生产工况多云混合GPU算力集群(腾讯云、阿里云、华为云、AWS混部),企业长期规模化运行AI训练、推理业务,核心诉求是 打破单GPU单价误区,实现全维度真实成本最优调度,精准控制多云算力总成本,避免表面低价、隐性成本超支的问题。

生产核心痛点传统算力调度仅对比GPU实例小时单价,成本计算维度单一,与企业实际账单严重不符。云端GPU算力总成本包含GPU算力、系统盘、数据盘、公网带宽、跨云VPC打通、内网互通等多项隐性费用。经常出现 "单卡单价更低的云厂商,叠加配套资源费用后,整体成本反而更高" 的情况,导致调度策略失真、降本效果不达预期。

举个例子腾讯云A100竞价实例单价4.2元/小时,看似低于阿里云同规格5.1元/小时,但业务需搭配500G高性能云盘、10M固定公网带宽,产生额外存储、带宽月度费用;而阿里云同规格实例自带200G免费系统盘,无额外基础存储成本。叠加隐性费用后,两家厂商真实总成本基本持平,仅看GPU单价会导致调度决策严重偏差。

实际的完整链路:

      1. 配置化成本模型定义:Operator摒弃硬编码单价逻辑,支持全维度附加成本项配置,可自定义录入GPU小时单价、系统盘单价、数据盘单价、公网带宽费用、跨云VPC互通费用、内网传输成本等所有计费维度;
      2. 实时综合成本核算:每轮调度打分阶段,自动根据业务所需磁盘规格、带宽配置、多云组网方式,实时计算每一款机型、每朵云的真实综合单位成本,替代传统的单一GPU单价对比;
      3. 综合成本优先级调度:调度打分机制以 "全维度真实总成本" 为核心依据,优先分配综合成本最低的云厂商、机型、可用区,而非单纯的低价GPU机型,保证调度决策贴合企业实际账单;
      4. 成本数据可观测沉淀:将各机型、各云厂商的分项成本、综合成本录入监控指标,支持账单溯源、成本对比分析,方便运维持续优化算力配比与资源配置。

落地效果:实现多云算力真实账单级成本最优调度,彻底规避单一单价调度的决策误区,精准识别隐性成本损耗,整体AI算力综合成本再优化10%-20%,让降本策略落地到真实账单,而非理论价格。 

4.3.3、场景六:竞价价格动态波动,实时成本超限自动替换治理

适用生产工况:长期驻留的GPU竞价实例集群,包含常态化推理服务、持续迭代的微调训练任务,核心诉求是实时管控动态价格波动,杜绝静默成本超支,保障算力运行成本始终在预算阈值内。

生产核心痛点:云厂商竞价实例价格为动态波动值,无固定定价。日常运行中常出现机型日间低价、夜间涨价,或高峰期价格翻倍的情况。集群若无实时价格监控与治理能力,运行中的实例会静默涨价,长期累积导致整体算力成本严重超限,人工巡检滞后、整改不及时,成本管控完全不可控。

实际的完整链路:

      1. 全局实时价格巡检:Operator在每一轮Reconcile协调循环中,自动拉取集群内所有运行中GPU竞价实例的实时最新价格,同步更新实例价格状态;
      2. 预算阈值比对校验:将实例实时单价与业务预设阈值 spec.maxPricePerHour 进行比对,精准识别价格超上限的异常实例;
      3. 超限实例状态标记:对所有成本超限的实例,统一标记 price_exceeded 专属状态,纳入待替换资源队列;
      4. 无感滚动替换执行:触发优雅替换流程,先调度创建同规格、低价合规的新GPU实例,等待新节点资源就绪、状态正常后,再优雅驱逐超限实例上的业务Pod,最终销毁高价超限实例;
      5. 容错机制适配:替换过程存在短暂的新旧实例并存期,会出现瞬时小幅成本上浮,Operator默认兼容该正常现象,不触发异常告警,保证业务平稳过渡。

 4.4、CloudSync Controller——多云状态同步

轮询间隔的设计不是拍脑袋的,要参考云厂商 API 限流:  

云厂商API 限流实例状态查询延迟建议轮询间隔
腾讯云 20 次 /min 5-10s 30s(留 50% 余量)
阿里云 100 次 /min(按 UID) 3-5s 15s
AWS 2 次 /sec(按 Region) 2-5s 10s
华为云 60 次 /min 5-8s 20s

多厂商并行轮询,每个厂商独立 goroutine,互不影响。某个厂商 API 不可用时,只影响该厂商的实例状态更新,不影响其他厂商。

五、多云适配执行层

5.1、统一 Provider 接口

type CloudGPUProvider interface {
      // 创建竞价实例,返回实例 ID 和状态
      // idempotencyToken 用于幂等控制
      CreateInstances(ctx context.Context, req CreateInstancesRequest) ([]InstanceResult, error)

      // 销毁实例
      TerminateInstances(ctx context.Context, instanceIDs []string) error

      // 查询实例状态
      GetInstanceStatus(ctx context.Context, instanceIDs []string) ([]InstanceStatus, error)

      // 查询竞价实例当前价格
      GetSpotPrice(ctx context.Context, region, instanceType string) (float64, error)

      // 查询库存状态
      GetInventoryStatus(ctx context.Context, region, instanceType string) (InventoryStatus,
  error)

      // 获取中断通知(仅 AWS 支持,其他厂商返回空列表)
      GetInterruptNotices(ctx context.Context, region string) ([]InterruptNotice, error)
  }
    

5.2、各厂商适配的关键差异

5.2.1、腾讯云——波动型 vs 计划型

波动型实例没有中断通知,只能靠轮询状态发现实例被回收。计划型实例会通过事件总线提前通知,但需要用户在控制台配置事件订阅。

适配层处理:

 func (p *TencentCloudProvider) GetInterruptNotices(ctx context.Context, region string)
  ([]InterruptNotice, error) {
      // 波动型:无法主动获取,返回空
      // 计划型:通过云 API DescribeScheduledInstances 查询计划回收
      if p.InstanceMode == "fluctuate" {
          return []InterruptNotice{}, nil
      }
      return p.queryPlannedInterruptions(ctx, region)
  }  
    

5.2.2、阿里云——首小时稳定保证

阿里云抢占式实例有一个其他厂商没有的特性:创建后第一个小时不会被中断。这意味着刚创建的实例至少有 60 分钟的安全窗口。

适配层处理:

func (p *AliCloudProvider) GetInstanceStatus(ctx context.Context, instanceIDs []string)
  ([]InstanceStatus, error) {
      statuses := p.queryInstanceStatus(ctx, instanceIDs)
      for i, s := range statuses {
          // 首小时内标记为稳定状态
          if time.Since(s.CreatedAt) < time.Hour {
              s.InterruptRisk = "low"  // 首小时内中断风险极低
              s.MinRemainingUptime = time.Hour - time.Since(s.CreatedAt)
          }
      }
      return statuses, nil
  }
    

调度器可以利用这个特性:对于 StableFirst 策略,优先调度阿里云实例,因为至少有 1 小时保证。

5.2.3、AWS——2 分钟中断通知

AWS 是唯一提供中断通知的主流厂商,通过实例元数据服务的 spot/instance-action 端点获取。

适配层处理:

func (p *AWSProvider) GetInterruptNotices(ctx context.Context, region string)
  ([]InterruptNotice, error) {
      // 方式 1:通过 EC2 DescribeInstances 过滤 State=stopping 的 Spot 实例
      // 方式 2:在节点上通过 DaemonSet 轮询元数据服务(更及时)
      // 两者结合:DaemonSet 负责实时检测,CloudSync 负责兜底
      return p.describeSpotInterruptions(ctx, region)
  }
    

5.3、API 容错

每个云厂商的 API 都会偶发超时、限流、内部错误。适配层必须统一处理:

type RetryConfig struct {
      MaxRetries    int           // 最大重试次数,默认 3
      InitialDelay  time.Duration // 首次重试延迟,默认 1s
      MaxDelay      time.Duration // 最大重试延迟,默认 30s
      RetryableErrors []string    // 可重试的错误码
  }

  // 腾讯云可重试的错误码
  // ResourceInsufficient → 不可重试(换机型)
  // InternalError → 可重试
  // RequestLimitExceeded → 可重试,但需加长延迟

  // AWS 可重试的错误码
  // InsufficientInstanceCapacity → 不可重试(换机型/AZ)
  // RequestLimitExceeded → 可重试
  // ServiceUnavailable → 可重试
    

六、与 Kubernetes 原生体系协同

6.1、污点与容忍

竞价 Spot 节点会统一打上专属污点,相当于标记为 可中断节点。只有配置了对应容忍度(toleration)的 AI 作业,才允许调度到这类节点;以此规避数据库等不可中断业务被误调度,保障核心服务稳定。

# Spot 节点自动打的污点
  taints:
    - key: spotgpu.zuoyang.io/spot-instance
      effect: NoSchedule
    - key: spotgpu.zuoyang.io/interrupting     # 中断中
      effect: NoSchedule                         # 阻止新 Pod 调度到即将回收的节点  
    

Pod 侧需要加容忍:

tolerations:
    - key: spotgpu.zuoyang.io/spot-instance
      operator: Exists
      effect: NoSchedule
    # 不容忍 interrupting 污点,中断中的节点不会调度新 Pod 
    

6.2、PriorityClass 与抢占

apiVersion: scheduling.k8s.io/v1
  kind: PriorityClass
  metadata:
    name: gpu-training-high
  value: 1000000
  preemptionPolicy: PreemptLowerPriority
  ---
  apiVersion: scheduling.k8s.io/v1
  kind: PriorityClass
  metadata:
    name: gpu-inference-medium
  value: 500000
    

6.2.1、场景七:优先级抢占引发断点损坏,训练任务数据一致性防护

适用生产工况:集群内同时运行高优先级大模型训练任务、中优先级推理 / 离线任务,基于 k8s PriorityClass 实现资源抢占调度;业务全部部署在 Spot 竞价节点上,依赖 Operator 完成中断检测、断点保存、自动续算,兼顾资源利用率与训练数据完整性。
生产核心痛点:当 Spot 节点资源紧张时,k8s 调度器会按照优先级规则,用高优先级 Pod 抢占低优先级 Pod。若抢占动作发生在训练进程执行 checkpoint 断点保存的窗口期内,Pod 会被强制终止,直接导致模型权重、运行状态写入不完整,断点文件损坏,后续任务无法正常续跑。同时原生 PodDisruptionBudget(PDB)仅能拦截 kubectl drain 等主动驱逐,无法阻拦调度器的优先级抢占行为,单纯依靠 PDB 无法彻底解决该问题。

实际的完整链路:

      1. 标记断点进行状态:Operator 检测到节点中断信号后,立即为正在执行断点保存的训练 Pod 添加注解:spotgpu.zuoyang.io/checkpoint-in-progress=true,标识当前处于数据落盘阶段。
      2. 临时创建 PDB 防护规则:自动为当前节点生成专属 PodDisruptionBudget 资源,针对带有上述注解的 Pod 设置 minAvailable: 1,拦截主动类驱逐操作,避免人为运维操作打断断点流程。
        apiVersion: policy/v1
        kind: PodDisruptionBudget
        metadata:
          name: checkpoint-protection-<node-name>
        spec:
          minAvailable: 1
          selector:
            matchLabels:
              spotgpu.zuoyang.io/checkpoint-in-progress: "true"
      3. 区分驱逐类型,针对性防护:明确 PDB 的能力边界:该规则仅防护手动驱逐、节点排空等自愿驱逐场景,无法阻止 k8s 调度器的优先级抢占。
      4. 主流落地方案:将断点保存时长严格管控在 gracefulShutdownSeconds(默认 120s)优雅退出窗口内,缩短临界风险时长,从流程上规避抢占冲突;
      5. 清理防护标记:训练进程完成 checkpoint 写入后,Operator 自动移除 Pod 上的状态注解,并删除临时创建的 PDB 资源,恢复节点正常驱逐、抢占能力。

落地效果:

        • 手动节点排空、运维驱逐等操作,不会打断断点保存流程,杜绝人为操作导致的文件损坏;
        • 依靠限时优雅窗口管控断点耗时,大幅降低调度抢占与断点流程重叠的概率;
        • 训练断点文件完整性得到保障,任务中断后可正常续跑,避免因断点损坏导致全量重训;
        • 不改动 k8s 原生优先级调度逻辑,兼顾集群资源抢占能力与业务数据安全。

6.3、GPU Device Plugin 集成

6.3.1、场景八:GPU 资源上报延迟引发调度失败治理

适用生产工况:基于 GPU 竞价节点构建 AI 训练、推理集群,节点上线后依赖 NVIDIA Device Plugin 完成 GPU 资源注册与上报。集群自动化扩缩容、竞价实例重建场景频繁,要求节点就绪后可立刻承接业务 Pod 调度,保障算力流转连续性。
生产核心痛点:新节点完成初始化并进入Ready状态后,NVIDIA Device Plugin 仍存在 10~30 秒的资源上报延迟。此阶段节点未正常上报nvidia.com/gpu资源,若 k8s 调度器将 GPU 业务 Pod 调度至该节点,会因无法匹配 GPU 资源配额,直接导致 Pod 启动失败、任务异常。

实际的完整链路:

      1. 节点初始化阶段添加防护污点:Operator 完成云主机创建、k8s 节点注册后,第一时间为节点打上调度污点,阻止业务 Pod 提前调度:
        taints:
          - key: node.alpha.spotgpu.zuoyang.io/gpu-not-ready
            effect: NoSchedule
        
                        

        该污点会拒绝所有新 Pod 调度至当前节点。

      2. 节点侧轮询检测 GPU 状态:节点启动后运行专属 Init Container,循环执行 nvidia-smi 命令探测 GPU 可用性,持续监听 Device Plugin 的资源上报状态。
      3. 条件满足后自动清除污点:
        • 当 Init Container 检测到 GPU 资源正常加载、Device Plugin 上报完成后,调用 k8s API Server 移除节点上 gpu-not-ready 污点,节点开放正常调度权限。
        • 整个等待 + 检测流程耗时约 15~40 秒,完全覆盖 Device Plugin 上报延迟窗口。
      4. 正常承接业务调度:污点移除后,调度器可正常将 GPU 相关 Pod 调度至该节点,资源配额校验正常,Pod 顺利启动运行。

落地效果:

        • 彻底规避因 Device Plugin 上报延迟导致的 Pod 调度失败、启动异常问题;
        • 依靠污点 + 节点自检的组合方案,实现节点就绪与 GPU 资源可用的时序对齐;
        • 全流程自动化执行,无需人工介入节点上线校验,适配竞价节点大规模自动重建、弹性扩缩容场景;
        • 不改动原生 Device Plugin 组件,兼容标准 NVIDIA GPU 运维体系。

七、生产级高可用与可观测

7.1、高可用

    • Controller 多副本 + 领导选举:Kubebuilder 默认支持,配置 --leader-elect=true,同一时刻只有一个Controller 实例在执行 Reconcile,其他实例热备。
    • 操作幂等设计:所有创建/删除操作通过幂等 token 保证重复调用不产生副作用。即使 Controller 重启、Reconcile 重入,也不会创建重复实例。
    • 限流与熔断:对云厂商 API 的调用加 sentinel 限流,超限请求排队等待而不是直接失败。连续失败 N 次后触发熔断,该厂商暂时标记为不可用,流量切换到其他厂商。

7.2、可观测Metrics(暴露给 Prometheus)

7.2.1、Prometheus 监控指标表 

指标名称 指标类型 指标含义
spotgpu_pool_current_instances Gauge 当前运行实例数
spotgpu_pool_interrupt_total Counter 累计中断次数
spotgpu_pool_hourly_cost Gauge 当前小时成本
spotgpu_pool_rebuild_latency_seconds Histogram 从实例中断到重建就绪的耗时
spotgpu_schedule_score Gauge 最近一次调度打分值
spotgpu_provider_api_errors_total Counter 云厂商 API 调用失败累计次数

7.2.2、k8s 事件(Events)列表 

事件名称事件说明
SpotInstanceCreated 竞价实例创建成功
SpotInstanceInterrupted 实例接收到云厂商中断通知
SpotInstanceRebuildStarted 中断实例触发重建流程
SpotInstanceRebuildCompleted 重建完成,新实例正常就绪
SpotPriceExceeded 实例实时价格超出预设阈值
ScaleUpFailed 扩容失败,事件附带具体失败原因

7.2.3、Prometheus 告警规则示例

# 中断率突增
  - alert: SpotGPUHighInterruptRate
    expr: rate(spotgpu_pool_interrupt_total[5m]) > 0.5
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "资源池 {{ $labels.pool }} 中断率过高"

  # 资源池容量不足
  - alert: SpotGPUPoolUnderCapacity
    expr: spotgpu_pool_current_instances < spotgpu_pool_min_instances
    for: 10m
    labels:
      severity: critical

  # 成本超限
  - alert: SpotGPUCostOverBudget
    expr: spotgpu_pool_hourly_cost > spotgpu_pool_max_hourly_cost
    for: 30m
    labels:
      severity: warning  
    

八、部署与落地

8.1、部署方式

    • Operator 以 Deployment 部署在管控集群,2 副本 + 领导选举
    • 多云凭证用 Secret 管理,严格 RBAC:Operator ServiceAccount 只有操作 GPUSpotPool 等 CRD 和 Node/Pod 的权限,不能访问其他资源
    • 提供 Helm Chart,支持 --set providers.tencent.enabled=true --set providers.aws.enabled=false 按需启用云厂商

8.2、小步快跑落地

8.2.1、第一步:单云单区域验证

选一个云厂商(建议腾讯云或阿里云,API 文档中文化、国内网络延迟低),验证:

      • 创建/删除竞价实例
      • 主动模拟中断(手动终止实例),验证中断检测 + 重建流程
      • 单个训练任务的 checkpoint + 断点续算

验证标准:中断后 5 分钟内任务恢复运行,checkpoint 数据完整。

8.2.2、第二步:接入非核心训练任务

选择可容忍中断的离线训练任务,观察:

      • 7 天内中断率和重建成功率
      • 实际成本 vs 按量计费成本
      • 训练任务的有效算力利用率(排除中断重建的时间)

预期数据:成本下降 70-85%,中断率 5-20%(取决于时段和区域),重建成功率 > 95%。

8.2.3、第三步:多云多区域混部

      • 逐步接入阿里云、AWS
      • 训练任务 + 推理服务混部
      • 完善 CostFirst/StableFirst 策略的参数调优
      • 建立成本看板和中断率趋势图

等我有时间了,再开下一篇 进入编码实战:Kubebuilder 项目初始化、CRD 定义与代码生成、Provider 接口实现、Reconcile 调谐逻辑