CI/CD部署相同的Terraform模块给多个组织团队。

huangapple go评论67阅读模式
英文:

CI/CD Deployment of the same Terraform Module for multiple Organizational Teams

问题

I am facing difficulties creating a proper setup for a CI/CD driven Terraform deployment strategy.
我正在面临难题,无法创建适合CI/CD的Terraform部署策略。

What I am looking for doesn't fit a classic "stages" approach and instead is more of multiple production deployments of the same infrastructure components for different teams (organizational).
我寻找的不适合传统的“阶段”方法,而是更适用于为不同团队(组织)部署相同基础设施组件的多个生产部署。

For example.. In my typical Software Engineering projects, the team has a CI/CD Pipeline where infrastructure is, depending on stage / job, deployed to the equivalent infrastructure stage for their software. They know how to do stuff and are YBI/YRI enabled.
例如...在我典型的软件工程项目中,团队拥有CI/CD流水线,根据阶段/任务部署基础设施,以适应其软件的等效基础设施阶段。他们知道如何操作并且启用了YBI/YRI。

In the Platform I have modules, again two stages (test and production) and a Repository glueing it together. Deployed via CI/CD. All good so far.
在平台上,我有模块,再次有两个阶段(测试和生产)和一个将它们连接在一起的存储库。通过CI/CD部署。到目前为止一切顺利。

Now I have a project at hand where a lot of teams will require the same piece of infrastructure (a finished TF module) but do not use GIT / CI/CD / any modern method / automation. Training them is out of scope. Actually they are required to just "get the infrastructure" to use it by the organization.
现在我手头有一个项目,许多团队将需要相同的基础设施部件(已完成的TF模块),但不使用GIT/CI/CD/任何现代方法/自动化。培训他们不在范围内。实际上,他们只需要“获取基础设施”以供组织使用。

On the other hand, I still want to be able to maintain the deployed infrastructure instead of "fire and forget". Therefore, me and my team will provision, hand over, and maintain the infrastructure. They are free to use it within the provided settings.
另一方面,我仍然希望能够维护已部署的基础设施,而不是“点火然后忘记”。因此,我和我的团队将提供、移交和维护基础设施。他们可以在提供的设置内自由使用它。

Requirements I want to achieve:
我想实现的要求:

  • One GIT Repository with all the deployments inside (keeping the "Organizational Project" together)
  • 一个GIT存储库,其中包含所有部署内容(保持“组织项目”在一起)
  • One state file per deployment ("Organizational Team")
  • 每个部署一个状态文件(“组织团队”)
  • CI/CD deploys added Terraform configurations automatically on main merge
  • CI/CD在主合并时自动部署已添加的Terraform配置
  • CI/CD doesn't update already existing Terraform configurations when new ones are added (it should, however, be possible by my team. Non CI/CD in this case is viable)
  • CI/CD在添加新配置时不会更新已存在的Terraform配置(但我的团队应该可以做到这一点。在这种情况下,非CI/CD是可行的)
  • CI/CD configuration should not be required to be extended for new Terraform configurations
  • 不应该需要扩展CI/CD配置以适应新的Terraform配置
  • It shouldn't require complex bash / sh magic
  • 不应该需要复杂的bash / sh魔法

F.e.
例如。

./team2/main.tf
./.../main.tf

The folders have a main.tf using the module with team variable values and a providers.tf with provider setup for the team (Azure Subscription).

Now that seems simple and where is the question. I want this to be executed with CI/CD. Colleagues should be able to create an MR with a new folder + terraform configuration and get the infrastructure that we can maintain from there but also hand it over to be used.

I haven't found anything really helpful while a lot of inputs are close.

I am pretty sure I am missing something very easy and just fail to google / ChatGPT the problem correctly.

Using GitLab-CI + Azure btw.

Thanks for your inputs.

最接近的发现是https://stackoverflow.com/questions/68556638/ci-cd-with-terragrunt-terraform-mono-repo

英文:

I am facing difficulties creating a proper setup for a CI/CD driven Terraform deployment strategy.

What I am looking for doesn't fit a classic "stages" approach and instead is more of a multiple production deployments of the same infrastructure components for different teams (organizational).

For example.. In my typical Software Engineering projects, the team has a CI/CD Pipeline where infrastructure is, depending on stage / job, deployed to the equivalent infrastructure stage for their software. They know how to do stuff and are YBI/YRI enabled.

In the Platform I have modules, again two stages (test and production) and a Repository glueing it together. Deployed via CI/CD. All good so far.

Now I have a project at hand where a lot of teams will require the same piece of infrastructure (a finished TF module) but do not use GIT / CI/CD / any modern method / automation. Training them is out of scope. Actually they are required to just "get the infrastructure" to use it by the organization.

On the other hand, I still want to be able to maintain the deployed infrastructure instead of "fire and forget". Therefor me and my team will provision, hand over and maintain the infrastructure. They are free to use it within the provided settings.

Requirements I want to achieve:

  • One GIT Repository with all the deployments inside (keeping the "Organizational Project" together)
  • One state file per deployment ("Organizational Team")
  • CI/CD deploys added Terraform configurations automatically on main merge
  • CI/CD dosen't update already existing Terraform configurations when new ones are added (it should however be possible by my team. Non CI/CD in this case is viable)
  • CI/CD configuration should not be required to be extended for new Terraform configurations
  • It shouldn't require complex bash / sh magic

F.e.

./team1/main.tf
./team2/main.tf
./.../main.tf

The folders have a main.tf using the module with team variable values and a providers.tf with provider setup for the team (Azure Subscription).

Now that seems simple and where is the question. I want this to be executed with CI/CD. Colleagues should be able to create a MR with a new folder + terraform configuration and get the infrastructure that we can maintain from there but also hand it over to be used.

I haven't found anything really helpful while a lot of inputs are close.

I am pretty sure I am missing something very easy and just fail to google / ChatGPT the problem correctly.

Using GitLab-CI + Azure btw.

Thanks for your inputs.

Closest finding is https://stackoverflow.com/questions/68556638/ci-cd-with-terragrunt-terraform-mono-repo

答案1

得分: 1

以下是您要翻译的内容:

"以下大纲应该可以实现您想要的目标。这假设您正在使用gitlab管理的terraform状态,否则您需要根据您用于管理远程状态的系统来调整解决方案。

假设您有以下结构:

.
├── projects
│   ├── team1
│   │   └── main.tf
│   ├── team2
│   │   └── main.tf
│   └── team3
│       └── main.tf
└── tf-autodeploy

此shell脚本 tf-autodeploy(如下所述)接受一个参数,即包含每个独立的tf定义集的根目录(projects 在上面的结构中)。它将遍历每个目录,检查terraform状态是否已存在;如果不存在,将运行terraform apply。

然后,您可以配置CI配置文件(相关部分)来定义两个作业:一个用于自动更新_新_基础设施部署(而不是对现有状态的更改),以及一个可以手动运行的作业,指定要更新的项目的变量。

auto_tf_apply:
  # 仅在合并到默认分支后自动部署_新_基础设施
  needs: [init, validate]
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      changes: projects/**/*
  script:
    - tf-autoupdate " ${CI_PROJECT_DIR}/projects";


tf_apply_manual:
  when: manual
  needs: [init, validate, plan]
  variables:
    PROJECT:
      description: "要部署更改的项目(例如,'team1')"
    TF_ROOT: "$CI_PROJECT_DIR/projects/$PROJECT"
    TF_STATE_NAME: "$PROJECT"
  script:
    - if [[ "$PROJECT" == "" ]]; then exit 1; fi
    - cd $TF_ROOT
    - gitlab-terraform apply

tf-autoupdate 脚本在 auto_tf_apply 作业中运行,满足了“CI/CD在主要合并时自动添加Terraform配置”和“不更新已存在的Terraform配置”的要求。

tf_apply_manual 作业允许您通过运行手动作业并指定变量值来手动更新现有配置,用于特定项目(例如,team1)进行更新。

有关更多上下文,请参阅GitLab文档中的示例。"

以下是 tf-autodeploy 脚本的内容:

#!/usr/bin/env bash
# tf-autodeploy
root=$1
for project_name in "$root"/*; do
    pushd "${root}/${project_name}"
    export TF_STATE_NAME="${project_name}"
    export TF_ROOT="${root}/${project_name}"
    # 检查状态是否已存在
    if ! gitlab-terraform state list
    then
        echo "为 ${project_name} 创建新的部署"
        gitlab-terraform apply
    else
        echo "状态已存在,跳过 ${project_name}"
    fi
    popd
done
英文:

The following outline should accomplish what you want. This assumes you're using gitlab-managed terraform state, otherwise you'll need to adapt the solution for whatever system you use to manage your remote state.

Assume you have a structure like so:

.
├── projects
│   ├── team1
│   │   └── main.tf
│   ├── team2
│   │   └── main.tf
│   └── team3
│       └── main.tf
└── tf-autodeploy

This shell script tf-autodeploy (described below) accepts one argument, which is the root directory containing subdirectories for each independent set of tf definitions (projects in the above structure). It will traverse each directory, check if terraform state already exists; if it does not exist, it will terraform apply will be run.

Then you can have your ci configuration that (in relevant part) defines two jobs: one to apply automatic updates for new infrastructure deployments (not changes to existing state) and a job that can be run manually and specifying a variable of which project to update.

auto_tf_apply:
  # automatically deploy _new_ infrastructure only once merged to default branch
  needs: [init, validate]
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      changes: projects/**/*
  script:
    - tf-autoupdate "${CI_PROJECT_DIR}/projects"


tf_apply_manual:
  when: manual
  needs: [init, validate, plan]
  variables:
    PROJECT:
      description: "The project to deploy changes to (e.g., 'team1')"
    TF_ROOT: "$CI_PROJECT_DIR/projects/$PROJECT"
    TF_STATE_NAME: "$PROJECT"
  script:
    - if [[ "$PROJECT" == "" ]]; then exit 1; fi
    - cd $TF_ROOT
    - gitlab-terraform apply

The tf-autoupdate script run in the auto_tf_apply job satisfies the requirements of "CI/CD deploys added Terraform configurations automatically on main merge" and "dosen't update already existing Terraform configurations"

The tf_apply_manual job allows you to manually update existing configurations by running the manual job and specifying the variable value for the specific project (e.g., team1) to be updated.

For additional context, see the examples in the gitlab documentation.


The contents of an example the tf-autodeploy script

#!/usr/bin/env bash
# tf-autodeploy
root=$1
for project_name in "$root"/*; do
    pushd "${root}/${project_name}"
    export TF_STATE_NAME="${project_name}"
    export TF_ROOT="${root}/${project_name}"
    # check if state already exists
    if ! gitlab-terraform state list
    then
        echo "creating new deployment for ${project_name}"
        gitlab-terraform apply
    else
        echo "state already exists, skipping ${project_name}"
    fi
    popd
done

huangapple
  • 本文由 发表于 2023年5月25日 20:04:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76332075.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定