You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS与Terraform:遍历远程状态配置安全组Ingress的语法问题

问题描述

我在配置Terraform时遇到语法问题,通过以下代码读取S3中的Terraform远程状态:

data "terraform_remote_state" vpc {
    backend = "s3"
    config = {
        region         = "eu-west-1"
        bucket         = "some-terraform-bucket"
        key            = "some-vpc-state.tfstate"
    }
}

该远程状态包含类型为list(string)的private_subnets_cidr_blocks,值如下:

private_subnets_cidr_blocks 
value   
0   "20.10.8.0/24"
1   "20.10.9.0/24"
2   "20.10.10.0/24"
type    
0   "list"
1   "string"

我尝试将这些CIDR块添加到安全组的Ingress规则中,使用了如下配置:

module "security_group" {
  source  = "terraform-aws-modules/security-group/aws"
  version = "~> 5.0"

  name        = "${var.name}-${var.environment}-redis"
  description = "Redis example security group"
  vpc_id      = data.terraform_remote_state.vpc.outputs.vpc_id
  count = length(data.terraform_remote_state.vpc.outputs.elasticache_subnets_cidr_blocks)
  # ingress
  ingress_with_cidr_blocks = [
    {
      for_each = data.terraform_remote_state.vpc.outputs.private_subnets_cidr_blocks
      from_port   = 6379
      to_port     = 6379
      protocol    = "tcp"
      description = "Redis access from within VPC"
      cidir_blocks = [each.value]
    }
  ]

  tags = local.default_tags
}

但出现错误:

The given value is not suitable for module.security_group.var.ingress_with_cidr_blocks declared at .terraform/modules/security_group/variables.tf:85,1-36: element 0: element "cidir_blocks": string required.

我期望将CIDR块拼接为如下格式的字符串供Terraform处理:

cidr_blocks = "20.10.8.0/24, 20.10.9.0/24,20.10.10.0/24"
解决方案

错误原因分析

  1. for_each使用位置错误:不能在ingress_with_cidr_blocks的单个对象内部使用for_each,需用Terraform列表推导式生成规则列表。
  2. 拼写错误:配置中写的cidir_blocks是笔误,正确参数名应为cidr_blocks,这是报错的直接原因之一。
  3. 格式不匹配:该安全组模块的cidr_blocks支持字符串(逗号分隔)或列表类型,原写法把单个CIDR放入列表,叠加拼写错误导致类型不兼容。

正确实现方式

写法1:合并所有CIDR为单条规则(逗号分隔字符串)

用join函数将列表拼接成逗号分隔的字符串,创建一条覆盖所有私有子网的Ingress规则:

module "security_group" {
  source  = "terraform-aws-modules/security-group/aws"
  version = "~> 5.0"

  name        = "${var.name}-${var.environment}-redis"
  description = "Redis example security group"
  vpc_id      = data.terraform_remote_state.vpc.outputs.vpc_id

  ingress_with_cidr_blocks = [
    {
      from_port   = 6379
      to_port     = 6379
      protocol    = "tcp"
      description = "Redis access from within VPC"
      cidr_blocks = join(", ", data.terraform_remote_state.vpc.outputs.private_subnets_cidr_blocks)
    }
  ]

  tags = local.default_tags
}

写法2:为每个CIDR创建单独Ingress规则

如果需要为每个子网CIDR生成独立规则,使用列表推导式:

module "security_group" {
  source  = "terraform-aws-modules/security-group/aws"
  version = "~> 5.0"

  name        = "${var.name}-${var.environment}-redis"
  description = "Redis example security group"
  vpc_id      = data.terraform_remote_state.vpc.outputs.vpc_id

  ingress_with_cidr_blocks = [
    for cidr in data.terraform_remote_state.vpc.outputs.private_subnets_cidr_blocks : {
      from_port   = 6379
      to_port     = 6379
      protocol    = "tcp"
      description = "Redis access from ${cidr}"
      cidr_blocks = cidr # 直接用单个字符串,或用列表[cidr]也可,模块均支持
    }
  ]

  tags = local.default_tags
}

额外说明

  • 移除了不必要的count参数,只需创建一个安全组,内部包含对应Ingress规则即可。
  • 该安全组模块的ingress_with_cidr_blocks参数中,cidr_blocks同时支持字符串(逗号分隔)和列表类型,两种写法都能被正确解析。

内容的提问来源于stack exchange,提问作者Ric_Harvey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 12:53:25