如果迁移失败,如何自动回滚并通知 Slack?

解读

在国内真实面试场景中,这道题考察的是“可观测性 + 自动化运维 + 跨系统通知”的综合能力。面试官想确认:

  1. 你是否能把 Cloud SQL 的快照/时间点恢复能力与CI/CD 流水线结合;
  2. 能否用Google Cloud 原生工具(Cloud Build、Workflows、Logging)完成零人工干预的回滚;
  3. 能否把告警通道对接到国内可访问的 Slack webhook(或企业微信、飞书),并满足合规(数据不出境、密钥不落盘)。
    回答时要体现“失败判定 → 回滚触发 → 数据一致性校验 → 通知送达”的闭环,且每一步都给出可落地的配置片段

知识点

  1. Cloud SQL 自动备份与时间点恢复(PITR)
    • 每日自动备份默认保留 7 天,可按需保留 30 天
    • 通过 gcloud 命令行或 Admin API 可秒级创建恢复任务,恢复后实例 IP 不变,仅底层磁盘回滚。
  2. Cloud Build + Cloud Workflows 的“双保险”
    • Cloud Build 负责执行迁移脚本(Flyway、Liquibase、Django Migration);
    • Cloud Workflows 负责编排重试与回滚,支持声明式语法,可内嵌条件判断与循环,单工作流最长 1 年,适合长事务。
  3. 失败判定策略
    • 应用健康探针:迁移后 Cloud Build 步骤调用 /health/db连续 3 次 502/500 即判定失败
    • 数据校验 SQL:对核心业务表SELECT COUNT(*) <> 预期行数CHECKSUM TABLE 不一致即失败;
    • 超时熔断:Cloud Build 步骤设置 timeout = 10min,防止脚本假死。
  4. 回滚原子性
    • 同一代码库里提前准备好 rollback.dml.sql版本号与迁移脚本一一对应
    • 回滚前自动创建临时实例(克隆当前主实例),先验证回滚脚本无语法错误,再对主实例执行,避免二次故障
  5. Slack 通知合规方案
    • 国内 VPC 无法直接访问 hooks.slack.com,需通过Google Cloud 的 Secret Manager + 无服务器连接器(Serverless VPC Connector) 把 webhook URL 当密文存储;
    • Cloud Logging 路由severity=ERRORresource.labels.database_id=project:instance 的日志实时推送到 Pub/Sub,再由Cloud Functions 2nd gen 消费并调用 Slack webhook,全程内网出流量,满足等保 2.0 要求。
  6. 幂等与重试
    • 整个 Workflows 配置幂等键使用 ${build.id},防止重复回滚;
    • 对 Slack 调用设置指数退避,最大 3 次,避免限流 429

答案

  1. 预置快照
    迁移前 Cloud Build 步骤执行
    gcloud sql backups create --async --project=$PROJECT_ID --instance=$INSTANCE_ID --description="pre-mig-$(date +%Y%m%d-%H%M%S)"
    拿到 backupId 并写入 backup_id.txt 作为制品,供回滚步骤使用。

  2. 迁移与判定
    同一 Cloud Build 的 cloudbuild.yaml 里顺序执行:
    a) flyway migrate 脚本;
    b) 数据校验 python scripts/validate.py(连接 Cloud SQL Auth Proxy 私有 IP,5 秒内重连 3 次);
    c) 健康检查 curl -f http://internal-lb/health/db
    任一步骤返回非 0,即把 exit_code=1 写入 /workspace/.failed

  3. 自动回滚
    Cloud Build 的 finally 块始终运行:

    if [ -f /workspace/.failed ]; then
      gcloud sql backups restore $BACKUP_ID \
        --project=$PROJECT_ID --instance=$INSTANCE_ID \
        --restore-instance=$INSTANCE_ID \
        --quiet --async --format="value(name)" > /workspace/restore_id.txt
    fi
    

    由于恢复操作异步,需把 restore_id.txt 传给下一步 Workflows,轮询直到 status=DONE

  4. 通知 Slack
    在 Cloud Logging 创建基于日志的指标 metric="cloudsql_migration_failure",过滤条件:

    resource.type="cloud_sql_database"
    severity=ERROR
    textPayload:"RESTORE_DONE"
    

    配置告警策略:阈值 >0 即触发,通知渠道选 Pub/Sub topic slack-alerts
    Cloud Functions(Python 3.11)订阅该 topic:

    • 从 Secret Manager 读取 slack_webhook_url
    • 构造 Markdown 消息:
      【Cloud SQL 迁移失败】
      项目:project实例:{project} 实例:{instance}
      已自动回滚至备份:backupId恢复操作ID{backupId} 恢复操作 ID:{restoreId}
    • POST 到 Slack,超时 5 秒失败重试 3 次
  5. 一键闭环
    把整个流程封装成Terraform 模块

    • cloudbuild_trigger.tf 监听 Cloud Source Repositoriesmain 分支;
    • workflows.tf 声明 Workflows YAML,版本锁定
    • secret_manager.tf 把 Slack webhook 存为 SECRETIAM 仅授予 Cloud Functions SA
      交付给开发团队时,只需 terraform apply,即可5 分钟内在新环境复现完整的“失败即回滚+Slack 通知”能力。

拓展思考

  1. 双云容灾场景:如果客户要求阿里云 RDS 与 Cloud SQL 互为主备,可在Cloud Workflows 里再调用阿里云 API 做反向回滚,同一套失败判定逻辑复用,实现跨云一致性
  2. 灰度迁移:把**影子实例(Cloud SQL 只读副本提升后的独立实例)**作为灰度目标,迁移成功后再切换 DNS,失败直接释放影子实例,零回滚时间
  3. 成本优化:对非核心库关闭自动备份,改用每日导出 SQL 到 Cloud Storage Nearline失败时通过导入恢复节省 30% 存储成本,但 RPO 从 5 分钟降到 1 小时,需在SLA 文档里明确告知业务方。