如何让Terraform仅重新部署代码变更的Cloud Function?
实现仅重新部署代码变更的Cloud Function
你当前的问题核心在于所有Cloud Function共用了同一套代码归档和存储桶对象资源,导致单个函数代码变更会触发全局MD5更新,进而所有函数都被重新部署。要解决这个问题,关键是让每个函数拥有独立的代码归档、存储桶对象资源,具体实现如下:
1. 为每个函数创建独立的代码归档
每个函数的代码目录独立,单独定义data.archive_file资源,这样只有对应目录下的代码变更时,该资源的output_md5才会变化。
示例代码:
# 函数A的代码归档 data "archive_file" "function_a_source" { type = "zip" source_dir = "./functions/function-a" # 函数A专属代码目录 output_path = "./build/function-a.zip" } # 函数B的代码归档 data "archive_file" "function_b_source" { type = "zip" source_dir = "./functions/function-b" # 函数B专属代码目录 output_path = "./build/function-b.zip" }
2. 为每个函数创建独立的存储桶对象
每个函数对应独立的google_storage_bucket_object,用自身归档的MD5命名,确保只有该函数代码变更时,存储桶对象名称才会更新。
示例代码:
# 函数A的存储桶对象 resource "google_storage_bucket_object" "function_a_zip" { name = "function-a#${data.archive_file.function_a_source.output_md5}" bucket = var.bucket.name source = data.archive_file.function_a_source.output_path } # 函数B的存储桶对象 resource "google_storage_bucket_object" "function_b_zip" { name = "function-b#${data.archive_file.function_b_source.output_md5}" bucket = var.bucket.name source = data.archive_file.function_b_source.output_path }
3. 每个Cloud Function关联自身的存储桶对象
让每个google_cloudfunctions_function资源只引用对应函数的存储桶对象名称,这样只有当该对象名称变化时,函数才会触发重新部署。
示例代码:
# 函数A的Cloud Function配置 resource "google_cloudfunctions_function" "function_a" { name = "function-a" runtime = "java11" available_memory_mb = 256 source_archive_bucket = var.bucket.name source_archive_object = google_storage_bucket_object.function_a_zip.name timeout = 120 entry_point = "com.example.FunctionA" event_trigger { event_type = "google.storage.object.finalize" resource = "projects/${var.project_id}/buckets/${var.bucket.name}" } environment_variables = { PROJECT_ID = var.project_id } } # 函数B的Cloud Function配置 resource "google_cloudfunctions_function" "function_b" { name = "function-b" runtime = "java11" available_memory_mb = 256 source_archive_bucket = var.bucket.name source_archive_object = google_storage_bucket_object.function_b_zip.name timeout = 120 entry_point = "com.example.FunctionB" event_trigger { event_type = "google.pubsub.topic.publish" resource = "projects/${var.project_id}/topics/my-topic" } environment_variables = { PROJECT_ID = var.project_id } }
进阶:用Terraform模块封装(推荐)
如果函数数量较多,重复写上述配置会很繁琐,用模块封装单个Cloud Function的逻辑,通过模块调用创建多个函数,既保证资源独立,又简化维护。
模块目录结构
modules/ cloud-function/ main.tf variables.tf outputs.tf
模块main.tf示例
# 模块内的代码归档 data "archive_file" "source" { type = "zip" source_dir = var.source_dir output_path = "${var.build_dir}/${var.function_name}.zip" } # 模块内的存储桶对象 resource "google_storage_bucket_object" "zip_file" { name = "${var.function_name}#${data.archive_file.source.output_md5}" bucket = var.bucket_name source = data.archive_file.source.output_path } # 模块内的Cloud Function resource "google_cloudfunctions_function" "function" { name = var.function_name runtime = var.runtime available_memory_mb = var.memory source_archive_bucket = var.bucket_name source_archive_object = google_storage_bucket_object.zip_file.name timeout = var.timeout entry_point = var.entry_point event_trigger { event_type = var.event_trigger_type resource = var.event_trigger_resource } environment_variables = var.environment_variables timeouts { create = "60m" } }
根模块调用示例
# 创建函数A module "function_a" { source = "./modules/cloud-function" function_name = "function-a" runtime = "java11" memory = 256 timeout = 120 entry_point = "com.example.FunctionA" source_dir = "./functions/function-a" build_dir = "./build" bucket_name = var.bucket.name event_trigger_type = "google.storage.object.finalize" event_trigger_resource = "projects/${var.project_id}/buckets/${var.bucket.name}" environment_variables = { PROJECT_ID = var.project_id } } # 创建函数B module "function_b" { source = "./modules/cloud-function" function_name = "function-b" runtime = "java11" memory = 256 timeout = 120 entry_point = "com.example.FunctionB" source_dir = "./functions/function-b" build_dir = "./build" bucket_name = var.bucket.name event_trigger_type = "google.pubsub.topic.publish" event_trigger_resource = "projects/${var.project_id}/topics/my-topic" environment_variables = { PROJECT_ID = var.project_id } }
这样修改后,只有代码发生变更的函数对应的归档、存储桶对象会更新,进而触发该函数的重新部署,其他函数不受影响。
内容的提问来源于stack exchange,提问作者GiuxG97
相关产品推荐
相关产品推荐

