如何使用Terraform实现GCP AppEngine源码与基础设施分离部署
实现分离部署的可行方案
核心思路是明确两边的配置权责边界,Terraform只管控基础设施相关的配置和App Engine底座资源,gcloud只负责代码上传部署,避免配置互相覆盖。
第一步:拆分配置权责
先明确两类配置的管理主体,从根源避免冲突:
- Terraform 管控范围(不允许业务侧手动修改):
- App Engine 应用初始化(区域绑定、关联服务账号、IAM权限配置)
- 实例规格(比如你当前用的
F4_1G)、自动扩缩容规则、资源配额限制 - 基础设施级环境变量(比如数据库连接地址、云服务权限配置、公共环境标识)
- 服务级配套资源:防火墙规则、自定义域名映射、SSL证书、流量拆分策略
- gcloud/业务代码仓库 管控范围:
- Node.js 源码打包、版本上传
- 和代码强绑定的配置:runtime版本、启动命令、路由handlers、静态资源映射、业务级环境变量(比如功能开关、日志级别)
第二步:Terraform侧配置实现
不要在Terraform中定义关联源码包的google_app_engine_standard_app_version资源(否则每次terraform apply都会触发代码重部署,和gcloud部署流程冲突),只做底座配置和基础设施配置片段生成,示例配置逻辑:
- 初始化GCP provider,创建App Engine应用底座
# 配置GCP provider provider "google" { project = "你的GCP项目ID" region = "你部署App Engine的区域,比如asia-northeast1" } # 初始化App Engine应用(项目下第一次部署App Engine才需要这个资源) resource "google_app_engine_application" "app" { project = "你的GCP项目ID" location_id = "你部署App Engine的区域" } # 生成基础设施层的App Engine配置片段,完全由Terraform管理 resource "local_file" "appengine_infra_config" { content = <<EOF # 由Terraform自动生成,请勿手动修改 instance_class: F4_1G env_variables: ENVIRONMENT: 'develop' # 后续要加扩缩容、资源限制等配置直接写在这里 EOF filename = "${path.module}/app.infra.generated.yaml" }
- 执行
terraform apply,确认App Engine底座创建完成,同时生成app.infra.generated.yaml配置文件,把这个文件存在基础设施仓库,或者上传到团队内部的配置存储,供业务部署时拉取。
第三步:业务侧部署流程调整
业务代码仓库里只保留最小化的app.yaml,只存和代码强绑定的配置,示例:
# 业务侧维护的app.yaml runtime: nodejs12 # 这里只写启动命令、handlers、业务环境变量这类和代码相关的配置 # 不要重复写instance_class、基础设施环境变量这类Terraform管控的配置项
调整CI/CD中的部署步骤:
- 拉取最新代码,安装依赖、完成构建
- 拉取Terraform生成的最新
app.infra.generated.yaml配置文件到代码根目录 - 执行部署命令,gcloud会自动合并两份yaml的配置,优先级以最后传入的文件为准:
gcloud app deploy app.yaml app.infra.generated.yaml --version=${代码版本标识,比如git commit hash}
关键注意事项
- 两边不要重复定义相同配置项,避免合并时出现非预期的覆盖:比如已经在Terraform生成的配置里写了
instance_class,业务侧的app.yaml就不要再写这个字段 - 敏感配置(比如数据库密码、API密钥)不要明文写在任何yaml文件里,统一存到GCP Secret Manager,Terraform侧授权App Engine默认服务账号读取对应密钥,通过Secret Manager的引用方式注入环境变量
- 流量切换操作统一由Terraform管控:业务部署新版本时默认不分配流量,等部署完成后通过Terraform调整流量拆分比例,逐步切流,避免发布故障
- 你当前用的
nodejs12runtime已经停止官方支持,建议后续逐步升级到仍在维护的Node.js版本(比如nodejs18、nodejs20)
内容的提问来源于stack exchange,提问作者Duc Nguyen Viet
相关产品推荐
相关产品推荐

