Terraform 中 cidrsubnet 函数的所有组件的动态插值

Dynamic interpolation of all components of cidrsubnet function in Terraform

在 Terraform 中有没有一种方法可以插入 cidrsubnet 函数的所有三个组件?我问这个的原因是因为我想创建具有不同 CIDR 前缀的 VPC,因此 cidrsubnet 函数负责为我创建子网。

据推测,VPC“prod”具有 CIDR 10.10.0.0/16,而 VPC“dev”具有 CIDR 10.20.0.0/24 .我正在寻找一种解决方案,其中相同的代码将通过插入 cidrsubnet 函数的值来为我创建子网,如下所示:

# map for different CIDR

variable "VPC_CIDR" {
    type = "map"
    default = {
        "dev" = "10.10.0.0/24"
        "prod" = "10.10.0.0/16"
    }
}

variable "PRI_SUBNET_COUNT" {
  default = "1"
}

# intended logic which interpolates netnum (impractical code)

if var.VPC_CIDR = "prod"
  netnum = 4
elif var.VPC_CIDR = "dev"
  netnum = 3   
else 
  netnum = 2

resource "aws_subnet" "sub-node-private" {
    count = var.PRI_SUBNET_COUNT
    cidr_block = cidrsubnet(var.VPC_CIDR, var.netnum, count.index + 2) #all three components interpolated

以上代码将为生产创建子网 CIDR 10.10.0.0/20,为开发创建子网 CIDR 10.10.0.0/28。这样我的代码保持不变,只有变量被插值。

N.B:此代码用于演示目的。众所周知,这不是 Terraform 中 if/else 的实用代码。

如果调用者可以选择 var.VPC_CIDR 的键,那么最好将 CIDR 前缀和用于其子网的新位数组合在变量中。由于命名 Terraform 变量的常规方式是小写,因此我将在以下示例中将其重命名为 vpc_cidr

variable "vpc_cidr" {
  type = map(object({
    cidr_block  = string
    subnet_bits = number
  }))
  default = {
    dev = {
      cidr_block  = "10.10.0.0/24"
      subnet_bits = 3
    }
    prod = {
      cidr_block  = "10.10.0.0/16"
      subnet_bits = 4
    }
  }
}

variable "pri_subnet_count" {
  type    = number
  default = 1
}

locals {
  vpc_subnets = flatten([
    for name, vpc in var.vpc_cidr : [
      for i in count(var.pri_subnet_count) : {
        name        = "${name}-${i}"
        vpc_name    = name
        cidr_block  = vpc.cidr_block
        subnet_bits = vpc.subnet_bits
        network_num = i + 2
      }
    ]
  ])
}

resource "aws_vpc" "example" {
  for_each = var.vpc_cidr

  cidr_block = each.value.cidr_block
}

resource "aws_subnet" "private" {
  for_each = { for s in local.vpc_subnets : s.name => s }

  vpc_id     = aws_vpc.example[each.value.vpc_name].id
  cidr_block = cidrsubnet(each.value.cidr_block, each.value.subnet_bits, each.value.network_num)
  # ...
}

如果名称 "prod" 和 "dev" 是固定的,因此您的模块将假定它们将始终被指定,您可以以类似于什么的方式自动导出 subnet_bits 值你这样描述的:

variable "vpc_cidr" {
  type = object({
    # Force caller to provide "dev" and "prod" values, so
    # that it will match up with the attributes in
    # local.subnet_bits defined below.
    dev  = string
    prod = string
  })
  value = {
    dev = "10.10.0.0/24"
    prod = "10.10.0.0/16"
  }
}

variable "pri_subnet_count" {
  type    = number
  default = 1
}

locals {
  subnet_bits = {
    dev  = 3
    prod = 4
  }

  vpcs = {
    for name, cidr_block in var.vpc_cidr : name => {
      cidr_block  = cidr_block
      subnet_bits = local.subnet_bits[name]
    }
  }

  vpc_subnets = flatten([
    for name, vpc in local.vpcs : [
      for i in count(var.pri_subnet_count) : {
        name        = "${name}-${i}"
        vpc_name    = name
        cidr_block  = vpc.cidr_block
        subnet_bits = vpc.subnet_bits
        network_num = i + 2
      }
    ]
  ])
}

resource "aws_vpc" "example" {
  for_each = local.vpcs

  cidr_block = each.value.cidr_block
}

resource "aws_subnet" "private" {
  for_each = { for s in local.vpc_subnets : s.name => s }

  vpc_id     = aws_vpc.example[each.value.vpc_name].id
  cidr_block = cidrsubnet(each.value.cidr_block, each.value.subnet_bits, each.value.network_num + 2)
  # ...
}

上面说明的一般模式是构建数据结构 local.vpc_subnets,其中包含您要创建的每个子网的一个元​​素。然后允许为每个元素重复 aws_subnet.private,并将填充子网上的 vpc_idcidr_block 参数所需的所有值聚集在一起。