【问题标题】:Terraform Child module dependency on a calling resourceTerraform 子模块对调用资源的依赖
【发布时间】:2021-07-09 15:48:10
【问题描述】:

我正在尝试在多个子模块之间创建依赖关系,这些子模块应该能够单独创建资源,并且应该能够在它们相互依赖时创建资源。

基本上我正在尝试创建多个虚拟机,并基于作为输出返回的 ip 地址和 vip ip 地址,我想创建 lbaas 池和 lbaas 池成员。

我将项目结构保持如下

 - Root_Folder
    - main.tf // create all the vm's 
    - output.tf
    - variable.tf
    - calling_module.tf
    - modules
        - lbaas-pool
            - lbaas-pool.tf // create lbaas pool
            - variable.tf
            - output.tf
        - lbaas-pool-members  
            - lbaas-pool-members.tf // create lbaas pool member
            - variable.tf
            - output.tf

calling_module.tf 包含对 lbaas-pool 模块和 lbaas-pool-members 的引用,因为这两个模块依赖于 main.tf 文件生成的资源的输出。 它给出了以下错误:

未声明托管资源。

由于资源尚未生成,在运行 terraform plan 和 apply 命令时试图加载尚未创建的资源对象。不确定他的结构是否声明了资源之间的模块隐式依赖关系,以便模块可以单独工作以及在需要完整堆栈时工作。

预期行为:

main.tf 输出参数应该在 terraform 版本 0.14 中自动创建依赖项,但从上述错误看来情况并非如此。

【问题讨论】:

  • 听起来您正试图直接引用模块内main.tf 中定义的资源,而不是将该资源作为输入传递给这些模块。您确实需要根据站点规则显示您的代码minimal reproducible example
  • 我无法添加完整的代码。但更多细节 main.tf 包含资源配置。它生成一个虚拟机。 Output.tf 包含创建 vm 后返回的资源参数。现在我想在 lbaas-pool.tf 文件中添加输出变量。由于 lbaas-pool.tf 需要 fqdn 生成的输出作为 main.tf 资源的一部分。同样对于 lbaas-pool-member.tf 需要池成员 ipaddr 作为 main.tf 资源的一部分生成。我的要求是调用根模块生成vm时,首先要创建vm,vm的out参数可以作为lbaas-pool和lbaas-pool-members的输入变量。
  • Calling_module.tf 有对子模块 lbaas-pool.tf 和 lbaas-pool-members.tf 的模块调用。此外,为了创建模块之间的内部依赖关系,我尝试在 lbaas-pool.tf 中添加数据块。数据块名称为 main.tf 资源名称。并添加了一个与 main.tf 的输出变量相同的变量名。但这在我尝试运行 terraform 计划时不起作用。它因问题中提到的错误而失败。

标签: terraform terraform-modules terraform0.14.7


【解决方案1】:

假设您有一个将实例 ID 作为输入的模块,因此在 modules/lbaas-pool 中,您在 variable.tf 中有这个

variable "instance_id" {
   type = string
}

现在假设您在 main.tf 中定义了该实例资源:

resource "aws_instance" "my_instance" {
  ...
}

然后将该资源传递给calling_module.tf(或与main.tf 位于同一文件夹中的任何其他.tf 文件中)中定义的任何模块,您可以这样做:

module "lbaas-pool" {
  src="modules/lbaas-pool"
  instance_id = aws_instance.my_instance.id
  ...
}

注意这里根本没有定义output。根级别的任何output 都用于将输出公开到命令行控制台,而不是用于将内容发送到子模块。

还要注意这里没有定义data 源。您不是在编写将按特定顺序运行的脚本,而是在编写模板来告诉 Terraform 您希望您的最终基础设施是什么样子。 Terraform 读取所有内容,创建依赖关系图,然后按照它确定的顺序部署所有内容。在运行terraform planapply 时,您通过data 源引用的任何内容都必须已经存在。 Terraform 不会在根模块中创建所有内容,然后加载子模块并在那里创建所有内容,它会根据依赖关系图以任何必要的顺序创建内容。

【讨论】:

  • 我明白这一点。但我的问题陈述有点不同。我想在 terraform 中生成一个图表,假设将 main.tf 的计算值添加到子模块 lbaas-pool 中。我从你上面的回答中了解到我不能选择上面问题中提到的结构。如果我调用父模块,它应该首先从 main.tf 调用资源。一旦 main.tf 执行完成,计算值可以在 lbaas-pool.tf 模块中使用,一旦执行完成,它会调用 lbaas-pool-members.tf 模块来创建池成员。
  • 您一直在使用诸如“调用”和“执行”模块之类的术语,听起来好像您将它们视为单独的可执行脚本,但实际上并非如此。
  • 对于数据源,我将其添加到 lbaas-pool.tf 文件中,并尝试创建对 main.tf 资源的引用。但数据源不知何故不起作用。我尝试为 main.tf 创建一个输出参数,并在数据源的 lbaas-pool.tf 中使用相同的名称。返回错误。
  • 您一直使用诸如“调用”和“执行”模块之类的术语,这听起来像是您将它们视为单独的可执行脚本,而实际上并非如此。您拒绝提供 [mvce]。您的 cmets 只是重申您的问题,并不表示您已阅读我的答案。
  • 实际上我正在尝试使资源单独工作以及在需要时按此顺序生成。为了保持复杂性。因为我不想把所有东西都放在一个层次上,并试图把它放在小模块中。
猜你喜欢
  • 2020-09-16
  • 2019-11-04
  • 2023-02-23
  • 1970-01-01
  • 2020-02-05
  • 1970-01-01
  • 2020-03-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多