云成本治理最难的部分,往往不是生成账单报表,而是让工程团队真正采取行动。法国电信企业 Orange 的做法很直接:暂时放下交付待办,把专门的一天留给云成本清理;资深成员现场指导,排行榜展示成果,业务赞助者当天就能看到节省效果。
这些被称为 FinOps Clean Days 的活动,与游戏化黑客松和持续运营的实践社区结合后,为 Orange 超过 100 人的 FinOps 社区带来了高于 70 的内部净推荐值。更值得关注的不是活动形式本身,而是它揭示了一条可复用的路径:FinOps 要先成为组织行为,再由 AI Agent 将这种行为扩展到更多团队。
为什么一张成本报表通常改变不了行为
在持续部署的敏捷团队中,成本优化天然处于劣势。产品需求、故障、技术债和交付期限都比“检查闲置资源”更紧迫。即使工程师知道某个环境可能存在浪费,这项工作也很容易被继续推回 backlog。
Orange 的 Clean Days 改变了三个条件:
- 时间受到保护:成本优化不再与正常迭代争抢零散时间。
- 工作具有协作性:新成员可以跟随有经验的实践者边做边学。
- 结果公开可见:排行榜、奖励和当天可展示的成果形成即时反馈。
这也符合组织变革常见的四个支点:
| 变革支点 | Clean Days 中的体现 | Agent 可以如何增强 |
|---|---|---|
| 理解与认同 | 分享账单变化、优化案例和支出来源 | 在日常工具中推送与团队直接相关的成本解释 |
| 正式机制 | 预留活动时间,建立固定社区和沟通渠道 | 自动生成任务、审批记录和治理报告 |
| 榜样作用 | 排行榜让优秀实践和成果变得可见 | 识别可复用的优化,并推荐给其他团队 |
| 技能与机会 | 资深成员现场指导新人 | 提供上下文说明、修复步骤和待审核变更 |
关键点是:排行榜并不是为了把 FinOps 变成一次竞赛,而是让原本不可见的行为变得可见。Agent 也不应该只是增加一个聊天入口,而应该减少从“发现问题”到“完成修改”的摩擦。
Agent 应该填补哪一种断点
当 FinOps 社区扩大到上百人,而企业拥有数千名工程师时,中心团队不可能直接服务每个人。此时可以沿着 FinOps 生命周期寻找参与度下降的位置,而不是一开始就追求全自动化。
认知断点:团队不知道自己的影响
可以部署只读的洞察 Agent,将成本、环比变化和异常资源推送到团队已有的聊天工具、工单系统或开发者门户。通知必须能回答“这与我有什么关系”,而不只是发送全公司账单。
带宽断点:团队知道问题,但没有时间处理
修复型 Agent 可以把优化建议转换成可审核的变更,例如:
- 调整非生产环境的实例规格;
- 为临时环境补充自动关闭策略;
- 删除已经确认无归属的存储卷;
- 生成基础设施即代码的合并请求,而不是直接修改线上资源。
“准备好合并的变更”比“这里可能节省 20%”更容易进入工程流程。
复杂度断点:报告和归属需要大量手工工作
编排型 Agent 可以收集账单、标签、资源所有者和历史工单,生成统一报告。它适合处理机械但耗时的工作,但最终结论仍应保留数据来源,避免让不可解释的摘要成为财务依据。
可以这样实践:先做一个只读成本洞察 Agent
下面是一个可直接改造的最小示例。它从 Google Cloud Billing 导出的 BigQuery 表中读取最近几天的项目净成本,然后发送到支持 {"text": "..."} 请求格式的团队 Webhook。
这不是对 Orange 内部实现的复刻,而是一种低风险起步方式。运行前需要满足以下假设:
- 已将 Cloud Billing 数据导出到 BigQuery;
- 执行身份拥有目标数据集的只读权限和 BigQuery Job 执行权限;
- 团队 Webhook 接受 JSON POST 请求;
- 将示例中的表名替换为自己的完整表名。
创建 requirements.txt:
google-cloud-bigquery==3.25.0
requests==2.32.3
创建 cost_insight_agent.py:
import os
import requests
from google.cloud import bigquery
BILLING_TABLE = os.environ["BILLING_TABLE"]
WEBHOOK_URL = os.environ["WEBHOOK_URL"]
LOOKBACK_DAYS = int(os.getenv("LOOKBACK_DAYS", "7"))
TOP_N = int(os.getenv("TOP_N", "10"))
def load_costs():
client = bigquery.Client()
query = f"""
SELECT
COALESCE(project.id, 'unassigned') AS project_id,
ROUND(
SUM(
cost + IFNULL(
(SELECT SUM(credit.amount) FROM UNNEST(credits) AS credit),
0
)
),
2
) AS net_cost
FROM `{BILLING_TABLE}`
WHERE usage_start_time >= TIMESTAMP_SUB(
CURRENT_TIMESTAMP(), INTERVAL @days DAY
)
GROUP BY project_id
ORDER BY net_cost DESC
LIMIT @top_n
"""
config = bigquery.QueryJobConfig(
query_parameters=[
bigquery.ScalarQueryParameter("days", "INT64", LOOKBACK_DAYS),
bigquery.ScalarQueryParameter("top_n", "INT64", TOP_N),
]
)
return list(client.query(query, job_config=config).result())
def build_message(rows):
lines = [f"Cloud cost insight: last {LOOKBACK_DAYS} days"]
if not rows:
lines.append("No billing records found.")
else:
for index, row in enumerate(rows, start=1):
lines.append(f"{index}. {row.project_id}: {row.net_cost:.2f}")
lines.extend([
"",
"Read-only report: verify ownership and workload context before remediation.",
])
return "\n".join(lines)
def main():
message = build_message(load_costs())
response = requests.post(
WEBHOOK_URL,
json={"text": message},
timeout=15,
)
response.raise_for_status()
print(message)
if __name__ == "__main__":
main()
安装并运行:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
export BILLING_TABLE="my-billing-project.billing_export.gcp_billing_export_v1_XXXXXX"
export WEBHOOK_URL="https://example.internal/hooks/finops"
export LOOKBACK_DAYS="7"
export TOP_N="10"
# 本地开发时可以使用 gcloud 的应用默认凭据;生产环境应使用专用服务账号。
gcloud auth application-default login
python cost_insight_agent.py
这个示例故意不使用大模型,也不修改资源。它先验证三个更基础的问题:数据是否可信、通知是否送达正确团队、团队是否会根据通知采取行动。确认这些环节有效后,再考虑让 Agent 解释异常、创建工单或生成合并请求。
可以进一步把脚本部署为定时任务,并加入成本环比、标签缺失和资源所有者映射。若要使用 LLM 生成摘要,应先删除账号标识、合同价格等敏感字段,并让模型输出附带查询时间、数据范围和原始记录链接。
从建议到执行:自治能力要逐级开放
直接执行云资源修改可能带来停机、数据丢失和合规风险。更稳妥的路线是按信任程度逐级开放能力:
finops_agent_policy:
stage_1_observe:
permissions:
- billing.read
- asset_inventory.read
actions:
- send_insight
approval_required: false
stage_2_propose:
permissions:
- repository.pull_request.create
- ticket.create
actions:
- propose_rightsizing
- generate_iac_change
approval_required: true
stage_3_execute:
permissions:
- approved_resource_update
actions:
- apply_preapproved_change
approval_required: true
safeguards:
- maintenance_window
- rollback_plan
- maximum_daily_savings_scope
- audit_log
这里的 YAML 是治理策略示例,不对应某个现成产品的固定格式。实践时应将它映射到 IAM、代码仓库保护规则、审批系统和审计日志。
无代码或低代码团队可以通过企业级 Agent 构建工具快速验证只读场景;需要精细控制的开发团队则可以选择支持代码框架、身份治理和工具调用控制的平台。无论采用哪种产品,权限边界都应该由确定性的策略控制,而不是交给模型自己判断。
值得复制的是顺序,而不只是工具
Orange 的经验说明,FinOps 是业务变革问题,也是工程效率问题。Clean Days、实践社区和游戏化机制先建立了共同语言、技能与责任感,Agent 才有机会把这些能力送到中心团队无法直接触达的人群。
落地时可以用下面的检查清单控制节奏:
- 是否为优化工作提供了不会被 sprint 挤占的时间?
- 每条成本洞察是否能定位到团队、项目和负责人?
- 建议是否包含可执行步骤,而不只是金额和趋势?
- 只读 Agent 的数据准确率和团队采纳率是否已经得到验证?
- 自动修改前是否具备审批、回滚、限额和审计机制?
- 是否同时衡量节省金额、工程投入和业务风险?
不要从“Agent 能自动关闭多少资源”开始,而要从“团队为什么没有采取行动”开始。文化建立责任,流程保护时间,Agent 降低摩擦。三者按这个顺序组合,FinOps 才可能真正成为每个人的工作。