4. 预算、预警与配额治理
在 Google Cloud 中,成本失控往往不是“突然多花了一笔钱”,而是缺少一条从“预算阈值触发”到“自动响应”的闭环。预算本身只是监控工具,它不会阻止资源创建;真正能止血的是把预算提醒接入 Pub/Sub,再由 Cloud Run Functions 或 Cloud Run 服务执行配额调整、标签校验、资源停机等动作。本节围绕这条治理链路展开,重点讲清楚每个环节的配置对象、参数含义和判断依据。
一、预算的三种范围与阈值设计
Cloud Billing 预算支持三种范围:Billing account 级(覆盖该结算账号下所有项目)、Project 级(单项目)、Folder 级(组织内文件夹聚合)。生产环境建议至少配置两层:结算账号级做总闸门,项目级做责任到人。预算金额可以设为固定值,也可以基于上一周期实际支出按百分比滚动计算。
阈值规则是预算的核心。每条规则包含“触发百分比”和“触发基准”。基准有两种:Forecasted(预测值)和 Actual(实际值)。例如一条规则设为“Actual 达到 80%”,表示当月实际支出达到预算的 80% 时触发;另一条设为“Forecasted 达到 100%”,表示按当前消费速率预测月底会超支时提前告警。建议配置 50%、80%、100%、120% 四档,前两档用于提醒,后两档用于自动化响应。
二、从预算到 Pub/Sub:通知链路
预算的 Pub/Sub 通知不是“发一条消息”那么简单,它需要先创建主题、授予权限、再在预算中绑定。关键权限是让 Cloud Billing 的服务账号具备向该主题发布消息的能力。配置顺序如下:
# 1. 创建主题
gcloud pubsub topics create budget-alerts
# 2. 允许 Cloud Billing 发布消息
gcloud pubsub topics add-iam-policy-binding budget-alerts \
--member="serviceAccount:billing-budget-alert@system.gserviceaccount.com" \
--role="roles/pubsub.publisher"
# 3. 在预算中绑定该主题(控制台或 API)
# 预算 -> Notifications -> Connect a Pub/Sub topic
绑定后,每次阈值触发都会向主题推送一条 JSON 消息,字段包括 budgetDisplayName、costAmount、budgetAmount、alertThresholdExceeded、currencyCode 等。下游函数据此判断“是提醒还是执行”。
三、自动化响应的三种典型动作
收到 Pub/Sub 消息后,响应函数通常做三类动作:
- 通知类:把消息转发到 Slack、钉钉或工单系统,附带项目 ID、当前花费和阈值,便于人工介入。
- 限制类:调用 Cloud Quotas API 降低特定配额,例如把某项目的
compute.googleapis.com/cpus从 100 降到 20,阻止继续扩容。 - 停机类:对非生产项目批量停止 Compute Engine 实例或删除临时资源,适用于沙箱、测试环境。
下面这张图展示了从预算触发到自动化响应的完整信号链,包含阈值判断、Pub/Sub 分发和三类响应分支。
四、配额限制:比预算更硬的约束
预算提醒是“事后感知”,配额才是“事前约束”。Google Cloud 的配额分为速率配额(如每秒 API 调用数)和分配配额(如某区域 CPU 总数)。在成本治理中,最常用的是对 compute.googleapis.com/cpus、compute.googleapis.com/instances、run.googleapis.com/container_instances 等分配配额设置上限。
配额调整可以通过控制台“IAM 与管理 → 配额”页面操作,也可以用 Cloud Quotas API 自动化。下面是一个用 API 降低项目 CPU 配额的示例:
# 查询当前配额
gcloud alpha quotas info describe compute.googleapis.com/cpus \
--project=my-sandbox --region=asia-east1
# 提交降配请求(示例值)
gcloud alpha quotas update compute.googleapis.com/cpus \
--project=my-sandbox --region=asia-east1 \
--value=20 --preferred-value=20
需要注意:配额调整不是瞬时生效,部分配额需要审批。因此自动化响应中应把“降配”设计为幂等操作,并在日志中记录请求 ID,便于追踪是否真正生效。
五、治理流程的闭环设计
把上述环节串起来,一个可落地的预算超支治理流程包含五个阶段:预算定义 → 阈值触发 → Pub/Sub 分发 → 分级响应 → 复盘调参。其中“分级响应”是核心:低阈值只通知,中阈值降配额,高阈值停机。每次响应后,函数应把结果写入 Cloud Logging,并可选地更新预算金额或阈值,避免同一周期内反复触发。
env: sandbox 或 env: test 标签,并通过标签过滤避免误停生产资源。建议先在 dry-run 模式下运行函数,只记录“将要执行的动作”而不真正调用停机 API。六、一个可参考的响应函数判断逻辑
下面用伪代码展示函数如何根据 Pub/Sub 消息中的 alertThresholdExceeded 字段选择动作。该字段是一个 0~1 之间的小数,例如 0.8 表示达到 80%。
def handle_budget_alert(event, context):
data = json.loads(base64.b64decode(event['data']))
threshold = data.get('alertThresholdExceeded', 0)
project = data.get('projectId')
cost = data.get('costAmount')
budget = data.get('budgetAmount')
if threshold >= 1.2:
stop_non_prod_instances(project) # 停机
elif threshold >= 1.0:
reduce_cpu_quota(project, 20) # 降配额
elif threshold >= 0.8:
notify_channel(project, cost, budget) # 预警
else:
log_only(project, cost) # 仅记录
这段逻辑的关键在于:阈值判断必须放在函数内部,而不是依赖预算侧的多条规则分别触发不同主题。统一入口、统一判断,才能保证响应顺序和幂等性。实际部署时,建议把 stop_non_prod_instances 和 reduce_cpu_quota 拆成独立函数,通过 Pub/Sub 的多个订阅分别消费,避免单点故障。
最后,治理流程不是一次配置就结束。每月应复盘一次:哪些阈值被频繁触发、哪些响应动作真正生效、预算金额是否需要调整。把复盘结果回写到预算和配额配置中,才能让这套机制持续贴合业务实际。