Terraform中能否使用同名key不同值的多个local块?
Terraform 同名本地变量(local)的优先级问题
问题背景
现有以下Terraform本地变量块,其中domain值为cs,用于生成S3制品桶名称:
locals { organization = "xxxx" domain = "cs" env = { prod = "prod" stg = "stg" dev = "dev" } } locals { s3_artifact_bucket_name = { prod = join("-", [ local.s3_artifact_bucket_name_prefix, local.env["prod"] ]) stg = join("-", [ local.s3_artifact_bucket_name_prefix, local.env["stg"] ]) dev = join("-", [ local.s3_artifact_bucket_name_prefix, local.env["dev"] ]) } s3_artifact_bucket_name_prefix = join("-", [ local.organization, local.domain, local.s3_bucket_awsresource, local.s3_artifact_bucket_purpose ]) s3_bucket_awsresource = join("-", [ "bucket", var.cd_account_id ]) s3_artifact_bucket_purpose = "artifacts-iac" }
现在需要新增一个本地变量块,其中domain值为common,用于生成访问日志S3桶名称:
locals { # placeholder for access logs bucket name domain = "common" s3_bucket_awsresource = join("-", [ "bucket", var.cd_account_id ]) s3_bucket_purpose = "s3-access-logs" access_logs_bucket_region = "us-east-1" }
后续引用local.domain时希望指向common而非cs,有两个疑问:
- 最终
local.domain会指向哪个值? - 是否允许在不同
locals块中使用同名的domain键并赋予不同值?
核心结论
- 同名local变量的覆盖规则
Terraform会按locals块的定义顺序处理,后定义的locals块中的同名变量会直接覆盖之前的。也就是说,你新增的domain = "common"块在原有domain = "cs"块之后,最终local.domain的值会是common,所有后续引用local.domain的地方都会使用这个值。
但要注意:原有locals块中依赖local.domain的变量(比如s3_artifact_bucket_name_prefix),会使用定义它们时生效的domain值——也就是最初的cs,因为这些变量是在第一个domain所在块之后、第二个domain块之前定义的,Terraform在计算这些变量时,当时的local.domain还是cs。
- 是否允许同名键?
允许在多个locals块中使用同名变量键,但会触发Terraform的变量覆盖行为,容易引发逻辑混淆,不推荐这么做。
更清晰的解决方案
为了避免变量覆盖带来的混乱,建议给不同用途的domain变量起明确的名字,比如:
locals { organization = "xxxx" domain_cs = "cs" domain_common = "common" env = { prod = "prod" stg = "stg" dev = "dev" } } # 生成制品桶的相关变量 locals { s3_artifact_bucket_name = { prod = join("-", [ local.s3_artifact_bucket_name_prefix, local.env["prod"] ]) stg = join("-", [ local.s3_artifact_bucket_name_prefix, local.env["stg"] ]) dev = join("-", [ local.s3_artifact_bucket_name_prefix, local.env["dev"] ]) } s3_artifact_bucket_name_prefix = join("-", [ local.organization, local.domain_cs, local.s3_bucket_awsresource, local.s3_artifact_bucket_purpose ]) s3_bucket_awsresource = join("-", [ "bucket", var.cd_account_id ]) s3_artifact_bucket_purpose = "artifacts-iac" } # 生成访问日志桶的相关变量 locals { s3_bucket_awsresource_access_logs = join("-", [ "bucket", var.cd_account_id ]) s3_bucket_purpose_access_logs = "s3-access-logs" access_logs_bucket_region = "us-east-1" } locals { s3_artifact_access_logs_bucket_name = join("-", [ local.organization, local.domain_common, local.s3_bucket_awsresource_access_logs, local.s3_bucket_purpose_access_logs, local.access_logs_bucket_region ]) }
这样每个变量的用途明确,不会出现覆盖导致的意外行为,代码可读性也更高。
内容的提问来源于stack exchange,提问作者Jatin Mehrotra
相关产品推荐
相关产品推荐

