Terraform中如何在for_each里引用未在映射中的file_system_id?
解决方案:Terraform中引用for_each创建的EFS资源ID
问题核心
你当前的EFS资源aws_efs_file_system.efs使用的for_each逻辑错误——遍历了var.efs_config的每个配置键(如efs_enabled、efs_creation_token),导致会创建多个无效的EFS实例,同时后续无法正确引用唯一的file_system_id。需要先修正EFS的创建逻辑,再解决引用问题。
步骤1:修正EFS文件系统的for_each配置
将EFS的for_each调整为仅在efs_enabled为true时创建单个实例,确保资源集合只有一个元素:
resource "aws_efs_file_system" "efs" { # 仅当EFS启用时,创建一个以"single_efs"为键的实例 for_each = var.efs_config.efs_enabled ? { single_efs = var.efs_config } : {} creation_token = each.value.efs_creation_token encrypted = each.value.efs_encrypt kms_key_id = aws_kms_key.efs_kms.arn tags = { Name = replace("${var.project_name}-${each.value.efs_vpc}-EFS", " ", "") } }
步骤2:引用EFS ID到备份策略
使用for_each关联EFS资源,确保仅当EFS存在时才创建备份策略,直接通过each.value.id获取ID:
resource "aws_efs_backup_policy" "efs_backup_policy" { for_each = aws_efs_file_system.efs file_system_id = each.value.id backup_policy { status = "ENABLED" } }
步骤3:在挂载目标中引用EFS ID
由于只有一个EFS实例,使用one()函数提取唯一的file_system_id,同时修正subnet_id的空值问题(原逻辑会导致web子网的EC2无法获取子网ID):
resource "aws_efs_mount_target" "efs_mount_target" { for_each = var.ec2_servers # 提取唯一的EFS文件系统ID file_system_id = one(aws_efs_file_system.efs.*.id) # 移除无效的subnet_name判断,确保正确获取子网ID subnet_id = aws_subnet.private["${each.value.vpc_name}.${each.value.subnet_name}.${each.value.availability_zone}"].id # 注意:固定IP会导致多AZ挂载目标冲突,建议移除或配置AZ专属IP # ip_address = lookup(var.efs_config, "efs_private_ip") security_groups = [aws_security_group.ec2[each.key].id] }
关键说明
one()函数:当资源集合只有一个元素时,自动提取其值,避免手动指定键名。- 挂载目标IP问题:每个挂载目标的IP必须在对应子网的可用IP范围内,且同一子网内不能重复,固定IP仅适用于单AZ场景,多AZ需配置不同IP。
内容的提问来源于stack exchange,提问作者George Drew
相关产品推荐
相关产品推荐

