将 Makefile 与 Terraform 和拆分项目布局一起使用



我有一个类似于

stage
└ Makefile
└ terraform.tfvars
└ vpc
└ services
└ frontend-app
└ backend-app
└ vars.tf
└ outputs.tf
└ main.tf
└ data-storage
└ mysql
└ redis

其中Makefile的内容类似于

.PHONY: all plan apply destroy
all: plan
plan:
terraform plan -var-file terraform.tfvars -out terraform.tfplan
apply:
terraform apply -var-file terraform.tfvars
destroy:
terraform plan -destroy -var-file terraform.tfvars -out terraform.tfplan
terraform apply terraform.tfplan

据我了解,Terraform只会在当前目录中的模板上运行。 所以我需要在那里cd stage/services/backend-app并跑terraform apply

但是,我希望能够从Makefile管理整个堆栈。 我还没有看到一种将论点传递给make的干净方法.

我的目标是有这样的目标

make s3 plan # verify syntax
make s3 apply # apply plan

除非有更好的方法从父目录运行 terraform? 是否有类似于以下内容的内容:

make all plan  # create stage plan
make all apply # apply stage plan

另一种解决方案可能是在每次运行时创建一个 tmp 文件夹并使用terraform init ...terraform get...,如下所示(该示例还显示了使用部分配置的远程状态管理):

readonly orig_path=$(pwd) && 
mkdir tmp && 
cd tmp && 
terraform init -backend=true -backend-config="$tf_backend_config" -backend-config="key=${account}/${envir}/${project}.json" $project_path && 
terraform get $project_path && 
terraform apply && 
cd $orig_path && 
rm -fR tmp

或者可以将上述内容包装到一个 shell 脚本中,然后从"apply"等下的 make 文件中调用它。

--添加此部分以解决 Sam Hammamy 的评论/问题 --

一般来说,根据当前版本的 terraform 处理项目的方式,我们确实希望提前考虑如何构建我们的项目,以及如何将它们分解为可管理的仍然有效的部分。这就是为什么我们通常将它们分解为"基础"项目,如 VPC、VPN、安全组、IAM 策略、堡垒等,而不是"功能"项目,如"数据库"、"Web 集群"等。我们通常运行/部署/修改"基本"部分一次或偶尔,而"功能"部分我们可能每天重新部署几次。

这意味着,随着 IaC 代码的碎片化,我们也将相应地对远程状态进行碎片化,以及项目部署的执行。

对于反映该"哲学"的项目结构,我们通常最终会得到与此类似的项目结构(未显示常见模块):

├── projects
│   └── application-name
│       ├── dev
│       │   ├── bastion
│       │   ├── db
│       │   ├── vpc
│       │   └── web-cluster
│       ├── prod
│       │   ├── bastion
│       │   ├── db
│       │   ├── vpc
│       │   └── web-cluster
│       └── backend.config
└── run-tf.sh

其中每个项目都是一个子文件夹,对于每个application_name/env/component = 文件夹(即 dev/vpc),我们添加了一个占位符后端配置文件:backend.tf

terraform {
backend "s3" {
}
}

其中,每个组件的文件夹内容将包含类似于以下内容的文件:

│       ├── prod
│       │   ├── vpc
│       │   │   ├── backend.tf
│       │   │   ├── main.tf
│       │   │   ├── outputs.tf
│       │   │   └── variables.tf

在"application_name/"或"application_name/env"级别,我们添加了一个 backend.config 文件,其中包含以下内容:

bucket     = "BUCKET_NAME"
region     = "region_name"
lock       = true
lock_table = "lock_table_name"
encrypt    = true

我们的包装器 shell 脚本需要参数应用程序名称、环境、组件和实际的地形 cmd 运行。

run-tf.sh 脚本的内容(简体):

#!/bin/bash
application=$1
envir=$2
component=$3
cmd=$4
tf_backend_config="root_path/$application/$envir/$component/backend.config"
terraform init -backend=true -backend-config="$tf_backend_config" -backend-config="key=tfstate/${application}/${envir}/${component}.json" 
terraform get
terraform $cmd

下面是典型的 run-tf.sh 调用(从 Makefile 执行):

$ run-tf.sh application_name dev vpc plan
$ run-tf.sh application_name prod bastion apply

我们使用shell脚本来处理这个确切的用例,它可以更好地处理cd

但是,您可以通过使用环境变量或直接在目标后面的命令行上设置它来设置 Make 变量,如下所示:

make target FOO=bar

因此,在您的情况下,您可能需要以下内容:

ifndef LOCATION
$(error LOCATION is not set)
endif
.PHONY: all plan apply destroy
all: plan
plan:
cd $(LOCATION) && 
terraform plan -var-file terraform.tfvars -out terraform.tfplan
apply:
cd $(LOCATION) && 
terraform apply -var-file terraform.tfvars
destroy:
cd $(LOCATION) && 
terraform plan -destroy -var-file terraform.tfvars -out terraform.tfplan
terraform apply terraform.tfplan

我可能倾向于有一个运行terraform get并且还配置远程状态的目标,但现在设置它应该是微不足道的。

最新更新