TerraformでAWSリソース1種類を複数個作成する
ここんとこTerraformづくしです。前回はAPIGatewayとLambdaとSNSとS3を一気にまとめて作成するものを作ったわけですが、諸般の事情から複数のDynamoDBと複数のLambdaそして複数のAPIGateway、、はてはS3まで準備しないといけなくなったので、いろいろと試行錯誤しながら準備しました。
1つのリソースを複数個用意するとかいうサンプルがなかなかなかったので
役に立つかなと思って備忘録として残しておきます。
*なんかもっと効率いい方法あれば教えてほしい。
そしてTerraformはプログラムではないのでforとかifの使い方に癖があるし
結構な制約事項となります。けれども、1個覚えればどこのクラウドだろうが
オンプレだろうが1つの記述法で行けるというのは非常に魅力的なんですよねぇ。
https://dev.classmethod.jp/articles/terraform-network-variable/
https://cloudfish.hatenablog.com/entry/2020/02/19/183548
https://dev.classmethod.jp/articles/terraform_count_delete/
https://qiita.com/keiichi-hikita/items/9fd20e8ad6afe4e5ef72
https://febc-yamamoto.hatenablog.jp/entry/2018/02/02/120207
https://github.com/terraform-providers/terraform-provider-aws/issues/3176
1つのリソースを複数個用意するとかいうサンプルがなかなかなかったので
役に立つかなと思って備忘録として残しておきます。
*なんかもっと効率いい方法あれば教えてほしい。
そしてTerraformはプログラムではないのでforとかifの使い方に癖があるし
結構な制約事項となります。けれども、1個覚えればどこのクラウドだろうが
オンプレだろうが1つの記述法で行けるというのは非常に魅力的なんですよねぇ。
◆設定
1.terraformファイル群
(1)ルートに置くもの
# main.tf ----------------- resource "aws_sns_topic" "this_sns_topic" { name = var.sns_topic_name } module "lambda" { source = "./lambda" } module "apigateway" { source = "./apigateway" region = var.region account_id = var.account_id } module "dymano" { source = "./dynamodb" } module "s3" { source = "./s3" } ----------------- # variables.tf ----------------- variable "access_key" { description = "AWS Access Key" } variable "secret_key" { description = "AWS Secret Key" } variable "role_arn" { description = "AWS Role ARN for Assume Role" } variable "region" { description = "AWS Region" default = "ap-northeast-1" } variable "sns_topic_name" { default = "sns_dev_topic" } variable "account_id" { default = "XXXXXXX" } ----------------- # provider.tf ----------------- provider "aws" { access_key = var.access_key secret_key = var.secret_key region = var.region } -----------------
(2)Lambdaディレクトリ配下
# main.tf ----------------- data "archive_file" "arc_dev_function" { for_each = var.import_lambda_dirs type = "zip" source_dir = "${path.module}/src/${lookup(each.value, "filename")}" output_path = "${path.module}/upload/${lookup(each.value, "filename")}.zip" } resource "aws_lambda_function" "lambda_functions" { for_each = var.import_lambda_dirs filename = "${path.module}/upload/${lookup(each.value, "filename")}.zip" function_name = lookup(each.value, "filename") role = var.lambda_function_arn handler = "lambda_function.lambda_handler" source_code_hash = base64sha256("${path.module}/upload/${lookup(each.value, "filename")}.zip") runtime = var.lambda_runtime memory_size = var.lambda_memory timeout = var.lambda_timeout environment { variables = lookup(each.value, "environment_setting") } tags = lookup(each.value, "tag_setting") } ----------------- # variables.tf ----------------- variable "import_lambda_dirs" { default = { dir1 = { filename = "01_sample" environment_setting = { ENV_SAMPLE = "sample1" } tag_setting = { "tag" = "sample1" } } dir2 = { filename = "02_sample" environment_setting = { ENV_SAMPLE = "sample2" } tag_setting = { "tag" = "sample2" } } dir3 = { filename = "03_sample" environment_setting = { ENV_SAMPLE = "sample3" } tag_setting = { "tag" = "sampl3" } } } } variable "lambda_role_arn" { default = "AWS Role ARN for Assume Role" } variable "lambda_runtime" { default = "python3.8" } variable "lambda_memory" { default = 128 } variable "lambda_timeout" { default = 30 } variable "lambda_function_arn" { default = "arn:aws:iam::XXXXX:role/LambdaRole" } -----------------
(3)APIGatewayディレクトリ配下
# main.tf ----------------- data "template_file" "apigateway_template" { for_each = var.apigateway_param template = file("${path.module}/swagger_definition/${lookup(each.value, "filename")}.yml") vars = { region = var.region account_id = var.account_id function_name = lookup(each.value, "functionname") base_path = lookup(each.value, "basepath") } } resource "aws_api_gateway_rest_api" "my_api_gateway" { for_each = var.apigateway_param name = lookup(each.value, "filename") description = "This is my API for demonstration purposes" body = data.template_file.apigateway_template[each.key].rendered } resource "aws_api_gateway_deployment" "apiDeployment" { for_each = var.apigateway_param rest_api_id = aws_api_gateway_rest_api.my_api_gateway[each.key].id stage_name = lookup(each.value, "basepath") } resource "aws_lambda_permission" "lambda_permission" { for_each = var.apigateway_param statement_id = "AllowMyDemoAPIInvoke" action = "lambda:InvokeFunction" function_name = lookup(each.value, "functionname") principal = "apigateway.amazonaws.com" source_arn = "${aws_api_gateway_rest_api.my_api_gateway[each.key].execution_arn}/*/*/*" } ----------------- # variables.tf ----------------- variable "region" {} variable "account_id" {} variable "apigateway_param" { default = { param1 = { index = 0 filename = "sample1" functionname = "01_sample" basepath = "test" } param2 = { index = 1 filename = "sample2" functionname = "02_sample" basepath = "test" } param3 = { index = 2 filename = "sample3" functionname = "03_sample" basepath = "test" } } } -----------------
(4)DynamoDBディレクトリ配下
# main.tf ----------------- resource "aws_dynamodb_table" "basic-dynamodb-table1" { for_each = var.hash_range_param name = lookup(each.value, "table_name") billing_mode = "PAY_PER_REQUEST" hash_key = lookup(each.value, "table_hashkey") range_key = lookup(each.value, "table_rangekey") attribute { name = lookup(each.value, "table_hashkey") type = lookup(each.value, "hash_type") } attribute { name = lookup(each.value, "table_rangekey") type = lookup(each.value, "hash_type") } tags = lookup(each.value, "tags") } resource "aws_dynamodb_table" "basic-dynamodb-table2" { for_each = var.hash_only_param name = lookup(each.value, "table_name") billing_mode = "PAY_PER_REQUEST" hash_key = lookup(each.value, "table_hashkey") attribute { name = lookup(each.value, "table_hashkey") type = lookup(each.value, "type") } tags = lookup(each.value, "tags") } ----------------- # variables.tf ----------------- variable "hash_range_param" { default = { param1 = { index = 0 table_name = "hash_range_sample1" table_hashkey = "hash_key" table_rangekey = "range_key" hash_type = "S" range_type = "S" tags = { tag = "sample1" } } param2 = { index = 1 table_name = "hash_range_sample2" table_hashkey = "hash_key" table_rangekey = "range_key" hash_type = "S" range_type = "S" tags = { tag = "sample2" } } } } variable "hash_only_param" { default = { param1 = { index = 0 table_name = "hash_only_sample1" table_hashkey = "key_id" type = "S" tags = { tag = "sample1" } } param2 = { index = 1 table_name = "hash_only_sample2" table_hashkey = "key_id" type = "S" tags = { tag = "sample2" } } } } -----------------
(5)S3ディレクトリ配下
# main.tf ----------------- resource "aws_s3_bucket" "bucket" { for_each = var.buckets bucket = lookup(each.value, "bucket_name") acl = lookup(each.value, "acl") tags = lookup(each.value, "tags") } ----------------- # variables.tf ----------------- variable "buckets" { default = { param1 = { index = 0 bucket_name = "sample-bucket-20200517-1" acl = "private" tags = { tag = "sample1" } } param2 = { index = 1 bucket_name = "sample-bucket-20200517-2" acl = "private" tags = { tag = "sample2" } } } } -----------------
2.ディレクトリ構造
|-- apigateway | |-- main.tf | |-- swagger_definition | | |-- sample1.yml | | |-- sample2.yml | | `-- sample3.yml | `-- variables.tf |-- dynamodb | |-- main.tf | `-- variables.tf |-- lambda | |-- main.tf | |-- src | | |-- 01_sample | | | `-- lambda_function.py | | |-- 02_sample | | | `-- lambda_function.py | | `-- 03_sample | | `-- lambda_function.py | |-- upload | `-- variables.tf |-- main.tf |-- provider.tf |-- s3 | |-- main.tf | `-- variables.tf |-- terraform.tfstate |-- terraform.tfstate.backup `-- variables.tf
3.実行コマンド
$ terraform init $ terraform plan $ terraform apply $ terraform destroy
◆参考
・複数リソース作り方
https://qiita.com/ringo/items/875f08ec550f0826f0dchttps://dev.classmethod.jp/articles/terraform-network-variable/
https://cloudfish.hatenablog.com/entry/2020/02/19/183548
https://dev.classmethod.jp/articles/terraform_count_delete/
https://qiita.com/keiichi-hikita/items/9fd20e8ad6afe4e5ef72
https://febc-yamamoto.hatenablog.jp/entry/2018/02/02/120207
・環境変数関連
https://qiita.com/tksugimoto/items/c1dd29a587e5689a1f6a・APIGateway
https://medium.com/@jmarhee/using-for-each-in-terraform-in-modules-7fb5a240a0d9・DynamoDB
https://www.terraform.io/docs/providers/aws/r/dynamodb_table.htmlhttps://github.com/terraform-providers/terraform-provider-aws/issues/3176
コメント