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

将Makefile与Terraform和拆分项目布局一起使用,makefile,terraform,Makefile,Terraform,我有一个类似于 stage └ Makefile └ terraform.tfvars └ vpc └ services └ frontend-app └ backend-app └ vars.tf └ outputs.tf └ main.tf └ data-storage └ mysql └ redis .PHONY: all plan apply destroy

我有一个类似于

stage
  └ Makefile
  └ terraform.tfvars
  └ vpc
  └ services
      └ frontend-app
      └ backend-app
          └ vars.tf
          └ outputs.tf
          └ main.tf
  └ data-storage
      └ mysql
      └ redis
.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
其中
Makefile
的内容与

stage
  └ Makefile
  └ terraform.tfvars
  └ vpc
  └ services
      └ frontend-app
      └ backend-app
          └ vars.tf
          └ outputs.tf
          └ main.tf
  └ data-storage
      └ mysql
      └ redis
.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
│       ├── prod
│       │   ├── vpc
│       │   │   ├── backend.tf
│       │   │   ├── main.tf
│       │   │   ├── outputs.tf
│       │   │   └── variables.tf

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

但是,您可以通过使用环境变量或直接在目标后面的命令行上设置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

我可能倾向于有一个运行
terraformget
并配置远程状态的目标,但现在设置起来应该很简单。

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

但是,您可以通过使用环境变量或直接在目标后面的命令行上设置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
,也配置远程状态,但现在设置起来应该很简单。

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

或者将上面的代码包装成一个shell脚本,并从makefile的“apply”下调用它

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

总的来说,对于当前版本的terraform处理项目的方式,我们确实希望提前思考如何构建我们的项目,以及如何将它们分解为可管理的、仍然具有功能的部分。这就是为什么我们通常将它们分解为“基础性”的原因VPC、VPN、安全组、IAM策略、堡垒等项目与“db”、“web群集”等“功能性”项目相比,我们通常运行/部署/修改“基本”项目一次或偶尔一次,而“功能性”项目我们可能一天重新部署几次

这意味着,通过像这样对IaC代码进行分段,我们也将相应地对远程状态进行分段,并执行项目部署

对于反映“理念”的项目结构,我们通常以类似的项目结构结束(未显示常见模块):

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

terraform {
    backend "s3" {
    }
}
其中,每个组件的文件夹内容将包含类似以下内容的文件:

make all plan  # create stage plan
make all apply # apply stage plan
│       ├── prod
│       │   ├── vpc
│       │   │   ├── backend.tf
│       │   │   ├── main.tf
│       │   │   ├── outputs.tf
│       │   │   └── variables.tf
在“application\u name/”或“application\u name/env”级别,我们添加了一个backend.config文件,其内容如下:

bucket     = "BUCKET_NAME"
region     = "region_name"
lock       = true
lock_table = "lock_table_name"
encrypt    = true
我们的包装器shell脚本需要参数应用程序名称、环境、组件和实际运行的terraform cmd

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

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


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

或者将上面的代码包装成一个shell脚本,并从makefile的“apply”下调用它

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

总的来说,对于当前版本的terraform处理项目的方式,我们确实希望提前思考如何构建我们的项目,以及如何将它们分解为可管理的、仍然具有功能的部分。这就是为什么我们通常将它们分解为“基础的”“VPC、VPN、安全组、IAM策略、堡垒等项目与“db”、“web群集”等“功能性”项目相比,我们通常会运行/部署/修改“基本”项目一次或偶尔一次,而“功能性”项目则可能一天重新部署几次

这意味着,通过像这样对IaC代码进行分段,我们也将相应地对远程状态进行分段,并执行项目部署

对于反映“理念”的项目结构,我们通常以类似的项目结构结束(未显示常见模块):

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

terraform {
    backend "s3" {
    }
}
其中,每个组件的文件夹内容将包含类似以下内容的文件:

make all plan  # create stage plan
make all apply # apply stage plan
│       ├── prod
│       │   ├── vpc
│       │   │   ├── backend.tf
│       │   │   ├── main.tf
│       │   │   ├── outputs.tf
│       │   │   └── variables.tf
在“application\u name/”或“application\u name/env”级别,我们添加了一个backend.config文件,其内容如下:

bucket     = "BUCKET_NAME"
region     = "region_name"
lock       = true
lock_table = "lock_table_name"
encrypt    = true
我们的包装器shell脚本需要参数应用程序名称、环境、组件和实际运行的terraform cmd

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

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


远程状态如何以这种方式包含所有组件?在每次应用
terraform
后,远程状态都会更新。因此,如果您正在保存$project\u path,子目录如何包含在此状态中?我在上面添加了一个新的部分,以详细介绍示例,解释每个子项目的远程状态管理,以及