成本优化

一次性优化能省 30%,半年后又涨回去了

成本治理必须变成一套持续运行的机制,有人负责、有例会、有指标、有考核,否则一定反弹。

机制四要素

可见性

每个业务线负责人每月都能看到自己的账单构成、环比变化和优化建议清单。看不见就不会管。

责任制

每个成本中心指定 owner,异动超过阈值需要在例会上说明原因。不是问责,是让优化有人推。

自动化

闲置资源扫描、非生产定时启停、未打标拦截、预算告警,能自动的都自动化,不靠人记。

激励

把节省下来的预算部分返还给业务线用于技术投入,比单纯考核降本指标更有效。

月度运营节奏

  1. 每月 1-3 日

    账单结算与报表生成

    上月账单出账,自动生成各业务线成本报表并推送给 owner。

  2. 每月 5 日

    异动分析

    识别环比涨幅超过 15% 的成本项,逐项归因:是业务增长、架构变更还是配置失误。

  3. 每月 8 日

    FinOps 例会

    各业务线 owner 参加,过异动项、过优化建议、认领本月优化任务。控制在 45 分钟内。

  4. 每月 10-25 日

    优化执行

    按认领的任务推进优化,进展在群里同步,遇阻由 FinOps 负责人协调。

  5. 每月 28 日

    效果复盘

    统计本月完成的优化项与实际节省额,更新到累计节省看板。

  6. 每季度末

    承诺折扣复盘

    评估覆盖率与利用率,决定是否加购或调整,并做下季度预算规划。

成本异动自动告警

python cost_anomaly_alert.py
"""成本异动检测与告警。

每天凌晨执行,对比昨日与前 7 天同期的日均成本,
按业务线维度找出异动并推送到企业微信/钉钉。
"""

from __future__ import annotations

import json
import os
from datetime import date, timedelta

import boto3
import urllib3

ce = boto3.client("ce", region_name="us-east-1")   # Cost Explorer 只在 us-east-1
http = urllib3.PoolManager()

WEBHOOK = os.environ["ALERT_WEBHOOK"]
SPIKE_PCT = float(os.environ.get("SPIKE_PCT", "20"))
MIN_DELTA_USD = float(os.environ.get("MIN_DELTA_USD", "50"))


def daily_cost_by_tag(start: date, end: date, tag_key: str = "CostCenter") -> dict[str, dict[str, float]]:
    """返回 {日期: {业务线: 成本}}。"""
    resp = ce.get_cost_and_usage(
        TimePeriod={"Start": start.isoformat(), "End": end.isoformat()},
        Granularity="DAILY",
        Metrics=["UnblendedCost"],
        GroupBy=[{"Type": "TAG", "Key": tag_key}],
    )
    out: dict[str, dict[str, float]] = {}
    for result in resp["ResultsByTime"]:
        day = result["TimePeriod"]["Start"]
        out[day] = {}
        for group in result["Groups"]:
            raw = group["Keys"][0]
            name = raw.split("$", 1)[1] or "__UNTAGGED__"
            out[day][name] = float(group["Metrics"]["UnblendedCost"]["Amount"])
    return out


def detect_spikes() -> list[dict]:
    today = date.today()
    yesterday = today - timedelta(days=1)
    baseline_start = today - timedelta(days=8)

    data = daily_cost_by_tag(baseline_start, today)
    y_key = yesterday.isoformat()
    if y_key not in data:
        return []

    yesterday_cost = data[y_key]
    baseline_days = [d for d in data if d != y_key]

    spikes = []
    for cc, cost in yesterday_cost.items():
        history = [data[d].get(cc, 0.0) for d in baseline_days]
        if not history:
            continue
        avg = sum(history) / len(history)
        if avg <= 0:
            continue
        delta = cost - avg
        pct = 100.0 * delta / avg
        if pct >= SPIKE_PCT and delta >= MIN_DELTA_USD:
            spikes.append({
                "cost_center": cc,
                "yesterday": round(cost, 2),
                "baseline_avg": round(avg, 2),
                "delta": round(delta, 2),
                "pct": round(pct, 1),
            })

    return sorted(spikes, key=lambda s: s["delta"], reverse=True)


def notify(spikes: list[dict]) -> None:
    if not spikes:
        return
    lines = ["## 成本异动提醒",", f"检测日期:{date.today() - timedelta(days=1)}","]
    for s in spikes:
        lines.append(
            f"- **{s['cost_center']}**:${s['yesterday']} "
            f"(7 日均值 ${s['baseline_avg']},↑{s['pct']}%,"
            f"多支出 ${s['delta']})"
        )
    lines += ["", "请对应负责人在今日内确认原因。"]

    payload = {"msgtype": "markdown", "markdown": {"content": "\n".join(lines)}}
    http.request(
        "POST", WEBHOOK,
        body=json.dumps(payload).encode("utf-8"),
        headers={"Content-Type": "application/json"},
    )


def lambda_handler(event, context):  # noqa: ARG001
    spikes = detect_spikes()
    notify(spikes)
    return {"spike_count": len(spikes), "spikes": spikes}

同时设置绝对金额门槛和百分比门槛,避免小金额波动刷屏。开发环境从 $1 涨到 $2 也是 100%,但没人关心。

下一步

把云的复杂度交给我们,你只管做业务

留下需求,沐杉云的解决方案架构师会在一个工作日内联系你,提供免费的现状评估、迁移方案草案与 TCO 测算表。