Terraform だけで ECS タスクを業務時間外は停止させる!
この記事はスターフェスティバル Advent Calendar 2022 4 日目の記事です
昨日は @koonagi の 食事付きのオンライン採用イベントを開催しました! でした
どんなメンバーが働いているのか、どんな課題に取り組んでいるのかをランチを食べながら気軽に知れるイベントとなっておりますので、ぜひ応募してみてください!
はじめに
2022 年は円安の影響もあり AWS のコストが今まで以上に上がってしまいましたね
その影響もあり、僕が所属しているスターフェスティバルでは AWS のコスト削減の機運が高まることになりました
インフラよくわからん勢の僕ですが、少しでもコスト削減に協力したい!ということで僕が担当しているアプリケーション(Fargate)を業務時間外は自動で停止させるということをやってみることにしました!
しかし、いざ調べてみると Lambda を作らないといけないなど少し手間がかかるやり方が多く、もう少し楽にやりたい!となってしまったのでこの記事ではその方法を紹介します!
やり方
AWS には ECS タスクのスケーリングを任意の時間に実行する仕組みがあります
この仕組みを使って業務の終了時間に ECS タスクを 0 個にスケールインし業務の開始時間に n 個にスケールアウトすれば Lambda などを作らずに済むのではと考えました
この方法では、terraform 上で新たに aws_appautoscaling_target
と aws_appautoscaling_scheduled_action
を扱うだけで済みます
そのため、Lambda などを作成せずに terraform をちょっといじるだけで完結することができ、とても楽です!
aws_appautoscaling_target
正直あまりわかってないですが オートスケーリングの対象となるリソースの定義です
aws_appautoscaling_scheduled_action
このリソースでは何時にどんなスケーリングをするかといった定義を行えます
今回のユースケースでは
- 業務終了時間にタスク数を 0 にし
- 業務開始時間にタスク数を元に戻す
という 2 つの aws_appautoscaling_scheduled_action
を作成すれば良いことになります
コード例
それでは実際に書いたコードを若干改変して紹介します
locals {
# for_eachで回せるようにすることで、停止させるサービスの増減に手軽に対応できるように
ecs_services = {
# 同じサービスが重複して存在しないよう、サービス名をキーにしている
# (クラスタを跨げば同じサービス名が存在することはありえるが、弊社のサービスの命名規則的にありえないためこんな感じに)
"${aws_ecs_service.foo-service.name}" = {
cluster = aws_ecs_cluster.foo-cluster.name
max_capacity = 2
min_capacity = 1
}
# ...
}
}
# サービスごとの aws_appautoscaling_target を作成
resource "aws_appautoscaling_target" "down-ecs-appautoscaling-target" {
for_each = local.ecs_services
max_capacity = each.value.max_capacity
min_capacity = each.value.min_capacity
resource_id = "service/${each.value.cluster}/${each.key}"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
}
# サービスごとに22時になったらタスク数を0にするスケジュールを組む
# 弊社はコアタイムなしのフルフレックスなので22時まで働いていいのだ。朝が弱い人でも安心!
resource "aws_appautoscaling_scheduled_action" "down-ecs-task-scheduled-action" {
for_each = local.ecs_services
name = "${each.key}-down"
service_namespace = aws_appautoscaling_target.down-ecs-appautoscaling-target[each.key].service_namespace
resource_id = aws_appautoscaling_target.down-ecs-appautoscaling-target[each.key].resource_id
scalable_dimension = aws_appautoscaling_target.down-ecs-appautoscaling-target[each.key].scalable_dimension
schedule = "cron(0 22 ? * * *)"
timezone = "Asia/Tokyo"
scalable_target_action {
min_capacity = 0
max_capacity = 0
}
}
# サービスごとに朝5時になったらタスク数を元に戻すスケジュールを組む
# 早く出社して昼過ぎに退勤すると1日がめちゃ長く感じるのでオススメ!
resource "aws_appautoscaling_scheduled_action" "up-ecs-task-scheduled-action" {
for_each = local.ecs_services
name = "${each.key}-up"
service_namespace = aws_appautoscaling_target.down-ecs-appautoscaling-target[each.key].service_namespace
resource_id = aws_appautoscaling_target.down-ecs-appautoscaling-target[each.key].resource_id
scalable_dimension = aws_appautoscaling_target.down-ecs-appautoscaling-target[each.key].scalable_dimension
schedule = "cron(0 5 ? * * *)"
timezone = "Asia/Tokyo"
scalable_target_action {
max_capacity = each.value.max_capacity
min_capacity = each.value.min_capacity
}
}
おわりに
この記事では Terraform だけで ECS タスクを増減させる方法を紹介しました
冒頭でも軽く触れましたが、僕自身は AWS にそこまで詳しくないため、もっと良い方法がある場合は是非教えてください!
また最近新たに弊社のプロダクト開発部の Twitter アカウントができたので、フォローしてみてください!
明日は DPontaro による Prisma に関する記事です!お楽しみに!
Discussion