如果 Terraform 模板里同时声明了 database_version = "MYSQL_8_0_40" 和 maintenance_version,哪一个字段会决定首次部署的镜像版本?

解读

在国内云原生面试中,这道题考察的是候选人对 Cloud SQL 版本语义模型Terraform Provider 资源生命周期 的精准理解。
很多候选人会把 maintenance_version 当成“首次拉镜像的版本号”,结果答错。
面试官想听到的是:

  1. 两个字段分别控制哪一层版本;
  2. 首次 Create 时 Terraform 把哪个值写进 GCP API;
  3. 后续 Update 时两个字段如何互动;
  4. 如果填错会出现什么国内常见报错(如“maintenance_version is not available in the selected zone”)。

知识点

  • database_version:Cloud SQL 实例的 Major.Minor.Patch 引擎版本,属于 不可降级 的“家族”标识;首次部署时 GCP 用该字段决定 初始小版本镜像
  • maintenance_version补丁级别滚动发布标识,格式如 MYSQL_8_0_40.R20240101.01_00;它只在 实例已存在 后参与 补丁升级决策,对 首次创建 无影响。
  • Terraform google_sql_database_instance 资源在 Create 阶段只把 database_version 写进 settings.databaseVersion 字段;maintenance_version忽略(Provider 源码层面直接跳过)。
  • 国内金融、政企项目常因合规要求 锁定补丁号,此时需用 google_sql_database_instance.settings.maintenance_window + maintenance_version二次更新,但 不能回退
  • 若误将 maintenance_version 写成 低补丁号,首次 apply 不会报错,但后续 maintenance_window 触发时会被 GCP 自动修正到最新可用补丁,导致 Terraform 漂移,需重新 import 状态。

答案

首次部署的镜像版本完全由 database_version 字段决定;maintenance_version 在创建阶段被 Terraform 忽略,仅对后续补丁升级生效。
因此,MYSQL_8_0_40 会被 GCP 解析为“8.0.40 家族当前最新补丁”,成为实例初始化时真正拉起的镜像;maintenance_version 此时形同虚设

拓展思考

  1. 国内双录合规场景下,客户要求“必须跑 8.0.40 的确定补丁号”,如何固化?
    答:首次仍用 database_version = “MYSQL_8_0_40” 创建,随后立即 patchgoogle_sql_database_instance.settings.maintenance_version = “MYSQL_8_0_40.R20240101.01_00”,并 关闭自动维护窗口(maintenance_window 置为 never),即可 冻结补丁
  2. 如果后续 Google 发布 8.0.41 家族,而客户想原地升级,Terraform 应如何写?
    答:只能 重建实例(database_version 不可降级也不可 横向升级 到 8.0.41),需使用 read replica 提升导出导入 方式完成 跨小版本升级,否则 plan 会报 “database_version cannot be changed”
  3. 国内 Terraform 企业版(私有 Controller)常因 缓存 Provider 版本 导致 maintenance_version 字段校验失败,如何快速排障?
    答:在 CI 阶段 显式指定 provider 版本约束
    required_providers {
      google = {
        source  = "hashicorp/google"
        version = "~> 5.0"
      }
    }
    
    预检可用补丁列表
    gcloud sql tiers list --project=xxx --filter="databaseVersion=MYSQL_8_0_40” --format="value(maintenanceVersion)”
    
    确保 maintenance_version 落在 可用集合,即可避免 apply 阶段 400 错误