2

我正在尝试使用远程存储(Terraform Cloud)设置一个 terraform 项目,该项目将主要提供 Google Cloud Platform 资源。作为基础架构的一部分,我需要 3 个环境,这些环境将使用 terraform 工作空间进行管理。每个环境在我的存储库中都有自己的目录,在每个环境中我将定义环境特定的资源。目录结构类似于:

|- terraform-project
   |- environments
   |  |- staging
   |  |  |- main.tf
   |  |  |- outputs.tf
   |  |  |- variables.tf
   |  |- production
   |     |- main.tf
   |     |- outputs.tf
   |     |- variables.tf
   |- backend.tf
   |- main.tf
   |- outputs.tf
   |- variables.tf

但是,每个环境都需要使用相同的 Google Cloud Platform 项目。我通常会在最根main.tf文件中使用以下内容创建项目:

resource "random_id" "project_id" {
  byte_length = 4
  prefix      = "${var.project_name}-"
}

resource "google_project" "project" {
  name            = var.project_name
  project_id      = random_id.project_id.hex
  billing_account = var.billing_account
  org_id          = var.org_id
}

所以我的问题是我如何只创建一次项目并在环境之间共享它?在每个环境中执行以下main.tf操作不起作用:

resource "google_compute_network" "vpc_network" {
  name    = "staging-network"
  project = google_project.project.project_id
}

google_project.project.project_id找不到资源。大概是因为该terraform plan environments/{staging,production}命令不知道查找目录树。

我考虑过使用一个模块,但鉴于上面的代码使用了一个随机 id,这不会导致为每个环境创建一次项目,而是使用不同的 id?


编辑:另一个想法是创建一个core工作区,其中包含 Google Cloud Platform 项目的设置以及任何其他共享资源。然后每个环境将包含一个data指向core工作区远程状态的块:

data "terraform_remote_state" "core" {
  backend = "remote"
  ...
}

resource "google_compute_network" "vpc_network" {
  name    = "staging-network"
  project = data.terraform_remote_state.core.outputs.project_id
}

这是一个可接受的解决方案吗?

4

2 回答 2

1

我最终提出的想法是创建另一个工作空间来保存共享的“核心”基础架构部分。这就是所谓core的,它的唯一目的(至少现在)是创建谷歌云平台项目。然后它输出项目 id 以供其他工作区使用。最终的目录结构如下所示:

|- terraform-project
   |- environments
   |  |- core
   |  |  |- main.tf
   |  |  |- outputs.tf
   |  |  |- variables.tf
   |  |- staging
   |  |  |- main.tf
   |  |  |- outputs.tf
   |  |- production
   |     |- main.tf
   |     |- outputs.tf
   |- backend.tf

whereenvironments/core/main.tf有以下配置:

provider "google" {
  project = "admin-project"
  version = "~> 3.6.0"
}

resource "random_id" "project_id" {
  byte_length = 4
  prefix      = "${var.project_name}-"
}

resource "google_project" "project" {
  name            = var.project_name
  project_id      = random_id.project_id.hex
  billing_account = var.billing_account
  org_id          = var.org_id
}

并且每个其他环境main.tf文件都具有以下配置:

provider "google" {
  project = "admin-project"
  version = "~> 3.6.0"
}

data "terraform_remote_state" "core" {
  backend = "remote"

  config = {
    organization = "my-org"
    workspaces = {
      name = "networking-core"
    }
  }
}

resource "google_compute_network" "vpc_network" {
  name        = "my-network"
  project     = terraform_remote_state.core.outputs.project_id
}

这当然会在我使用的工作空间之间创建依赖关系,但我并不认为这必然是一个缺点。

于 2020-05-10T23:24:41.663 回答
0

使用以下项目目录

| - Terraform Project
  |- staging
    |- main.tf
    |- backend.tf
    |- provider.tf
    |- vars.tf
    |- output.tf
  |- production
    |- main.tf
    |- backend.tf
    |- provider.tf
    |- vars.tf
    |- output.tf
  |- modules
    |- main.tf
    |- vars.tf
    |- output.tf

主要业务逻辑将在 modules/main.tf 文件中。

在为每个环境配置资源时,您的 {{env_type}}/main.tf 将调用该模块,例如:-

暂存/main.tf:-

module "example" {
  source = "../modules/"
}

暂存/provider.tf:-

provider "google" {
  project     = var.PROJECT_NAME
  credentials = "xxxxxxxxxxx"
  region      = "${var.REGION}"
}

生产环境类型也是如此,因此您可以将相同的代码和项目用于多个环境类型的示例

于 2020-05-10T07:17:42.013 回答