遍历Terraform Locals未触发基础设施变更问题排查
问题背景
我的Terraform locals定义如下:
locals { preprocessed = { "first" = { tags = { name = "test" env = "dev" } users = [ "Admin", "DataEng" ] group_parameters = [ { name = "rds.logical_replication" value = "1" apply_method = "pending-reboot" } ] } processed = { for instance, settings in local.preprocessed : instance => { tags = settings.tags user_roles = [ for role in settings.admin_user_roles : "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${role}" ] group_parameters = settings.group_parameters } } }
通过terraform console验证,预期的processed结果应为:
processed = { "first" = { "group_parameters" = [ { "apply_method" = "pending-reboot" "name" = "rds.logical_replication" "value" = "1" } ] "tags" = { "env" = "dev" "name" = "test" } "user_roles" = [ "arn:aws:iam::123456789123:role/Admin", "arn:aws:iam::123456789123:role/DataEng" ] } }
但使用该processed遍历创建KMS密钥模块时:
module "kms_key" { for_each = local.processed source = "git@github.com:xyz/kms.git?ref=v1.0" external_access_principals = each.value["user_roles"] key_alias = each.key key_description = "key to encrypt ${each.key} instance" tags = each.key.tags }
执行terraform plan/apply时输出No changes. Your infrastructure matches the configuration.,无资源创建;但将local.processed替换为静态的预期结果时,Terraform能正常触发创建。
问题原因与修复
1. 字段引用错误:settings.admin_user_roles不存在
在processed的user_roles生成逻辑中,你引用了settings.admin_user_roles,但preprocessed里对应的字段是users,而非admin_user_roles。这会导致user_roles生成空列表,如果KMS模块对external_access_principals的空值有跳过逻辑(比如没有符合条件的主体则不创建资源),就会出现无变更的情况。
修复代码:
user_roles = [ for role in settings.users : "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${role}" ]
2. 模块参数引用错误:each.key.tags无效
模块调用中,each.key是processed的键(字符串"first"),字符串没有tags属性,正确的引用应该是each.value.tags。这个错误可能被模块的可选参数逻辑忽略,但叠加第一个错误会加剧异常。
修复后的模块调用:
module "kms_key" { for_each = local.processed source = "git@github.com:xyz/kms.git?ref=v1.0" external_access_principals = each.value["user_roles"] key_alias = each.key key_description = "key to encrypt ${each.key} instance" tags = each.value.tags }
3. 验证方式
在terraform console中直接执行local.processed,查看实际生成的user_roles是否为空列表,即可确认第一个问题的存在——你之前验证时可能手动修改了字段名,才得到了预期结果,但实际代码未修正。
内容的提问来源于stack exchange,提问作者Abhishek Malik

