今天,我正在努力构建几个定制的Terraform模块。我试图弄清楚如何解决模块中的依赖项的问题。在TF 0.12发布之前,我们无法声明一个模块依赖于另一个模块。因此,在此根目录下main.tf:

# ROOT level main.tf
# -------------------------------------------------------------------
# Create NAT Gateway - Associates EIP as well
# -------------------------------------------------------------------
module "vpc_nat_gateway" {
  source            = "./vpc_nat_gateway"
  vpc_id            = "${ module.vpc.id }"
  public_subnet_ids = "${ module.vpc_subnets.public_subnet_ids }"
  private_cidr      = "${ var.private_cidr }"
  common_tags       = "${ local.common_tags }"
}

# -------------------------------------------------------------------
# Create Private Routes
# -------------------------------------------------------------------
module "vpc_private_route" {
  source         = "./vpc_private_route"
  vpc_id.        = "${ module.vpc.id }"
  nat_gateway_id = "${ module.vpc_nat_gateway.nat_gateway_id }"
  common_tags    = "${ local.common_tags }"
}

# vpc_private_route module - main.tf
data "aws_nat_gateway" "az1" {
  vpc_id = "${ var.vpc_id }"

  tags {
    Name = "*NAT GW AZ 1"
  }
}

data "aws_nat_gateway" "az2" {
  vpc_id = "${ var.vpc_id }"

  tags {
    Name = "*NAT GW AZ 2"
  }
}


结果输出为:

------ SNIP -----
module.vpc_nat_gateway.aws_nat_gateway.nat[1]: Creation complete after 1m50s (ID: nat-02a7f4279cec3a6c8)
module.vpc_nat_gateway.aws_nat_gateway.nat.0: Still creating... (2m0s elapsed)
module.vpc_nat_gateway.aws_nat_gateway.nat[0]: Creation complete after 2m0s (ID: nat-0695a12d9c0305e4c)

    Error: Error applying plan:

    3 error(s) occurred:

    * module.vpc_private_route.data.aws_subnet_ids.private: data.aws_subnet_ids.private: no matching subnet found for vpc with id vpc-0b530d1885e74067b
    * module.vpc_private_route.data.aws_nat_gateway.az2: data.aws_nat_gateway.az2: no matching NAT gateway found: {
    Filter: [{
        Name: "vpc-id",
        Values: ["vpc-0b530d1885e74067b"]
        },{
        Name: "tag:Name",
        Values: ["*NAT GW AZ 2"]
        }]
    }
    * module.vpc_private_route.data.aws_nat_gateway.az1: data.aws_nat_gateway.az1: no matching NAT gateway found: {
    Filter: [{
        Name: "vpc-id",
        Values: ["vpc-0b530d1885e74067b"]
        },{
        Name: "tag:Name",
        Values: ["*NAT GW AZ 1"]
        }]
    }


在输出中观察到,创建了Nat网关。 Terraform show输出告诉我们过滤器是正确的:

    module.vpc_nat_gateway.aws_nat_gateway.nat.0:
        id = nat-0695a12d9c0305e4c
        allocation_id = eipalloc-023ca087ad4fb830e
        network_interface_id = eni-015e39fc8d3bc0de3
        private_ip = 172.16.254.16
        public_ip = 18.215.5.116
        subnet_id = subnet-0f2c039e8fd804f30
        tags.% = 7
        tags.Environment = development
        tags.Infrastructure = No
        tags.Name = **redacted** NAT GW AZ 1
    module.vpc_nat_gateway.aws_nat_gateway.nat.1:
        id = nat-02a7f4279cec3a6c8
        allocation_id = eipalloc-0a95264c2eef26673
        network_interface_id = eni-03bddcca2fbeeff44
        private_ip = 172.16.254.84
        public_ip = 3.91.167.246
        subnet_id = subnet-08ee61f3aa43acbe9
        tags.% = 7
        tags.Environment = development
        tags.Infrastructure = No
        tags.Name = **redacted** NAT GW AZ 2


执行后续terraform apply运行没有任何错误。

# Yes, the IDs are different in this example than from above.
# ---- SNIP ----
    module.vpc_private_route.data.aws_nat_gateway.az1:
        id = nat-0c127e538a26b2bd5
        allocation_id = eipalloc-01775b8e88502d4b9
        network_interface_id = eni-0b0bd2203bd3f5873
        private_ip = 172.16.254.45
        public_ip = 3.83.199.207
        state = available
        subnet_id = subnet-050f6fc499a455a97
        tags.% = 7
        tags.Environment = development
        tags.Infrastructure = No
        tags.Name = **redacted** NAT GW AZ 1
        vpc_id = vpc-057a1208002394e1b
    module.vpc_private_route.data.aws_nat_gateway.az2:
        id = nat-0325fe2ba1184815b
        allocation_id = eipalloc-0df309e8b533b35b6
        network_interface_id = eni-00e850031318b2a41
        private_ip = 172.16.254.92
        public_ip = 3.88.44.14
        state = available
        subnet_id = subnet-0191ae48f099aa808
        tags.% = 7
        tags.Infrastructure = No
        tags.Name = **redacted** NAT GW AZ 2
        vpc_id = vpc-057a1208002394e1b
    module.vpc_private_route.data.aws_subnet_ids.private:
        id = vpc-057a1208002394e1b
        ids.# = 2
        ids.1528047303 = subnet-03a4f5228ae9f1714
        ids.1908543416 = subnet-0d915cc4899877eb9
        tags.% = 1
        tags.Name = *Private*
        vpc_id = vpc-057a1208002394e1b


我应该做些什么来使此TF模块在轮询资源之前等待创建资源?在Ansible中,我可以发出等待命令或运行循环以搜索条件,然后再继续。

谢谢您的想法!

请注意显示的所有“ id”在阅读本文之前,此输出中的信息将失效。所有数据均已根据环境安全政策进行了清理。

#1 楼

有一种解决方法,可以使Terraform进行模块依赖性。您可以强制模块注意Terraform这样调用它:

# ROOT level main.tf
# -------------------------------------------------------------------
# Create NAT Gateway - Associates EIP as well
# -------------------------------------------------------------------
module "vpc_nat_gateway" {
  source            = "./vpc_nat_gateway"
  vpc_id            = "${ module.vpc.id }"
  public_subnet_ids = "${ module.vpc_subnets.public_subnet_ids }"
  private_cidr      = "${ var.private_cidr }"
  common_tags       = "${ local.common_tags }"
}

# -------------------------------------------------------------------
# Create Private Routes
# -------------------------------------------------------------------
module "vpc_private_route" {
  source         = "./vpc_private_route"
  vpc_id.        = "${ module.vpc.id }"
  nat_gateway_id = "${ module.vpc_nat_gateway.nat_gateway_id }"
  common_tags    = "${ local.common_tags }"

  depends_on = ["${module.vpc_nat_gateway.nat_gateway_id}"]
}


# vpc_private_route module - main.tf
variable "depends_on" {
  default = []
}

resource "null_resource" "depends_on" {
  triggers {
    depends_on = "${join("", var.depends_on)}"
  }
}

data "aws_nat_gateway" "az1" {
  vpc_id = "${ var.vpc_id }"

  tags {
    Name = "*NAT GW AZ 1"
  }

  depends_on = [
    "null_resource.depends_on"
  ]
}

data "aws_nat_gateway" "az2" {
  vpc_id = "${ var.vpc_id }"

  tags {
    Name = "*NAT GW AZ 2"
  }

  depends_on = [
    "null_resource.depends_on"
  ]
}


它增加了很多样板,但是您将获得理想的效果。

评论


感谢@Briansbum提供的意见和出色的示例。我第二天要在办公室尝试此方法,并进行报告。

–史蒂文K7常见问题解答
19年2月2日,下午2:17

#2 楼

最受欢迎的答案是版本0.12.24中的Terraform已过时。

depends_on是一个受保护的变量,不能在module中使用。 。

我更新了以下示例。

# ROOT level main.tf
# -------------------------------------------------------------------
# Create NAT Gateway - Associates EIP as well
# -------------------------------------------------------------------
module "vpc_nat_gateway" {
  source            = "./vpc_nat_gateway"
  vpc_id            = module.vpc.id
  public_subnet_ids = module.vpc_subnets.public_subnet_ids
  private_cidr      = var.private_cidr
  common_tags       = local.common_tags
}

# -------------------------------------------------------------------
# Create Private Routes
# -------------------------------------------------------------------
module "vpc_private_route" {
  source         = "./vpc_private_route"
  vpc_id.        = module.vpc.id
  nat_gateway_id = module.vpc_nat_gateway.nat_gateway_id
  common_tags    = local.common_tags

  # Depends is a custom variable, depends_on is a reserved keyword.
  depends = [module.vpc_nat_gateway.nat_gateway_id]
}


# vpc_private_route module - main.tf
variable "depends" {
  default = []
}

resource "null_resource" "depends_on" {
  triggers = {
    depends_on = "${join("", var.depends)}"
  }
}

data "aws_nat_gateway" "az1" {
  vpc_id = var.vpc_id

  depends_on = [
    null_resource.depends_on
  ]
}

data "aws_nat_gateway" "az2" {
  vpc_id = var.vpc_id

  depends_on = [
    null_resource.depends_on
  ]
}


#3 楼

这些都是黑客(可以理解,因为您无法在Terraform <0.13中明确地做到这一点)。
现在,有了0.13,我们对模块有了depends_on:https://github.com/hashicorp/terraform/blob/v0 .13 / CHANGELOG.md#0130-august-10-2020