Terraform重新部署GCP Cloud Functions后代码未更新的原因排查
问题:Terraform重新部署GCP Cloud Functions后代码未更新
我通过Terraform配置,使用对应Zip包在GCP上部署了多个Cloud Functions。修改函数代码并生成新Zip包后,通过同一Terraform配置重新部署,部署成功但函数未更新为新代码。服务账号拥有创建资源的全部权限,执行terraform apply后函数仍使用旧源代码。
我的Terraform代码
main.tf
# Creating a storage bucket to store cloud function objects resource "google_storage_bucket" "bucket" { name = "${var.project_id}-bucket1" location = var.region } data "archive_file" "function_src" { for_each = var.functions type = "zip" output_path = "/tmp/${each.value.zip}" source_dir = "../function-zips" } resource "google_storage_bucket_object" "function_zip" { for_each = var.functions name = each.key bucket = google_storage_bucket.bucket.name source = each.value.zip } resource "google_cloudfunctions2_function" "function" { for_each = var.functions name = each.value.name location = var.region build_config { runtime = each.value.runtime entry_point = each.value.entrypoint source { storage_source { bucket = google_storage_bucket.bucket.name object = google_storage_bucket_object.function_zip[each.key].name } } } service_config { min_instance_count = 1 available_memory = "128Mi" timeout_seconds = 120 all_traffic_on_latest_revision = false service_account_email = "terraform-gcf@terraform-cloud-functions-ems.iam.gserviceaccount.com" } } resource "google_cloud_run_service_iam_member" "member" { for_each = var.functions location = google_cloudfunctions2_function.function[each.key].location service = each.key role = "roles/run.invoker" member = "allUsers" }
provider.tf
provider "google" { project = var.project_id region = var.region credentials = "../tf-key.json" }
variables.tf
variable "project_id" { default = "terraform-cloud-functions-ems" } variable "region" { default = "us-central1" } variable "functions" { type = map(object({ zip = string name = string trigger = string runtime = string entrypoint = string })) default = { "createemployee" : { zip = "../function-zips/create-employee.zip" name = "createEmployee" trigger = "http-trigger" runtime = "go121" entrypoint = "CreateEmployee" }, "deleteemployee" : { zip = "../function-zips/delete-employee.zip" name = "deleteEmployee" trigger = "http-trigger" runtime = "go121" entrypoint = "DeleteEmployee" }, "searchemployee" : { zip = "../function-zips/search-employee.zip" name = "searchEmployee" trigger = "http-trigger" runtime = "go121" entrypoint = "SearchEmployees" }, "getemployeebyid" : { zip = "../function-zips/get-employee-by-id.zip" name = "getEmployeeById" trigger = "http-trigger" runtime = "go121" entrypoint = "GetEmployee" }, "getallemployees" : { zip = "../function-zips/get-all-employees.zip" name = "getAllEmployees" trigger = "http-trigger" runtime = "go121" entrypoint = "GetAllEmployees" }, "updateemployee" : { zip = "../function-zips/update-employee.zip" name = "updateEmployee" trigger = "http-trigger" runtime = "go121" entrypoint = "UpdateEmployee" } } }
问题原因分析
- 打包逻辑错误:
data "archive_file"的source_dir设为整个../function-zips目录,会把所有函数的Zip包重新打包一次,而非基于修改后的单个函数代码生成新包;同时Terraform的data资源默认缓存结果,源文件变化时不会自动重新生成包。 - GCS对象未更新:
google_storage_bucket_object直接使用本地旧Zip路径,Terraform无法检测到文件内容变化,不会重新上传到存储桶。 - 流量未切换到新版本:
all_traffic_on_latest_revision = false导致即使生成了新的函数修订版,流量仍指向旧版本,直观表现为代码未更新。 - 函数未触发重新构建:GCF v2未感知到GCS对象的变化,没有触发新的构建流程。
解决方案
1. 修复代码打包逻辑
调整archive_file为单个函数代码目录打包,并添加哈希校验触发更新:
data "archive_file" "function_src" { for_each = var.functions type = "zip" output_path = "/tmp/${each.value.zip}" // 假设每个函数的代码存放在单独目录,如../functions/createemployee source_dir = "../functions/${each.key}" // 依赖代码文件的MD5哈希,确保代码变化时重新生成Zip depends_on = [filemd5("../functions/${each.key}/main.go")] }
2. 确保GCS对象更新
使用archive_file生成的新Zip作为源,并添加MD5哈希检测变化:
resource "google_storage_bucket_object" "function_zip" { for_each = var.functions name = each.key bucket = google_storage_bucket.bucket.name source = data.archive_file.function_src[each.key].output_path // 用生成的Zip的MD5值触发GCS对象更新 md5hash = data.archive_file.function_src[each.key].md5 }
3. 让函数感知变化并切换流量
修改函数配置,确保触发重新构建并自动切换到最新版本:
resource "google_cloudfunctions2_function" "function" { for_each = var.functions name = each.value.name location = var.region build_config { runtime = each.value.runtime entry_point = each.value.entrypoint source { storage_source { bucket = google_storage_bucket.bucket.name object = google_storage_bucket_object.function_zip[each.key].name } } // 依赖GCS对象,确保对象更新后触发函数构建 depends_on = [google_storage_bucket_object.function_zip[each.key]] } service_config { min_instance_count = 1 available_memory = "128Mi" timeout_seconds = 120 all_traffic_on_latest_revision = true // 自动切换流量到最新版本 service_account_email = "terraform-gcf@terraform-cloud-functions-ems.iam.gserviceaccount.com" } }
4. 清理缓存并重新部署
- 删除
/tmp目录下的旧Zip文件 - 执行
terraform refresh刷新状态 - 重新运行
terraform apply
内容的提问来源于stack exchange,提问作者Shreyas Awankar
相关产品推荐
相关产品推荐

