如何基于 Cloud Scheduler 实现每晚自动停止开发实例?
解读
面试官真正想考察的是:
- 你是否理解 Cloud SQL 的计费模型(停机后仅收存储与 IP 保留费,可节省 70% 以上开发环境成本)。
- 能否把 Cloud Scheduler → Pub/Sub → Cloud Functions → Cloud SQL Admin API 这一“无服务器自动化”链路讲完整,并给出 IAM、错误重试、幂等性、时区 等落地细节。
- 是否具备 国内网络合规 意识:函数必须部署在 上海/北京/香港 任一区域,且 Pub/Sub 触发器需走 GCP 国内域名(*.googleapis.cn),否则调度会受跨境链路影响。
- 能否区分 开发/生产标签,避免误关核心库——这是国内金融、政企客户面试时的红线。
知识点
- Cloud Scheduler:完全托管的 Cron 服务,最小粒度 1 分钟,支持 北京时间(Asia/Shanghai) 时区,国内账号默认走 vpc-cn 出口,延迟可稳定在 1 s 内。
- Pub/Sub 消息:至少一次投递,需函数内部做 幂等校验(可用 instance.state 二次确认)。
- Cloud SQL Admin API v1beta4:patch 方法设置 settings.activationPolicy=NEVER 即停机;settings.activationPolicy=ALWAYS 即开机。
- IAM 最小权限:Cloud Scheduler 服务账号授予 roles/cloudscheduler.jobRunner;函数运行时账号授予 roles/cloudsql.editor 与 roles/iam.serviceAccountUser(用于生成访问令牌)。
- 国内合规:若客户已开通 Cloud SQL 中国版(vpc-cn),函数必须同区域部署,否则无法解析 private.googleapis.cn 内网域名。
- 成本陷阱:停机后若仍分配 外部 IP,会继续收 $0.01/小时 的 IP 保留费;开发环境建议勾选 “仅内网 IP” 或使用 Cloud SQL Auth Proxy + VPC-SC 访问,彻底省费。
- 高阶加分:用 Terraform 把 Scheduler + Pub/Sub + Function 做成 模块,通过 count = env == "dev" ? 1 : 0 自动关闭非生产环境,体现 IaC 思维。
答案
-
给实例打标签:
为所有开发 Cloud SQL 实例打上 environment=dev,用于函数过滤,防止误操作生产。 -
创建 Pub/Sub 主题:
gcloud pubsub topics create nightly-cloudsql-stop --project=PROJECT_ID -
部署 Cloud Functions(第二代,上海区域):
运行时选 Python 3.11,入口函数 main,代码核心逻辑:- 用 Google Auth Library 拿到 OAuth2 令牌,作用域 **https://www.googleapis.com/auth/sqlservice.admin**。
- 调用 sqladmin.instances.list(project=PROJECT_ID),过滤 environment=dev 且 state=RUNNABLE。
- 对命中实例并发调用 patch(settings.activationPolicy=NEVER),并记录 operation name 到 Cloud Logging。
- 若 API 返回 409/400(如已停机),直接 return 200 实现幂等。
-
创建 Cloud Scheduler 作业:
gcloud scheduler jobs create pubsub stop-dev-sql \ --schedule="0 23 * * *" \ --time-zone="Asia/Shanghai" \ --topic=nightly-cloudsql-stop \ --message-body="{}" \ --project=PROJECT_ID -
IAM 授权:
- 函数服务账号 roles/cloudsql.editor
- Scheduler 服务账号 roles/pubsub.publisher
-
验证:
第二天凌晨查看 Cloud Logging:protoPayload.methodName="cloudsql.instances.patch" protoPayload.request.@type="type.googleapis.com/sqladmin.instances.patch" protoPayload.response.settings.activationPolicy="NEVER"若出现且 cost table 中无实例运行费用,即证明成功。
拓展思考
- 开机链路:再建一个 06:30 的 Scheduler,消息体 {"action":"start"},函数内改为 activationPolicy=ALWAYS,即可实现 “7×12 开发环境”,比 24 h 运行再省 50% 费用。
- 自动弹性:结合 Cloud Monitoring 指标(如 database/cpu/utilization < 5% 持续 30 min)通过 Alerting + Pub/Sub 触发停机,比固定 Cron 更精细,适合国内 敏捷团队 的 “夜测晨开” 场景。
- 多项目管控:用 Cloud Asset Inventory + Cloud IAM 条件 把函数权限限定在 folder层级,新增 dev 项目无需再改 IAM,满足国内 大型央企多子公司 的 统一财务单元 需求。