首页 > 解决方案 > 使用 terraform 创建子网的顺序

问题描述

我需要创建 6 个低于 cidr 值的子网,但是在使用 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

解决方案


更新答案:

感谢评论中的讨论,我修改了我的答案:

您假设字典中的顺序。这不是预期的行为。从您的示例中可以看出,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您假设索引的排序与 for 相同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 创建任何资源之前,它会创建一个图形结构来表示它想要跟踪(创建、更新、删除)的所有对象以及彼此之间的依赖关系。

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

当 Terraform 现在尝试创建属性时,它会在(可能)多个线程中同时创建资源,如果它们不相互依赖,则可能同时创建资源。这就是为什么您可能会在 terraform 的多次运行中看到非常不同的执行顺序。

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


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

回答这些问题应该会带您进入正确的方向,根据您所需的布局对代码进行建模。


推荐阅读