1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自前ウェブサイトを構築してみた Part5 - 時間ベース Auto Scaling で 29% コスト削減

1
Posted at

はじめに

Part4 までで FARGATE_SPOT によるコスト削減を実現しましたが、今回は 時間ベースの 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

構成図

image.png

稼働スケジュール

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)

小さな改善の積み重ねが大きな効果に

苦労した点

  1. Cron 式のタイムゾーン変換

    • 最初 JST のまま設定して 9 時間ズレた
    • コメントで JST 時刻を明記して対応
  2. min_capacity = 0 の設定

    • デフォルトは min_capacity = 1
    • 0 に設定しないと完全停止できない

参考資料

AWS 公式ドキュメント

読んだ本

  1. AWS コンテナ設計・構築本格入門

  2. 入門 Terraform - インフラ時代のインフラ統合管理


次回予告

Part6: 監視・アラート基盤の構築

以下を実装予定:

  1. CloudWatch Alarms

    • タスク停止アラート
    • CPU/メモリ使用率監視
    • ALB エラー率監視
  2. SNS 通知

    • メール通知
    • Slack 連携
  3. 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 の作成
  • 🔧 さらなるコスト最適化の検討

GitHubリポジトリ

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?