はじめに
2022/11/10にEventBridgeにアップデートが入り、これまでのスケジュール方法以外にAtな起動がAsia/Tokyoのタイムゾーンの時間記述で作成できるようになった。これは超便利!
Terraformも2022/11/25に早々に対応されたようだ。
ということで、さっそくTerraformでサクッと自動構築をしてみよう。
起動するLambda
シンプルにイベントデータを表示するだけで作っておく。
import pprint
def lambda_handler(event, context):
pprint.pprint(event)
上記を実行するLambdaの定義として以下のようにTerraformで作成する。
権限はこの後EvnetBridge Scheduler側のサービスロールに付与するため、Lambda Permissionの設定は不要のようだ。
################################################################################
# Lambda #
################################################################################
data "archive_file" "example" {
type = "zip"
source_dir = "../scripts/example"
output_path = "../outputs/example.zip"
}
resource "aws_lambda_function" "example" {
depends_on = [
aws_cloudwatch_log_group.lambda,
]
function_name = local.lambda_function_name
filename = data.archive_file.example.output_path
role = aws_iam_role.lambda.arn
handler = "example.lambda_handler"
source_code_hash = data.archive_file.example.output_base64sha256
runtime = "python3.9"
memory_size = 128
timeout = 600
}
################################################################################
# IAM Role for Lambda #
################################################################################
resource "aws_iam_role" "lambda" {
name = local.iam_role_name_lambda
assume_role_policy = data.aws_iam_policy_document.lambda_assume.json
}
data "aws_iam_policy_document" "lambda_assume" {
statement {
effect = "Allow"
actions = [
"sts:AssumeRole",
]
principals {
type = "Service"
identifiers = [
"lambda.amazonaws.com",
]
}
}
}
resource "aws_iam_role_policy" "lambda_custom" {
name = local.iam_policy_name_lambda
role = aws_iam_role.lambda.name
policy = data.aws_iam_policy_document.lambda_custom.json
}
data "aws_iam_policy_document" "lambda_custom" {
statement {
effect = "Allow"
actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
]
resources = [
"*",
]
}
}
################################################################################
# CloudWatch Logs #
################################################################################
resource "aws_cloudwatch_log_group" "lambda" {
name = "/aws/lambda/${local.lambda_function_name}"
retention_in_days = 3
}
################################################################################
# Lambda Permission #
################################################################################
resource "aws_lambda_permission" "allow_apigateway" {
statement_id = "AllowExecutionFromCloudWatch"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.example.function_name
principal = "scheduler.amazonaws.com"
}
EventBridge Schedulerを動かすのに必要なIAMロール
IAMロールは以下のように作成する。信頼関係されたエンティティのサービスとしてscheduler.amazonaws.com
を指定しよう。
今回は単純にLambda実行するだけなので、個別の権限としてはlambda:InvokeFunction
があれば良い。
################################################################################
# IAM Role for EventBridge Scheduler #
################################################################################
resource "aws_iam_role" "eventbridge_scheduler" {
name = local.iam_role_name_eventbridge_scheduler
assume_role_policy = data.aws_iam_policy_document.eventbridge_scheduler_assume.json
}
data "aws_iam_policy_document" "eventbridge_scheduler_assume" {
statement {
effect = "Allow"
actions = [
"sts:AssumeRole",
]
principals {
type = "Service"
identifiers = [
"scheduler.amazonaws.com",
]
}
}
}
resource "aws_iam_role_policy" "eventbridge_scheduler_custom" {
name = local.iam_policy_name_eventbridge_scheduler
role = aws_iam_role.eventbridge_scheduler.name
policy = data.aws_iam_policy_document.eventbridge_scheduler_custom.json
}
data "aws_iam_policy_document" "eventbridge_scheduler_custom" {
statement {
effect = "Allow"
actions = [
"lambda:InvokeFunction",
]
resources = [
"*",
]
}
}
EvnetBridge Schedulerの定義
さて、↑ここまでで準備は整ったので、あとは本丸のEventBridge Schedulerの定義だ。
ポイントは、schedule_expression
でatで指定している点だ。これはschedule_expression_timezone
で指定したタイムゾーンで動いてくれる。flexible_time_window
は、時間をずらして起動したい場合等に使えるが今回はOFFにする。target
で↑で作ったLambdaとIAMロールのARNを指定すれば準備完了だ。
################################################################################
# EventBridge Scheduler #
################################################################################
resource "aws_scheduler_schedule_group" "example" {
name = local.eventbridge_scheduler_group_name
}
resource "aws_scheduler_schedule" "example" {
name = local.eventbridge_scheduler_schedule_name
group_name = aws_scheduler_schedule_group.example.name
state = "ENABLED"
schedule_expression = "at(2022-12-10T22:18:00)"
schedule_expression_timezone = "Asia/Tokyo"
flexible_time_window {
mode = "OFF"
}
target {
arn = aws_lambda_function.example.arn
role_arn = aws_iam_role.eventbridge_scheduler.arn
}
}
EvnetBridge SchedulerがLambdaに渡すイベントの形式
さて、上記で実行したLambdaの結果をCloudWatchで確認すると、以下のようにJSONが出力されている。
残念ながら、time
の部分はUTCになってしまうが、いつ起動予定のタスクだったかは確認できるようだ。
{
"account": "XXXXXXXXXXXX",
"detail": "{}",
"detail-type": "Scheduled Event",
"id": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"region": "ap-northeast-1",
"resources": [
"arn:aws:scheduler:ap-northeast-1:XXXXXXXXXXXX:schedule/eventbridge-scheduler-example-group/eventbridge-scheduler-example-schedule"
],
"source": "aws.scheduler",
"time": "2022-12-10T13:18:00Z",
"version": "0"
}
これで、Atで時限起動するLambdaを簡単に作れるようになった!