AWSでTerraformを使用して展開しているインフラストラクチャがあります。このインフラストラクチャは、ワークスペースを使用しているさまざまな環境に展開できます。
展開内のほとんどのコンポーネントはワークスペースごとに個別に作成する必要がありますが、主に次のコンポーネント間で共有したいいくつかの主要コンポーネントがあります。
例えば:
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ワークスペース間でリソースとその状態を共有するにはどうすればよいですか?
共有リソースについては、別のテンプレートで作成し、テンプレートで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
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
を実行した後に共有リソースが破壊されるリスクがなくなります。