Совместное использование проекта Google Cloud Platform в рабочих пространствах terraform

Я пытаюсь настроить проект terraform, используя удаленное хранилище (Terraform Cloud), который в первую очередь будет предоставлять ресурсы 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} не знает, что нужно искать в дереве каталогов.

Я думал об использовании модуля, но, учитывая, что в приведенном выше коде используется случайный идентификатор, не приведет ли это к тому, что проект будет создаваться один раз для каждой среды, но с другим идентификатором?


Изменить. Еще одна идея - создать 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
}

Это приемлемое решение?


person tomasbasham    schedule 09.05.2020    source источник


Ответы (2)


Идея, к которой я пришел в конце концов, заключалась в том, чтобы создать еще одно рабочее пространство для хранения общих, «основных» частей инфраструктуры. Это называется core, и его единственная цель (по крайней мере, на данный момент) - создать проект Google Cloud Platform. Затем он выводит идентификатор проекта, который будет использоваться другими рабочими пространствами. Окончательная структура каталогов выглядела так:

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

где environments/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
}

Конечно, теперь это создает зависимость между рабочими пространствами, которые я использую, но я не считаю это недостатком.

person tomasbasham    schedule 10.05.2020

Используйте следующий каталог проекта

| - 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 вызовет модуль, например: -

staging / main.tf: -

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

staging / provider.tf: -

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

То же самое будет для типа производственной среды, поэтому вы можете использовать один и тот же код и проект для нескольких примеров типа среды.

person karan sharma    schedule 10.05.2020
comment
Как это помогает в создании единого проекта Google Cloud Platform и его совместном использовании между средами? Хотя я понимаю, что модули - это многократно используемые фрагменты инфраструктуры, они, как правило, используются для увеличения количества нескольких, но похожих ресурсов. Если бы я включил модуль в каждую среду, terraform попытался бы создать проект для каждой? - person tomasbasham; 10.05.2020