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

时间:2019-09-02 16:19:01

标签: 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" {}

非常感谢。

1 个答案:

答案 0 :(得分:0)

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

  • 资源
  • 输入变量
  • 输出值
  • 本地值

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

使用输入变量的依赖性

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

例如,在子模块中:

variable "vpc_id" {
  type = string
}

resource "aws_subnet" "example" {
  vpc_id = var.vpc
  # ...
}

然后在调用模块中:

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

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

  vpc_id = aws_vpc.example.id
}

使用上述配置,module.example.aws_subnet.example取决于module.example.var.vpc_id,而aws_vpc.example取决于variable "subnet_depends_on" { type = any } resource "aws_subnet" "example" { depends_on = [var.subnet_depends_on] # ... } 。因此,由于传递依赖性,仅在应用VPC之后才应用子网。

在不常见的情况下,您需要能够创建依赖项而不传递任何特定的值,则可以使用上面的略微变体。在子模块中:

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

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

  subnet_depends_on = [aws_vpc.example]
}

在呼叫者中:

subnet_depends_on

在这种情况下,vpc_id value 是无关紧要的,我们仅将其用于依赖关系。我建议仅在没有变量传入必要对象的情况下才使用此模式,但是在某些边缘情况下此模式很方便。 (在上面显示的示例中没有必要,因为无论如何您总是需要填充子网的resource "aws_vpc" "example" { # ... } output "vpc_id" { value = aws_vpc.example.id } ,并且该引用将创建必要的隐式依赖关系,如上所示。)

使用输出值进行依存关系

类似的把戏与输出值相反。如果我们反转以上示例,以便由子模块创建VPC,由父模块创建子网,则子模块可能如下所示:

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

resource "aws_subnet" "example" {
  vpc_id = module.example.vpc_id
  # ...
}

...并在调用模块中:

aws_subnet.example

现在module.example.vpc_id取决于module.example.aws_vpc.example,而resource "aws_vpc" "example" { # ... } output "vpc_applied" { value = true # the value is irrelevant depends_on = [aws_vpc.example] } 取决于module "example" { source = "./modules/example" } resource "aws_subnet" "example" { depends_on = [module.example.vpc_applied] # ... } 。因此,由于传递依赖性,与以前一样,仅在应用VPC之后才应用子网。

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

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,
  ]
}

然后在调用模块中:

module.example.instance_ip_address

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

特别是对于输出值,这两者之间存在一个折衷:如果要返回一个描述特定对象的值,但是您知道该值在应用了其他对象后才有用。上面通过返回一个值但还包括一些其他依赖项。例如,在另一个子模块中,该子模块使用安全组创建EC2实例,该安全组的规则必须完全应用才可以访问:

  depends_on = [module.example]

在这种情况下,如果调用模块中的资源引用了module.example,则即使IP地址值不包括有关这些安全组的任何信息,也要等到安全组完成后才能应用该资源。 。这使我们可以表示,直到安全组规则完全填充为止,该IP地址实际上才是有用的,即使它是在较早之前分配的。

取决于整个模块

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

~

之所以可行,是因为pathlib是一个对象,它收集模块的所有输出,因此引用它与引用所有输出相同: all 必须对它们的表达式进行求值以构造该对象,因此包括所有传递依赖项。