【问题标题】:How can I run terraform code in sequence?如何按顺序运行 terraform 代码?
【发布时间】:2019-04-25 02:28:54
【问题描述】:

我正在尝试围绕 AWS 基础设施设置一些自动化。刚刚碰到一个关于模块依赖的问题。由于 terraform 中没有“包含”类型的选项,因此实现我的目标变得有点困难。

以下是场景的简短描述:

在我的根目录中,我有一个文件main.tf

由多个模块块组成 例如。

module mytest1
{
source = mymod/dev
}

module mytest2
{
source = mymod2/prod
}

每个 dev 和 prod 都有很多 tf 文件 我存在于prod 目录中的 .tf 文件很少需要来自dev 目录中存在的资源的一些输出

由于模块没有依赖关系,我在想是否有任何方法可以按顺序运行模块或任何其他想法?

【问题讨论】:

    标签: amazon-web-services terraform


    【解决方案1】:

    不完全确定您的用例是否让 prod 和 dev 需要按照您所说的方式进行交互。

    我希望您可能具有以下文件夹结构:

    • 文件夹 1:Dev(包含用于开发的模块)
    • 文件夹 2:Prod(包含 prod 模块)
    • 文件夹 3:资源(包含 dev 和 prod 模块都使用的通用资源块)

    然后,当您为文件夹 1 运行 terraform apply 时,它将通过将模块中的变量传递给资源(在文件夹 3 中)来创建您的开发基础架构。

    当您为文件夹 2 运行 terraform apply 时,它将通过将模块中的变量传递给资源(在文件夹 3 中)来创建您的产品基础架构。

    如果由于某种原因您不能这样做,那么输出变量或数据源可能会帮助您检索所需的信息。

    【讨论】:

      【解决方案2】:

      没有理由为不同的环境使用不同的模块。通常,lower envs 和 prod 之间的区别在于每个资源的数量和层级,您可以使用变量将其传递到模块内部。

      要解决这个问题,您可以使用terraform workspaces 并为每个环境创建一个工作区,例如:

      terraform worskspace new staging
      

      这将创建一个具有自己状态的全新工作区。如果您需要定义要创建的资源数量,您可以使用变量 sor terraform 工作空间名称本身,例如:

      # Your EC2 Module
      "aws_instance" "example" {
          count = "${terraform.workspace == "prod" ? 3 : 1}"
      }
      
      # or
      
      "aws_instance" "example" {
          count = "${lenght(var.subnets)}" # you are likely to have more subnets for prod
      }
      
      
      # Your module
      module "instances" {
      source = "./modules/ec2"
      subnets = "my subnets list"
      }
      

      就是这样,您可以让所有模块在任何环境下工作,只需创建工作区并更改管道上每个模块的变量并每次应用计划。

      You can read more about workspaces here

      【讨论】:

      • 只是为了清除它与environment 无关。它只是一个目录名称。每个目录由多个 .tf 文件组成,这些 .tf 文件具有依赖关系。而且我想按顺序运行模块,以便第二个模块将获得第一个模块的所有资源输出。由于包含类型的功能在 terraform 中不可用,所以我正在使用模块。实际上模块无关。每个目录里面都有很多文件所以不希望它们弄乱我的根目录。因此我将它们放在不同的目录中,通过模块执行它们
      【解决方案3】:

      我不太确定您是否要求生产环境依赖于开发环境,但抛开细节不谈,在 Terraform 中创建资源之间和模块之间的顺序的惯用方法是使用引用表达式。

      您没有说生产环境消耗了开发环境的哪个方面,但是为了举例,假设生产环境需要在开发环境中创建的 VPC 的 id。在这种情况下,开发模块会将该 VPC id 导出为输出值:

      # (this goes within a file in your mymod/dev directory)
      output "vpc_id" {
        value = "${aws_vpc.example.id}"
      }
      

      那么你的生产模块反过来就会有一个输入变量来指定这个:

      # (this goes within a file in your mymod2/prod directory)
      variable "vpc_id" {
        type = "string"
      }
      

      有了这些,你的父模块就可以在两者之间传递值来建立你正在寻找的依赖关系:

      module "dev" {
        source = "./mymod/dev"
      }
      
      module "prod" {
        source = "./mymod2/prod"
      
        vpc_id = "${module.dev.vpc_id}"
      }
      

      之所以有效,是因为它创建了以下依赖链:

      module.prod's input variable vpc_id depends on
      module.dev's output value vpc_id, which depends on
      module.dev's aws_vpc.example resource
      

      然后,您可以在生产模块中的任何位置使用var.vpc_id 来获取该 VPC id,这会在该依赖链中创建另一个链接,告诉 Terraform 它必须等到创建 VPC 才能采取任何依赖于 VPC 的操作存在。

      请特别注意,参与依赖链的是单个变量和输出,而不是整个模块。这意味着,如果您在 prod 模块中有任何资源不需要需要 VPC 存在,那么 Terraform 可以立即开始创建它们,而无需等待开发模块首先完全完成,同时仍确保在采取任何确实需要的操作之前完成 VPC 创建。

      在文档部分Module Composition 中有更多关于此模式的信息。它在编写时考虑了 Terraform v0.12 语法和功能,但如果您使用 v0.11 语法和功能来表达它,通用模式仍然适用于早期版本,就像我在上面的示例中所做的那样。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-17
        • 1970-01-01
        • 1970-01-01
        • 2021-03-16
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多