web-dev-qa-db-ja.com

Terraformワークスペース間でリソースを共有する

AWSでTerraformを使用して展開しているインフラストラクチャがあります。このインフラストラクチャは、ワークスペースを使用しているさまざまな環境に展開できます。

展開内のほとんどのコンポーネントはワークスペースごとに個別に作成する必要がありますが、主に次のコンポーネント間で共有したいいくつかの主要コンポーネントがあります。

  • 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ロールであり、そのLambdaのすべてのインスタンスで共有する必要があり、再作成は1回のみにする必要があります。

2番目のリソースはLambda関数で、その名前は現在のワークスペースに依存するため、各ワークスペースはデプロイされ、異なるLambdaの状態を追跡します。

異なるTerraformワークスペース間でリソースとその状態を共有するにはどうすればよいですか?

16
mittelmania

共有リソースについては、別のテンプレートで作成し、テンプレートでterraform_remote_stateを使用して参照します。これらのリソースについては、それらに関する情報が必要です。

以下はこれを実装する方法ですが、おそらく他の方法で実装できます。 YMMV

共有サービステンプレート(IAMロールを配置する場所)では、Terraformバックエンドを使用して、共有サービステンプレートの出力データをConsulに格納します。また、他のテンプレートで使用するすべての情報をoutputする必要があります。

shared_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

11
kenlukas

name値がすでにプロビジョニングされているリソースと一致する場合、name属性を持つaws_iam_roleのようなリソースは新しいインスタンスを作成しません。

したがって、以下はLambdaGeneralRoleという名前の単一のaws_iam_roleを作成します。

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プロバイダーは、次の場合に1つのS3 bucket name 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を実行した後に共有リソースが破壊されるリスクがなくなります。

0
Igwe Kalu