Terraform 具有地形的子网的创建顺序

Terraform 具有地形的子网的创建顺序,terraform,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.

我需要创建低于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的顺序创建

地形模块:

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))}
    }
}
最新答复: 由于评论中的讨论,我修改了我的答案:

您正在假定字典中的顺序。这不是故意的行为。从您的示例中,可以看到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\u zones
不匹配,您假定索引的排序与
var.private\u子网的排序相同

依靠上述顺序(按字母顺序)不是一个好的解决方案,因为它可能会随着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\u zones
列表的索引。但是,您也可以直接考虑使用可用性区域。 代码的调整非常简单:获取(
element(…)
)列表元素以获取映射,然后
查找(…)
所需的键

旧答案(此处不适用): 在Terraform创建任何资源之前,它会创建一个图形结构来表示它要跟踪的所有对象(创建、更新、删除)以及它们之间的依赖关系

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

当Terraform现在尝试创建属性时,它会在(可能)多个线程中同时创建属性,并且如果资源彼此不依赖,则可能同时创建资源。 这就是为什么您可能会在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"
 }
请注意,这是一项功能,因为如果要创建的许多资源彼此之间没有依赖关系,那么它们都是同时创建的,通过长时间运行的创建操作可以节省大量时间


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


回答这些问题会使您正确地根据所需布局对代码进行建模。

为什么您的
private\u子网
是一个地图而不是一个简单的列表?在这里,您似乎根本没有使用x、y、z值。我们正在根据这些名称设置标记和其他一些计算。我很确定,它只是通过一些散列对映射进行排序,而不是其他任何内容。对于相同的密钥,它应该是稳定的。不能保证执行顺序。多个资源通常由多个线程创建(您可以观察到,如果您有一个创建时间很长的资源,即一个
azurerm\u kubernetes\u集群
)。当它被创建时,其他资源被并行地创建。虽然确定图的一个部分的算法可能是固定的(从而为同一版本提供相同的结果),没有任何保证。除了它在地图中循环,所以它是按键排序的。执行顺序与此顺序无关。OP只关心顺序,因为它将子网链接到与预期不同的可用性区域,因为循环的顺序不同。我怀疑他们是否关心哪个子网是首先创建的。