很多团队第一次真正重视云成本,不是因为做了年度预算,而是因为某天早上收到一张异常账单:NAT Gateway 流量暴涨、测试环境 GPU 忘记关、日志桶生命周期没配、跨区复制开错区域。问题不是 AWS 没有成本工具,而是只在月底看账单,发现时已经晚了。
这篇文章给出一套"小团队也能落地"的 AWS 成本护栏:用 AWS Budgets 做预算阈值,用 Cost Anomaly Detection 识别异常模式,用 SNS/Lambda/预算动作把告警变成处理流程。目标不是粗暴停服务,而是在费用刚异常时就能发现、定位、收敛并复盘。
本文基于 AWS Billing and Cost Management、AWS Budgets、AWS Cost Anomaly Detection 官方文档整理;具体控制台路径和能力以你账号所在区域、Organizations 设置和最新文档为准。

1. 先设计成本护栏,而不是先写脚本
成本治理容易走两个极端:一种是只看月账单,发现慢;另一种是上来就自动停机,误伤生产。更稳的方案是分层:
- 第一层:预算阈值。比如月预算 80% 预警、100% 升级、120% 必须人工确认。
- 第二层:异常检测。不是看绝对金额,而是看费用是否偏离历史模式。
- 第三层:动作编排。非生产资源可以自动收敛,生产资源先告警和审批。
- 第四层:复盘归因。靠标签、账单报告和成本分类找到具体服务、账号、项目。

2. 基础准备:标签和账单权限
先准备两类东西。
第一类是资源标签。至少建议统一:
text
Project=xxx
Env=prod|staging|dev
Owner=team-or-person
CostCenter=dept-code
AutoShutdown=true|false
第二类是权限。成本工具通常需要 Billing/Cost Explorer/Budgets 相关权限。生产账号里不要把完整 Billing 权限随便给工程师,可以建立只读成本角色,再把告警动作交给一个受控的自动化角色。
一个最小化的自动化思路是:
text
Budgets / Anomaly Detection
↓ SNS Topic
↓ Lambda
↓ 判断 Env、Owner、服务类型
↓ 通知 / 工单 / 非生产收敛动作
3. 配置 AWS Budgets:月预算和日预算都要有
只设月预算不够。比如月预算 300 美元,一个测试实例在第一天就烧掉 80 美元,月底预算仍可能"看起来还没爆",但事故已经发生。
建议至少配两种预算:
月预算
适合管理总盘子。可以按账户、服务、标签、成本类别筛选。
建议阈值:
text
80% -> 通知 Owner 和技术负责人
100% -> 通知负责人 + 财务/运营
120% -> 创建高优先级工单,要求当天复盘
日预算
适合抓突发异常。比如平时每天 10 美元,突然某天到 80 美元,日预算能更早提醒。
建议阈值:
text
实际成本 > 日预算 100% -> 通知
预测成本 > 日预算 150% -> 升级
连续 2 天超过基线 -> 复盘标签和资源清单

4. 配置 Cost Anomaly Detection:让系统识别"不像平时"的费用
Budgets 看阈值,Cost Anomaly Detection 看异常模式。它适合发现这些问题:
- NAT Gateway 或 Data Transfer 突然升高;
- CloudWatch Logs 日志量异常;
- 新开了昂贵机型;
- 某个服务过去几乎不用,今天突然产生大量费用;
- 某个账号或项目突然偏离历史基线。
一个实用配置方式:
text
Monitor type: AWS services 或 Linked account
Alert threshold: 先从较低金额试运行,再按误报调整
Alert recipients: SNS topic + 邮件列表
如果你有多个业务线,建议按账号、标签或 Cost Category 分组,否则所有异常都打到一个告警里,后续很难归因。
5. 用 SNS + Lambda 做响应,不要只发邮件
邮件告警经常被淹没。更可控的方式是把 Budgets 和异常检测通知发到 SNS,再由 Lambda 解析消息。
示例 Lambda 伪代码:
python
import json
def handler(event, context):
for record in event["Records"]:
msg = json.loads(record["Sns"]["Message"])
account = msg.get("account") or msg.get("accountId")
service = msg.get("service") or "unknown"
amount = msg.get("anomalyScore", {}).get("currentScore")
# 真实环境:查询资源标签、Owner、Env,再决定动作
print({
"account": account,
"service": service,
"amount_or_score": amount,
"action": "notify_owner_and_create_ticket"
})
生产环境不要只靠告警消息直接停资源。更稳的做法是让 Lambda 只做三件事:
- 查资源和标签,判断是否属于非生产;
- 通知 Owner,并创建工单;
- 对明确标记
AutoShutdown=true的非生产资源执行收敛。
6. 预算动作可以用,但要先灰度
AWS Budgets 支持预算动作,例如应用 IAM policy、Service Control Policy 或对 EC2/RDS 资源执行动作。这个能力很有用,但也有风险。
建议实践:
- 先在 dev/staging 账号验证;
- 先做通知型动作,再做限制型动作;
- 生产账号只对明确白名单资源启用;
- 所有动作必须可回滚,并保留操作日志;
- 对核心数据库、生产负载、支付链路不要用"一刀切"停机策略。
一个可落地的分级策略:
text
Dev: 超预算后通知 + 自动停止未打保护标签的实例
Staging: 通知 + 人工确认后执行
Prod: 通知 + 工单 + 审批,不自动停核心资源

7. 验证方法:别等真爆账单才知道告警坏了
上线后要验证四件事:
bash
# 1. 检查预算是否存在
aws budgets describe-budgets --account-id <ACCOUNT_ID>
# 2. 检查 SNS Topic 订阅
aws sns list-subscriptions-by-topic --topic-arn <TOPIC_ARN>
# 3. 检查 Lambda 是否有最近调用
aws logs describe-log-groups --log-group-name-prefix /aws/lambda/<FUNCTION_NAME>
# 4. 检查 Cost Explorer 中按服务/标签归因
aws ce get-cost-and-usage \
--time-period Start=2026-07-01,End=2026-07-29 \
--granularity DAILY \
--metrics UnblendedCost \
--group-by Type=DIMENSION,Key=SERVICE
你还应该每月做一次演练:模拟非生产资源异常增长,确认告警能到达、Owner 能识别、工单能创建、动作能回滚。
8. 常见坑
第一,预算只按总账号设置,没有按项目或标签拆分。这样告警来了也不知道谁负责。
第二,标签不规范。资源没有 Owner 和 Env,后续自动化动作就不敢执行。
第三,邮件收件人太多。人越多越没人处理,最好有明确的一线 Owner。
第四,自动停机策略太激进。成本治理不能以业务事故为代价。
第五,只关注 EC2,忽略 NAT Gateway、CloudWatch Logs、跨区流量、快照、对象存储生命周期等隐性费用。
9. 推荐落地顺序
如果你今天就要开始,不要一次做太大:
- 先统一标签;
- 建月预算和日预算;
- 开 Cost Anomaly Detection;
- 用 SNS 发到一个明确负责人;
- Lambda 先只记录和通知;
- 非生产资源再加自动收敛动作;
- 每月复盘 Top 服务和异常账单。
这套方案不保证你的账单永远最低,但能把"月底才发现爆了"变成"当天发现、当天处理、月底复盘"。对小团队来说,这就是最有价值的成本护栏。
如果你需要国际云服务器合规开户流程咨询、AWS/GCP/Azure 实例选型、成本控制与部署运维支持,可以通过平台私信沟通。实名、验证码、支付和合同确认均由客户本人完成。
参考资料:
- AWS Billing and Cost Management User Guide
- AWS Budgets User Guide
- AWS Cost Anomaly Detection Documentation
- AWS Cost Explorer API Reference