在其他地形文件中使用输出地形文件

Using outputs terraform files in other terraform files

我是 Terraform 的新手,有几个问题。在 terraform 中,有没有办法在另一个 tf 文件中使用模块的输出,WITHOUT 有一个“主”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 实例。我想 treat/manage 这些作为两个单独的操作。 IE。首先,我会 运行 terraform 来创建 vpc 和子网,然后我可能会 运行 terraform 在 prod/test 中为各种项目创建实例。在此示例中,我将只有 1 个 VPC 用于测试,1 个 VPC 用于生产。我不希望每个项目都有一个 VPC(我再次假设如果在其中一个子项目中引用了 vpc.tf 模块,TF 可能会创建)。

以这种方式管理 Terraform 代码是最佳实践吗?我担心的是,如果最终有很多项目需要 EC2 实例,我不希望所有这些都在一个巨大的 main.tf 中。我认为 safer/cleaner 将这些都单独维护,只要可以引用 vpc 输出即可。如果我正在建立一个新项目,我也不希望我的 terraform plan/applies 变慢并检查每个项目的每一个资源。

我的问题的第二部分是 - 考虑以下代码片段:

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 file/project 中调用相同的“main-vpc”模块,它不会尝试重新创建它?

我在 Whosebug 上阅读了其他几篇文章,但它们都暗示模块的输出只能在同一 tf 文件中的另一个模块中引用。

我评论过的其他一些帖子:

如果您想保留当前的文件夹结构,最好在每个项目中添加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 状态文件

Is terraform smart enough to determine that a VPC was already created with an ENV

不,不是。您必须为此编写自己的逻辑。一种常见的方法是通过变量

variable "vpc_id" {
  default = ""
}

那么如果您没有为给定的项目明确指定 vpc_id,它将创建新的 VPC。否则,它将使用您提供的 var.vpc_id 作为输入参数。使用 data sources 然后您将获得该 VPC 的其他信息,例如它的子网。

有了这个设置,你会先cd到每个项目文件夹,然后再部署它,例如

cd ./prd-project-1
terraform apply

如果我理解你的问题,你希望拥有仍然可以相互访问输出的独立项目。因此,例如,启动 EC2 实例的项目可以引用在创建 VPC 的项目中定义的子网。

有两种方法可以做到这一点。首先,您可以使用数据源来查询当前的部署环境。例如,下面将查找带有值为“prod”的 ENV 标签的 VPC(假设我没有打错任何字):

data "aws_vpc" "prod" {
  tags = { "ENV": "prod" }
}

其次,您可以使用远程状态(为了安全起见,无论如何这是个好主意)。每个项目都会将其输出写入数据存储(S3 很常见,但 Terraform 提供自己的存储),其他项目将引用它们。

虽然 SO 不喜欢链接,但我无法比 Terraform 文档更好地解释它:https://www.terraform.io/docs/language/state/backends.html