57.4 FinOps 实践
一句话
FinOps 的产出不是“省了多少钱”,而是**“每个业务单位花了多少钱、为什么”**:先让成本可见(标签 + 分摊),再让成本可比(单位经济),最后才是优化(rightsizing / 承诺折扣 / 存储分层)。
三步闭环
| 步 | 做什么 | 产出 |
|---|---|---|
| 可见 | 资源打标签(业务/环境/负责人),账单按标签分摊 | 每个业务线的真实成本 |
| 可比 | 单位经济:每次请求/每单/每用户的成本 | “这个功能值不值”的判断依据 |
| 优化 | rightsizing、承诺折扣、存储分层、闲置回收 | 降本清单 + 预算 |
🔑 顺序不能反:没有可见性就优化,等于蒙眼砍预算——砍掉的可能是核心链路,留下的却是闲置资源。
代码:单位经济与三把刀
package main
import "fmt"
type cost struct {
name string
amount float64 // 月成本
}
func main() {
// 一个月度账单(示意)
bill := []cost{
{"计算(EC2/K8s)", 120_000},
{"存储", 60_000},
{"数据库", 40_000},
{"网络/CDN", 30_000},
{"可观测性", 20_000},
}
total := 0.0
for _, c := range bill {
total += c.amount
}
const orders = 500_000.0
fmt.Printf("月成本 %.0f,月订单 %.0f → 单位成本 %.3f/单\n\n", total, orders, total/orders)
// 三把刀:作用在同一项上的手段要“按顺序作用在剩余成本上”,不能相加
computeBase := 120_000.0
computeCuts := []struct {
name string
ratio float64
}{
{"rightsizing(降配)", 0.30},
{"承诺折扣(RI/SP)", 0.40},
{"闲置回收", 0.05},
}
fmt.Printf("%-26s %-16s %-10s %-10s %s\n", "手段", "作用项", "可省比例", "月省", "剩余基数")
computeSaving := 0.0
base := computeBase
for _, c := range computeCuts {
s := base * c.ratio
computeSaving += s
base -= s
fmt.Printf("%-26s %-16s %-10.0f%% %-10.0f %.0f\n", c.name, "计算", c.ratio*100, s, base)
}
storageSaving := 60_000.0 * 0.50
obsSaving := 20_000.0 * 0.40
fmt.Printf("%-26s %-16s %-10.0f%% %-10.0f %.0f\n", "存储分层", "存储", 50.0, storageSaving, 60_000.0-storageSaving)
fmt.Printf("%-26s %-16s %-10.0f%% %-10.0f %.0f\n", "日志采样与保留期", "可观测性", 40.0, obsSaving, 20_000.0-obsSaving)
saving := computeSaving + storageSaving + obsSaving
naive := computeBase*(0.30+0.40+0.05) + storageSaving + obsSaving
fmt.Printf("\n按顺序作用(正确):省 %.0f(%.1f%%),优化后单位成本 %.3f/单\n",
saving, saving/total*100, (total-saving)/orders)
fmt.Printf("把比例直接相加(错误):省 %.0f —— 高估了 %.0f\n", naive, naive-saving)
fmt.Println("\n=== 注意:三把刀有重叠,不能简单相加 ===")
fmt.Println("rightsizing 之后再用 RI,折扣基数变小;存储分层后预留容量也要重算")
}
本机实测(macOS,Apple M1,Go 1.27):
月成本 270000,月订单 500000 → 单位成本 0.540/单
手段 作用项 可省比例 月省 剩余基数
rightsizing(降配) 计算 30 % 36000 84000
承诺折扣(RI/SP) 计算 40 % 33600 50400
闲置回收 计算 5 % 2520 47880
存储分层 存储 50 % 30000 30000
日志采样与保留期 可观测性 40 % 8000 12000
按顺序作用(正确):省 110120(40.8%),优化后单位成本 0.320/单
把比例直接相加(错误):省 128000 —— 高估了 17880
=== 注意:三把刀有重叠,不能简单相加 ===
rightsizing 之后再用 RI,折扣基数变小;存储分层后预留容量也要重算
读数:
| 手段 | 作用项 | 可省比例 | 说明 |
|---|---|---|---|
| rightsizing | 计算 | 30% | 把长期低利用率的实例降配 |
| 承诺折扣 | 计算 | 40% | 只对“稳定负载”买预留 |
| 存储分层 | 存储 | 50% | 冷数据下沉(46.6) |
| 闲置回收 | 计算 | 5% | 未挂载盘、空闲实例、僵尸负载 |
| 日志采样 | 可观测性 | 40% | 保留期与采样率 |
⚠️ 这几项的比例不能直接相加:rightsizing 降了基数后,RI 的折扣金额随之变小;存储分层后预留容量也要重算。本节实测:按顺序作用省 110,120(40.8%),把比例直接相加算出来是 128,000(47.4%)——高估 17,880。预算按前者做,后者只配叫“上限估算”。
成本可见性的最小要求
| 要求 | 做法 |
|---|---|
| 每笔资源有主 | 标签:team、env、service、owner |
| 账单能分摊 | 按标签聚合,共享资源(网络/DB)按用量分摊 |
| 预算有告警 | 月度预算的 80%/100%/120% 三档 |
| 异常能定位 | 日环比突增 > 30% 自动告警,附 Top 变化项 |
反模式
| 反模式 | 后果 |
|---|---|
| 没有标签就谈优化 | 不知道省的是谁的钱、会不会伤业务 |
| 只看总账单,不看单位成本 | 业务翻倍、成本翻倍被当成“正常” |
| 为省小钱砍掉可观测性 | 故障定位变慢,损失远大于省下的钱 |
| 一刀切削峰 | 大促时容量不足,损失更大 |
| 买了 RI 却持续降配 | 承诺用不完,反而浪费 |
| 成本优化一次性运动 | 三个月后回到原点,没有机制 |
自检
Q1 为什么“单位成本”比“总成本”更适合做 FinOps 的北极星?
▸ 答案:因为总成本会随业务增长自然上升,无法判断“效率是否变好”。单位成本(每单/每千次请求/每用户)把规模因素除掉:业务翻倍、单位成本不变,说明效率持平;单位成本下降,说明优化真实有效。它也能直接支撑定价与毛利判断。
Q2 为什么“rightsizing 30% + RI 40%”不能简单相加成 70%?
▸ 答案:因为两者作用在同一个基数上,且有先后依赖。先 rightsizing 把计算成本从 120k 降到 84k,RI 的 40% 只能作用在 84k 上(省 33.6k),而不是原来的 48k。正确算法是“按顺序重算账单”,或对每一项用“优化后的成本”作基数。任何“百分比相加”的降本预测都会高估。
Q3 一个团队要砍 30% 云成本,你会先看哪三样?
▸ 答案:① 闲置与低利用率(未挂载盘、CPU < 10% 的实例、长期无人访问的存储)——这是纯浪费,砍了不影响业务;② 存储分层与保留期(冷数据下沉、日志采样)——影响面小、收益确定;③ 承诺折扣与规格匹配(稳定负载买 RI、按实际用量选规格)。最后才动“容量与冗余”,因为那会直接影响可用性。
Q4 为什么账单优化通常从 “闲置资源” 开始?
▸ 答案:因为闲置资源的优化收益确定、风险最低:未挂载的云盘、闲置的负载均衡、长期 0 请求的服务、开发环境整月开机——删掉不影响业务,收益立刻体现在账单上。相比之下 “换实例规格/改架构” 有风险、需要验证,应放在后面。
Q5 为什么用 “单位成本” 而不是 “总成本” 做决策?
▸ 答案:因为总成本会随业务增长自然上升,看不出效率;单位成本(每千次请求成本、每单成本、每 GB 处理成本)才能回答 “我们变贵了还是变高效了”。FinOps 的核心指标是单位成本随规模下降(规模效应),而不是 “总账单变小”。
关联
- 前置:57.2 容量模型、39.1 成本模型与单位经济
- 并列:39.5 FinOps 与账单治理(待补)、57.3 冗余系数
- 下游:46.6 数据生命周期、39.6 成本驱动的架构决策(待补)
- 待补:39.5 FinOps 与账单治理、39.6 成本驱动的架构决策(未写,无链接)