我正在考虑将我们的一些基础设施代码切换到Terraform,因为我们在使用AWS CloudFormation时遇到了一些困难。
让我举一个我正在努力实现的目标的例子。我有一个ECS集群,它可以运行大约10多种不同的任务定义。每个任务定义包含几乎相同的配置,因此为了避免代码重复,我正在构建一个可重用的模块。
根据我所收集的,有三种主要的方法来构建你的地形目录。
1:
project
├── modules
| ├─ ecs
| ├── main.tf
| ├── variables.tf
| ├── task
| ├── main.tf
| ├── variables.tf
|
|
└── env
| ├─── dev.tfvars
| ├─── prod.tfvars
| ├─── stage.tfvars
| ├─── 10+
|
|
|── main.tf
|── variable.tf
有了这种结构,我必须从env文件夹中获取变量,并将其与-var-files="env/dev.tfvars"
一起传递,然后在我的main.tf中,我必须将变量传递到模块/ecs/task/main.tf,这似乎是一条很长的路,需要很多步骤才能将变量传递给ecs/task/main.tf
2.
project
├── modules
| ├─ ecs
| ├── main.tf
| ├── variables.tf
| ├── task
| ├── main.tf
| ├── variables.tf
|
|
└── stage
| ├─── main.tf
| ├─── variable.tf
| ├─── stage.tfvars
|
└── dev
| ├─── main.tf
| ├─── variable.tf
| ├─── dev.tfvars
|
└── 10+
| ├─── main.tf
| ├─── variable.tf
| ├─── X.tfvars
如果您希望将基于环境的变量应用于modules/ecs/task/main.tf
,则必须从main.tf
开始,例如在调用modules/ecs/main.tf
的阶段。并且从那里通过CCD_ 5施加它,然后CCD_。
这种方法的问题还在于,每当我添加一个新模块时,我都必须将其添加到所有不同环境的主模块中。tf
3.
project
├── modules
| ├── ecs
| ├── main.tf
| ├── variables.tf
| ├── task
| ├── main.tf
| ├── variables.tf
|
|
|
|
|── main.tf
|── variable.tf
使用terraform工作区,我可以使用模块/ecs/task/variables.tf中的本地程序来确定我正在构建的环境。像这样:
modules/ecs/task.variables.tf
locals {
env="${terraform.workspace}"
masterAccountIDS = {
"default"="12121212"
"dev"="84848484"
}
masterAccountID="${lookup(local.masterAccountIDS, local.env)}"
}
但这需要每次添加新环境时,我都要遍历所有的variables.tf文件,并添加一个新条目,例如"stage"。
我想不出一种方法可以让我不复制粘贴代码,或者在添加新环境时插入新东西,或者把它们都放在一个地方,所以我可能只需要编辑一个文件。
使用工作区是目前最好的选择。我正在使用下面这样的东西在一个地方管理所有变量-
默认值。tf-
/* DEFAULT VARIABLES */
locals {
tags = {
Project = "${var.project}"
Contact = "vivek@vivekyadav.me"
Requester = "Vivek"
Creator = "Vivek"
ManagedBy = "TF"
Environ = "${local.workspace["environ"]}"
}
}
locals {
meta = {
name_prefix = "hpy-${local.workspace["environ"]}-${local.workspace["project_name"]}"
account_id = "${local.workspace["account_id"]}"
region_name = "${local.workspace["region_name"]}"
}
}
/* CUSTOM VARIABLES - ENVIRONMENT SPECIFIC */
################ DEFAULT LOCALS - DEFINE ENV VARIABLES FOR APP #################
locals {
env = {
default = {
project_name = "${var.project}"
region_name = "${var.region}"
environ = "dev"
account_id = "356******001"
}
default_list = {
}
################ DEV LOCALS - DEFINE ENV VARIABLES FOR APP #################
dev = {
environ = "dev"
}
dev_list = {
}
################ UAT LOCALS - DEFINE ENV VARIABLES FOR APP #################
uat = {
environ = "uat"
}
uat_list = {
}
################ PREP LOCALS - DEFINE ENV VARIABLES FOR APP #################
prep = {
environ = "prep"
}
prep_list = {
}
################ PRD LOCALS - DEFINE ENV VARIABLES FOR APP #################
prod = {
environ = "prod"
account_id = "3621****8334"
}
prod_list = {
}
}
################ EXPORTING ENV/WORKSPACE VARIABLES FOR APP #################
workspace = "${merge(local.env["default"], local.env[terraform.workspace])}"
workspace_lists= "${merge(local.env["default_list"], local.env[format("%v_list",terraform.workspace)])}"
}
现在你可以在你的主定义中调用以上变量
main.tf-
module "s3" {
source = "s3"
tags = "${local.tags}"
meta = "${local.meta}"
workspace = "${local.workspace}"
workspace_list = "${local.workspace_list}"
}
现在,您可以调用下面定义的模块内的变量-
"${var.workspace["environ"]}"
PS-这是一个变通方法,但效果确实很好,就像现在一样。Terraform应该提供一些开箱即用的东西来管理它