在其他 terraform 文件中使用输出 terraform 文件
Posted
技术标签:
【中文标题】在其他 terraform 文件中使用输出 terraform 文件【英文标题】:Using outputs terraform files in other terraform files 【发布时间】:2021-12-18 10:27:19 【问题描述】:我是 terraform 的新手,有几个问题。在 terraform 中有没有办法在另一个 tf 文件中使用模块的输出,没有有一个“主”terraform 文件,或者在同一个文件中定义两个模块?
例如,这是一个项目结构:
project/
├── networking
│ ├── init.tf
│ ├── terraform.tfvars
│ ├── variables.tf
│ └── vpc.tf
├── prd-project-1
│ ├── init.tf
│ ├── instances.tf
│ ├── terraform.tfvars
│ └── variables.tf
├── prd-project-2
│ ├── init.tf
│ ├── instances.tf
│ ├── terraform.tfvars
│ └── variables.tf
├── prd-project-3
│ ├── init.tf
│ ├── instances.tf
│ ├── terraform.tfvars
│ └── variables.tf
├── test
│ ├── init.tf
│ ├── instances.tf
│ ├── terraform.tfvars
│ └── variables.tf
vpc.tf
将创建一个 VPC 和子网。
instances.tf
将根据之前在 vpc.tf
中创建的 vpc-id 和子网创建 EC2 实例。我想将这些作为两个单独的操作来处理/管理。 IE。首先,我会运行 terraform 来创建 vpc 和子网,然后我可能会运行 terraform 来在 prod/test 中为各种项目创建实例。在此示例中,我将只有 1 个 VPC 用于测试,1 个 VPC 用于生产。我不希望每个项目都有一个 VPC(我再次假设如果在其中一个子项目中引用了 vpc.tf
模块,TF 可能会创建它)。
以这种方式管理 terraform 代码是最佳做法吗?我担心的是,如果最终有很多项目需要 EC2 实例,我不希望所有这些都集中在一个巨大的 main.tf
中。我认为,只要可以引用 vpc 输出,单独维护这些都更安全/更清洁。如果我正在建立一个新项目,我也不希望我的 terraform 计划/应用程序缓慢并检查每个项目的每个资源。
我的问题的第二部分是 - 考虑以下代码 sn-p:
module "main-vpc"
source = "../modules/vpc"
ENV = "prod"
AWS_REGION = var.AWS_REGION
module "instances"
source = "../modules/instances"
ENV = "prod"
VPC_ID = module.main-vpc.vpc_id
PUBLIC_SUBNETS = module.main-vpc.public_subnets
terraform 是否足够聪明,可以确定已经使用 ENV = prod 创建了 VPC,并且如果我在另一个 tf 文件/项目中调用相同的“main-vpc”模块,它不会尝试重新创建它?
我在 *** 上阅读了其他一些帖子,但它们都暗示一个模块的输出只能在同一个 tf 文件中的另一个模块中引用。
我看过的其他一些帖子:
Using outputs from other tf files in terraform Pass terraform output from one file to another Terraform module - output variable as input for another module Terraform structure for two aws accounts【问题讨论】:
抱歉,不清楚你想做什么。拥有 main.tf 有什么问题? 例如,如果我有 100 个项目。我想对项目 84 进行更改,运行 terraform plan/apply 将是一项长期/耗时的任务,因为它需要遍历每个项目并检查更改。相反,我想包含和部署单独的项目,但参考其他模块的输出,例如VPC ID 和子网 ID。 我认为你必须重新设计你的方法。您要么将项目完全分离,要么使用 terraform 工作区将它们分开。 【参考方案1】:如果您想保留当前的文件夹结构,最好在每个项目中添加main.tf
:
project/
├── networking
│ ├── init.tf
│ ├── terraform.tfvars
│ ├── variables.tf
│ └── vpc.tf
├── prd-project-1
│ ├── main.tf
│ ├── init.tf
│ ├── instances.tf
│ ├── terraform.tfvars
│ └── variables.tf
├── prd-project-2
│ ├── main.tf
│ ├── init.tf
│ ├── instances.tf
│ ├── terraform.tfvars
│ └── variables.tf
├── prd-project-3
│ ├── main.tf
│ ├── init.tf
│ ├── instances.tf
│ ├── terraform.tfvars
│ └── variables.tf
├── test
│ ├── init.tf
│ ├── instances.tf
│ ├── terraform.tfvars
│ └── variables.tf
那么每个main.tf
将如下所示:
module "main-vpc"
source = "../networking"
ENV = "prod"
AWS_REGION = var.AWS_REGION
module "instances"
source = "../instances"
ENV = "prod"
VPC_ID = module.main-vpc.vpc_id
PUBLIC_SUBNETS = module.main-vpc.public_subnets
这样您就可以将项目分开,并且每个项目都有自己的 TF 状态文件。
terraform 是否足够智能,可以确定 VPC 是否已使用 ENV 创建
不,不是。您必须为此编写自己的逻辑。一种常见的方式是通过一个变量
variable "vpc_id"
default = ""
如果您没有为给定项目明确指定vpc_id
,它将创建新的 VPC。否则,它将使用您作为输入参数提供的var.vpc_id
。使用data sources,您将获得该 VPC 的其他信息,例如其子网。
进行此设置后,您将首先 cd
到每个项目文件夹,然后再部署它,例如
cd ./prd-project-1
terraform apply
【讨论】:
【参考方案2】:如果我理解您的问题,您希望拥有仍然可以访问彼此输出的独立项目。因此,例如,启动 EC2 实例的项目可以引用在创建 VPC 的项目中定义的子网。
有两种方法可以做到这一点。首先,您可以使用数据源查询当前的部署环境。例如,以下内容将查找带有 ENV
标签且值为“prod”的 VPC(假设我没有输入任何拼写错误):
data "aws_vpc" "prod"
tags = "ENV": "prod"
其次,您可以使用远程状态(为了安全起见,这无论如何都是个好主意)。每个项目都会将其输出写入数据存储(S3 很常见,但 Terraform 提供自己的存储),并且它们会被其他项目引用。
虽然 SO 不喜欢链接,但我无法比 Terraform 文档更好地解释它:https://www.terraform.io/docs/language/state/backends.html
【讨论】:
@Marcin - 我想你想回复 OP? 非常感谢。这很有意义,并且完美地回答了我的问题。以上是关于在其他 terraform 文件中使用输出 terraform 文件的主要内容,如果未能解决你的问题,请参考以下文章
防止 terraform 函数“模板文件”输出 heredoc
在 azure 后端存储中使用状态文件将 terraform 的输出传递到 Azure Devops Pipeline