Terraform AWS modulesでコンテナLambdaをデプロイする実装方法
歴史シミュレーションゲーム好きのくろすけです!
StepFunctions を再キャッチアップする中で Terraform で Lambda をサクッと作成してみたので思ったことなども含め記事にしてみます。
以前ちょっとだけ terraform-aws-modules を使ってみたのですが、設計思想が若干合わないと思った箇所があり、あまり使用していませんでした。
ですが改めて車輪の再発明をしているのは時間の無駄だなと思い、再度使ってみることにしました。
概要
本記事では、terraform-aws-modules/lambda/aws モジュールを使用して、Dockerコンテナイメージベースのシンプルなダミー用Lambda関数をデプロイしてみます。
やってみた
1. ディレクトリ構成の準備
まず、以下のようなディレクトリ構成を準備しました。
.
├── infra/
│ └── services/
│ └── lambda/
│ └── krsk/
│ ├── main.tf
│ ├── provider.tf
│ ├── terraform.tfvars
│ └── variables.tf
└── lambda/
└── dummy/
├── app.py
└── Dockerfile
2. Lambda関数のコード作成
シンプルなダミーLambda関数を作成します。
lambda/dummy/app.py:
import json
def lambda_handler(event, context):
"""
Simple dummy AWS Lambda function.
"""
# Log the received event
print(f"Received event: {json.dumps(event)}")
# Create a response
response = {
"statusCode": 200,
"body": json.dumps({"message": "Hello from Dummy Lambda!", "event": event}),
}
return response
受け取ったイベントをログに出力し、シンプルなレスポンスを返すだけの関数です。
3. Dockerfileの作成
次に、Lambda関数をコンテナ化するためのDockerfileを作成します。
lambda/dummy/Dockerfile:
FROM public.ecr.aws/lambda/python:3.12
COPY app.py ${LAMBDA_TASK_ROOT}
CMD [ "app.lambda_handler" ]
4. Terraformコードの作成
terraform-aws-modulesを使ってLambda関数をデプロイするTerraformコードを作成します。
infra/services/lambda/krsk/main.tf:
locals {
lambda_source_dir = "${path.module}/../../../../lambda/dummy"
source_hash = sha256(join("", [
for f in fileset(local.lambda_source_dir, "**") :
filesha256("${local.lambda_source_dir}/${f}")
]))
}
module "docker_image" {
source = "terraform-aws-modules/lambda/aws//modules/docker-build"
create_ecr_repo = true
ecr_repo = "${var.sys_name}-${var.env}-repo"
use_image_tag = true
image_tag = substr(local.source_hash, 0, 12)
source_path = local.lambda_source_dir
}
module "lambda_function" {
source = "terraform-aws-modules/lambda/aws"
function_name = "${var.sys_name}-${var.env}-lambda"
create_package = false
image_uri = module.docker_image.image_uri
package_type = "Image"
architectures = ["arm64"]
timeout = 60
memory_size = 512
tracing_mode = "Active"
publish = true
attach_policy = true
policy = "arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy"
tags = {
Environment = var.env
Name = "${var.sys_name}-${var.env}-lambda"
}
depends_on = [module.docker_image]
}
module "lambda_alias" {
source = "terraform-aws-modules/lambda/aws//modules/alias"
name = var.env
function_name = module.lambda_function.lambda_function_name
function_version = module.lambda_function.lambda_function_version
description = "environment alias (krsk)"
}
コードのポイント
以下の2点でLambdaエイリアスベースのデプロイを実現しています。
1. Lambdaソースディレクトリ自動変更検出
locals {
...(中略)...
source_hash = sha256(join("", [
for f in fileset(local.lambda_source_dir, "**") :
filesha256("${local.lambda_source_dir}/${f}")
]))
}
module "docker_image" {
...(中略)...
use_image_tag = true
image_tag = substr(local.source_hash, 0, 12)
...(中略)...
}
Lambdaソースディレクトリ内の全ファイルのハッシュ値を計算し、コードが変更されたことをハッシュ値で検出できるようになっています。
ハッシュ値を image_tag に使用することで、結果的にLambdaソースディレクトリ内の変更を検知しDockerイメージのビルド、ECRへのプッシュを自動で実行する処理を実現しています。
3. lambdaモジュール
module "lambda_function" {
...(中略)...
publish = true
...(中略)...
}
module "lambda_alias" {
...(中略)...
function_name = module.lambda_function.lambda_function_name
function_version = module.lambda_function.lambda_function_version
...(中略)...
}
publish を true にすることで自動で新しいバージョンを発行し、最新バージョンをエイリアスにアタッチします。
やってみてわかったこと
- LambdaのソースコードとインフラのデプロイをTerraformで一気通貫に実行できる
- 上記のため、アプリとインフラで一つのCI/CDとしてまとめることができる
- 簡単な検証用の環境としては使い勝手が良さそう
ただし、
- システム運用中の環境には向かないケースが多いかも
- ゴールデンイメージを使い回すなら、アプリとインフラのライフサイクルが異なってくる
- 運用中の環境としては向いてなさそう
あとがき
terraform-aws-modulesは、Terraformによる開発を簡素化してくれる素晴らしいツールだと改めて実感しました。
ただし使ってみてどこまでモジュールの機能を活用するかはケースバイケースで考慮する必要があることも実感しました。
terraform-aws-modulesを使ってみて効率的に開発できることを実感したので、今後は積極的に活用していこうと思います。
以上、くろすけでした!






