使用terraform在每个可用区域中创建多个子网

时间:2019-07-12 12:31:34

标签: amazon-web-services terraform vpc

我是新来的Terraform。我想使用terraform在AWS的特定区域中为每个可用性区域创建一个公共子网和三个私有子网。通过引用以下链接https://medium.com/@maneetkum/create-subnet-per-availability-zone-in-aws-through-terraform-ea81d1ec1883,我可以为每个可用性区域创建一个私有和公共子网。但是,我需要将创建的一个私有子集拆分为另一个2。在terraform中可能吗?

data "aws_availability_zones" "available" {}resource "aws_vpc" "myVpc" {
  cidr_block           = "10.20.0.0/16"
  enable_dns_hostnames = true
  tags {
    Name = "myVpc"
  }
}
resource "aws_subnet" "public_subnet" {
  count = "${length(data.aws_availability_zones.available.names)}"
  vpc_id = "${aws_vpc.myVpc.id}"
  cidr_block = "10.20.${10+count.index}.0/24"
  availability_zone = "${data.aws_availability_zones.available.names[count.index]}"
  map_public_ip_on_launch = true
  tags {
    Name = "PublicSubnet"
  }
}
resource "aws_subnet" "private_subnet" {
  count = "${length(data.aws_availability_zones.available.names)}"
  vpc_id = "${aws_vpc.myVpc.id}"
  cidr_block = "10.20.${20+count.index}.0/24"
  availability_zone= "${data.aws_availability_zones.available.names[count.index]}"
  map_public_ip_on_launch = false
  tags {
    Name = "PrivateSubnet"
  }
}

上面的代码用于在每个可用区域中创建一个私有和公共子网。

2 个答案:

答案 0 :(得分:0)

您可以简单地复制private_subnet资源元素以在每个可用区中创建两个新的子网:

...
resource "aws_subnet" "private_subnet" {
  count = "${length(data.aws_availability_zones.available.names)}"
  vpc_id = "${aws_vpc.myVpc.id}"
  cidr_block = "10.20.${20+count.index}.0/24"
  availability_zone= "${data.aws_availability_zones.available.names[count.index]}"
  map_public_ip_on_launch = false
  tags {
    Name = "PrivateSubnet"
  }
}
resource "aws_subnet" "private_subnet_2" {
  count = "${length(data.aws_availability_zones.available.names)}"
  vpc_id = "${aws_vpc.myVpc.id}"
  cidr_block = "10.30.${20+count.index}.0/24"
  availability_zone= "${data.aws_availability_zones.available.names[count.index]}"
  map_public_ip_on_launch = false
  tags {
    Name = "PrivateSubnet2"
  }
}

您将需要修改每个子网的CIDR块,以确保它们不会相互重叠。

答案 1 :(得分:0)

可以创建多个子网,并自动将它们放入可用区,而无需复制代码。让我们保持事情DRY。为避免重复代码,请使用 Terraform 元参数和内置函数的魔力。具体来说,使用“count”和“cidrsubnet”。 “count”将生成任意数量的子网副本。

如果您想为每个子网提供唯一的值,例如子网的标签 Name,您可以为每个子网提供一个唯一的助记名称,方法是使用您指定的名称创建数据字典。想分配给每个子网。然后在创建子网时使用“count.index”分配它们。如果工作量太大,您也可以在名称中嵌入 count.index

不同的区域有不同数量的可用区。为确保将子网分配给实际退出的可用区,您应该动态生成 list of the Availability Zones。这样,您就知道列表中的所有可用区实际上在您工作的区域都可用。

如果您有更多子网,然后该区域有可用区,会发生什么情况?使用 modulo 算法来包装您的工作索引。不要直接使用 index.count,而是使用列表的 moduloindex.count 上执行 length。这将环绕索引,因此您的工作索引永远不会溢出可用区列表的长度。

但是,真正的魔法是“cidrsubnet”命令。下面的示例将采用传递的基本 CIDR 块的大小(恰好是 /16),添加第二个参数 (4),并生成一个 /20 CIDR 块。第三个参数通过可用的 CIDR 块索引,从而确保每个子网获得不同的子 CIDR 块。

注意:相关的 cidrsubnets 命令有很大的不同。所以,要小心,不要混淆这两个函数。

resource "aws_subnet" "area_subnets" {
  count                   = 4 # creates four subnets
  vpc_id                  = var.area_vpc_id
  map_public_ip_on_launch = var.map_public_ip_on_launch

  cidr_block           = cidrsubnet(var.area_subnet_cidr, 4, count.index)
  availability_zone_id = data.aws_availability_zones.available.zone_ids[count.index % length(data.aws_availability_zones.available.zone_ids)]

  tags = tomap({ "Name" = "${var.subnet_names[count.index]}" })
}

variable "subnet_names" {
  type = list(string)
  default = [
    "Primary NAT Gateway Subnet",
    "Secondary NAT Gateway Subnet",
    "Channel A Subnet",
    "Channel B Subnet"
  ]
}

variable "map_public_ip_on_launch" {
  type    = bool
  default = true
}

variable "area_vpc_id"
    documentation = "The Terraform ID of the containing VPC"
    type = string
    default = "vpc-abcdefghijklmno"
}

variable "area_subnet_cidr"
    documentation = "The base CIDR that you are working with"
    type = string
    default = "10.0.0.0/16"
}

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

  filter { # Only fetch Availability Zones (no Local Zones)
    name   = "opt-in-status"
    values = ["opt-in-not-required"]
  }
}