【问题标题】:Effective GitLab CI/CD workflow with multiple Terraform configurations?具有多种 Terraform 配置的有效 GitLab CI/CD 工作流程?
【发布时间】:2019-09-02 21:02:26
【问题描述】:

我的团队在 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 文件,这将需要很长时间才能应用更新对于任何一个变化。理想情况下,我们希望摆脱基于服务的配置方法,而转向更多基于应用程序的配置,但无论哪种方式,手头的问题都是一样的。

这种方法在从命令行手动应用更新时运行良好,但我很想将其移至 GitLab CI/CD 以更好地自动化我们的工作流程,而这就是问题所在。

在我现有的设置中,如果我对staging/s3/main.tf 进行单个更改,GitLab 似乎没有一个开箱即用的好方法,只为该特定配置运行 terraform planterraform apply .

如果我将所有内容都移动到整个 AWS 账户的单个 main.tf 文件中(或多个文件但绑定到单个状态文件),我可以简单地让 GitLab 触发一个工作来执行 planapply到那个配置。根据我们在每个账户中拥有的 AWS 资源的数量,运行它可能需要 15 分钟,但我想这是一个潜在的选择。

似乎我的问题最终可能与 GitLab 如何处理“monorepos”有关,而不是与 Terraform 如何处理其工作流程有关(毕竟,如果我简单地告诉 Terraform 会很高兴地计划/应用我的更改什么已经改变),尽管我也有兴趣了解人们如何构建他们的 Terraform 环境给定 - 或为了完全避免 - 这些限制。

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

【问题讨论】:

    标签: continuous-integration gitlab terraform


    【解决方案1】:

    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/*
    

    我还假设存在位于共享位置的模块,以表明此模式还可以在 repo 中的其他位置查找更改,而不仅仅是运行 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 将在下次触发时将其恢复为应有的状态。

    【讨论】:

    • 很棒的电话!我完全忘记了幂等性,但这是有道理的。话虽如此,您将如何在我的所有配置中完成单个planapply?由于 repo 的根目录中没有“基本”配置,你会建议一个简单的for 循环来查找.tf 文件吗?看起来有一种方法可以通过递归包含modules 来做到这一点,但这可能需要做很多工作。
    • 我不会一次性应用东西。将事物拆分到不同位置的全部目的是因为您想要限制爆炸半径或者您想要专注于特定的应用程序/环境。对我来说,将所有这些都捆绑到一个 CI 工作中似乎是一个非常糟糕的主意。如果您担心要定义大量 CI 作业,因为您有许多不同的目录要运行 Terraform,那么您可以查看生成 .gitlab-ci.yml 文件,而不是手动写出 CI 作业。
    • 抱歉,我想我明白你的意思了:为每个 Terraform 配置定义一个 CI 作业,并且——理想情况下——让 GitLab 在推送到 master 时自动运行所有这些作业(因为未更改configs 应该是无操作的)。或者使用only.changes 确定每个作业的范围,但缺点是它增加了复杂性并且失去了将 Terraform 之外的更改同步到未提交的配置的能力。即使我误解了事情,您的回答也提供了丰富的信息。谢谢!
    猜你喜欢
    • 2019-10-26
    • 1970-01-01
    • 2020-10-27
    • 2022-01-19
    • 2021-10-19
    • 2022-07-27
    • 2018-10-03
    • 2021-07-22
    • 2019-08-07
    相关资源
    最近更新 更多