ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

非生产环境自动化停机实战:基于 K8s CronJob 与云 API 的定时休眠调度器

非生产环境自动化停机实战:基于 K8s CronJob 与云 API 的定时休眠调度器 非生产环境自动化停机实战基于 K8s CronJob 与云 API 的定时休眠调度器在很多中大型技术团队的云上账单中开发环境Dev、功能测试环境Test和集成预发环境Staging所消耗的服务器算力与云数据库资源往往占据了公司整张账单的35% 到 45%。然而拉出这些非生产环境的调用监控指标就会看到一个极其触目惊心的算力浪费现实研发和测试人员的正常工作时间集中在周一至周五的 09:30 到 20:30 之间。这意味着在工作日夜间的 13 个小时以及周六、周日和法定长假全天这些承载着数十个微服务副本、独立测试数据库、Redis 缓存的庞大集群有超过 65% 的时间处于完全无人的纯空转状态。每个月数十万元的算力预算就在无人问津的寂静黑夜里顺着空转的 CPU 风扇白白蒸发了。很多团队尝试推行“下班前手动关机”但最终都死于“人性的惰性”——总有人忘记关机或者第二天早晨因为缺少某个服务导致联调受阻。推行成本工程必须用确定性的自动化代码消灭对人工记忆的依赖。我们通过自研轻量级 Kubernetes 休眠调度控制器Sleep Operator配合云厂商 OpenAPI实现了非生产环境的“日落而息、日出而作”直接砍掉了非生产环境 60% 以上的月度账单。一、自动化休眠的架构设计状态快照与优雅唤醒实现自动化停机最核心的技术难点不在于“怎么把副本数变成 0”而在于如何在第二天早晨 100% 精准无误地恢复原状。很多微服务在测试环境并不是统一缩容成 1 个副本的有些服务测试时开着 3 个副本有些边缘模块原本就是关停的。如果机械地全量设为 1会破坏原有的测试上下文。因此调度控制器必须遵循**“状态快照State Snapshot与元数据持久化”**设计[ 工作日 21:00 定时休眠触发 ] │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 1. 扫描带有 sleep-scheduleenabled 标签的测试命名空间 │ │ 2. 遍历所有 Deployment / StatefulSet读取当前 replicas 数量 │ │ 3. 将真实副本数写入 Annotation: yuejoy.ai/original-replicas │ │ 4. 将实际 replicas 更新为 0Kubernetes 自动回收 Pod 算力 │ │ 5. 调用云厂商 OpenAPI 将测试 RDS/Redis 制作快照并停机/降规格 │ └─────────────────────────────────────────────────────────────┘ ▲ │ 状态恢复 [ 工作日 08:30 定时唤醒触发 / 研发钉钉群指令唤醒 ] │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ 1. 唤醒云数据库与缓存实例等待就绪探针绿灯通过 │ │ 2. 读取 Annotation 中备份的 original-replicas 原始数值 │ │ 3. 将 Deployment 副本数恢复至历史快照值服务秒级拉起 │ └─────────────────────────────────────────────────────────────┘二、基于 Go 1.27 实现的轻量 Kubernetes 休眠控制器核心逻辑以下是休眠控制器的核心调度逻辑直接调用 Kubernetes client-go 原生接口运行开销不足 30MB 内存package operator import ( context fmt strconv metav1 k8s.io/apimachinery/pkg/apis/meta/v1 k8s.io/client-go/kubernetes ) const ( AnnotationOriginalReplicas yuejoy.ai/original-replicas LabelSleepEnabled sleep-scheduleenabled ) type EnvironmentScheduler struct { kubeClient kubernetes.Interface } func NewScheduler(client kubernetes.Interface) *EnvironmentScheduler { return EnvironmentScheduler{kubeClient: client} } // HibernateNamespace 将目标命名空间内的所有应用安全休眠 func (s *EnvironmentScheduler) HibernateNamespace(ctx context.Context, namespace string) error { deployments, err : s.kubeClient.AppsV1().Deployments(namespace).List(ctx, metav1.ListOptions{}) if err ! nil { return fmt.Errorf(failed to list deployments: %w, err) } for _, d : range deployments.Items { currentReplicas : *d.Spec.Replicas if currentReplicas 0 { // 原本就是 0 副本的无需处理 continue } // 1. 在 Pod 元数据中快照备份原本的副本数量 if d.Annotations nil { d.Annotations make(map[string]string) } d.Annotations[AnnotationOriginalReplicas] strconv.Itoa(int(currentReplicas)) // 2. 将副本数归零 zeroReplicas : int32(0) d.Spec.Replicas zeroReplicas _, err : s.kubeClient.AppsV1().Deployments(namespace).Update(ctx, d, metav1.UpdateOptions{}) if err ! nil { fmt.Printf([ERROR] 休眠应用 %s 失败: %v\n, d.Name, err) continue } fmt.Printf([INFO] 应用 %s 已成功休眠 (备份原始副本数: %d)\n, d.Name, currentReplicas) } return nil } // WakeupNamespace 将目标命名空间内的所有应用按快照精准唤醒 func (s *EnvironmentScheduler) WakeupNamespace(ctx context.Context, namespace string) error { deployments, err : s.kubeClient.AppsV1().Deployments(namespace).List(ctx, metav1.ListOptions{}) if err ! nil { return fmt.Errorf(failed to list deployments: %w, err) } for _, d : range deployments.Items { backupVal, exists : d.Annotations[AnnotationOriginalReplicas] if !exists { // 没有备份快照的默认恢复为 1 个副本 backupVal 1 } targetReplicasInt, _ : strconv.Atoi(backupVal) targetReplicas : int32(targetReplicasInt) d.Spec.Replicas targetReplicas // 清理已恢复的 Annotation 标记 delete(d.Annotations, AnnotationOriginalReplicas) _, err : s.kubeClient.AppsV1().Deployments(namespace).Update(ctx, d, metav1.UpdateOptions{}) if err ! nil { fmt.Printf([ERROR] 唤醒应用 %s 失败: %v\n, d.Name, err) continue } fmt.Printf([INFO] 应用 %s 已成功唤醒恢复至 %d 副本\n, d.Name, targetReplicas) } return nil }三、研发体验不妥协基于聊天机器人的按需动态唤醒ChatOps很多成本治理项目之所以推行夭折是因为粗暴的关机引发了研发人员的强烈反弹“我今天刚好要在晚上 10 点加班联调一个紧急 Bug环境被自动关了我只能干瞪眼”。为了兼顾成本控制与研发体验我们必须配套ChatOps 动态按需续期机制提前 15 分钟告警预告每天 20:45钉钉/企微机器人自动在研发群推送通知“测试环境将在 21:00 进入节能休眠状态。如需继续加班联调请点击下方【延期 2 小时】按钮或在群内回复/env extend test 2h”。零门槛自助一键拉起周末或假期偶发紧急修复研发无需找运维申请权限直接在群内输入命令/env wakeup test。后台控制器在 60 秒内将测试环境从快照拉起并在 3 小时后未检测到请求时自动重新进入休眠。四、落地后的算力节约收益账本在一家拥有 40 个测试微服务、3 套测试环境的中型团队落地这套定时调度器后月度收益核算如下算力计费核算维度改造前 (7×24 全天无休)改造后 (定时休眠 按需唤醒)财务节约明细工作日每周运行时长120 小时55 小时(08:30-19:30)运行时长减少 54.1%周末及法定节假日全月约 192 小时满载全休眠(偶发加班约 10 小时)节假日闲置算力削减 94.8%每月有效开机综合占比100% (720 小时)约 35%(255 小时)总运行时长减少近 65%测试环境月度云账单3.2 万元1.18 万元每年净省出 24.2 万元真金白银成本工程从来不是靠苦口婆心的道德约束而是把最锋利的工程工具打磨成完全无感、自动化运转的制度底座。用代码给算力挤出水分企业才能拥有更加健康的现金流与更强的生存韧性。
返回列表