在启动之前等待另一个模块完成的 terraform 模块

seb*_*ian 4 terraform

我正在寻找一种解决方法,因为模块不能依赖于其他模块。

我相信这就是您应该如何创建一个模块,该模块在启动之前等待另一个模块完成。但是,我发现这对我仍然不起作用。我的设置方式有什么问题吗?

有了这个,我仍然看到 module2 中的资源被构建,不依赖于其他任何东西。

module "module1" {
    source = "./module1"
}

module "module2" {
    source = "./module2"
    somevar = "${module.module1.somevar}"
}

./module1/outputs.tf

output "somevar" {
  value = "nothing"
}


./module2/variables.tf

variable "somevar" {}
Run Code Online (Sandbox Code Playgroud)

非常感谢。

Mar*_*ins 8

在今天的 Terraform 中,以下项参与了引用依赖关系图:

  • 资源
  • 输入变量
  • 输出值
  • 当地价值观

因为输入变量和输出值存在于模块的接口处,我们可以使用它们来创建跨模块边界的依赖关系。

使用输入变量的依赖性

如果您在子模块中声明一个变量,则对该变量的任何引用都将创建对调用者在定义该变量值时引用的任何对象的间接依赖关系。

例如,在子模块中:

variable "vpc_id" {
  type = string
}

resource "aws_subnet" "example" {
  vpc_id = var.vpc
  # ...
}
Run Code Online (Sandbox Code Playgroud)

然后在调用模块中:

resource "aws_vpc" "example" {
  # ...
}

module "example" {
  source = "./modules/example"

  vpc_id = aws_vpc.example.id
}
Run Code Online (Sandbox Code Playgroud)

通过上面的配置,module.example.aws_subnet.example取决于module.example.var.vpc_id,而这又取决于aws_vpc.example。因此,由于传递依赖关系,只有在应用 VPC 后才会应用子网。

在需要能够在不传递任何特定值的情况下创建依赖项的特殊情况下,您可以使用上述的一个轻微变体。在子模块中:

variable "subnet_depends_on" {
  type = any
}

resource "aws_subnet" "example" {
  depends_on = [var.subnet_depends_on]

  # ...
}
Run Code Online (Sandbox Code Playgroud)

在调用者中:

resource "aws_vpc" "example" {
  # ...
}

module "example" {
  source = "./modules/example"

  subnet_depends_on = [aws_vpc.example]
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,价值subnet_depends_on是不相关的,并且我们不使用它仅依赖关系是这样。我建议仅当还没有传入必要对象的变量时才使用此模式,但此模式在某些边缘情况下很方便。(在我上面展示的示例中没有必要,因为vpc_id无论如何您总是需要填充子网的 ,并且该引用将创建必要的隐式依赖项,如上所示。)

使用输出值输出依赖关系

类似的技巧以另一种方式工作,输出值。如果我们反转上面的示例,让子模块创建 VPC,父模块创建子网,子模块可能如下所示:

resource "aws_vpc" "example" {
  # ...
}

output "vpc_id" {
  value = aws_vpc.example.id
}
Run Code Online (Sandbox Code Playgroud)

...在调用模块中:

module "example" {
  source = "./modules/example"
}

resource "aws_subnet" "example" {
  vpc_id = module.example.vpc_id
  # ...
}
Run Code Online (Sandbox Code Playgroud)

现在aws_subnet.example取决于module.example.vpc_id,而这又取决于module.example.aws_vpc.example。因此,由于传递依赖关系,只有在应用 VPC 之后才会应用子网。

还有一个不代表特定值的变体,尽管在这个方向上我们仍然需要返回一些值,即使它只是一个占位符。在子模块中:

resource "aws_vpc" "example" {
  # ...
}

output "vpc_applied" {
  value = true # the value is irrelevant

  depends_on = [aws_vpc.example]
}
Run Code Online (Sandbox Code Playgroud)

然后在调用模块中:

module "example" {
  source = "./modules/example"
}

resource "aws_subnet" "example" {
  depends_on = [module.example.vpc_applied]

  # ...
}
Run Code Online (Sandbox Code Playgroud)

和以前一样,这仅适用于异常情况。在这种情况下不合适,因为实际上我们需要 VPC id 来创建子网。但是,在某些情况下,无论任何特定值都必须应用依赖项排序,而上述模式可以实现这一点。

特别是对于输出值,这两者之间存在折衷:如果您返回一个描述特定对象的值,但您知道该值在应用其他一些对象之前不会有用,您可以将上述内容混合使用返回一个值,但还包括一些额外的依赖项。例如,在创建 EC2 实例的不同子模块中,该实例的安全组必须完全应用其规则才能访问:

output "instance_ip_address" {
  value = aws_instance.example.private_ip

  # Callers won't be able to connect to this until the
  # security group rules are all applied.
  depends_on = [
    aws_security_group_rule.example1,
    aws_security_group_rule.example2,
  ]
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,如果调用模块module.example.instance_ip_address中的资源引用了该资源,则在安全组完成之前不会应用该资源,即使 IP 地址值不包含有关这些安全组的任何信息。这允许我们表示 IP 地址在安全组规则完全填充之前实际上没有,即使它是更早分配的。

依赖于整个模块

Terraform 也允许依赖于整个子模块:

  depends_on = [module.example]
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为module.example是一个将模块的所有输出收集在一起的对象,因此引用它与引用所有输出相同:必须评估它们的所有表达式以构造该对象,因此所有包括传递依赖。