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



有没有更好的方法来优化下面的代码,这样我就不必一次又一次地要求可用性区域,而是可以一次完成。因为区域是可变的,所以我不能定义硬编码的可用区域。你们好吗?我希望我的公共子网是/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]
}

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

其中的一个关键部分是确保Terraform了解每个子网都属于一个特定的可用性区域,这样,当可用性区域集发生变化时,Terraform可以为新可用性区域添加一个新子网,也可以为现已删除的可用性区域删除一个现有子网,而不会影响其他未更改的子网。实现这一点的最简单方法是使用资源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地址空间分配给可用性区域,这样网络就不会因可用性区域集的未来更改而重新编号。

aws_availability_zone数据源的文档包括一个声明映射表的示例,该映射表为每个区域和每个可用性区域分配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块10.1.48.0/20的单个aws_vpc.example,其中48是十六进制0x30的十进制表示,其中3是us-west-2的数字
  • 具有CIDR块10.1.49.0/24us-west-2a中的子网aws_subnet.example["us-west-2a"],其中49是十六进制0x31的十进制表示
  • 具有CIDR块10.1.51.0/24us-west-2c中的子网aws_subnet.example["us-west-2c"],其中51是十六进制0x33的十进制表示

请注意,10.1.50.0/24没有子网,因为50(十六进制0x32(是为假设的us-west-2b保留的。通过按子网字母静态分配这些地址,我们可以确保它们不会随着时间的推移而随着可用性区域的添加和删除而更改。

您可以使用count和cidrsubnets自动创建子网。

例如:

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]
}

以上将自动在每个AZ中创建子网cidr块(/24,假设vpc为/16(。

最新更新