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
コメント