我的团队在3 different AWS accounts中将AWS用于我们的基础架构。我们将它们简称为sandbox
,staging
和production
。
我最近针对我们的AWS基础架构设置了Terraform,针对我们的账户设置了其层次结构,然后通过应用程序或AWS服务本身进行了映射。回购结构如下所示:
staging
iam
groups
main.tf
users
main.tf
s3
main.tf
sandbox
iam
...
production
applications
gitlab
main.tf
route53
main.tf
...
我们为每个AWS服务(例如IAM或S3)或应用程序(例如GitLab)使用单独的配置,因此每个帐户最终不会花费大量时间.tf
来存储大量staging/s3/main.tf
文件为任何一项更改应用更新。理想情况下,我们希望摆脱基于服务的配置方法,而转向更多基于应用程序的配置,但是手头的问题仍然是相同的。
从命令行手动应用更新时,这种方法效果很好,但是我很乐意将其移至GitLab CI / CD,以更好地自动化我们的工作流程,这就是问题所在。
在现有设置中,如果我对terraform plan
进行了一次更改,那么GitLab似乎没有开箱即用的好方法,只能运行terraform apply
或{{1 }}进行具体配置。
如果我改为将所有内容移到整个AWS帐户的单个main.tf
文件中(或多个文件,但绑定到一个状态文件),那么我可以简单地让GitLab触发一项工作来完成plan
或apply
仅用于该配置。根据我们每个帐户中拥有的AWS资源的数量,运行该服务可能需要15分钟,但是我认为这是一个潜在的选择。
似乎我的问题可能最终与GitLab如何处理“ monorepos”有关,而不是与Terraform如何处理其工作流程有关(毕竟,如果我简单地告诉它什么,Terraform会很乐意计划/应用我的更改)发生了变化),尽管我也很想听听人们如何构造给定的Terraform环境,或者为了完全避免这些限制。
有人在他们的环境中解决过这样的问题吗?
答案 0 :(得分:3)
Terraform的优点在于它是幂等的,因此即使什么都没有改变,您也可以应用它,无论如何这将是一个无人值守的动作。
如果由于某种原因您真的只想在发生更改时在特定目录上运行计划/应用程序,则可以使用only.changes
来实现这一点,这样Gitlab仅在指定文件发生更改时才运行作业。
因此,如果您具有现有结构,那么就像执行以下操作一样简单:
stages:
- terraform plan
- terraform apply
.terraform_template:
image: hashicorp/terraform:latest
before_script:
- LOCATION=$(echo ${CI_JOB_NAME} | cut -d":" -f2)
- cd ${LOCATION}
- terraform init
.terraform_plan_template:
stage: terraform plan
extends: .terraform_template
script:
- terraform plan -input=false -refresh=true -module-depth=-1 .
.terraform_apply_template:
stage: terraform apply
extends: .terraform_template
script:
- terraform apply -input=false -refresh=true -auto-approve=true .
terraform-plan:production/applications/gitlab:
extends: .terraform_plan_template
only:
refs:
- master
changes:
- production/applications/gitlab/*
- modules/gitlab/*
terraform-apply:production/applications/gitlab:
extends: .terraform_apply_template
only:
refs:
- master
changes:
- production/applications/gitlab/*
- modules/gitlab/*
我还假设存在位于共享位置的模块,以指示该模式还可以查找回购中其他位置的变化,而不仅仅是运行Terraform的目录。
如果不是这种情况,并且您的结构较为扁平,并且很高兴有一个申请工作,则可以将其简化为:
stages:
- terraform
.terraform_template:
image: hashicorp/terraform:latest
stage: terraform
before_script:
- LOCATION=$(echo ${CI_JOB_NAME} | cut -d":" -f2)
- cd ${LOCATION}
- terraform init
script:
- terraform apply -input=false -refresh=true -auto-approve=true .
only:
refs:
- master
changes:
- ${CI_JOB_NAME}/*
production/applications/gitlab:
extends: .terraform_template
尽管通常可以通过允许Terraform在每次推送上针对所有适当的目录运行(可以仅在对master或其他适当分支的推送上运行)来避免这种情况,因为如上所述,Terraform是幂等的,因此它不会如果什么都没有改变,什么也不要做。这还有一个好处,如果您的自动化代码没有更改,但是提供程序中发生了更改(例如有人打开了安全组),那么Terraform将把它重新设置为下次触发时的状态。