我是地形的新手,有一些问题。在terraform中,是否有一种方法可以在另一个tf文件中使用模块的输出,WITH具有";主";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
CCD_ 1将创建VPC和子网。instances.tf
将基于先前在vpc.tf
中创建的vpc id和子网来创建EC2实例。我想把这些当作两个单独的行动来处理。首先,我会运行terraform来创建vpc和子网,然后我可能会运行terra form来为各种项目在prod/test中创建实例。在这个例子中,我只有1个用于测试的VPC和1个用于生产的VPC。我不希望每个项目都有一个VPC(我再次假设,如果vpc.tf
模块在其中一个子项目中被引用,TF可能会创建(。
以这种方式管理地形代码是最佳实践吗?我担心的是,如果最终有许多项目需要EC2实例,我不希望所有这些都在一个巨大的main.tf
中。我认为,只要vpc的输出可以参考,单独维护这些是更安全/更干净的。我也不希望我的地形图计划/应用程序太慢,如果我要建立一个新项目,就要检查每个项目中的每一个资源。
我问题的第二部分是——考虑以下代码片段:
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是否足够聪明,可以确定VPC已经用ENV=prod创建,并且如果我调用相同的"prod";主vpc";另一个tf文件/项目中的模块?
我在这里读过一些关于stackoverflow的其他帖子,但它们都暗示了一个模块的输出只能在同一tf文件中的另一个模块中引用。
我审查过的其他一些帖子:
- 在terraform中使用其他tf文件的输出
- 将地形输出从一个文件传递到另一个文件
- Terraform模块-输出变量作为另一个模块的输入
- 两个aws帐户的Terraform结构
如果您想保留当前的文件夹结构,最好将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状态文件。
地形是否足够智能,可以确定VPC已经使用ENV 创建
不是。你必须为此编写自己的逻辑程序。一种常见的方法是通过可变
variable "vpc_id" {
default = ""
}
那么,如果您没有为给定的项目显式指定vpc_id
,它将创建新的VPC。否则,它将使用您提供的var.vpc_id
作为输入参数。使用数据源,您可以获得该专有网络的其他信息,例如其子网。
有了这种设置,在部署之前,您将首先将vpc.tf
0发送到每个项目文件夹,例如
cd ./prd-project-1
terraform apply
如果我理解您的问题,您希望拥有仍然可以访问彼此输出的独立项目。因此,例如,一个启动EC2实例的项目可以引用在创建VPC的项目中定义的子网。
有两种方法可以做到这一点。首先,您可以使用数据源来查询当前部署环境。例如,下面将查找具有值为"0"的ENV
标签的VPC;"戳";(假设我没有错别字(:
data "aws_vpc" "prod" {
tags = { "ENV": "prod" }
}
其次,您可以使用远程状态(出于安全考虑,这是一个好主意(。每个项目都会将其输出写入一个数据存储区(S3是常见的,但Terraform提供了自己的存储区(,并且它们会被其他项目引用。
虽然SO不喜欢链接,但我无法比Terraform文档更好地解释它:https://www.terraform.io/docs/language/state/backends.html