Terraform:以编程方式为多个VPC对等连接生成多个路由表

时间:2016-10-28 00:19:28

标签: amazon-web-services devops terraform

使用terraform-0.7.7。我或多或少地关注最佳实践回购,AWS部分:

https://github.com/hashicorp/best-practices/tree/master/terraform

我正在努力想出一个用于构建VPC的通用模板。我们的想法是拥有一个带有多个子模块的network模块(vpc,private_subnet等),并且只需从terraform.tfvars文件中插入不同的变量,以构建不同的环境。

让我们在.tfvars文件中说一个环境我有一个可用区列表,另一个列表包含私有子网的IP块:

azs             = "us-west-2a,us-west-2b,us-west-2c"
private_subnets = "10.XXX.1.0/24,10.XXX.2.0/24,10.XXX.3.0/24"

network / private_subnets模块将根据这些列表愉快地创建子网,路由表和关联:

resource "aws_subnet" "private" {
  vpc_id            = "${var.vpc_id}"
  cidr_block        = "${element(split(",", var.cidrs), count.index)}"
  availability_zone = "${element(split(",", var.azs), count.index)}"
  count             = "${length(split(",", var.cidrs))}"

  tags      { Name = "${var.name}-${element(split(",", var.azs), count.index)}-private" }
  lifecycle { create_before_destroy = true }
}

resource "aws_route_table" "private" {
  vpc_id = "${var.vpc_id}"
  count  = "${length(split(",", var.cidrs))}"

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = "${element(split(",", var.nat_gateway_ids), count.index)}"
  }

  tags      { Name = "${var.name}-${element(split(",", var.azs), count.index)}-private" }
  lifecycle { create_before_destroy = true }
}

resource "aws_route_table_association" "private" {
  count          = "${length(split(",", var.cidrs))}"
  subnet_id      = "${element(aws_subnet.private.*.id, count.index)}"
  route_table_id = "${element(aws_route_table.private.*.id, count.index)}"

  lifecycle { create_before_destroy = true }
}

效果很好。对于每个环境,我都有不同的azsprivate_subnets列表,并且正确创建了VPC。 NAT网关在此之前在不同的模块中创建。我有一个NAT网关,一个私有子网和一个私有路由表,每个AZ。

但现在我试图以同样的方式创建VPC对等连接。

peer_vpc_ids    = "vpc-XXXXXXXX, vpc-YYYYYYYY"
peer_vpc_blocks = "10.XXX.0.0/16, 10.YYY.0.0/16"

所以现在我需要编写进入私有路由表的Terraform代码,并为每个VPC对等连接添加路由。

问题是,我需要迭代两个变量:AZ列表和对等连接列表,而Terraform似乎不允许这样做。 AFAICT,你不能在Terraform中做嵌套循环。

我错过了什么吗?有没有更好的方法来解决这个问题?

当然,我可以手工编写一些自定义的意大利面条代码,无论如何构建VPC,但这里的目标是保持代码的可组合性和可维护性,并将逻辑与属性分开。

1 个答案:

答案 0 :(得分:1)

你可以通过element插值方法的一些数学来实现这个目的:

resource "aws_vpc_peering_connection" {
  peer_vpc_ids = "${element(var.vpc_ids, count.index)}"
  peer_vpc_blocks = "${element(var.vpc_blocks,floor(count.index / length(var.vpc_ids))}"
  count = "${length(var.vpc_ids) * length(var.vpc_blocks)}"
}

具体而言,element(var.vpc_blocks,floor(count.index / length(var.vpc_ids))调用将使每个var.vpc_ids值的VPC块增加1。