承诺折扣、预留与 Spot 选型
一次看似成功的降本采购,可能在业务迁移后变成持续一整期的固定损失。某团队根据上个高峰月购买了承诺折扣,又把批处理节点全部切到 Spot。账面折扣率非常漂亮,稳定负载却因为规格和区域变化无法消耗预留,批处理在集中回收时反复重跑,在线服务为了兜底临时扩回按需实例。最终,承诺闲置、重算资源和应急容量同时付费,实际成本反而高于采购前。
折扣不是容量能力,预留也不一定预留了物理容量。架构决策必须同时回答:哪部分需求足够稳定,权益能匹配哪些服务、规格和区域,未使用承诺怎样损失,Spot 中断怎样恢复,以及业务收缩或迁移时怎样退出。真正需要优化的是单位有效工作成本,而不是控制台显示的折扣百分比。
先把四种能力拆开
按需容量按实际使用付费,变化成本最低,单价通常不是最优,却提供最重要的退出能力。承诺类权益用期限和最低消费换取较低费率;资源预留可能绑定服务、实例族、区域或规格,灵活性通常低于消费型承诺。Spot 使用云平台可回收容量,价格较低,但可用性与存活时间都不能作为业务保证。
同一个“预留”名称在不同云平台上可能表示计费权益、容量保留或两者组合。Azure 官方明确说明 Reservations 是计费折扣,不改变资源运行状态;AWS Savings Plans 的核心对象是承诺消费,而不是一组永久属于客户的实例;Google Cloud CUD 还要继续区分 spend-based 与 resource-based。采购单必须保存产品类型、权益 scope、匹配维度和容量保证语义,不能只保存“买了多少台”。
组合容量通常分成四层:
| 层 | 承担的需求 | 核心证据 | 主要风险 |
|---|---|---|---|
| 稳定预留层 | 长期不变且需要确定容量的基线 | 规格、区域、可用区和容量保证 | 锁定错误形态 |
| 灵活承诺层 | 稳定消费、形态可能变化的基线 | 每小时 eligible spend 与权益匹配 | 承诺闲置 |
| Spot 层 | 可重试、可切片、可检查点的弹性任务 | 中断率、恢复时间和重算成本 | 集中回收与容量枯竭 |
| 按需安全垫 | 波峰、迁移、故障和退出窗口 | 峰值缺口与恢复 SLO | 单价较高 |
先做 Rightsizing,再决定承诺额度。把浪费打折仍然是浪费;资源请求、节点容量和弹性策略的证据应沿用 Kubernetes 容量建模、余量与 Rightsizing,不要在采购模型里重新推导调度器和伸缩器行为。
覆盖率和利用率回答不同问题
覆盖率衡量有多少合格用量获得了承诺权益:
coverage = covered eligible usage / total eligible usage利用率衡量已购买承诺有多少真正被合格用量消耗:
utilization = applied commitment / purchased commitment覆盖率低可能意味着承诺买少了,也可能是工作负载变形后不再匹配;利用率低则直接说明已经支付的权益被浪费。二者不能相互替代。把 coverage 追到 100% 往往会在低谷制造闲置,把 utilization 追到 100% 也可能只覆盖极小基线,放弃了可实现的稳定节省。
组合决策还需要三个金额:
realized savings = on_demand_equivalent - effective_cost
unused commitment loss = purchased_commitment - applied_commitment
spot net benefit = on_demand_equivalent - spot_cost - retry_cost - recovery_capacity_costeffective_cost 应使用摊销后的权益成本,并保留未使用承诺。只把享受折扣的用量计入成本,会把闲置权益从报表里删除。摊销、币种和时间窗口应沿用家族内的定价口径,不在采购台账里另造一套金额事实。
从账单和运行证据建立候选基线
至少收集多个完整业务周期的小时级数据,保留业务低谷、发布窗口、故障切流和季节峰值。输入分成三组:
账单事实:eligible usage、on-demand equivalent、applied benefit、unused commitment、scope、服务、区域与规格。运行事实:请求量、队列深度、CPU/内存请求、节点数、批任务完成量、SLO 和故障容量。变更事实:迁移计划、实例族升级、区域调整、产品下线、合同期限和退出窗口。
一份可审计的候选策略可以存入仓库:
policyId: compute-portfolio
version: "v3"
chargeBasis: EffectiveCost
window: rolling-business-cycles
scope:
billingAccounts: ["<billing-account>"]
services: ["compute"]
layers:
reservation:
maxCoverageRatio: 0.45
requiredUtilizationRatio: 0.95
dimensions: [service, region, instanceFamily]
flexibleCommitment:
maxCoverageRatio: 0.25
requiredUtilizationRatio: 0.90
spot:
allowedWorkloadClasses: [batch-retryable, ci-worker, stateless-worker]
minOnDemandFloorRatio: 0.20
maxInterruptionLossRatio: 0.03
recoverySloSeconds: 600
guardrails:
excludeMigrationCandidates: true
requireRightsizingEvidence: true
requireFinanceApproval: true
requireExitAssessment: true这些比例不是通用答案,而是策略输入。每次变更都要记录推导数据集、敏感性分析、审批人和生效窗口。策略解析器必须拒绝比例和超过 1、Spot 白名单为空却配置 Spot 比例、没有按需安全垫或没有退出评估的版本。
正向实验:从小时基线算出安全承诺
下面的 DuckDB 实验用十二个语义小时模拟稳定基线。保存为 commitment-selection.sql,然后执行 duckdb < commitment-selection.sql:
WITH hourly(hour_id, eligible_units) AS (
VALUES
('T+01', 100), ('T+02', 102), ('T+03', 98), ('T+04', 105),
('T+05', 160), ('T+06', 172), ('T+07', 108), ('T+08', 101),
('T+09', 97), ('T+10', 104), ('T+11', 165), ('T+12', 99)
), candidate AS (
SELECT 90::DECIMAL(18,2) AS committed_units
), scored AS (
SELECT hour_id,
eligible_units,
LEAST(eligible_units, committed_units) AS applied_units,
committed_units - LEAST(eligible_units, committed_units) AS unused_units,
eligible_units - LEAST(eligible_units, committed_units) AS uncovered_units
FROM hourly CROSS JOIN candidate
)
SELECT
ROUND(SUM(applied_units) / SUM(eligible_units), 4) AS coverage,
ROUND(SUM(applied_units) / SUM(applied_units + unused_units), 4) AS utilization,
MAX(uncovered_units) AS max_hourly_burst,
SUM(unused_units) AS unused_commitment
FROM scored;预期得到 utilization = 1.0000、unused_commitment = 0,覆盖率低于 1,最大波峰仍由按需或可中断容量承担。这说明候选值覆盖了稳定地板,而没有为了追逐高覆盖率购买峰值。
再把费率和恢复代价放进同一模型。假设按需单位成本为 1,承诺单位成本为 0.72,Spot 单位成本为 0.35,但每个 Spot 单位还产生 0.08 的预期重算与恢复成本:
SELECT
90 * 0.72 AS commitment_cost,
30 * (0.35 + 0.08) AS spot_effective_cost,
20 * 1.00 AS on_demand_floor_cost,
90 * 0.72 + 30 * 0.43 + 20 AS portfolio_cost,
140 * 1.00 AS on_demand_equivalent;预期组合成本为 97.7,按需等价成本为 140。这只是候选场景,不是采购报价;真实分析必须使用组织账单的有效费率和合同口径。
反向实验:高折扣怎样制造负节省
把承诺从 90 提高到 150,再让业务迁移后的稳定用量降到 85。即使承诺费率更低,闲置仍会吞掉收益:
WITH scenario AS (
SELECT
85::DECIMAL(18,2) AS eligible_units,
150::DECIMAL(18,2) AS committed_units,
1.00::DECIMAL(18,2) AS on_demand_rate,
0.65::DECIMAL(18,2) AS commitment_rate
)
SELECT
eligible_units / committed_units AS utilization,
committed_units - eligible_units AS unused_units,
eligible_units * on_demand_rate AS on_demand_cost,
committed_units * commitment_rate AS commitment_cost,
eligible_units * on_demand_rate - committed_units * commitment_rate AS realized_savings
FROM scenario;预期利用率约为 0.5667,未用承诺为 65,realized_savings = -12.5。折扣率从视觉上更高,实际却比按需多花 12.5。门禁应阻断低于利用率阈值、迁移计划未评估或压力测试只覆盖平均值的采购单。
Spot 的反例则故意放大中断重算:
SELECT
40 * 0.35 AS spot_charge,
40 * 0.60 AS retry_and_recovery,
40 * 1.00 AS on_demand_equivalent,
40 * 1.00 - 40 * (0.35 + 0.60) AS net_benefit;net_benefit 只剩 2。若再计入超时赔付或人工响应,Spot 已没有经济优势。不能只用实例账单计算 Spot 节省,任务重试、检查点存储、按需兜底和 SLO 损失都属于决策成本。
Spot 必须先通过可中断性验收
适合 Spot 的工作负载应具备幂等重试、细粒度切片、外部持久化、检查点、跨规格与跨故障域调度能力。状态只保存在本地盘、不能重放的消息消费者、同步数据库节点、严格尾延迟在线链路和紧耦合并行任务通常不应直接进入 Spot 池。
不同平台的通知窗口和保证并不相同。AWS EC2 Spot interruption notice 通常在中断前提供两分钟通知,但休眠行为有例外;Azure Spot VM 没有 SLA,并可能在收到 30 秒通知后被驱逐;Google Cloud Spot VM 也不属于 Compute Engine SLA,并要求工作负载能够处理抢占。应用不能把通知当作一定到达的事务消息。
Kubernetes 中的节点选择、污点容忍、PDB、优先级、drain 和节点生命周期由 节点启动、排空与整合 负责。成本策略只消费这些运行证据:中断事件数、任务恢复时间、丢失工作量、按需补位量和业务 SLO,不重写调度配置。
验收至少包括:
正常完成一次可检查点任务,保存完成量与成本基线。注入一次可控中断,证明通知处理不是唯一恢复路径。让整个 Spot 池暂时不可用,证明按需地板能维持最低业务能力。
验证恢复任务不会重复提交外部副作用。清理测试节点后核对磁盘、IP、快照、队列和临时凭证没有残留费用。
采购决策是一项受控变更
采购者需要账单购买权限,分析者只需要读取摊销成本、用量与推荐数据。业务 owner 提交稳定性、迁移和 SLO 证据;平台 owner 证明容量形态与中断恢复;FinOps owner 维护模型;财务与采购审批期限、付款和合同。单个身份不应同时生成推荐、购买权益、修改 scope 并批准会计分摊。
真实账号、合同折扣、私有费率、资源 ID 和采购订单属于敏感数据。分析仓库使用脱敏账户键和受控费率视图,导出文件设置 TTL,查询、下载、购买、交换、scope 变更和自动续订都进入审计。CI 中只能验证策略 schema 和匿名场景,不放云账单 token 或合同附件。
采购前证据包至少包含:
candidate id + policy version
data watermark + eligible scope
rightsizing evidence + migration exclusions
coverage/utilization sensitivity curve
break-even and downside scenario
spot interruption and recovery evidence
on-demand safety floor
term, payment, renewal and exit constraints
approvals + effective windowAzure 官方建议在购买新权益前先 Rightsize,并区分稳定配置适合 Reservation、动态形态适合 Savings Plan;同时,Savings Plan 不能像 Reservation 那样取消或交换。这类退出约束必须在审批前进入决策记录,而不是采购后才从产品页面发现。
持续治理关注组合漂移
每小时或每天计算 coverage、utilization、unused commitment、on-demand spill、Spot interruption loss 和恢复 SLO;每个业务周期复核实例族、区域、服务和 owner 变化。利用率下降先判断是用量下降、权益匹配失败、scope 漂移还是账单延迟,不能直接购买更多权益修复低覆盖。
容量模型应保留 P50、P75、P90 等候选地板及其下行风险。采购只覆盖在悲观场景仍可消耗的稳定部分;计划迁移、架构改造、产品下线和未验证增长不进入长期承诺。自动续订默认需要重新审批,不能因为上一期利用率高就绕过新一轮迁移检查。
常见故障可沿证据分层定位:
| 现象 | 优先检查 | 可能原因 | 处置 |
|---|---|---|---|
| 利用率骤降 | scope、规格、区域、eligible meter | 工作负载迁移或权益匹配失败 | 修正 scope,评估交换或停止续订 |
| 覆盖率下降但利用率高 | 用量增长、按需 spill | 稳定基线增长或短期波峰 | 区分持久增长与季节波峰 |
| Spot 账单低但总成本升高 | 重试、恢复、临时盘和按需补位 | 中断损失未计入 | 降低 Spot 比例,改造检查点 |
| 推荐量大幅波动 | 数据水位、异常周期、费率版本 | 不完整窗口或模型漂移 | 冻结采购,重跑历史场景 |
| 采购后归属争议 | 摊销口径、共享政策、owner 快照 | 权益费用与受益方脱节 | 使用冻结批次重算 showback |
回滚、升级和退出不能等到到期前
策略升级先以 shadow 模式重算相同账单窗口,对比每种权益的覆盖、利用、净节省和受益 owner。超过批准阈值时停止发布,保存新旧策略、数据水位和差异原因。策略回滚只改变后续推荐,不得伪造已经购买权益能够撤销;已有合同通过 scope 调整、交换、转用、转售或停止续订等平台允许路径处理。
Spot 扩容回滚先冻结新增可中断容量,再把关键工作负载迁回按需地板,确认队列、检查点和外部副作用收敛后清理节点池。直接删除 Spot 池可能让持久请求、自动伸缩对象、磁盘和队列继续创建资源。
退出某个云平台或成本工具时,导出权益库存、购买订单、付款计划、匹配规则、摊销明细、利用记录、scope 变更、自动续订状态和审计日志。撤销购买与账单读取身份,删除临时分析集和导出文件,并用后续账单证明没有新承诺、没有失去 owner 的残留费用。架构师真正交付的是一套在增长、收缩和中断中都能解释的容量组合,而不是一张高折扣采购清单。
