はじめに
AWS Lambda を Terraform で構築し、 EventBridge や CloudWatch Logs の Subscription Filter を使ってトリガーする方法について解説します。
・EventBridge を利用して Lambda を実行する
→ カスタムイベントをトリガーにする場合に適用
・Subscription Filter を利用して Lambda を実行する
→ CloudWatch Logs のログパターンを検知して実行する場合に適用
それぞれの Terraform コードを交えながら解説していきます。
1. EventBridge から Lambda を起動する
EventBridge のルールを作成し、指定したイベントが発生した際に Lambda をトリガーする構成を作成します。
構成の概要
・aws_lambda_function で Lambda 関数を作成
・aws_cloudwatch_event_rule でカスタムイベントのルールを定義
・aws_cloudwatch_event_target でルールと Lambda を紐付け
・aws_lambda_permission で EventBridge からの実行を許可
Terraform コード
provider "aws" {
region = "us-east-1"
}
resource "aws_lambda_function" "eventbridge_lambda" {
function_name = "eventbridge_lambda"
handler = "index.handler"
runtime = "python3.9"
filename = "lambda.zip"
role = aws_iam_role.lambda_exec.arn
}
resource "aws_cloudwatch_event_rule" "eventbridge_rule" {
name = "eventbridge_rule"
description = "Trigger Lambda on custom event"
event_pattern = jsonencode({
source = ["custom.myapp"]
})
}
resource "aws_cloudwatch_event_target" "lambda_target" {
rule = aws_cloudwatch_event_rule.eventbridge_rule.name
arn = aws_lambda_function.eventbridge_lambda.arn
}
resource "aws_lambda_permission" "allow_eventbridge" {
statement_id = "AllowExecutionFromEventBridge"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.eventbridge_lambda.function_name
principal = "events.amazonaws.com"
source_arn = aws_cloudwatch_event_rule.eventbridge_rule.arn
}
principal = "events.amazonaws.com"
⇅
principal = "logs.amazonaws.com"
結構間違いやすいので、ご注意ください。
Eventbridgeの場合は"events.amazonaws.com"です。
IAM Role
resource "aws_iam_role" "lambda_exec" {
name = "lambda_exec_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}]
})
}
resource "aws_iam_policy_attachment" "lambda_logs" {
name = "lambda_logs"
roles = [aws_iam_role.lambda_exec.name]
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
※ 必要に応じてポリシーを追加してください。
2. Subscription Filter から Lambda を起動する
CloudWatch Logs の特定のログパターンを検知し、Lambda をトリガーする構成を作成します。
構成の概要
・aws_lambda_function で Lambda 関数を作成
・aws_cloudwatch_log_group を作成(ログが出力されるグループ)
・aws_cloudwatch_log_subscription_filter でログフィルターを定義
・aws_lambda_permission で CloudWatch Logs からの実行を許可
Terraform コード
provider "aws" {
region = "us-east-1"
}
resource "aws_lambda_function" "subscription_lambda" {
function_name = "subscription_lambda"
handler = "index.handler"
runtime = "python3.9"
filename = "lambda.zip"
role = aws_iam_role.lambda_exec.arn
}
resource "aws_cloudwatch_log_group" "example_log_group" {
name = "/aws/lambda/example_log_group"
}
resource "aws_cloudwatch_log_subscription_filter" "subscription_filter" {
name = "log_subscription_filter"
log_group_name = aws_cloudwatch_log_group.example_log_group.name
filter_pattern = ""
destination_arn = aws_lambda_function.subscription_lambda.arn
}
resource "aws_lambda_permission" "allow_logs" {
statement_id = "AllowExecutionFromLogs"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.subscription_lambda.function_name
principal = "logs.amazonaws.com"
source_arn = aws_cloudwatch_log_group.example_log_group.arn
}
principal = "logs.amazonaws.com"
⇅
principal = "events.amazonaws.com"
結構間違いやすいので、ご注意ください。
Subscription Filterの場合は"logs.amazonaws.com"です。
IAM Role
resource "aws_iam_role" "lambda_exec" {
name = "lambda_exec_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}]
})
}
resource "aws_iam_policy_attachment" "lambda_logs" {
name = "lambda_logs"
roles = [aws_iam_role.lambda_exec.name]
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
※ 必要に応じてポリシーを追加してください。
まとめ
本記事では、Terraform を使用して AWS Lambda を構築し、 EventBridge と CloudWatch Logs の Subscription Filter を用いてトリガーする方法を解説しました。
・EventBridge: カスタムイベントをトリガーに Lambda を実行
・Subscription Filter: CloudWatch Logs の特定パターンを検知して Lambda を実行
どちらの方法もユースケースによって使い分けることが重要です。お役に立てれば幸いです。