为Terraform中的每个AWS可用性区域自动创建一个子网

时间:2020-09-21 11:12:49

标签: amazon-web-services terraform

是否有更好的方法来对下面的代码进行计时,所以我不必一遍又一遍地询问可用性区域,而可以一次完成一次。由于区域是可变的,所以我无法定义硬编码的可用性区域。你们能不能让我的公共子网设为/ 24

provider "aws" {
    region = var.region
}

resource "aws_vpc" "app_vpc" {
  cidr_block           = var.vpc_cidr
  enable_dns_support   = true
  enable_dns_hostnames = true
  tags = {
    Name = var.vpc_name
  }
}


data "aws_availability_zones" "available" {
  state = "available"
}

#provision public subnet
resource "aws_subnet" "public_subnet_01" {
  vpc_id     = aws_vpc.app_vpc.id
  cidr_block = var.public_subnet_01
  availability_zone = data.aws_availability_zones.available.names[0]
  tags = {
    Name = "public_subnet_01"
  }
  depends_on = [aws_vpc_dhcp_options_association.dns_resolver]
}
resource "aws_subnet" "public_subnet_02" {
  vpc_id     = aws_vpc.app_vpc.id
  cidr_block = var.public_subnet_02
  availability_zone = data.aws_availability_zones.available.names[1]
  tags = {
    Name = "public_subnet_02"
  }
  depends_on = [aws_vpc_dhcp_options_association.dns_resolver]
}
resource "aws_subnet" "public_subnet_03" {
  vpc_id     = aws_vpc.app_vpc.id
  cidr_block = var.public_subnet_03
  availability_zone = data.aws_availability_zones.available.names[2]
  tags = {
    Name = "public_subnet_03"
  }
  depends_on = [aws_vpc_dhcp_options_association.dns_resolver]
}

2 个答案:

答案 0 :(得分:0)

您可以使用countcidrsubnets自动创建子网。

一个例子是:

resource "aws_subnet" "public_subnet" {

  count             = length(data.aws_availability_zones.available.names)

  vpc_id            = aws_vpc.app_vpc.id
  cidr_block        = cidrsubnet(aws_vpc.app_vpc.cidr_block, 8, count.index)
  availability_zone = data.aws_availability_zones.available.names[count.index]
  
  tags = {
    Name = "public_subnet_${count.index}"
  }
  
  depends_on = [aws_vpc_dhcp_options_association.dns_resolver]
}

以上内容将自动在每个可用区中创建子网并进行分配 cidr块(/ 24,假设vpc是/ 16)。

答案 1 :(得分:0)

使用aws_availability_zones数据源要考虑的一个重要危险是可用区域集会随着时间的推移而变化,因此编写配置很重要,这样您就不会发现自己陷入困境。 Terraform认为您打算替换当前正在使用的子网,因此无法销毁。

其中的关键部分是确保Terraform理解每个子网都属于一个特定的可用区,以便在可用区集发生更改时Terraform可以为新的可用区添加新的子网或删除现有的现在已删除的可用区域的子网,而不会影响其他未更改的子网。最简单的方法是将resource for_each与一组可用区域结合使用:

resource "aws_subnet" "public" {
  for_each = aws_avaiability_zones.available.names

  # ...
}

以上内容将声明子网实例,每个子网实例的地址都包含可用性区域名称,如下所示:

  • aws_subnet.public["eu-west-1a"]
  • aws_subnet.public["eu-west-1b"]
  • aws_subnet.public["eu-west-1e"]

由于它们由可用区名称标识,因此Terraform可以看到每个子网都属于一个特定的可用区。

特别是对于子网,还有一个额外的挑战:我们必须为每个子网分配自己的CIDR块,这意味着我们需要一种系统的方式来将IP地址空间分配给可用区,以便将来的更改不会对网络进行重新编号到可用区域集。

the aws_availability_zone data source的文档包括一个声明映射表的示例,该映射表为每个区域和每个可用区分配1到14之间的数字,然后该数字用于填充IP地址的一个八位字节中的一个,以创建一个每个(区域,AZ)对使用单独的前缀。该示例仅创建一个VPC和一个子网,但是只要我们每次使用新区域或更新映射表时,都可以使用for_each对每个可用性区域进行扩展,就可以对其进行扩展。分配了新的可用区后缀字母(每个字母最多14个):

variable "region_number" {
  # Arbitrary mapping of region name to number to use in
  # a VPC's CIDR prefix.
  default = {
    us-east-1      = 1
    us-west-1      = 2
    us-west-2      = 3
    eu-central-1   = 4
    ap-northeast-1 = 5
  }
}

variable "az_number" {
  # Assign a number to each AZ letter used in our configuration
  default = {
    a = 1
    b = 2
    c = 3
    d = 4
    e = 5
    f = 6
    # and so on, up to n = 14 if that many letters are assigned
  }
}

data "aws_region" "current" {}

# Determine all of the available availability zones in the
# current AWS region.
data "aws_availability_zones" "available" {
  state = "available"
}

# This additional data source determines some additional
# details about each VPC, including its suffix letter.
data "aws_availability_zone" "all" {
  for_each = aws_avaiability_zones.available.names

  name = each.key
}

# A single VPC for the region
resource "aws_vpc" "example" {
  cidr_block = cidrsubnet("10.1.0.0/16", 4, var.region_number[data.aws_region.current.name])
}

# A subnet for each availability zone in the region.
resource "aws_subnet" "example" {
  for_each = aws_availability_zone.all

  vpc_id            = aws_vpc.example.id
  availability_zone = each.key
  cidr_block        = cidrsubnet(aws_vpc.example.cidr_block, 4, var.az_number[each.value.name_suffix])
}

例如,如果我们在us-west-2工作,并且有可用区us-west-2aus-west-2c,则上面将声明:

  • 带有CIDR块aws_vpc.example的单个10.1.48.0/20,其中48是十六进制0x30的十进制表示形式,其中3是us-west-2的数字。
  • aws_subnet.example["us-west-2a"]中具有us-west-2a的子网10.1.49.0/24中的子网aws_subnet.example["us-west-2c"],其中49是十六进制0x31的十进制表示形式。
  • us-west-2c中具有10.1.51.0/24的子网10.1.50.0/24中的子网us-west-2b,其中51是十六进制0x33的十进制表示形式。

请注意,nodeWords没有子网,因为为假设的ihash保留了50(十六进制0x32)。通过子网字母静态分配这些地址,我们可以确保随着添加和删除可用性区域,它们不会随时间变化。