App Runnerはリクエストがない場合でも費用が発生します。
(プロビジョニングされたコンテナインスタンスは最低でも1つ必要。それに割り当てられたメモリに対して費用がかかる。)
App Runnerサービスを一時停止をすることで上記の費用は削減できますが、手動で一時停止・再開するのは面倒なので、夜間などの明らかに使わない時間だけ自動で一時停止にするような仕組みについて紹介します。
EventBridge Schedulerを使って定期的に一時停止する
EventBridge Schedulerを使い、定期的にApp Runnerサービスを一時停止・再開する仕組みをつくることで実現できます。
やり方
まず、
- 一時停止
- 再開
を行うScheduleの作成をします。
ここでは仮に
- 一時停止: 毎日15:00(UTC)
- 再開: 毎日00:00(UTC)
にしています。
# Event Scheduler
resource "aws_scheduler_schedule_group" "auto-pause-and-resume" {
name = "auto-pause-and-resume"
}
resource "aws_scheduler_schedule" "auto-pause" {
group_name = aws_scheduler_schedule_group.auto-pause-and-resume.name
name = "auto-pause"
schedule_expression = "cron(0 15 * * ? *)"
schedule_expression_timezone = "UTC"
state = "ENABLED"
flexible_time_window {
mode = "OFF"
}
target {
arn = "arn:aws:scheduler:::aws-sdk:apprunner:pauseService"
input = jsonencode({
ServiceArn = "App RunnerサービスのARN"
})
role_arn = "TODO"
retry_policy {
maximum_event_age_in_seconds = 86400
maximum_retry_attempts = 0
}
}
}
resource "aws_scheduler_schedule" "auto-resume" {
group_name = aws_scheduler_schedule_group.auto-pause-and-resume.name
name = "auto-resume"
schedule_expression = "cron(0 0 * * ? *)"
schedule_expression_timezone = "UTC"
state = "ENABLED"
flexible_time_window {
mode = "OFF"
}
target {
arn = "arn:aws:scheduler:::aws-sdk:apprunner:resumeService"
input = jsonencode({
ServiceArn = "App RunnerサービスのARN"
})
role_arn = "TODO"
retry_policy {
maximum_event_age_in_seconds = 86400
maximum_retry_attempts = 0
}
}
}
上記のScheduleに加え、SchedulerがApp Runnerサービスを一時停止・再開できるようなAssumeRoleをアタッチしてあげる必要があります。
そのため、まず以下のIAM Roleを作成します。
# IAM role
data "aws_iam_policy_document" "auto-pause-and-resume-assume-role-policy" {
statement {
effect = "Allow"
actions = [
"sts:AssumeRole"
]
principals {
type = "Service"
identifiers = [
"scheduler.amazonaws.com"
]
}
}
}
data "aws_iam_policy_document" "auto-pause-and-resume-inline-policy" {
statement {
effect = "Allow"
actions = [
"apprunner:PauseService",
"apprunner:ResumeService"
]
resources = [
"App RunnerサービスのARN"
]
}
}
resource "aws_iam_role" "auto-pause-and-resume" {
name = "auto-pause-and-resume"
assume_role_policy = data.aws_iam_policy_document.auto-pause-and-resume-assume-role-policy.json
inline_policy {
name = "auto-pause-and-resume-inline-policy"
policy = data.aws_iam_policy_document.auto-pause-and-resume-inline-policy.json
}
}
そして、作成したIAM RoleをScheduleにアタッチしてあげます。
resource "aws_scheduler_schedule" "auto-pause" {
# ...
target {
# ...
- role_arn = "TODO"
+ role_arn = aws_iam_role.auto-pause-and-resume.arn
# ...
}
resource "aws_scheduler_schedule" "auto-resume" {
# ...
target {
# ...
- role_arn = "TODO"
+ role_arn = aws_iam_role.auto-pause-and-resume.arn
# ...
}
これで完了です!
最終的なterraformのコード
# Event Scheduler
resource "aws_scheduler_schedule_group" "auto-pause-and-resume" {
name = "auto-pause-and-resume"
}
resource "aws_scheduler_schedule" "auto-pause" {
group_name = aws_scheduler_schedule_group.auto-pause-and-resume.name
name = "auto-pause"
schedule_expression = "cron(0 15 * * ? *)"
schedule_expression_timezone = "UTC"
state = "ENABLED"
flexible_time_window {
mode = "OFF"
}
target {
arn = "arn:aws:scheduler:::aws-sdk:apprunner:pauseService"
input = jsonencode({
ServiceArn = "App RunnerサービスのARN"
})
role_arn = aws_iam_role.auto-pause-and-resume.arn
retry_policy {
maximum_event_age_in_seconds = 86400
maximum_retry_attempts = 0
}
}
}
resource "aws_scheduler_schedule" "auto-resume" {
group_name = aws_scheduler_schedule_group.auto-pause-and-resume.name
name = "auto-resume"
schedule_expression = "cron(0 0 * * ? *)"
schedule_expression_timezone = "UTC"
state = "ENABLED"
flexible_time_window {
mode = "OFF"
}
target {
arn = "arn:aws:scheduler:::aws-sdk:apprunner:resumeService"
input = jsonencode({
ServiceArn = "App RunnerサービスのARN"
})
role_arn = aws_iam_role.auto-pause-and-resume.arn
retry_policy {
maximum_event_age_in_seconds = 86400
maximum_retry_attempts = 0
}
}
}
# IAM role
data "aws_iam_policy_document" "auto-pause-and-resume-assume-role-policy" {
statement {
effect = "Allow"
actions = [
"sts:AssumeRole"
]
principals {
type = "Service"
identifiers = [
"scheduler.amazonaws.com"
]
}
}
}
data "aws_iam_policy_document" "auto-pause-and-resume-inline-policy" {
statement {
effect = "Allow"
actions = [
"apprunner:PauseService",
"apprunner:ResumeService"
]
resources = [
"App RunnerサービスのARN"
]
}
}
resource "aws_iam_role" "auto-pause-and-resume" {
name = "auto-pause-and-resume"
assume_role_policy = data.aws_iam_policy_document.auto-pause-and-resume-assume-role-policy.json
inline_policy {
name = "auto-pause-and-resume-inline-policy"
policy = data.aws_iam_policy_document.auto-pause-and-resume-inline-policy.json
}
}
動作確認をしてると、定期的に実行されていることがわかります。
また、コストも削減できていることが確認できました。
さいごに
EventBridge Schedulerを使うことで思ったよりも簡単に自動停止できるようになりました。
これでプライベートのインフラコストが少し削減できたので、よかったです。
もし少しでも参考になれば幸いです。