如何避免自动关闭脚本误停生产实例?
解读
在国内金融、电商、政务云等场景,“自动关闭脚本”通常指基于标签、定时任务或成本治理平台(如阿里云“自动释放”、腾讯云“定时关机”、自研FinOps脚本)触发的批量关机/降配逻辑。Google Cloud SQL 虽为全托管,但实例状态仍可通过 gcloud、Terraform、Cloud Scheduler 或组织 Policy 被意外停止(例如把 activationPolicy=NEVER 当成“节省成本”手段)。一旦误停,跨区域高可用实例会触发故障转移,单区域实例则直接中断业务,且重新启动后 SLA 不赔偿。因此,面试核心不是“会不会停”,而是如何用 Google Cloud 原生机制与国内合规要求,构建多层“防呆”防线。
知识点
- IAM 最小权限与条件属性:利用
resource.name、resource.labels及request.time做**“拒绝停止生产”**组织级约束。 - 标签与命名规范:“env:prod” 标签必须不可被实例管理员篡改,需绑定 IAM 条件 + Resource Manager 标签锁定。
- Cloud IAM Deny Policy(2023 正式 GA):对
cloudsql.instances.stop、cloudsql.instances.delete、cloudsql.instances.update设置全局拒绝规则,优先级高于角色授权。 - Terraform 生命周期钩子:通过
lifecycle { prevent_destroy = true }+google_tags_location_tag_binding保证CI/CD 管道无法销毁生产实例。 - Policy Analyzer & Asset Inventory:每夜扫描**“谁可以 stop prod”,结果写入国内必须保留 180 天的日志审计桶**。
- Cloud Scheduler + Cloud Functions “双签”:关机脚本必须由两人分别提交 Secret Manager 版本,函数校验prod 标签 + 当前值班 on-call 名单后才可执行。
- Private Service Connect + VPC-SC 安全边界:把Cloud SQL Admin API 限定在专用网段,阻断公网临时凭证误调用。
- 预算与配额告警替代停机:利用Cloud Billing Budget API触发微信/飞书机器人,只告警不关机,符合国内“先审批后操作”合规流程。
- 多项目隔离:生产项目只授权给 SRE 组,Dev/Staging 项目给研发,关闭脚本所在 SA 无任何生产项目 IAM。
- Backstage/内部开发者平台模板:禁止传入 activationPolicy=NEVER,模板渲染时自动为 prod 实例追加**“do-not-stop:true” 标签及对应 Deny Policy**。
答案
面对面试官,我会给出**“四层七防”**实战方案,既体现 Google Cloud 原生能力,也贴合国内监管与企业文化:
-
标签与命名层
所有生产实例统一打上**“env:prod”与“business:core”标签,并通过Resource Manager 的“标签锁定”功能**禁止后续修改;命名强制以prod-开头,方便脚本快速过滤。 -
IAM 与组织策略层
在组织节点创建IAM Deny Policy,明文拒绝任何主体对匹配resource.matchTag('env','prod')的实例执行cloudsql.instances.stop或cloudsql.instances.delete;同时移除项目 Owner 的 cloudsql.admin 角色,仅保留**“Cloud SQL Client”+“Viewer”给开发,停机权限收归SRE 专属自定义角色**。 -
自动化脚本层
把关机逻辑封装进Cloud Functions Gen2,入口由Cloud Scheduler 每分钟轮询“成本标签”,但函数内部二次校验:- 实例标签是否包含**“do-not-stop:true”**;
- 当前时间是否在国内**“禁止变更窗口”**(如 0:00-06:00、双 11 大促、央行清算日);
- 调用者必须在Secret Manager 中写入双人审批的 JSON 片段,函数用Cloud Audit Logs 校验两人身份;
任一条件不满足立即抛出 403 并@飞书值班群。
-
审计与回滚层
所有cloudsql.instances.patch调用默认写入国内合规日志桶(保留 180 天,加密密钥在中国 KMS 区域);每夜用**Policy Analyzer 导出“who can stop prod”报告,异常权限自动开 Jira 工单,限期 24h 回收。万一误停,利用 Point-in-Time Recovery 与 跨区域热备实例,RTO < 5 分钟,并触发“P1 故障”**复盘流程。
通过**“标签锁定→Deny Policy→双签函数→审计复盘”四道闸门,100% 阻断自动脚本误停生产实例,同时满足等保 2.0 对“运维操作审批”与“日志留存”**的刚性要求。
拓展思考
-
如果公司混合云还有线下 MySQL,如何统一**“防误停”策略?
答:可把线下实例录入 Google Cloud Asset Inventory 的“非 Google 资源”,用Terraform 的 external data source同步标签,Deny Policy 虽不适用,但可在自研平台调用“工单系统 API”实现双人审批,形成“云上云下同一套标签+审批”。 -
FinOps 团队坚持“夜间关机省 30% 成本”,如何说服?
答:Google Cloud SQL 按秒计费但磁盘持续收费,关机节省的 CPU/RAM 费用不足 15%,却带来可用性降级与 SLA 失效;应改用共享 CPU 实例(db-f1-micro→db-g1-small)或 Commitment + 弹性池,既省钱又不中断,用成本报告量化对比即可。 -
Terraform 1.6 引入“import block”,如何防止导入时把 prod 实例误销毁?
答:在CI Pipeline 里强制加terraform plan -out=tfplan && terraform show -json tfplan | jq -r '.resource_changes[] | select(.change.actions[] | contains("delete")) | .address' | grep google_sql_database_instance | xargs -I {} echo "ERROR: trying to delete {}" && exit 1,任何删除动作直接阻断 MR,实现**“代码级防呆”**。 -
国内多云灾备场景,若使用Cloud SQL for SQL Server 的跨区域只读副本做灾备,停止主实例前如何确保副本已提升?
答:在双签函数中先调用gcloud sql instances promote-replica <read-replica-name> --project=<dr-project>,等待replicaName.promoteOperation.status=DONE后,再停止原主实例,并自动更新内网 DNS 指向新主,实现**“先提升后停机”,保证业务连续性与数据零丢失**。