【问题标题】:Managing Terraform multiple environments with Git使用 Git 管理 Terraform 多个环境
【发布时间】:2021-09-05 05:34:06
【问题描述】:

我研究并观看了一些有关管理多个环境的最佳方式的视频,但我仍然对如何以更好的方式管理它感到困惑。

假设我有一个具有以下结构的存储库:

main.tf
variables.tf
backend.tf
dev/
   variables.tfvar
   backend.dev.hcl
prod/
   variables.tfvar
   backend.production.hcl

然后,在我的存储库中,我有两个分支(dev 和 main)。 将生产变量值提交给我的开发分支是否有意义?遵循任何最佳实践来处理这种情况的最佳方法是什么?

我的最后一个问题,一旦有任何更改提交到 dev 分支,将更改合并到 prod 分支而不丢失任何 dev/prod terraform 配置的最佳方法是什么?

提前谢谢你!

【问题讨论】:

  • 您是否查看过 Terraform 工作空间?不能说它 100% 适合您的情况,不知道正在发生什么样的发展。但我认为值得发现:D
  • 谢谢 vidura。我看过 Terraform 工作空间,但我觉得我的疑虑更多是关于如何将 Terraform 代码从 dev 推送到 Prod。例如,tfstate 存储在存储桶中,但如果开发环境发生任何更改,它将在本地更新 tfstate 文件。我是否需要提交此文件然后也推送到 Prod 分支?这会弄乱(覆盖)Prod tfstate 文件。
  • 一个基本的 Terraform 原则是不要将状态文件提交给任何版本控制系统。而且我们不应该修改 Terraform 之外的状态文件。所以工作空间的想法是为单个配置维护多个状态文件。在这里,您可能需要为 2 个环境维护 2 个基础架构,但需要一个配置。在配置文件中,您可以指定如何根据活动工作区创建资源。

标签: git terraform


【解决方案1】:

这个问题的答案通常取决于您是在谈论 Terraform 配置的多个部署阶段本身,还是您将在 Terraform 上运行的任何应用程序/服务的多个部署阶段 -托管基础设施。

考虑这种区别的一种方法是考虑您将使用多个阶段来实现什么。如果您的目标是在生产环境中尝试运行terraform apply,那么您就是在谈论 Terraform 配置的多个部署阶段。如果您的目标是创建一个长期存在的暂存环境,以便您将应用程序/服务部署到其中,那么从部署管道的角度来看,暂存环境通常也是“生产”环境,因此通常应该这样对待。


要在将 Terraform 配置应用到“真实基础架构”之前对其进行测试,您可以使用 Terraform CLI workspaces 创建与您的配置相关联的临时附加状态,这样您就可以尝试应用更改而不影响“默认”中表示的主要基础架构" 工作区:

  • terraform workspace new temp-test 创建一个临时工作区。
  • 使用您的版本控制系统选择最近在default 工作区中应用的提交。这通常位于版本控制存储库的主分支上,但根据您使用 VCS 的方式,您可能需要选择较早的提交以排除尚未应用于实际系统的任何更改。
  • terraform apply 创建与默认工作区等效的基础架构,作为测试的基础。
  • 使用您的版本控制系统切换回您要测试的配置。这通常是存储库中的功能分支,可能附加到拉取请求。在此工作流的真实版本中,以您的分支名称命名临时工作区可能会有所帮助,这样您的同事就可以轻松查看哪些分支和工作区放在一起。
  • terraform apply 再次计划和应用新配置所代表的更改。
  • 如果应用成功,请检查它创建的基础架构以确保其按您预期的方式运行。
  • 完成后:
    • terraform destroy 破坏 temp-test 基础设施
    • terraform workspace select 回到默认工作区
    • terraform workspace delete temp-test删除临时工作区

为此,您需要小心避免在远程系统需要唯一名称的情况下与现有生产对象发生冲突。对于具有不同命名空间的帐户的系统,一个常见的选择是使用不同的帐户和完全独立的凭据进行测试,这意味着您可以使用远程系统的访问控制来避免“真实”基础设施的意外中断.


要创建一个长寿命的暂存或开发环境,以便在其自己的部署管道期间测试某些更高级别的组件,需要采用不同的策略:在这种情况下,支持暂存环境的基础架构是“生产”的一部分,只要涉及到应用程序的部署过程,因此通常应该这样建模。

为实现这一目标,同时确保两个基础架构堆栈除了有意的差异外保持相同,请将您的通用基础架构代码分解为一个或多个 modules,然后为生产基础架构调用这些模块一次,然后再为彼此环境的基础架构调用这些模块.

根据您系统的预期故障域,您可以选择在一个配置中同时表示生产和暂存基础架构,其中包含对同一模块的两次调用:

module "network-production" {
  source = "../modules/network"

  cidr_block = "10.1.0.0/16"
  # etc...
}

module "network-production" {
  source = "../modules/network"

  cidr_block = "10.2.0.0/16"
  # etc...
}

或者,为了确保它们都可以独立维护,您可以编写两个单独的配置,它们都调用同一个模块并分别terraform apply它们。

在这两种情况下,这里的想法是使用公共模块的输入变量来表示不同环境之间不可避免的差异,但在两种情况下保持声明的资源相同,但将它们都视为“生产基础设施”从应用程序管道的角度来看,通过将它们都保存在一个名为 default 的命名空间中,无论是在一个配置中还是在多个配置中,并通过在版本控制中使用相同的主分支来同时表示它们的“最新版本”。

如果您想测试对您的配置所做的更改,这些更改共同代表您的应用程序的管道所依赖的所有环境,您可以通过创建一个代表整个堆栈或一个特定环境的临时工作区并应用来自在将其合并到主分支之前分支到该堆栈并将其应用到默认工作区。


此答案是对 Terraform 文档 When to use Multiple Workspaces 中指南的详细说明。

但最终,在这种情况下,您有几个不同的选项需要权衡取舍,我建议您查看此建议和文档中的其他相关上下文,并自行决定哪些建议最符合您的需求. Terraform 是一种通用工具,旨在解决各种不同的问题,最终只有您可以将您的特定需求集映射到 Terraform 的功能。

【讨论】:

  • 嗨,马丁,非常感谢您的详细回答。这正是我一直在寻找的。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-03
  • 2018-12-11
  • 2020-04-16
  • 1970-01-01
  • 2015-10-30
  • 2018-07-15
  • 2018-04-16
相关资源
最近更新 更多