每个月第一个工作日的上午,我大概率是黑着脸从会议室出来的。不是业务出了什么问题,而是GCP账单又比我记忆中的数字高了一截。这绝不是个别现象——大多数团队在GCP上花的钱,至少有两三成处于“没人说得清为什么花”的状态。GCP成本优化这件事,难点还真不是找不到省钱技巧,而是你根本不知道钱到底花在了哪里。这篇文章会把我在生产环境里实际用过的路径完整整理出来:从看懂计费模型、把账单拆解到项目和标签,到真正能用Spot实例、承诺折扣、定时关机这些手段落地的省钱方案,最后再讲怎么用预算、告警和一套月度体检流程,让成本不反弹。适合刚接手GCP成本管理的工程师,也适合被月度账单吓到、准备系统性省钱的团队。
1. 账单为什么会失控:GCP计费模型里那些容易漏掉的点
很多人一上来就找“优惠”,但我建议先把GCP的计费机制搞明白。这个云平台的计费规则和别的厂商有很不一样的地方,同一个动作,在不同条件下可能是两种价格。你如果不清楚这几条底层逻辑,后面做的所有优化都有可能跑偏。
1.1 按秒计费是优势,但也助长了“不用白不用”的心态
GCP的Compute Engine是秒级计费,1分钟起算,相比按小时计费的老模式,理论上对用户更友好。测试环境开一台机器跑十分钟,成本几乎可以忽略。这个设计本身没问题,但它带来了一个副作用:因为“开机很便宜”,很多人就默认让资源一直在跑,反正跑一天也就几十块钱。然而一台中低配的VM看似单价不高,一个月连续运行下来,累计费用就变成了“一台新设备”级别;规格稍微往上走,一年下来够买好几台。账单往往不是被某一个昂贵操作打爆的,而是被大量“不关机、不过问、不清理”的闲置实例慢慢磨爆的。
按秒计费的另一个隐藏细节是:它只适用于常规的按需虚拟机。你如果创建了GPU实例、TPU节点,或者启用了某些特殊机型,计费粒度并不一样。同样,抢占式实例提前终止后的结算规则,也会因为“是否运行满一分钟”产生差异。实际做法应该是:先给所有计算资源分类,明确哪些是“常驻基数”,哪些是“可容忍中断的弹性负载”,哪些是“用完就该删的临时环境”,然后再决定用什么计费类型。这一步做好了,后面谈优化才有意义。
1.2 不跟着VM走的隐形支出:静态IP、磁盘与快照
比起虚拟机本身的费用,容易被忽略的是那些“不会因为你删除VM就消失”的资源。最典型的就是静态IP——只要你在项目里预留了一个静态IP,但它没有关联到任何正在运行的资源,它就开始计费。我见过不止一个团队,删了服务器忘了释放IP,结果每个月账单上多出一笔不大不小的固定开销,查看账单时还以为是税金。
磁盘和快照是另一个重灾区。GCP上创建VM时默认会带一块启动盘,很多操作习惯是:删除VM时不勾选“同时删除启动盘”,于是越来越多“孤儿磁盘”躺在项目里,每块按GB持续计费。快照更隐蔽,一个每天自动备份的磁盘,如果保留周期设成30天,快照数量会线性累积,而且GCP的快照计费是按实际占用存储空间算的,不是按“原磁盘大小”算。很多时候你只记得“开了备份”,却从没算过快照每个月到底吃掉了多少钱。我的建议是:每季度做一次磁盘和快照清理,把“无人认领”的资源全部列出来,该删就删,该压缩保留周期就压缩。
1.3 流量费用:账单上的“暗雷”
计算和存储毕竟有直观的Dashboard能看到,网络流量则完全处于“看不见摸不着”的状态。GCP的流量计费有几个关键点:同一区域(region)内不同可用区(zone)之间的流量是收费的,跨区域传输更贵,而流出到公网的出口带宽按GB计价,是成本的大头。尤其当你做了多区域高可用部署、读取大量外部数据源、或者向前端提供大文件下载时,网络费用经常会超过计算费用,成为账单里最大的单一项目。
再叠加一个容易忽略的配置:Cloud NAT。它不仅能帮你实现无公网IP出站,还会产生每GB处理费和小时费。很多习惯了NAT网关的团队,跑了一批批短任务,没太在意NAT的计费规则,一个月下来额外多了几百美元。对流量费用,我目前比较有效的做法是:在BigQuery账单里按SKU和区域聚合,专门找出“出口流量”相关的条目,看哪些实例/服务在持续产生高额流量。如果某个服务只是内部调用,却被配置了公网出口,立刻改成Internal通信,效果往往立竿见影。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 别猜了,先把账本打开:Cloud Billing + BigQuery 定位浪费源
我早期做成本优化也走过弯路:一会儿听销售说该买长期折扣,一会儿看博客说Spot实例能省钱,结果凭感觉做了很多动作,月底一看账单还是老样子。后来我才意识到,问题不在于“没有省钱手段”,而在于“我不知道该对哪个部分下手”。所以整个优化过程的第一步,不是改架构,而是把账本打开,搞清楚钱花在哪个服务、哪个项目、哪个团队手上。
2.1 第一步永远是打标签:成本归属的前提
GCP的标签(Labels)机制,官方设计出来就是干这个用的。你可以在项目、实例、磁盘、快照等资源上打键值对标签,比如 env:prod、team:data、cost-center:core。但很多团队上了生产也没认真打标签,导致成本像“一锅粥”一样搅在一起,谁也说不清哪个业务线最烧钱。
打标签这件事,最好在资源创建流程里就强制。借助项目内的Org Policy,可以要求所有新资源必须带必填标签,否则创建请求直接拒绝。历史资源也要找个时间批量补齐。我自己常用的一个笨办法是写一个脚本遍历所有实例,先按名字前缀猜归属,再让负责人确认,最终把标签补齐。这些工作虽然没有“技术含量”,却是成本归因的基础。没有标签,后面所有分析都只能停留在“大概”“可能”“也许”的层面。
2.2 把账单导出到BigQuery,用SQL回答“钱去哪了”
GCP在Cloud Billing里提供了一个我认为价值被严重低估的功能:把详细账单流式导出到BigQuery。开通后,系统每天自动生成一张按行记录的表,每一行对应一条计费明细,包含项目、服务、SKU、用量、价格、标签、区域等维度。有了这张表,你不再需要盯着Console里那几张图表反复猜测,直接可以用SQL问任何问题。
先看一张最基础的查询:按服务聚合成本。
sql复制SELECT
invoice.month AS billing_month,
service.description AS service,
ROUND(SUM(cost), 2) AS total_cost
FROM `your-project.billing_dataset.gcp_billing_export_v1_XXXX`
WHERE invoice.month = '202506'
GROUP BY billing_month, service
ORDER BY total_cost DESC
这是我的“第一视力表”。跑完这条SQL,你立刻就能看到费用前几名是Compute Engine、Cloud Storage还是BigQuery。接下来再下一层,查某个服务的具体SKU,就能定位到“是磁盘贵,还是机器规格贵,还是流量贵”。这套查询能力,比任何第三方成本管理工具都直观,因为它不带任何厂商的“黑盒”逻辑,所有数字都来自GCP自己出的账单。
另外一个很实用的技巧是:利用标签聚合。比如看每个团队当月的成本分摊:
sql复制SELECT
teams.value AS team,
ROUND(SUM(cost), 2) AS total_cost
FROM `your-project.billing_dataset.gcp_billing_export_v1_XXXX`,
UNNEST(labels) AS teams
WHERE teams.key = 'team'
GROUP BY team
ORDER BY total_cost DESC
把成本表发给各团队负责人之前,我一般会先用这条SQL把数据拉出来,让各团队自己认领各自的盘子。一旦负责人看到自己的标签下面挂着具体数字,他们就开始主动做优化了,这比后台设任何告警都管用。
2.3 我每次做成本分析必看的四个视角
账单表里的字段很多,但我不建议一开始就陷入细节。我固定的分析流程是四个视角轮着看,通常15分钟就能得出结论。
第一个是“按天增量”。用 usage_start_time 按天聚合,画出30天成本曲线,突然异常的尖峰往往对应某次业务发布、数据任务或误操作,这个视角能快速定位异常发生的时间点。第二个是“按SKU聚合”。某一天成本突然涨了,先看是哪类SKU在涨——是计算、存储还是网络,缩小排查范围。第三个是“按region聚合”。如果发现某个区域成本异常,而业务并不在该区域,可能是创建了错误区域的资源,或流量走了高价线路。第四个是“按标签聚合”。用于团队归属和业务线归属,账算到人头上。
这四个视角看下来,通常一张“重点优化清单”就出来了:哪些闲置机器可以关、哪些流量可以内网化、哪些项目该买承诺折扣。后面所有动作,都是从这份清单出发的。
3. 降本主力:Spot实例、承诺折扣与“关机大法”
账看清楚了,现在可以谈具体的省钱动作了。这一章是实操的重点,也是我认为GCP成本优化里性价比最高的三块:Spot实例、承诺折扣(CUD)和自动关机。三者覆盖的场景完全不同,不是互斥选择,而是可以叠加使用。
3.1 Spot实例:省一大半的前提是把“会没”当常态
Spot实例是GCP的抢占式资源,报价通常比按需便宜一大截,具体折扣比例取决于机型和当前区域供需,你只需要知道“便宜很多”就够了。代价是:Google随时可能因为资源回收而终止你的实例,所以它天生适合无状态、可重试、能容忍中断的工作负载。
我经常用Spot跑四类任务:批量数据处理、CI/CD构建节点、Kubernetes集群里的无状态Worker、以及夜间的周期任务。在这些场景下,实例被回收最多导致任务重跑,不会有业务损失。配套的做法是:工作负载要支持断点续跑,比如数据任务先写临时目录、完成后原子性搬迁;CI构建要支持从失败的Step重试;K8s里要设置合适的 PodDisruptionBudget,避免Spot节点回收时引起大量Pod同时重建。
容易踩的坑有两个。第一,不要在生产核心数据库或强一致状态服务上用Spot,这不是“赌运气”的事,而是设计上就不该允许主节点随时消失。第二,Spot的价格和容量是波动的,热门的GPU机型经常“一机难求”,你的业务要有在特定区域排不到容量时自动换区域的能力。我自己习惯在启动脚本里加入区域择机逻辑——先尝试最便宜区域,抢不到就换备选区域,而不是死等一个位置。
3.2 承诺折扣:按资源承诺还是按金额承诺,别选错
如果你有一批计算资源是7×24小时稳定运行的,那就属于“常驻基数”,这部分最适合买承诺折扣(Committed Use Discount,CUD)。它本质上是“用长期承诺换单价折扣”:你承诺在1年或3年内持续付费,GCP给你一个比按需低得多的价格。
CUD有两种模式,我做过对比:
| 模式 | 承诺方式 | 适用场景 |
|---|---|---|
| Resource-based | 承诺特定区域内特定机器类型(如某区域n2-standard-8)的vCPU和内存 | 资源规模稳定、区域明确、机型基本不变 |
| Spend-based | 承诺一段时间内的总花费金额,不限具体资源 | 资源类型多、项目杂、不想精细化管理 |
Resource-based的折扣通常更深,但锁定得也死。如果你承诺了某个机型的资源却用不满,剩下的承诺额度就是浪费。Spend-based更灵活,适合Graceful团队——只要账单上总金额够承诺线,具体是什么资源都无所谓。我自己现在的做法是:对核心集群用Resource-based锁一个合理规模,对分散在多个项目里的零散实例用Spend-based兜底。
这里有个很多人都有的误解:买了CUD不代表“全免费”。CUD只覆盖对应资源的计算费用,磁盘、网络、快照等照常按量计费。还有一点,Spot实例不适用于CUD,你在算折扣覆盖率时,要把Spot资源单独摘出来。购买CUD的精准度,取决于你对“常驻基数”的判断。与其拍脑袋买,不如看过去3个月的账单,取最低月份的用量作为承诺基准,这样即使业务收缩,也不至于浪费。
3.3 非生产环境自动关机:最直接、最容易被忽略的省钱操作
在所有优化项里,自动关机的“见效速度”是最快的,几乎没有之一。大部分非生产环境——开发环境、测试环境、预发环境——根本不需要24小时在线。白天大家工作的时候开着,晚上和周末关上,一个月能省一半以上的计算费用。
实现方式很灵活。小团队直接写脚本配合cron就能跑:
bash复制#!/usr/bin/env bash
# 每个工作日晚上10点停止所有带 env=dev 标签的实例
gcloud compute instances list \
--filter='labels.env=dev' \
--format='value(name,zone)' | while read -r name zone; do
gcloud compute instances stop "$name" --zone="$zone" --quiet
done
如果不想依赖某台机器跑cron,可以用Cloud Scheduler触发一个Cloud Functions,函数只负责调用Compute API把目标实例停掉。权限控制在服务账号上,只给它 compute.instances.stop 和 compute.instances.start 的角色,避免它误删任何资源。
自动关机有两个细节要处理好。第一,早上启动的时间要有讲究,最好在团队上班前半小时,别让研发打开电脑后还要等机器启动。第二,Cloud SQL这类托管数据库虽然也可以停止,但停止后计算费用会消失,存储费用仍然会持续产生,所以“停止”不等于“零成本”,这个预期要和团队说清楚。另外记得给开发机的启动盘打快照或保留好配置,万一关机后想恢复到某个历史状态,不至于手忙脚乱。
4. 从架构上省钱:存储分层、容器配额与BigQuery治理
如果说Spot、CUD、自动关机属于“价格层面”的省钱,那这一章讲的属于“架构层面”的省钱。前者不改变你使用云的方式,只是换一种更便宜的计费模式;后者则需要你重新审视资源的使用方式,从根源上减少浪费。两部分叠加,才是完整的成本优化。
4.1 存储生命周期:冷数据不该占标准存储的钱
GCP的Cloud Storage提供了多档存储类别,标准存储适合热数据,Nearline适合30天以上不访问的数据,Coldline适合季度级访问,Archive则适合一年到头可能都用不上的冷数据。价格依次降低,但取回数据时会产生额外费用。
很多团队的存储成本居高不下,核心原因就是“所有数据都塞在标准存储里”。一杯子的文件从创建那天起就没被读过,却一直按最高价计费。合理做法是配置生命周期规则(Lifecycle Rules),让系统自动把超过一定天数的对象迁移到更便宜的存储类别。比如说:日志文件保存30天后从标准存储转成Coldline,保存180天后转成Archive,一年后删除。
这里需要权衡的是“取回成本”。如果一个对象被迁移到了Archive,哪天突然要频繁访问,每次取回都要付额外费用。所以我通常建议按“数据访问频率”而不是“数据年龄”来决定迁移策略。如果你不确定数据是否会被再次访问,可以先转到Nearline试水,等到确实很久没人访问,再逐级下放。设置生命周期规则是纯配置操作,但收益非常稳定,是我遇到的所有项目里“投入产出比最高”的优化动作之一。
4.2 GKE的requests与装箱率:省容器钱的真正杠杆
如果你在用GKE,容器成本最大的浪费通常不在于节点贵,而在于requests值设置得太离谱。Kubernetes调度Pod时看的是requests,它决定了这个Pod在节点上预留多少资源。很多团队图省事,给所有容器一律设置 requests: 2C/4G,哪怕实际只用200m CPU,结果节点数量被顶得高高的,一台一台的空闲资源全都浪费了。
我的建议是分三步走。第一步,用Metrics Server或VPA(Vertical Pod Autoscaler)收集各工作负载的真实用量曲线,观察一周。第二步,根据P95或平均值合理下调requests,同时留好一定的安全余量,别为了省钱把requests压到比实际用量还低,否则节点过载,Pod会被OOM Kill。第三步,结合节点自动伸缩和Spot节点池,在所有高弹性工作负载上启用Spot,把成本降下来。这里有个概念要区分开:requests是调度预算,limits是运行时上限。降requests是提高装箱率的关键,但limits如果设得太低,业务高峰期会出现限流,需要根据监控数据反复微调。
还有一个容易被忽略的点:集群空闲时,Standard集群的控制平面仍然收费,节点组虽然可以缩到0,但管理费还挂在账上。如果你只有一个开发集群,且夜间几乎没人用,可以评估是否合并集群,或者迁移到Autopilot模式。Autopilot按Pod计费而不是按节点计费,不需要你管理节点池,对小规模、波峰波谷明显的业务更省心,但它的Pod单价通常比你自己管理节点要贵一些。到底是Standard还是Autopilot更省钱,要拿实际账单算一笔账,不要拍脑袋。
4.3 BigQuery:不是所有查询都值得全表扫描
BigQuery按扫描的数据量计费,这是它成本模型的核心。查询一个大表,如果每次都用 SELECT * 而不做任何裁剪,扫描量轻松飙到几TB,费用自然可怕。很多团队把BigQuery当成“随便查”的工具,结果账单里最刺眼的往往是它。
针对BigQuery的成本治理,我最看重三件事:分区、聚簇和槽位配额。
分区表是基本功。一张按天分区的业务表,查询时只要加上 _PARTITIONTIME 过滤条件,扫描量能缩小到原来的百分之一甚至千分之一。建表时就设计好分区键,远比事后优化便宜。聚簇(Clustering)则是让引擎在分区内部跳过无关文件,适合按某个高基数字段(如用户ID、订单号)过滤的场景。
槽位配额则是“从机制上防止跑飞”的手段。给项目或者某个数据集设置BigQuery槽位上限,当团队里的某个成员手滑发起一个全表扫描时,查询会排队等待而不是直接烧钱。再加上把每月设置一个总的花费上限,跑到阈值自动停掉非核心查询,整体上就能把风险锁住。槽位配额可能会让某些大查询变慢,但对控制成本来说,这里的“慢”其实是合理代价。
5. 给成本装上刹车:预算告警、自动化清理与月度体检
优化做到一定程度,成本曲线会先降下来,然后如果没人管,过几个月又开始慢慢爬升。这是云成本管理的常态。所以最后一步不是“一次性搞完”,而是建立一套让成本持续处于控制范围内的机制。这一章讲的都是日常工作流层面的东西,技术含量不算高,但价值极高。
5.1 预算告警怎么设,才不会变成“狼来了”
GCP的预算告警可以在Cloud Billing里直接创建,设定一个月度预算金额,当实际花费达到某个阈值时,系统会给指定的邮箱或者Webhook发通知。很多人设置了预算但觉得没用,原因是“告警天天响,后来就不看了”。这通常是阈值设得太低或者没有一个分级策略。
我建议按50%、75%、90%、100%四个阈值设置告警,这不是让工程团队每次都炸一遍,而是给不同的人不同的信息:50%的告警发给成本负责人,用来评估“这个月是否正常”;75%的告警发给各项目Owner,提醒“接下来要用钱的地方要谨慎”;90%触发时,只有我自己和财务能看到,因为这时候要准备解释并决定是否要临时关停一些非核心任务;100%则是最高级别,触发后自动化流程会限制部分高消耗操作。预算金额的设定也有讲究:不要设成“理想值”,而是参考最近三个月的平均实际花费上浮20%到30%作为“警戒线”,这样才能在异常真的发生时及时发现。
5.2 定时清理脚本:处理那些“看一眼就忘”的孤儿资源
静态IP、孤儿磁盘、废弃快照,这三类资源是云账单里最常见的“沉默成本”。它们不会因为你删了主资源而自动消失,也不会有任何人主动告诉你它们存在。唯一靠谱的办法,就是用脚本定期扫描并处理。
我自己的例行脚本会做三件事。第一,列出所有没有被实例引用的静态IP地址:
bash复制gcloud compute addresses list --filter='users:=[]'
第二,列出所有没有关联到任何实例的磁盘:
bash复制gcloud compute disks list --filter='users:=[]'
第三,列出所有超过30天的快照:
bash复制gcloud compute snapshots list \
--filter='creationTimestamp<2025-05-01T00:00:00Z'
脚本跑完后,把报告丢到成本群,让各资源Owner确认后再统一清理。千万别让脚本自动删除,万一误删了某个需要长期保留的数据盘,事故就大了。半自动比全自动更稳妥。我在实践中发现,只要这个流程坚持三个月,项目里的孤儿资源就会少很多,因为各团队知道有人每月检查,创建资源后会主动考虑“用完了要清理”。
5.3 月度成本体检清单,照着做就能防反弹
为了让成本优化不沦为“一次性运动”,我给自己订了一个“月度成本体检”清单,每个月第一周固定花一个小时走一遍。这个清单你也可以直接拿来用:
| 检查项 | 操作 | 预期效果 |
|---|---|---|
| 成本走势 | 看BigQuery按天聚合曲线,与上月同期对比 | 发现异常增量,及时介入 |
| Top SKU | 按SKU聚合Top 10,确认每个SKU都有业务归属 | 防止未知服务烧钱 |
| Spot覆盖率 | 统计Spot实例占所有可抢占负载的比例 | 提升弹性和批量任务覆盖 |
| CUD覆盖率 | 检查资源型承诺是否长期处于“未用满”状态 | 避免承诺浪费 |
| 孤儿资源 | 扫描未绑定IP、无归属磁盘和超期快照 | 清理沉默成本 |
| 磁盘大小 | 检查启动盘和PD盘容量,看是否超配 | 降低存储费用 |
| 网络出口 | 按SKU查出口流量,找出高消耗服务 | 评估是否需要内网化或CDN |
这套清单不一定能覆盖所有定制场景,但大部分团队的显性浪费都逃不出这几个大类。做完一轮后把结果和上个月的对比一下,你会发现成本优化是有复利效应的:第一个月把最大的浪费源清掉,后面每个月只要多关注增量,就能保持在一个健康的区间。
有不少人问我,为什么不在开头就放一堆打折信息,我说那是因为没看完账之前,你根本不知道哪些钱该省。我自己在多次优化实践中最大的感受是:真正省钱的不是某一个神秘技巧,而是把“看得见成本、分得清归属、控得住增量”这套基本功做到位。如果你现在被GCP的月度账单困扰,我建议别急着买各种包年套餐,先把账单导出到BigQuery,按本文的思路看一遍,再决定下一步动哪里。成本优化和收拾房间很类似,最怕的不是乱,而是你从来没有认真看过一遍。
