【问题标题】:Ephemeral environments using GCP, Cloud Build and Terraform workspaces使用 GCP、Cloud Build 和 Terraform 工作区的临时环境
【发布时间】:2021-07-15 22:21:46
【问题描述】:

正如标题所说,尝试利用 Cloud Build 和 Terraform 工作空间在同一个 GCP 项目中创建任意临时环境,映射到一个分支。

我的 Cloud Build 管道可以工作,但 terraform apply 似乎并没有尊重我尝试设置的工作空间,因为以前构建的资源被破坏了,即使它们应该在另一个工作空间中。

cloud_build.yaml

  - id: 'tf workspace'
    name: 'hashicorp/terraform:1.0.2'
    args: ['workspace','new',$BRANCH_NAME]

  - id: 'tf workspace'
    name: 'hashicorp/terraform:1.0.2'
    args: ['workspace','select',$BRANCH_NAME]

  - id: 'tf init'
    name: 'hashicorp/terraform:1.0.2'
    args: ['init']

  - id: 'tf plan'
    name: 'hashicorp/terraform:1.0.2'
    args: ['plan',"-var","branch_name=$BRANCH_NAME","-var","project_id=$PROJECT_ID"]

  - id: 'tf apply'
    name: 'hashicorp/terraform:1.0.0'
    args: ['apply',"-auto-approve","-var","branch_name=$BRANCH_NAME","-var","project_id=$PROJECT_ID"]

后端很简单:

terraform {
  backend "gcs" {
    bucket = "my-tfstate-bucket"
  }
}

我是否遗漏了一些关于工作空间的内容?似乎它们并没有真正反映在远程状态中。我知道您可以在 tf 后端配置中指定特定的工作区,但由于这些工作区是动态的,我一直希望通过 CLI 设置工作区会在上传的远程状态下设置某种命名空间并注意的分离。

编辑只是为了确认我以不同的方式命名所有组件,以当前分支名称作为后缀,但 TF 仍会销毁在运行不同分支时创建的组件。

【问题讨论】:

  • 每次应用后,terraform 是否正确地将新文件上传到您的 GCS 存储桶?这可能是由于命名空间命名与对象的 GCS 命名约定冲突,导致将状态上传到存储桶的过程失败,因此您总是停留在相同的状态。
  • 是的,只是看了一下状态文件,它最后更新的时间戳与最后一次部署尝试匹配。但是我在任何地方都没有在状态文件中看到任何“工作空间”的证据,我承认我对状态文件格式知之甚少,但你会认为它会以某种方式在工作空间状态之间划定,如果它们被设置,要么,要么完全上传不同的状态文件,但我只有一个。

标签: google-cloud-platform google-cloud-functions terraform google-cloud-build


【解决方案1】:

据我所知,terraform 工作空间允许您将 Terraform 状态存储在多个单独的命名(状态)文件中。

因此,工作空间仅与状态文件(命名)有关。它们不会影响 GCP 资源命名。

我了解到您希望将来自不同 git 分支的 GCP 资源部署到一个 GCP 项目中。

在大多数情况下,GCP 项目是一个“资源命名范围” - 这意味着在一个 GCP 项目中不能使用所选名称创建多个资源(给定类型的)。例如,我不能在一个 GCP 项目中创建 2 个名称相同的 pubsub 主题,或者创建 2 个名称相同的云函数等。

假设在您的 terraform 文件中(这是我的猜测,因为原始问题中没有 terraform 文件),您不处理依赖项 - GCP 资源名称作为 git branch 的函数(对于不同的分支部署的资源应该有不同的名称) - 我猜一个新的工作空间部署(apply)将项目中已经存在的内容与 TF 文件中描述的内容进行比较,并记录在你的状态文件中(对于新工作空间为空),并决定重新创建所有资源并将其记录在新的工作区状态文件中。我认为旧的工作区状态文件保持原样(未修改,未修改)。

为了解决这个问题,可能有必要开发一些机制(在 TF 文件中),以便这些文件中描述的每个 GCP 资源根据(功能上)获取名称(在 GCP 项目中必须是唯一的)依赖)git分支名称,这样不同git分支部署的资源之间就不会互相干扰了。

【讨论】:

  • 谢谢@al-dann,这也是我的猜测,但实际上我对所有组件的命名不同,将分支名称附加到末尾(我实际上只是为现在)。如果我在 branch_1 上部署,我会应用 cloud_function_branch_1,如果我在 branch_2 上部署,则 cloud_function_branch_1 会被销毁,而 cloud_function_branch_2 会被创建。
  • “workspaces”的使用是强制要求,还是只是为不同的git分支分别存储TF状态文件的一种机制?如果要求是第二个,而不是第一个 - 我可以修改我的答案并添加一个示例,如何在没有“工作空间”的情况下实现。
【解决方案2】:

想通了。因为云构建在构建之间缓存 Terraform 工作区,所以需要在workspace 命令之前调用init之前。切换我的步骤顺序解决了这个问题,我现在在我的存储桶中看到每个工作区名称的多个状态文件。

【讨论】:

    猜你喜欢
    • 2023-01-25
    • 2020-11-25
    • 2021-02-13
    • 2019-11-04
    • 1970-01-01
    • 2021-04-14
    • 2020-11-12
    • 2021-06-19
    • 2023-02-26
    相关资源
    最近更新 更多