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

如何让Terraform aws_security_group的使用遵循DRY原则

解决Terraform AWS安全组的DRY复用问题

我明白你的痛点——当前的实现只能让每个安全组绑定单条Ingress规则,没法在一个安全组里灵活添加多条规则,这确实不够复用。咱们可以通过调整变量结构+使用Terraform的dynamic块来解决这个问题,完美遵循DRY原则。

第一步:重构变量结构

首先修改variables.tf,让每个安全组变量包含一个ingress_rules列表,用来存储该安全组下的所有Ingress规则:

variable "security_groups" {
  type = list(object({
    name        = string
    description = string
    ingress_rules = list(object({
      from_port = number
      to_port   = number
      protocol  = string
      cidrs     = string
      description = optional(string) # 可选的规则描述
    }))
  }))
  default = [
    {
      name        = "staging_ssh_and_http"
      description = "Staging SSH and HTTP access"
      ingress_rules = [
        {
          from_port   = 22
          to_port     = 22
          protocol    = "tcp"
          cidrs       = "10.0.0.5/32,10.0.0.50/32,10.0.0.200/32"
          description = "Allow SSH from specific IPs"
        },
        {
          from_port   = 80
          to_port     = 80
          protocol    = "tcp"
          cidrs       = "0.0.0.0/0"
          description = "Allow HTTP from anywhere"
        }
      ]
    }
  ]
}

这里用了Terraform的object类型来定义更清晰的变量结构,每个安全组可以包含多条独立的Ingress规则,完全满足你的需求。

第二步:用Dynamic块生成Ingress规则

然后修改main.tf,使用dynamic "ingress"块来动态遍历每个安全组下的Ingress规则列表,自动生成对应的Ingress配置:

resource "aws_security_group" "this_security_group" {
  count = length(var.security_groups)

  name        = var.security_groups[count.index].name
  description = var.security_groups[count.index].description
  vpc_id      = aws_vpc.this_vpc.id

  # 动态生成Ingress规则
  dynamic "ingress" {
    for_each = var.security_groups[count.index].ingress_rules
    content {
      from_port       = ingress.value.from_port
      to_port         = ingress.value.to_port
      protocol        = ingress.value.protocol
      cidr_blocks     = split(",", ingress.value.cidrs)
      description     = ingress.value.description != "" ? ingress.value.description : "Ingress rule"
    }
  }

  # 默认Egress规则
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name        = var.security_groups[count.index].name
    environment = var.name
    terraform   = "true"
  }
}

关键变化说明:

  • 用dynamic "ingress"块替代了原来的单个ingress块,通过for_each遍历当前安全组的所有ingress_rules,自动生成对应数量的Ingress规则
  • 变量结构更清晰,每个安全组的规则都聚合在一起,维护起来更方便
  • 保留了CIDR字符串拆分的逻辑,同时新增了可选的规则描述,灵活性更高
  • 完全遵循DRY原则,不用为每个规则单独创建安全组,一个安全组可以包含任意数量的Ingress规则

这样调整后,你的模块就可以灵活地创建包含多条Ingress规则的安全组了,不管是单个端口还是多个端口的场景都能覆盖,复用性拉满!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:01:39