如果 Terraform 模板里同时声明了 database_version = "MYSQL_8_0_40" 和 maintenance_version,哪一个字段会决定首次部署的镜像版本?
解读
在国内云原生面试中,这道题考察的是候选人对 Cloud SQL 版本语义模型 与 Terraform Provider 资源生命周期 的精准理解。
很多候选人会把 maintenance_version 当成“首次拉镜像的版本号”,结果答错。
面试官想听到的是:
- 两个字段分别控制哪一层版本;
- 首次 Create 时 Terraform 把哪个值写进 GCP API;
- 后续 Update 时两个字段如何互动;
- 如果填错会出现什么国内常见报错(如“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 此时形同虚设。
拓展思考
- 国内双录合规场景下,客户要求“必须跑 8.0.40 的确定补丁号”,如何固化?
答:首次仍用 database_version = “MYSQL_8_0_40” 创建,随后立即 patch 到 google_sql_database_instance.settings.maintenance_version = “MYSQL_8_0_40.R20240101.01_00”,并 关闭自动维护窗口(maintenance_window 置为 never),即可 冻结补丁。 - 如果后续 Google 发布 8.0.41 家族,而客户想原地升级,Terraform 应如何写?
答:只能 重建实例(database_version 不可降级也不可 横向升级 到 8.0.41),需使用 read replica 提升 或 导出导入 方式完成 跨小版本升级,否则 plan 会报 “database_version cannot be changed”。 - 国内 Terraform 企业版(私有 Controller)常因 缓存 Provider 版本 导致 maintenance_version 字段校验失败,如何快速排障?
答:在 CI 阶段 显式指定 provider 版本约束
并 预检可用补丁列表:required_providers { google = { source = "hashicorp/google" version = "~> 5.0" } }
确保 maintenance_version 落在 可用集合,即可避免 apply 阶段 400 错误。gcloud sql tiers list --project=xxx --filter="databaseVersion=MYSQL_8_0_40” --format="value(maintenanceVersion)”