Google App Engine Budget 和 Daily Spending Limit 未生效
结论
你的设置本身没有问题,但无法限制 App Engine flexible environment 的实际费用:
- **Budget 只用于监控费用和发送告警,不是硬性消费上限。**费用超过
$0.01后,资源不会自动停止。 - App Engine 的 Daily Spending Limit 不适用于 flexible environment 实例产生的 Compute Engine 类费用。
- **Flexible environment 没有供实例每天自动恢复的免费 quota,通常还会保留至少一个运行实例。**即使没有请求,也会继续产生 CPU、RAM 和 Persistent Disk 费用。
因此,仅靠 Budget 或 Daily Spending Limit,无法做到”免费额度用完后自动停机”。如果开发环境不需要一直在线,可以停止 App Engine 版本、设置定时启停,或者改用能够缩容到零的运行环境。
为什么没有在 $0.01 时停止
Budget 只负责告警
Google Cloud Billing Budget 会跟踪支出,并在费用达到指定比例或预测金额时发送通知。它不会:
- 拒绝新请求;
- 停止 App Engine 实例;
- 禁用项目计费;
- 保证费用不超过预算。
预算数据还有统计延迟。即使通过预算通知触发自动化操作,停机前仍可能继续产生费用,所以不能将其视为精确的硬限额。
页面中的:
$7.25 / $0.01
表示预算范围内已统计到约 $7.25 的费用,并不表示系统承诺在费用达到 $0.01 时停止计费。
如果账单明细合计与预算页面不一致,可以检查:
- Budget 是否覆盖整个 billing account,而账单明细只筛选了某个项目;
- 是否存在其他 SKU、项目或服务;
- 两个页面的日期范围是否一致;
- 折扣、赠金、税费和未最终结算费用是否使用了不同的统计口径;
- 费用数据是否仍在延迟更新。
Daily Spending Limit 不控制 Flex 资源
Daily Spending Limit 是 App Engine 的旧式限额机制,只适用于明确受其支持的 App Engine 资源。Flexible environment 实例使用的是底层计算、内存和磁盘资源,相关费用不会被这个限额可靠地截断。
账单中的以下项目,就是 Flex 实例持续运行产生的费用:
App Engine Flex Instance Core Hours
App Engine Flex Instance RAM
Google Compute Storage PD Capacity
所以,控制台即使显示:
Enabled (Daily spending limit: $0.01)
也不代表 Flex 实例会在消费达到 $0.01 时停止。
为什么没有请求仍然收费
Flexible environment 更像持续运行的虚拟机环境,而不是按请求启动的纯无服务器环境。只要版本处于 serving 状态,即使实例空闲,也可能继续占用:
- vCPU;
- 内存;
- Persistent Disk;
- 其他网络或存储资源。
自动扩缩容可以减少实例数量,但 Flex 通常无法缩容到零。默认实例数和可用配置可能随运行时及平台策略变化,具体应以当前项目控制台和官方配置说明为准。
你可以限制最大实例数,防止流量导致费用快速增长:
runtime: python
env: flex
automatic_scaling:
min_num_instances: 1
max_num_instances: 1
target_cpu_utilization: 0.8
resources:
cpu: 1
memory_gb: 0.5
disk_size_gb: 10
这种配置只能控制成本增长,不能让空闲成本降为零。资源字段还必须满足当前 Flex 运行时规定的最小值,部署前需要根据实际运行时检查配置。
开发期间如何停止计费
开发环境不用时,可以停止正在运行的版本:
gcloud app versions list
确认服务名和版本号后执行:
gcloud app versions stop VERSION_ID \
--service=SERVICE_ID \
--project=PROJECT_ID
需要继续开发时,可以重新部署版本:
gcloud app deploy app.yaml \
--project=PROJECT_ID
也可以把流量切换到已有版本:
gcloud app services set-traffic SERVICE_ID \
--splits=VERSION_ID=1 \
--project=PROJECT_ID
停止前要确认该服务没有仍需处理的生产流量。版本停止后,账单可能因数据延迟而继续更新。已经产生的费用不会撤销,部分存储或其他独立资源也可能继续计费。
如果只是临时测试,可以在部署后使用,用完立即停止版本。也可以通过 CI/CD 或脚本封装部署和停止命令,省去每次进入控制台操作的步骤。
更适合”无人访问时零实例”的方案
如果应用兼容 App Engine standard environment,可以考虑迁移到 Standard。Standard 的自动扩缩容可以配置为无流量时缩容到零,例如:
runtime: python312
automatic_scaling:
min_instances: 0
max_instances: 1
Standard 和 Flex 在运行时、文件系统、系统依赖、请求时长及网络能力方面并不完全相同。迁移前要确认应用是否依赖:
- 自定义 Docker 镜像;
- 原生系统软件包;
- Flex 特有的网络或后台进程能力;
- 本地可写磁盘或长时间运行的请求。
Cloud Run 等其他可缩容到零的产品,也可能更适合临时开发服务。不过,数据库、静态 IP、磁盘和负载均衡器等外围资源仍可能单独计费。
能否根据 Budget 自动停机
可以通过以下链路实现近似的自动停机:
Cloud Billing Budget
↓
Pub/Sub budget notification
↓
Cloud Run function / Cloud Function
↓
停止 App Engine 版本或禁用项目计费
但这仍不是严格的消费上限,原因包括:
- 预算数据和通知存在延迟;
- 通知可能重复发送;
- 停止资源需要时间;
- 停止应用版本不一定会停止项目中的其他计费资源;
- 禁用 billing account 或项目计费属于高风险操作,可能影响所有相关服务。
自动化处理程序应只获得必要的最小权限,并处理消息去重、阈值判断和失败重试。不要因为收到一次 Pub/Sub 消息,就直接关闭整个 billing account。
是否需要解除信用卡绑定
不建议把解除信用卡绑定当作日常成本控制手段。支付方式、billing account 和项目资源属于不同层次。移除支付方式并不等于以可控方式停止应用,还可能造成欠费、账户暂停或项目资源受限等风险。
更稳妥的处理顺序是:
- 停止当前 Flex 版本,并确认没有其他版本仍在接收流量。
- 在 Billing Reports 中按项目和 SKU 检查剩余费用的来源。
- 将 Flex 的最大实例数限制在开发所需的最小规模。
- 不需要常驻服务时,通过脚本或 CI/CD 停止版本。
- 如果必须自动缩容到零,迁移到 App Engine Standard 或 Cloud Run。
- 保留 Budget 告警用于监控,但不要将其当作费用熔断器。
问题不在于 $0.01 设置失败,而在于 Budget 和 Daily Spending Limit 原本就不是 Flex 资源的硬性费用上限。
备注:内容仅供参考。
