前回はこのシリーズの趣旨と作るものの概要を書いた。今回は調査から構成の決定まで一気に書く。
前回の記事は👇
https://qiita.com/noobaimo/items/f272f79fc159b20f2d70
調査と絞り込み
探した先は2か所。AWS公式の導入事例ページと、freeeやZOZOのような企業の技術ブログだ。前者はアーキテクチャ図と使用サービスがセットで整理されていて読みやすく、後者はIaCの実態や運用上の判断まで読める。
AWS公式事例・Web/EC系・サーバーレス/SaaS系・データ分析基盤系の4カテゴリで計32件調べて、以下の基準で絞った。
もちろん、調べたのは私ではなくClaudeCode君である!選んだのは私。
- 実在企業が構成図を公開していること
- Terraformで一通り実装できること
- 数時間の検証後にdestroyして$5以内に収まること
- インフラ寄りの構成であること
残ったのは3件。
| 記号 | 企業/構成 | 特徴 |
|---|---|---|
| A | JPX総研(カーボン・クレジット取引) | CloudFront+API GW+ECS Fargate+Aurora+Step Functions/EventBridge |
| B | freeeサイン(電子契約) | WAF+ALB+ECS Fargate+Aurora PostgreSQL(Terraform全管理) |
| C | ベースフード(EC・定期通販) | CloudFront+ALB+ECS Fargate+Aurora+SQS+ElastiCache |
freeeサインを選んだ経緯
Cは早めに外した。ECS+AuroraのコアにElastiCacheとSQSが乗る分、学習コストが散る。
AとBで迷った。Aは日本取引所グループ傘下の金融取引システムで、2023年にAWS公式事例として公開されている。CloudFront+API Gateway+ECS Fargate+Auroraという構成に、Step FunctionsとEventBridgeのジョブ制御が乗っていて、読み取れる情報量が多い。
それでもBにした理由が2つ。
ひとつは、TerraformによるIaC管理が明言されていること。freeeの技術ブログには「全リソースをTerraformで管理している」と書いてある。本PJの核がTerraformで再現することなので、IaC前提で語られた事例を選ぶ意味はある。
もうひとつはシンプルに完結すること。Aを選んだ場合、Step FunctionsとEventBridgeのジョブ制御まで実装することになる。バッチ制御を発展課題に回すならBで十分だという判断になった。
出典: freee Developers Hub「freeeサインのAWSリージョン移行」
https://developers.freee.co.jp/entry/aws-region-migration
省いた範囲
Bを選んだ後、何を作って何を省くかを決めた。
CodeDeploy(Blue/Greenデプロイ)は使わない。
freeeサインの元ネタにはCodeDeployによるBlue/Greenデプロイが含まれているが、今回はECSのローリングアップデートで代替する。ECRにイメージをプッシュした後、aws ecs update-service --force-new-deployment を実行するだけでデプロイできる。ALBのターゲットグループも1つで済む。
CI/CDパイプラインは対象外。
GitHub Actionsやecspressoによるパイプラインは扱わない。スクリプトで手動デプロイできるので動作確認には支障ない。
マルチリージョンも省く。
元の記事はリージョン移行の話を含んでいるが、本PJは東京リージョン単体(ap-northeast-1)での再現。
CloudFront 追加の判断
オリジナルのfreeeサイン構成はWAFをALBに直アタッチするREGIONAL構成で、CloudFrontを含まない。今回はここを変更してRoute53 → CloudFront → ALBという経路にした。WAFも REGIONALスコープからCLOUDFRONTスコープに切り替えている。
理由は3点ある。
HTTPS終端のエッジ化。 ACM証明書をus-east-1に作成してCloudFrontにアタッチすることで、ユーザーから見た接続は常にHTTPS(TLS 1.2+)になる。CloudFront→ALB間はHTTP:80で完結し、ALBに証明書を持たせる必要がない。
WAFのアタッチ位置。 CloudFrontにWAF(CLOUDFRONTスコープ)を付けると、リクエストがリージョンに入る前のエッジ段階で検査・ブロックが走る。CLOUDFRONTスコープはus-east-1のAPIで作成する制約があり、Terraformではprovider aliasが必要になる。
ALBへの直接アクセスの排除。 ALBセキュリティグループのインバウンドをCloudFrontのマネージドプレフィックスリスト(com.amazonaws.global.cloudfront.origin-facing)だけに絞ることで、ALBのDNS名を直接叩いても接続できなくなる。
この変更に伴い、Route53のAレコード(CloudFrontへのAliasレコード)、us-east-1に作成するACM証明書、CloudFrontアクセスログの保存先S3バケット(90日保持)もオリジナルにはなかったリソースとして追加している。
最終的な構成
Internet
→ Route53(Aレコード → CloudFront)
→ CloudFront(WAF CLOUDFRONTスコープ / ACM証明書 / HTTPS終端)
→ ALB(CloudFrontからのみ許可)
→ ECS Fargate(2AZ、Rolling Update)
→ Aurora PostgreSQL Serverless(リードレプリカ)
補助リソース:
- ECR: コンテナイメージ管理(デプロイはECR push → force-new-deployment)
- Secrets Manager: Auroraの認証情報(ランダムパスワードを生成して注入)
- S3: CloudFrontアクセスログの保存(90日保持)
- CloudWatch Logs: コンテナのログ(14日保持)
- IAM: 実行ロール / タスクロールの2つに分ける
Terraformファイル構成
8ファイル構成にした。cdn.tfがCloudFront・WAF・ACM・Route53・S3をまとめて管理する。
| ファイル | 役割 | 主なリソース |
|---|---|---|
| providers.tf | Terraform・プロバイダー設定 | Terraformバージョン制約、AWSプロバイダー(東京 ap-northeast-1)、us-east-1エイリアス(CloudFront / ACM / WAF用)、全リソース共通タグ |
| variables.tf | 入力変数とローカル値 | プロジェクト名・VPC CIDR・タスクスペック・DB設定・ドメイン |
| network.tf` | VPCとネットワーク基盤 | VPC・3層サブネット×2AZ・IGW・NAT GW・ルートテーブル。SGはALB→ECS→RDSの一方向チェーン |
| database.tf | Aurora PostgreSQL | Serverless v2クラスター(writer AZ-a / reader AZ-c)・DBサブネットグループ・ランダムパスワード生成・Secrets Managerへの格納 |
| loadbalancer.tf | ALB(公開層) | ALB・ターゲットグループ |
| cdn.tf` | CDN・グローバル層 | WAF v2・ACM証明書・Route53・CloudFrontS3バケット |
| ecs.tf | コンテナ実行基盤 | ECRリポジトリ・IAMロール・CloudWatchロググループ・ECSクラスター・タスク定義・ECSサービス |
| outputs.tf | apply後の確認用出力 | サイトURL・CloudFrontドメイン名・ALB DNS(デバッグ用)・ECRリポジトリURL・S3ログバケット名・RDSエンドポイント(sensitive) |
コスト見積り(数時間検証→destroyの想定)
| サービス | 単価 | 3時間の概算 |
|---|---|---|
| Aurora Serverless v2 | $0.06/ACU-h(最小0.5 ACU) | $0.09 |
| NAT Gateway × 2 | $0.062/h × 2 | $0.37 |
| ALB | $0.025/h | $0.08 |
| ECS Fargate(2タスク) | 約$0.01/h | $0.03 |
| WAF CLOUDFRONT Web ACL | $5/月 | $0.02 |
| Route53 ホストゾーン | $0.50/月 | 誤差 |
| CloudFront | 無料枠(1 TB/月・1000万req) | $0.00 |
| S3(アクセスログ) | 無料枠 | $0.00 |
| ドメイン(.click など) | 年額 $3.00(一回限り) | $3.00 |
| 合計(概算) | ≒ $3.60 |
ドメイン代が大半を占める構成になった。
NAT Gatewayを1台に絞る(single_nat_gateway = true)なら時間課金分をさらに$0.19削減できる。
次回
構築編に入る。terraform applyして、ECRにイメージをプッシュして、HTTPSアクセスを確認して、Aurora接続を確認して、destroyするところまで書く。詰まったところも含めてそのまま書く予定。
