はじめに
Part4 までで FARGATE_SPOT によるコスト削減を実現しましたが、今回は 時間ベースの Auto Scaling を導入してさらなるコスト削減を実現します。
これまでの記事
- Part1: VPC 基盤インフラ構築
- Part2: HTTPS 対応
- Part3: ECS Fargate でアプリケーション稼働
- Part4: FARGATE_SPOT でコスト最適化
- Part5(本記事): 時間ベース Auto Scaling でさらなるコスト削減 ← 今ここ
対象読者
- ECS Fargate のコストをさらに削減したい方
- Application Auto Scaling の使い方を知りたい方
- 夜間・休日にサービスを停止してコスト削減したい方
- Terraform でスケジューリングを実装したい方
概要
Part4 で構築した 3 つの ECS サービスのうち、Node.js と .NET Blazor サービスに時間ベースの Auto Scaling を適用しました。
なぜ時間ベース Auto Scaling?
従来の課題:
- 24 時間稼働で深夜・早朝も課金
- 個人サイトで夜間のアクセスはほぼゼロ
- 無駄なコストが発生
時間ベース Auto Scaling の利点:
- 夜間停止で 29% コスト削減
- Application Auto Scaling で完全自動化
- Terraform で管理可能
開発環境
ローカル環境
| 項目 | バージョン/内容 |
|---|---|
| OS | Windows 11 |
| Terraform | v1.6.0 以上 |
| AWS CLI | v2.13.0 以上 |
AWS 環境
| 項目 | 内容 |
|---|---|
| リージョン | ap-northeast-1(東京) |
| ECS クラスター | app-cluster |
構成図
稼働スケジュール
00:00 ━━━━━ 05:00 ━━━━━━━━━━━━━━━━━━━━━━━ 22:00 ━━━━━ 24:00
🔴停止 🟢稼働(17時間) 🔴停止
稼働時間:
- 起動: 毎日 05:00 JST (UTC 20:00)
- 停止: 毎日 22:00 JST (UTC 13:00)
- 稼働時間: 17 時間/日
- 停止時間: 7 時間/日
対象サービス:
- ✅ Node.js サービス(時間制御)
- ✅ .NET Blazor サービス(時間制御)
- ❌ Static Site(常時稼働 - FARGATE_SPOT)
今回実現したこと
1. Application Auto Scaling によるスケジューリング
Auto Scaling Target の作成
# Application Auto Scaling: DesiredCount targets
# 夜間はタスク数を0、朝に復帰(東京タイムゾーン基準)
resource "aws_appautoscaling_target" "nodejs_desired" {
max_capacity = 2
min_capacity = 0
resource_id = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.nodejs.name}"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
}
resource "aws_appautoscaling_target" "dotnet_desired" {
max_capacity = 2
min_capacity = 0
resource_id = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.dotnet.name}"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
}
パラメータ解説:
| パラメータ | 値 | 説明 |
|---|---|---|
| max_capacity | 2 | 最大タスク数 |
| min_capacity | 0 | 最小タスク数(0 で完全停止可能) |
| scalable_dimension | ecs:service:DesiredCount | ECS サービスの DesiredCount をスケール |
| service_namespace | ecs | ECS サービス |
夜間停止スケジュール(22:00 JST)
# スケジュール: 毎日 22:00 に停止(0)、5:00 に起動(1)
# 注意: cron式はUTC基準。東京(UTC+9)の 22:00 は UTC 13:00、5:00 は UTC 20:00。
resource "aws_appautoscaling_scheduled_action" "nodejs_night_stop" {
name = "nodejs-night-stop"
service_namespace = aws_appautoscaling_target.nodejs_desired.service_namespace
resource_id = aws_appautoscaling_target.nodejs_desired.resource_id
scalable_dimension = aws_appautoscaling_target.nodejs_desired.scalable_dimension
schedule = "cron(0 13 ? * * *)" # 毎日 22:00 JST(UTC 13:00)
scalable_target_action {
min_capacity = 0
max_capacity = 0
}
}
動作:
- 毎日 22:00 JST に実行
- DesiredCount を 0 に設定(完全停止)
- min_capacity = 0, max_capacity = 0 でタスクを強制停止
朝起動スケジュール(05:00 JST)
resource "aws_appautoscaling_scheduled_action" "nodejs_morning_start" {
name = "nodejs-morning-start"
service_namespace = aws_appautoscaling_target.nodejs_desired.service_namespace
resource_id = aws_appautoscaling_target.nodejs_desired.resource_id
scalable_dimension = aws_appautoscaling_target.nodejs_desired.scalable_dimension
schedule = "cron(0 20 ? * * *)" # 毎日 5:00 JST(UTC 20:00)
scalable_target_action {
min_capacity = 1
max_capacity = 2
}
}
動作:
- 毎日 05:00 JST に実行
- DesiredCount を 1 に設定(起動)
2. Cron 式の理解
AWS のスケジュール Cron 式:
cron(分 時 日 月 曜日 年)
タイムゾーン変換:
- AWS Cron 式は UTC 基準
- 東京(JST)は UTC+9
変換例:
| JST | UTC | Cron 式 | 説明 |
|---|---|---|---|
| 22:00 | 13:00 | cron(0 13 ? * * *) |
夜間停止 |
| 05:00 | 20:00 | cron(0 20 ? * * *) |
朝起動 |
Cron フィールド解説:
cron(0 13 ? * * *)
│ │ │ │ │ └─ 年(* = 毎年)
│ │ │ │ └─── 曜日(* = 毎日)
│ │ │ └───── 月(* = 毎月)
│ │ └─────── 日(? = 任意)
│ └────────── 時(13 = UTC 13:00 = JST 22:00)
└───────────── 分(0 = 0分)
技術的なポイント
ポイント1: min_capacity = 0 で完全停止
今回の実装(時間制御):
resource "aws_appautoscaling_target" "nodejs_desired" {
min_capacity = 0 # 0 まで減らせる
max_capacity = 2
}
ポイント: min_capacity = 0 を設定することで、完全停止(DesiredCount = 0)が可能になる
ポイント2: Scheduled Action で強制的に停止/起動
夜間停止時:
scalable_target_action {
min_capacity = 0
max_capacity = 0 # max も 0 にすることで強制停止
}
朝起動時:
scalable_target_action {
min_capacity = 1 # 最低 1 タスク起動
max_capacity = 2
}
ポイント3: UTC とタイムゾーン変換
JST → UTC 変換式:
UTC 時刻 = JST 時刻 - 9 時間
例:
- JST 22:00 → UTC 13:00
- JST 05:00 → UTC 20:00(前日)
注意: 05:00 JST は UTC では前日の 20:00 になるが、Cron 式では「毎日」実行されるため問題なし
ポイント4: コスト計算
Part4(24 時間稼働):
Node.js: $5.19/月 × 24h = $5.19
.NET: $5.19/月 × 24h = $5.19
合計: $10.38/月
Part5(17 時間稼働):
稼働率 = 17h / 24h = 70.83%
Node.js: $5.19 × 0.7083 = $3.68/月
.NET: $5.19 × 0.7083 = $3.68/月
合計: $7.36/月
削減額:
$10.38 - $7.36 = $3.02/月(29% 削減)
年間: $3.02 × 12 = $36.24
コスト試算
Part4 からの変更
| サービス | Part4(24h) | Part5(17h) | 削減額 |
|---|---|---|---|
| Node.js | $5.19 | $3.68 | $1.51 |
| .NET Blazor | $5.19 | $3.68 | $1.51 |
| Static Site | $1.56 | $1.56 | $0 |
| ECS 合計 | $11.94 | $8.92 | $3.02 |
全体コスト(月額)
| サービス | 詳細 | Part4 | Part5 | 削減額 |
|---|---|---|---|---|
| ALB | 時間料金 + LCU | $20.00 | $20.00 | $0 |
| VPC Endpoint | $7.30 × 3 | $21.90 | $21.90 | $0 |
| ECS Fargate | 3 サービス | $11.94 | $8.92 | $3.02 |
| ECR | イメージ保存 | $0.50 | $0.50 | $0 |
| CloudWatch Logs | 7 日保持 | $3.26 | $3.26 | $0 |
| 合計 | $57.60 | $54.58 | $3.02 |
削減率: 約 5%(ECS 部分では 25%)
Part1 からの累計削減効果
| 項目 | Part1(想定) | Part5(現在) | 削減額 |
|---|---|---|---|
| VPC Endpoints | NAT Gateway: $32 | VPC Endpoints: $21.90 | $10.10 |
| ECS(SPOT) | - | Static Site: -$3.63 | $3.63 |
| ECS(時間制御) | - | Node.js + .NET: -$3.02 | $3.02 |
| 合計削減額 | $16.75/月 | ||
| 年間削減額 | $201/年 |
感想
学んだこと
1. Application Auto Scaling の柔軟性
Scheduled Action を使うことで、ECS タスクの完全な時間制御ができました。
# この設定だけで:
# - 毎日 22:00 に自動停止
# - 毎日 05:00 に自動起動
# - 完全に AWS が管理
resource "aws_appautoscaling_scheduled_action" "nodejs_night_stop" {
schedule = "cron(0 13 ? * * *)"
scalable_target_action {
min_capacity = 0
max_capacity = 0
}
}
2. コスト最適化は積み重ね
Part1 → Part5 の累計削減効果:
- VPC Endpoints: $10.10/月
- FARGATE_SPOT: $3.63/月
- 時間制御: $3.02/月
- 合計: $16.75/月(年間 $201)
小さな改善の積み重ねが大きな効果に
苦労した点
-
Cron 式のタイムゾーン変換
- 最初 JST のまま設定して 9 時間ズレた
- コメントで JST 時刻を明記して対応
-
min_capacity = 0 の設定
- デフォルトは min_capacity = 1
- 0 に設定しないと完全停止できない
参考資料
AWS 公式ドキュメント
読んだ本
次回予告
Part6: 監視・アラート基盤の構築
以下を実装予定:
-
CloudWatch Alarms
- タスク停止アラート
- CPU/メモリ使用率監視
- ALB エラー率監視
-
SNS 通知
- メール通知
- Slack 連携
-
CloudWatch Dashboard
- コスト可視化
- リソース使用状況の一元管理
お楽しみに!
まとめ
この記事で実現したこと
- ✅ Application Auto Scaling による時間制御
- ✅ 夜間停止(22:00-05:00)で 29% コスト削減
- ✅ Cron 式でスケジューリング
- ✅ Terraform による完全な IaC 化
コスト削減効果
- 月額 $3.02 削減(ECS 部分で 25% 削減)
- 年間 $36.24 削減
Part1 からの累計削減
- 月額 $16.75 削減
- 年間 $201 削減
次のステップ
- 🔧 監視・アラート基盤の構築
- 🔧 CloudWatch Dashboard の作成
- 🔧 さらなるコスト最適化の検討
