Совместное использование ресурсов между рабочими пространствами Terraform

У меня есть инфраструктура, которую я развертываю, используя Terraform в AWS. Эту инфраструктуру можно развернуть в разных средах, для которых я использую рабочие пространства.

Большинство компонентов в развертывании должны создаваться отдельно для каждой рабочей области, но у меня есть несколько ключевых компонентов, которыми я хочу поделиться между ними, в первую очередь:

  • Роли и разрешения IAM
  • Они должны использовать один и тот же API-шлюз, но каждое рабочее пространство должно развертываться по разным путям и методам

Например:

resource "aws_iam_role" "lambda_iam_role" {
  name = "LambdaGeneralRole"
  policy = <...>
}

resource "aws_lambda_function" "my_lambda" {
  function_name = "lambda-${terraform.workspace}"
  role = "${aws_iam_role.lambda_iam_role.arn}"
}

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

Второй ресурс - это лямбда-функция, имя которой зависит от текущего рабочего пространства, поэтому каждое рабочее пространство будет развертываться и отслеживать состояние другой лямбды.

Как я могу поделиться ресурсами и их состоянием между различными рабочими пространствами Terraform?

Ответ 1

Для общих ресурсов я создаю их в отдельном шаблоне и затем обращаюсь к ним, используя terraform_remote_state в шаблоне, где мне нужна информация о них.

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

В шаблоне общих сервисов (куда вы бы поместили свою роль IAM) я использую бэкэнд Terraform для хранения выходных данных для шаблона общих сервисов в Консуле. Вам также необходимо output любую информацию, которую вы хотите использовать в других шаблонах.

шаблон share_services

terraform {
  backend "consul" {
    address = "consul.aa.example.com:8500"
    path    = "terraform/shared_services"
  }
}

resource "aws_iam_role" "lambda_iam_role" {
  name = "LambdaGeneralRole"
  policy = <...>
}

output "lambda_iam_role_arn" {
  value = "${aws_iam_role.lambda_iam_role.arn}"
}

"Бэкэнд" в Terraform определяет, как загружается состояние и как выполняется такая операция, как apply. Эта абстракция позволяет хранить нелокальное состояние файла, выполнять удаленное выполнение и т.д.

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

terraform_remote_state:

Извлекает метаданные состояния из удаленного бэкэнда

индивидуальный шаблон

data "terraform_remote_state" "shared_services" {
    backend = "consul"
    config {
        address = "consul.aa.example.com:8500"
        path    = "terraform/shared_services"
    }
}

# This is where you use the terraform_remote_state data source
resource "aws_lambda_function" "my_lambda" {
  function_name = "lambda-${terraform.workspace}"
  role = "${data.terraform_remote_state.shared_services.lambda_iam_role_arn}"
}

Ссылки:

https://www.terraform.io/docs/state/remote.html

https://www.terraform.io/docs/backends/

https://www.terraform.io/docs/providers/terraform/d/remote_state.html

Ответ 2

Ресурсы, такие как aws_iam_role, имеющие атрибут name, не будут создавать новый экземпляр, если значение name соответствует уже подготовленному ресурсу.

Итак, следующее создаст один aws_iam_role с именем LambdaGeneralRole.

resource "aws_iam_role" "lambda_iam_role" {
  name = "LambdaGeneralRole"
  policy = <...>
}

...

resource "aws_iam_role" "lambda_iam_role_reuse_existing_if_name_is_LambdaGeneralRole" {
  name = "LambdaGeneralRole"
  policy = <...>
}

Аналогично, провайдер aws создаст одно имя S3 bucket my-store с указанием следующего:

resource "aws_s3_bucket" "store-1" {
  bucket        = "my-store"
  acl           = "public-read"
  force_destroy = true
}

...

resource "aws_s3_bucket" "store-2" {
  bucket        = "my-store"
  acl           = "public-read"
  force_destroy = true
}

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


Чтобы получить максимальную отдачу от этого подхода, определите общие ресурсы как отдельную конфигурацию. Таким образом, вы не рискуете уничтожить общий ресурс после запуска terraform destroy.