云成本巡检这件事,圈内人有个心照不宣的痛点:告警天天发,账单月月超,但真正动手去治理的人永远只有那么一两个运维。我早先做云上资源治理的时候,也是先搞了一套“成本巡检”,结果跑了两个月,发现它只是在每天定时往群里丢一张报表、几条告警——这属于典型的Inform阶段:把问题摆出来,但没人接力。后来我下决心把它重构成Operate阶段:巡检发现异常之后,直接自动创建治理任务,通过 Mission 调度把“发现问题、分配任务、执行处置、确认结果”整个闭环跑起来,才算是真正把云成本从“人工救火”拖进了“自动化运营”的轨道。
这篇内容,就是我当时重构这套巡检机制的核心思路和落地细节,包括成本数据怎么建模、巡检规则怎么设置才不容易误报、Mission 调度的任务编排怎么设计才能扛住真实生产环境。如果你正在被云上“成本失控”和“告警疲劳”两头夹击,或者说你想把成本治理从“靠人盯”变成“靠机制跑”,那这篇文章应该能给你一套直接可以抄作业的框架。
1. 为什么巡检机制必须经历从 Inform 到 Operate 的蜕变
先说一个我踩过的大坑。最早做成本巡检的时候,我认为只要把“资源利用率低”“空闲资源未释放”“按需购买过多”这些异常查出来,推到钉钉群里,运维同事自然会去处理。事实是:第一周还有人看一眼,第二周开始群里全是已读不回,第三周连我自己都不太想点开那个报表了。巡检如果没有后续的执行动作,本质上只是把问题从“看不见”变成了“不想看”——这是一种更高层次的成本浪费。
1.1 Inform 阶段:告而不治,成本黑洞的起点
Inform 阶段的典型特征是“巡检链路到告警为止”。系统每天定时抓取云资源数据,跑一遍预设的成本异常判定逻辑,然后输出一份报告或一批告警。看起来自动化程度很高,但模型其实是个断头路:
- 告警发出去之后,没有人对“处理结果”负责。
- 同一个资源持续产生告警,但没有任何机制阻止它继续产生费用。
- 运维人员需要自己登录云控制台,肉眼排查、手动释放、手动变配,整个过程没有任何系统性的记录和跟踪。
我见过一个比较夸张的案例:一台闲置的云数据库实例,从第一次被巡检出来到最终被销毁,中间隔了 47 天。这 47 天里系统一共发了 30 多次告警,但每次告警都因为“负责人出差”“暂时不敢动”“需要业务确认”等原因被搁置。等到真正销毁的时候,这台实例已经烧掉了近 3000 块钱。
这就是 Inform 阶段的根本问题:它把成本问题变成了人性考验——考验团队会不会主动跟进,结果通常经不起考验。
1.2 Operate 阶段:从“发现”到“闭环”的关键一跃
Operate 阶段要解决的核心问题只有一个:让系统具备“发现问题之后继续往前推进”的能力。巡检不再止步于告警,而是把每次异常转成一个“任务”,任务进入调度引擎,调度引擎负责分配、执行、验证、归档。
我重构之后的链路是这样跑的:
- 成本巡检引擎每天在固定时点扫描所有云资源。
- 发现异常之后,先做一次“可执行性判定”——判断这个异常是否适合自动化处置,比如闲置实例是否能直接释放,或者只能发通知给业务方。
- 能自动处置的,直接进入 Mission 调度队列;不能自动处置的,生成待人工确认的任务,并指定责任人。
- Mission 调度器按预定义策略执行任务,执行完成后校验结果,更新任务状态。
这套链路跑起来之后,我这边最直观的变化是:闲置资源从“发现到清理”的平均耗时从 47 天降到了 4 个小时左右,因为大部分动作交给了自动化任务去执行,不再依赖人来接力。
提示:一开始就追求全自动是有风险的。我建议把 Operate 拆成“半自动”和“全自动”两档,先跑半自动——系统自动生成处置建议,人工点击确认后再执行——跑一段时间、置信度足够了,再放开特定场景的全自动执行。
2. 巡检机制的底座:成本数据的采集与建模
没有干净的数据,后面所有的巡检规则和 Mission 调度都是空中楼阁。我在重构这套机制的时候,特意花了一周时间梳理云成本数据的采集和建模,这一周后来被证明是值得的——它决定了整个系统能做多精细。
2.1 数据源的接入与标准化
云成本数据散落在不同的地方,我自己的环境里至少有四类来源:
- 账单明细:记录了每一笔费用支出,最准确,但有 T+1 延迟,适合做月度级别的核算和趋势分析。
- 资源清单:通过云厂商的 API 拉取当前所有实例、存储、网络等资源的状态和配置,这是巡检最主要的实时数据源。
- 监控指标:CPU、内存、带宽、存储读写的实际使用量,用于判断资源是不是“闲置”或者“利用率过低”。
- 费用告警:云厂商自带的额度告警,比如账户余额低于某个阈值时触发,用于兜底。
这些数据源的格式、粒度、更新频率各不相同。我当时做了一件事:统一在数据接入层做标准化。无论数据来自哪个云厂商、哪种接口格式,接入之后全部转换成内部统一的字段模型,包括:
| 字段 | 含义 | 示例 |
|---|---|---|
| resource_id | 资源唯一标识 | i-2zeb2x7q3v8a1c5d |
| resource_type | 资源类型 | ecs / rds / slb / eip |
| region | 地域 | cn-hangzhou |
| instance_status | 运行状态 | running / stopped / released |
| monthly_cost | 月度费用估算 | 128.50 |
| cpu_usage | 近 24 小时 CPU 平均使用率 | 3.2 |
标准化之后,巡检引擎只面对一套统一的数据模型,规则配置也只需要写一次。后续即使新增云厂商或者新增资源类型,只需要在接入层加一个适配器就行。
2.2 成本指标的分层设计:账单级、资源级、分摊级
这是我这套机制中最关键的设计之一。早期我只看“账单总额”和“按产品线汇总”这种粗粒度数据,导致一个问题:某个团队说“我们上个月成本没怎么涨”,但打开明细发现只是他们名下的十几台资源互相抵消了涨幅。
后来我设计了三层成本指标:
- 账单级指标:关注整体费用走势、环比增长率、预算消耗进度。适合管理层看,也适合做全局巡检的“红线”。
- 资源级指标:关注每一台具体资源的费用和利用率。适合自动化巡检,因为处置对象是具体的资源实例。
- 分摊级指标:关注成本在业务线、项目组、环境之间的分摊情况。适合内部结算和成本追溯,也能帮助定位“哪条业务线在烧钱”。
这三层指标在巡检规则里的作用完全不同。账单级指标触发时,系统只发告警并生成“专项分析任务”;资源级指标触发时,系统直接进入 Mission 调度流程尝试自动化处置;分摊级指标触发时,系统则生成“负责人通知任务”,把费用明细打包发给对应业务线负责人。
我在实际运行中体会很深的一点是:很多做成本巡检的人只盯着账单总额,结果系统经常误报“成本异常”,因为账单总额的正常波动幅度本身就很大。拆成三层之后,每一层设不同的阈值和处置策略,误报率明显降下来了。
3. 巡检规则引擎:让异常无处可藏
规则引擎是巡检机制的大脑。规则设得太松,异常发现不了;设得太严,误报满天飞,Mission 调度器会被无意义的任务塞满。这一节是我重构过程中反复调试最久的部分,说几个比较实用的设计思路。
3.1 规则设计的三个核心维度:阈值、基线、趋势
我早期的巡检规则非常简单粗暴:只要 CPU 平均使用率低于 5%,就判定为闲置实例,直接标记待释放。结果误伤了好几个业务方的“低峰备用实例”——人家就是故意保持低利用率,用于承接双十一这类峰值的流量,直接释放会出大事故。
后来我把规则拆成了三个维度,必须同时满足才判定异常:
- 阈值维度:比如 CPU 使用率低于 5%,或者连续 30 天无主动连接。
- 基线维度:与过去 30 天或 90 天的自身数据做对比。比如某资源过去 30 天 CPU 平均使用率是 15%,这个月掉到 2%,说明确实闲置了;但如果它过去半年一直是 2%,那可能是“设计如此”,需要人工确认用途。
- 趋势维度:看费用的环比和同比变化趋势。比如 ECS 费用连续三个月每月增长超过 30%,即使绝对值不高,也可能存在配置过度的问题。
三者的优先级是:趋势维度先扫,发现明显变化的资源;基线维度做二次确认,过滤掉“一直如此”的情况;阈值维度做最终判定,决定是否触发 Mission 任务。
注意:不要让单个维度单独触发处置动作。我在测试阶段做过统计,如果只用阈值维度,误报率大概在 30% 左右;加入基线和趋势之后,误报率降到了 8% 以下。
3.2 降噪策略:如何把误报率打下来
误报不只是浪费大家的时间,更危险的是它会“训练”整个团队忽略系统告警。我见过一个团队,因为成本警告太频繁,最后所有人形成了一种默契:看见告警先不处理,等三天,如果同一台机器还在告警再去看。这已经完全失去了巡检的意义。
我的降噪三板斧:
- 同类告警合并。如果同一个地域的 20 台闲置 ECS 是同一天被发现的,不要生成 20 条独立告警,而是合并成一条,列出资源清单,系统按批次创建 Mission 任务。
- 冷却时间机制。同一资源在触发一次处置任务之后,48 小时内不再触发同类规则,除非任务执行失败重新进入队列。
- “连续 N 天确认”机制。某些场景下,资源确实会短暂出现“低利用率”,但很快又恢复。我目前对闲置实例的判定标准是:连续 7 天满足条件才触发处置,而不是某一次巡检发现低利用率就立刻处置。
用这套策略之后,我们群里的成本告警从每天几十条降到了每周三五条,但每一条都是值得处理的真问题。
4. Mission 调度:把巡检变成可持续运转的“自动驾驶”
如果说规则引擎是巡检的“眼睛”,那 Mission 调度就是巡检的“手”。发现异常只是第一步,真正决定巡检机制能不能落地的,是后续的任务调度体系是否高效、稳定、可持续。
4.1 Mission 调度的核心循环:分配、执行、确认、归档
我在设计 Mission 调度时,参考了运维工单系统的思路,把每个处置动作建模成一个完整的生命周期:
- 分配:异常触发规则之后,系统自动创建一个 Mission,并根据资源所属业务线、地域、操作类型,自动分配给对应的执行策略或责任人。
- 执行:如果是自动化任务,调度器按照预设的时间窗口和顺序执行具体操作——比如释放闲置实例、调整带宽、修改付费类型。如果是人工任务,则推送给责任人,要求在规定时间内完成处置。
- 确认:任务执行完成后,系统自动校验结果。比如释放实例的任务,会去查询该实例是否已处于 released 状态。
- 归档:确认通过的任务归档入库,记录执行人、执行时间、处置前后成本对比等元信息,用于后续效果分析。
这个循环看起来简单,但我在落地时发现,最容易出问题的是“分配”这个环节。初期我把所有任务都分配给“运维组”这个虚拟角色,结果是任务堆积在公共队列里,没有人主动认领,优先级高的重要任务也被淹没。
后来我改成了“按资源归属分配 + 分级调度”的策略:
- 每个项目组维护一份资源列表和对应的负责人。
- Mission 根据资源归属自动指定责任人,同时抄送项目组 Leader。
- 任务的优先级分为 P0(立即执行)、P1(4 小时内处理)、P2(24 小时内处理),调度器按优先级顺序执行。
改完之后,任务响应速度有了质的提升。因为责任明确到人,每一级都会有对应的跟进机制。
4.2 任务幂等与失败重试
这是整个 Mission 调度中技术含量最高的部分,也是我踩坑最多的地方。云资源的操作接口,很多并不保证“一次执行成功且结果唯一”。
举个最典型的例子:释放一台 ECS 实例。如果第一次调用释放接口超时了,但实际后端已经完成了释放操作,此时如果调度器盲目重试,再次调用释放接口,轻则返回“实例不存在”的报错,重则影响到同一个 API 请求中的其他操作。
我采用的方案是:为每一个 Mission 生成全局唯一的幂等键,以幂等键作为所有外部调用的参数,并让云厂商 API 侧保留请求记录。这样即使重复提交同一个任务,后端的处理逻辑也会识别出已经执行过,直接返回上一次的结果,而不会产生二次操作。
同时,对于失败任务,我设置了最多三次重试,每次重试间隔按 5 分钟、15 分钟、1 小时递增。超过三次重试仍然失败的任务,自动降级为人工处理流程,推送给对应责任人。
4.3 调度的频率与优先级设计
Mission 调度还有一个容易被忽略的细节:频率设计。巡检的触发频率和 Mission 的执行频率不应该完全相同。
- 巡检频率:我目前是每天 2 次,分别在 10:00 和 16:00 整点触发。这避免了数据源尚未同步导致的漏检,也为上午和下午各留出一次“发现问题并启动处置”的窗口。
- Mission 执行频率:P0 任务实时执行,P1 任务每小时批量执行,P2 任务每天 18:00 统一执行一次。
- 数据核对频率:每周一执行一次“全量资源对账”,把账单、资源清单和巡检记录做一次三方比对,找出“漏网之鱼”。
这个设计的思路是:巡检发现问题和任务执行处置解耦,避免系统因为某个环节卡住而导致整个链路阻塞。即使某一次巡检失败了,也不影响已经排队的 Mission 按计划执行。
5. 从巡检到治理:闭环运营的落地路径
很多团队做成本巡检,做到“发现问题并生成工单”就停了,这其实是把 Operate 做成了另一种形式的 Inform。真正的闭环运营,需要把巡检结果转化成持续的成本优化动作,然后通过数据验证每一次治理动作的效果。
5.1 巡检发现的 TOP 问题与治理动作的映射
我把过去半年巡检发现的成本问题做了归类统计,排在最前面的四类是:
- 闲置资源:包括运行中但长期无流量的 ECS、RDS 实例,以及已绑定但未使用的弹性公网 IP。
- 规格过剩:CPU、内存配置过高,但实际负载长期处于低位。
- 付费方式不匹配:按量付费的长期稳定负载,本可以使用包年包月或节省计划来降低成本。
- 存储冗余:快照数量过多、日志无故长期保留、废弃镜像未清理。
针对每一类问题,我设计了一个固定的治理动作表:
| 问题类型 | 自动/半自动 | 治理动作 |
|---|---|---|
| 闲置 ECS | 半自动 | 先停止实例,保留数据,观察 7 天后自动释放 |
| 闲置 EIP | 自动 | 直接解绑并释放 |
| 规格过剩 | 半自动 | 自动调整实例规格至合理档位 |
| 过期快照 | 自动 | 删除超过 60 天且无依赖的全量快照 |
| 按量付费转包年包月 | 半自动 | 根据近 90 天用量推荐转换方案,人工确认后执行 |
这里的“半自动”我都设置了“人工确认”环节,因为在资源变更类操作上,我支持“宁可慢一点,也不要误杀”。
5.2 效果度量与持续迭代
治理动作执行完之后,需要有一个可量化的反馈机制。我每个月会生成一份《云成本治理月报》,核心指标有三个:
- 月度节省金额:通过治理动作实际减少的费用支出,按资源类型和治理类型分别汇总。
- 治理覆盖率:已治理资源数占应治理资源数的比例,用来评估系统是否“应治尽治”。
- 同类问题复发率:已治理问题在后续 30 天内再次出现的比例,用来评估治理措施是否“断根”。
举个例子:发现某业务线有一台闲置 RDS,半自动任务先把它停了,一周后确认无业务影响,再执行释放。月报里就会记录为“RDS 闲置治理:节省 214 元/月,治理覆盖率 100%,同类问题复发率 0%”。
有了这些数据,我就能判断哪些规则太激进需要放宽,哪些规则太保守需要收紧,整个巡检机制和 Mission 调度会越来越贴近真实的业务形态。
6. 常见问题与排查技巧实录
这套机制我前前后后跑了将近一年,说几个我实际踩过并且花了比较多时间才解决的典型问题,希望你能避开这些坑。
6.1 巡检结果与账单对不上
现象:某天自动巡检显示“资源 A 处于闲置状态”,但当天账单里资源 A 依然产生了高额费用。
排查过程:我先怀疑是数据源延迟问题,检查了资源清单接口的更新时间,发现资源状态是实时的,但账单数据有 T+1 延迟。接着查了资源 A 的计费规则,发现问题不在源数据,而在巡检引擎的“日费用估算”逻辑——我用的是“月费用除以当月天数”来估算每日费用,但资源 A 是按量计费且使用了预留实例券抵扣,实际每日费用并不等于月均费用。
解决方案:把巡检引擎的费用估算逻辑改为“基于按量单价 + 最近三天的实际用量预估”,并在规则的触发条件里增加一条:月估算费用低于 100 元的资源不触发处置任务,因为处置成本可能超过节省的成本。
6.2 Mission 任务重复执行
现象:有一次系统里出现了同一个“释放闲置实例”的 Mission 被创建了三次,而且三次都执行成功,最后云厂商端因为重复释放报了错。
排查过程:我检查了巡检引擎的触发逻辑,发现是因为数据源偶尔会出现短暂抖动,一次巡检中同一个资源被规则引擎意外匹配了多次,进而创建了多个一模一样的 Mission。而 Mission 的幂等键是随机生成的 UUID,导致即使操作对象相同,也被当成不同任务执行。
解决方案:做了两个改造。第一,Mission 的幂等键从 UUID 改成“资源 ID + 操作类型 + 巡检批次”组合,保证同一批巡检内同一个资源不会被创建重复任务。第二,在任务执行前增加一道“前置校验”,执行释类操作前,先确认目标资源是否仍处于可释放的状态,如果已经是 released,直接标记任务为“已完成”。
6.3 调度高峰期的资源竞争
现象:上线初期,Mission 调度器每天 18:00 集中执行 P2 任务,结果有一次把某个地域的 OpenAPI 调用限流触发了,导致一批任务集体失败。
排查过程:我查看了云厂商 API 的限流阈值,发现同一账号在同一地域的写操作接口有分钟级 QPS 限制,而我们的调度器是无脑按任务列表顺序并发执行的。
解决方案:在 Mission 调度器里增加了“地域级并发度控制”,每个地域同时执行的写操作任务不超过 5 个,并且为批量操作增加随机延时,错开请求峰值。改造之后,再也没有出现过因为 API 限流导致的大面积失败。
6.4 任务失败但状态被误标记为成功
现象:有一次镜像清理任务执行的时候,调用删除接口返回成功,但实际镜像还留在系统里。
排查过程:后来发现是因为删除接口在异步任务场景下返回的“成功”只代表“受理成功”,不代表“删除完成”。当时调度器拿到成功响应就直接把 Mission 状态置为“已完成”,结果就是任务显示成功,实际上什么都没清理掉。
解决方案:在确认环节增加了二次验证机制。凡是资源释放、删除、变配类操作,任务执行完成后,必须重新查询一次目标资源的最终状态,确认已经达到预期状态才允许归档。查询失败或状态不符,任务自动回到“执行中”并触发重试。
7. 持续迭代这套机制的几个建议
最后想说一个不太被技术文章重视、但在实际运行中很重要的话题:巡检机制本身也需要被复盘和迭代。
我目前的做法是:每个月抽出半天时间,把上个月所有巡检规则触发的记录、Mission 执行的任务、治理动作节省的费用整体过一遍,问自己三个问题:
第一,有没有误报?误报的规则是阈值问题还是维度缺失? 第二,有没有漏报?哪些成本异常是巡检完全没有发现的?这通常意味着需要新增规则或者调整数据采集范围。 第三,Mission 调度有没有瓶颈?任务在哪个环节堆积最久?是自动化执行慢,还是人工确认被卡住了?
这套复盘机制看起来简单,但坚持下来之后,我发现两个明显的好处:一是巡检规则和真实业务场景的匹配度越来越高,误报率逐月下降;二是 Mission 调度器的执行效率持续提升,从发现问题到完成治理的平均耗时缩短了一半以上。
我个人的体会是,云成本巡检这件事,真正难的不是写几段规则、配几个定时任务,而是把“人、系统、流程”三者之间的关系理顺。Inform 做的是让人看见问题,Operate 做的是让系统解决问题,而可持续运行的机制,做的是让每一次巡检都比上一次更聪明一点。希望这篇文章能给你一些参考,至少能让你少踩几个我踩过的坑。