terraform子网的创建顺序

时间:2018-08-08 19:23:53

标签: terraform

我需要创建低于cidr值的6个子网,但是在使用terraform创建子网时,其顺序已更改。

private_subnets = {
    "10.1.80.0/27"   = "x"
    "10.1.80.32/27" = "x"
    "10.1.80.64/28"   = "y"
    "10.1.80.80/28" = "y"
    "10.1.80.96/27"   = "z"
    "10.1.80.128/27"   = "z"
 }

Terraform创建时具有10.1.80.0/27,10.1.80.128/27,10.1.80.32/27,10.1.80.64/28,10.1.80.80/28,10.1.80.96/27顺序

terraform模块:

resource "aws_subnet" "private" {
    vpc_id            = "${var.vpc_id}"
    cidr_block        = "${element(keys(var.private_subnets), count.index)}"
    availability_zone = "${element(var.availability_zones, count.index)}"
    count             = "${length(var.private_subnets)}"
    tags {
        Name         = "${lookup(var.private_subnets, element(keys(var.private_subnets), count.index))}
    }
}

1 个答案:

答案 0 :(得分:0)

更新的答案:

由于评论中的讨论,我修改了答案:

您正在假设字典中的顺序。这不是预期的行为。从您的示例中可以看到,terraform在内部按字母顺序对键进行排序,即,您可以将变量“认为”为

private_subnets = {
    "10.1.80.0/27"   = "x"
    "10.1.80.128/27" = "z"
    "10.1.80.32/27"  = "x"
    "10.1.80.64/28"  = "y"
    "10.1.80.80/28"  = "y"
    "10.1.80.96/27"  = "z"
 }

您遇到了问题,因为您与其他变量var.availability_zones不匹配,在该变量中您假定索引的排序方式与var.private_subnets相同。

依靠上述顺序(按字母顺序)并不是一个好的解决方案,因为它可能随任何版本的terraform改变(不保证键的顺序)。

因此,我建议使用地图列表:

private_subnets = [
    {
        "cidr" = "10.1.80.0/27"
        "name" = "x"
        "availability_zone" = 1
    },
    {
        "cidr" = "10.1.80.32/27"
        "name" = "x"
        "availability_zone" = 2
    }, 
    …
]

我将可用区域编码为您的var.availability_zones列表的索引。但是,您也可以考虑直接使用可用性区域。

代码的修改非常简单:获取(element(…))列表元素以获取地图,然后lookup(…)获得所需的键。

旧答案(此处不适用):

在Terraform创建任何资源之前,它会创建一个图结构来表示要跟踪(创建,更新,删除)的所有对象以及彼此之间的依赖关系。

在您的示例中,图中创建了6个不同的aws_subnet对象,它们彼此不依赖(一个子网中没有变量依赖于另一个子网)。

当Terraform现在尝试创建属性时,它将在多个线程中(潜在地)同时进行创建,并且如果它们彼此不依赖,则可能同时创建资源。 这就是为什么您可能会在terraform的多次运行中看到不同的执行顺序的原因。

请注意,这是一项功能,因为如果要创建的许多资源彼此不依赖,则可以同时创建所有资源,从而节省了长时间运行的创建操作的时间。


您的问题的解决方案是显式地建模您正​​在考虑的依赖项。为什么要先创建一个子网?如果是这样,如何使它们成为依赖项(例如,通过depends_on参数)?

回答此问题应使您朝正确的方向,以根据所需的布局对代码进行建模。