具有多种Terraform配置的有效的GitLab CI / CD工作流程?

时间:2019-04-12 06:38:06

标签: continuous-integration gitlab terraform

我的团队在3 different AWS accounts中将AWS用于我们的基础架构。我们将它们简称为sandboxstagingproduction

我最近针对我们的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触发一项工作来完成planapply仅用于该配置。根据我们每个帐户中拥有的AWS资源的数量,运行该服务可能需要15分钟,但是我认为这是一个潜在的选择。

似乎我的问题可能最终与GitLab如何处理“ monorepos”有关,而不是与Terraform如何处理其工作流程有关(毕竟,如果我简单地告诉它什么,Terraform会很乐意计划/应用我的更改)发生了变化),尽管我也很想听听人们如何构造给定的Terraform环境,或者为了完全避免这些限制。

有人在他们的环境中解决过这样的问题吗?

1 个答案:

答案 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将把它重新设置为下次触发时的状态。