- 1 EventBridge × VPC Lattice × Fargate 統合本番運用 — イベント駆動マイクロサービスの最短ルート
- 1.1 1. なぜEventBridge × VPC Lattice × Fargate 統合か — 3軸隣接領域の本番統合パターン
- 1.2 2. EventBridge本番運用 — Rule × EventBus × Pipes × Scheduler
- 1.2.1 EventBridge 4本柱の役割と選定基準
- 1.2.2 Rule Event Pattern 設計 — source + detail-type 厳密化
- 1.2.3 カスタムEventBus vs Default EventBus — 本番使い分け基準
- 1.2.4 EventBridge Pipes 実装 — SQS/DDB Streams → Fargate Task
- 1.2.5 EventBridge Scheduler — cron + Group + DLQ + Retry 設計
- 1.2.6 Fargate Task Target 統合 — TaskOverride でイベントペイロード受渡
- 1.2.7 Dead Letter Queue + Retry Policy 設計
- 1.2.8 mermaid01: EventBridge Rule → Fargate Task 起動フロー
- 1.3 3. VPC Lattice本番運用 — Service Network × TargetGroup × Auth Policy × Listener
- 1.3.1 3-1. VPC Lattice アーキテクチャ全体像 — 5層構造
- 1.3.2 3-2. Service Network 階層設計 — 環境別分離とTerraform実装
- 1.3.3 3-3. TargetGroup種別比較とFargate IP type選定
- 1.3.4 3-4. Listener設定 — プロトコル×ルーティングルール
- 1.3.5 3-5. Auth Policy設計 — IAM-based + IRSA連携
- 1.3.6 3-6. Service Discovery — DNS-based FQDN × VPC内アクセス
- 1.3.7 3-7. Multi-Account Lattice — RAM経由 Service Network共有
- 1.3.8 3-8. 本番Quota対策
- 1.3.9 3-9. Terraform実装まとめ — aws_vpclattice_service
- 1.4 4. Fargate本番運用 — ECS Task × Service Connect × Container Insights × IRSA
- 1.4.1 4-1. ECS Fargate基礎 — Task Definition / Cluster / Service設計
- 1.4.2 4-2. Service Connect実装 — ECS Native Service Mesh
- 1.4.3 4-3. VPC Lattice統合パターン — Service Connect併用 vs 単独選定
- 1.4.4 4-4. Container Insights Enhanced — Task/Container レベル監視
- 1.4.5 4-5. IRSA実装 — Task Role × Task Execution Role厳格分離
- 1.4.6 4-6. ENI Trunking — Task密度向上
- 1.4.7 4-7. Cold Start特性とPre-warming戦略
- 1.4.8 4-8. Multi-Architecture — ARM Graviton選定基準
- 1.4.9 mermaid02: Fargate Task ENI割当 + VPC Lattice TargetGroup登録フロー
- 1.5 5. 3層統合本番運用 — Event Pattern × Auth Policy × Distributed Trace × Multi-Account設計
- 1.5.1 5-1. 3層統合パターン全体フロー
- 1.5.2 5-2. IAM Auth Policy + IRSA 統合権限設計
- 1.5.3 5-3. Multi-Account本番設計 — Organizations OU + RAM共有 + Cross-Account EventBridge
- 1.5.4 5-4. Distributed Trace 3層統合 — X-Ray + ADOT Collector
- 1.5.5 5-5. Cost Allocation — 3層統合のコスト構造
- 1.5.6 5-6. Auto Scaling統合 — 予測×反応の2軸設計
- 1.5.7 5-7. Service Mesh代替パターン — App Mesh廃止 → VPC Lattice移行
- 1.5.8 5-8. 障害時Failover — DLQ + Retry + Circuit Breaker
- 1.6 6. 詰まりポイント7選 — 3層統合本番運用の地雷とフィックス
- 1.6.1 詰まり①: EventBridge Rule Event Pattern マッチ失敗
- 1.6.2 詰まり②: VPC Lattice TargetGroup Type 違いで Fargate Task 登録不可
- 1.6.3 詰まり③: EventBridge Pipes Source=DynamoDB Streams で DLQ 未設定によるイベント消失
- 1.6.4 詰まり④: Auth Policy IAM + IRSA 権限重複で認証失敗 (403 Unauthorized)
- 1.6.5 詰まり⑤: X-Ray Trace 3層断絶 (ADOT Collector 設定漏れ)
- 1.6.6 詰まり⑥: Multi-Account RAM 共有で Allowed Principals に個別 Account ARN を指定
- 1.6.7 詰まり⑦: Fargate Cold Start 15-30 秒で SLA 違反
- 1.7 7. アンチパターン→正解パターン変換演習5問
- 1.7.1 演習1: EventBridge Rule Event Pattern ワイルドカード放置 → 厳密化
- 1.7.2 演習2: VPC Lattice TargetGroup INSTANCE type → IP type + awsvpc 移行
- 1.7.3 演習3: EventBridge Pipes DLQ 未設定 → DLQ + RetryAttempts 追加
- 1.7.4 演習4: IAM Auth Policy + Task Role の別 Role 運用 → 同一 IAM Role 統合
- 1.7.5 演習5: X-Ray Trace 3層断絶 → ADOT Collector で Trace ID 伝播
- 1.8 8. まとめ + 隣接3シリーズ双方向リンク + 全クロスリンク
EventBridge × VPC Lattice × Fargate 統合本番運用 — イベント駆動マイクロサービスの最短ルート

本記事は Serverless本番運用 Vol2 (EventBridge×SQS×SNS×Kinesis) + Network本番運用 Vol2 (TGW×PrivateLink×DX) + Container本番運用 Vol1 (ECS×Fargate×ECR) の隣接領域を統合し、イベント駆動マイクロサービスを Fargate + VPC Lattice + EventBridge の3層で実装する本番運用ガイドです。
本記事の対象
- EventBridge Rule/EventBus基礎を理解しており Fargate Service 連携を本番設計したいエンジニア
- VPC Lattice Service Network で Microservice 間通信を実装中のチーム
- Service Discovery + Auth Policy + Container Insights の3層統合に課題を感じる中堅
本記事完遂後の発展: Service Connect + Container Vol2 GitOps編 (ArgoCD/Kustomize) で本番Kubernetes統合へ。
1. なぜEventBridge × VPC Lattice × Fargate 統合か — 3軸隣接領域の本番統合パターン
単一サービス運用の限界と3軸統合の必然性
マイクロサービスアーキテクチャが成熟するにつれ、EventBridge単体・VPC Lattice単体・Fargate単体での運用では回避できない本番課題が顕在化します。
EventBridge単体の限界: Rule → Lambda 直結は Lambda の15分制限という絶対的な壁に当たります。バッチ処理・動画エンコード・機械学習推論・大規模データ変換など、分単位〜時間単位の処理では Fargate Task への統合が必須です。Lambdaのタイムアウト上限を設計時に無視すると、本番で突然ジョブが切断されるインシデントを引き起こします。
VPC Lattice単体の限界: Service Network でマイクロサービス間通信を整備しても、イベント駆動でのサービス呼び出し機構がありません。同期HTTP呼び出しのみのアーキテクチャでは、サービス間の依存が密結合になり、一時的な障害が連鎖します。EventBridge との統合で非同期イベント発行とサービス間デカップリングが実現します。
Fargate単体の限界: ECS Service として常時稼働するコンテナは、低頻度バッチやイベントトリガー処理には過剰なコストです。EventBridge Scheduler + Fargate Task の組み合わせで、実行時のみコンテナを起動するサーバーレスバッチが実現します。VPC Lattice の Auth Policy と組み合わせることで、Fargate Task 間の IAM 認証通信も統一されます。
3軸統合で実現する5つの本番品質
| 品質軸 | 実現要素 | 単体では困難な理由 |
|---|---|---|
| Event-Driven | EventBridge Rule/EventBus/Pipes | Lambda 15分制限超ジョブは Fargate Task 必須 |
| Service Mesh | VPC Lattice Service Network + TargetGroup | サービス発見と認証をネットワーク層で統合 |
| Container Orchestration | Fargate + ECS Task Definition + awsvpc | イベント受信後のコンテナライフサイクル管理 |
| IAM Auth | VPC Lattice Auth Policy + Fargate Task Role | 二重認証の統合設計が単体では複雑化 |
| X-Ray Trace | EventBridge → Fargate → VPC Lattice の3層トレース | Trace Context 伝搬が層をまたぐと断絶 |
隣接3シリーズとの差別化
本記事は以下の3シリーズの延長上に位置しますが、統合設計という点で質的に異なります。
- Serverless本番運用 Vol2 (EventBridge×SQS×SNS×Kinesis): EventBridge の詳細設定と Lambda/SQS との非同期統合にフォーカス。コンテナ・ネットワーク層の統合は対象外。
- Network本番運用 Vol2 (TGW×PrivateLink×DX): VPC 間接続と Transit Gateway 中心。VPC Lattice のサービスメッシュ応用と EventBridge 統合は対象外。
- 本記事 (EventBridge×VPC Lattice×Fargate): 3層を同時に設計・実装し、イベント発火からコンテナ実行・サービス間通信・分散トレースまで一貫した本番運用パターンを提供。
- 痛点1: Lambda 15分制限超で Fargate 統合パターン不明
EventBridge Rule → Lambda でジョブを起動していたが、処理時間が15分超になると強制終了。Fargate Task Target への切り替え方法が不明で、TaskOverride で環境変数をイベントペイロードとして渡す設計にたどり着けない。 - 痛点2: VPC Lattice TargetGroup に Fargate Task が登録されない
ECS Service を VPC Lattice TargetGroup に登録しようとすると失敗。原因は Fargate がawsvpcネットワークモード必須なのに対し、TargetGroup が IP Type で ENI の IP を直接登録する仕様を知らないこと。 - 痛点3: Pipes + DynamoDB Streams → Fargate でデッドレターキュー設計不在
EventBridge Pipes の Source に DynamoDB Streams を設定し Fargate Task を起動する構成で、タスク失敗時の DLQ が未設定。失敗イベントがサイレントに消えて障害原因調査が不可能になる。 - 痛点4: VPC Lattice Auth Policy + Fargate Task Role の二重認証設計が複雑化
VPC Lattice の Service Auth Policy (SigV4 必須) と Fargate Task の IAM Role (ECS Task Execution Role + Task Role) が重なり、どの IAM Principal に何の権限が必要か整理できない。 - 痛点5: 3層 X-Ray 分散トレースが断絶
EventBridge → Fargate → VPC Lattice という呼び出し連鎖で X-Ray Service Map が繋がらない。EventBridge は X-Ray トレースを自動注入しないため、Fargate Task 側でのトレース ID 引き継ぎが必要なことを見落とす。
統合本番運用5原則
本記事を通じて以下の5原則を実装します。それぞれのセクションで具体的な Terraform コードとともに解説します。
- EventBus分離原則: 業務イベントはカスタム EventBus で分離。Default EventBus は AWS サービスイベント専用として混在を防ぐ。
- Service Network階層化原則: VPC Lattice Service Network はワークロード境界 (prod/staging) 単位で分離。一つの Service Network への過剰な Service 集約を避ける。
- Fargate awsvpcモード統一原則: すべての Fargate Task/Service で
awsvpcネットワークモードを使用。VPC Lattice TargetGroup (IP Type) との整合性を確保。 - Auth Policy統合原則: VPC Lattice Auth Policy と Fargate Task Role の IAM Principal を明示的にマッピング。暗黙の権限継承に頼らない。
- X-Ray 3層トレース原則: EventBridge → Fargate Task → VPC Lattice Endpoint の各層でトレース Context を明示的に伝搬。X-Ray SDK の手動計装を省略しない。
Serverless本番運用 Vol2 — EventBridge×SQS×SNS×Kinesis
2. EventBridge本番運用 — Rule × EventBus × Pipes × Scheduler

EventBridge 4本柱の役割と選定基準
EventBridge は単一サービスのように見えて、実際には4つの独立した機能柱で構成されています。本番運用では各柱の役割を明確に分離し、用途に応じて使い分けることが重要です。
| コンポーネント | 主用途 | Fargate統合パターン | 特記事項 |
|---|---|---|---|
| EventBridge Rule | イベントパターンマッチング → Target起動 | Rule → ECS RunTask | 1 Rule = 最大5 Targets |
| EventBus | イベントルーティングの分離・アーカイブ | カスタムEventBus → Rule → Fargate | Cross-account送信可能 |
| Pipes | ソース→Target 変換パイプライン | SQS/DDB Streams → Fargate Task | Filtering + Enrichment 内蔵 |
| Scheduler | cron/one-time スケジュール実行 | Scheduler → ECS RunTask | スケジューラ専用 (Rule.schedule_expression の後継) |
Rule Event Pattern 設計 — source + detail-type 厳密化
Event Pattern は source と detail-type の二段階で絞り込むのが本番品質の基本です。detail のみで絞り込むと、他サービスや他環境のイベントが意図せず一致するリスクがあります。
{
"source": ["com.myapp.order-service"],
"detail-type": ["OrderCreated"],
"detail": {
"status": ["PENDING"],
"amount": [{ "numeric": [">=", 10000] }]
}
}
このパターンは com.myapp.order-service が発行した OrderCreated イベントのうち、status=PENDING かつ amount >= 10000 のものだけを Fargate Task で処理します。source を省略すると Default EventBus の全イベントにマッチする可能性があるため、必ず指定してください。
Terraform での実装:
resource "aws_cloudwatch_event_rule" "order_fargate" {
name = "order-fargate-processor"
description = "OrderCreated(PENDING, amount>=10000) → Fargate Task"
event_bus_name = aws_cloudwatch_event_bus.app.name
event_pattern = jsonencode({
source= ["com.myapp.order-service"]
detail-type = ["OrderCreated"]
detail = {
status = ["PENDING"]
amount = [{ numeric = [">=", 10000] }]
}
})
tags = {
Environment = "production"
ManagedBy= "terraform"
}
}
カスタムEventBus vs Default EventBus — 本番使い分け基準
Default EventBus は AWS サービス (EC2 State Change, RDS, S3 Event Notification 等) が自動的にイベントを送信するバスです。業務アプリケーションのカスタムイベントを Default EventBus に混在させると、イベントの整理・アーカイブ・監査が複雑化します。
resource "aws_cloudwatch_event_bus" "app" {
name = "myapp-production"
tags = {
Environment = "production"
Purpose = "application-events"
}
}
# EventBus Policy: Cross-account イベント受信 (同一Org内)
resource "aws_cloudwatch_event_bus_policy" "app" {
event_bus_name = aws_cloudwatch_event_bus.app.name
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Sid = "AllowOrgAccounts"
Effect = "Allow"
Principal = { AWS = "*" }
Action = "events:PutEvents"
Resource = aws_cloudwatch_event_bus.app.arn
Condition = {
StringEquals = {
"aws:PrincipalOrgID" = var.organization_id
}
}
}]
})
}
カスタムEventBus を使うべき場合:
– アプリケーション固有のカスタムイベント発行
– 複数アカウント・複数環境への Cross-account ルーティング
– イベントのアーカイブ・リプレイが必要な業務フロー
– Default EventBus とのイベント分離が監査要件になる場合
Default EventBus を使うべき場合:
– EC2 インスタンス状態変化・RDS フェイルオーバー等の AWS サービスイベント受信
– CloudTrail イベントのリアルタイム反応 (API Call 監視等)
EventBridge Pipes 実装 — SQS/DDB Streams → Fargate Task
EventBridge Pipes は Source からのイベントを Filtering → Enrichment → Target の順に処理するフルマネージドパイプラインです。従来 Lambda を中継レイヤーとして挿入していた変換処理を、Pipes の Input Transformation で代替できます。
resource "aws_pipes_pipe" "ddb_to_fargate" {
name = "orders-ddb-to-fargate"
role_arn = aws_iam_role.pipes.arn
source = aws_dynamodb_table.orders.stream_arn
source_parameters {
dynamodb_stream_parameters {
starting_position= "LATEST"
batch_size = 10
maximum_retry_attempts = 3
dead_letter_config {
arn = aws_sqs_queue.pipes_dlq.arn
}
}
filter_criteria {
filter {
pattern = jsonencode({
eventName = ["INSERT"]
dynamodb = { NewImage = { status = { S = ["PENDING"] } } }
})
}
}
}
target = "arn:aws:ecs:${var.region}:${var.account_id}:cluster/${aws_ecs_cluster.app.name}"
target_parameters {
ecs_task_parameters {
task_definition_arn = aws_ecs_task_definition.order_processor.arn
launch_type= "FARGATE"
network_configuration {
aws_vpc_configuration {
subnets = var.private_subnet_ids
security_groups = [aws_security_group.fargate_task.id]
assign_public_ip = "DISABLED"
}
}
overrides {
container_override {
name = "order-processor"
environment {
name = "EVENT_PAYLOAD"
value = "$.detail"
}
environment {
name = "TRACE_ID"
value = "$.id"
}
}
}
task_count = 1
}
}
tags = {
Environment = "production"
ManagedBy= "terraform"
}
}
resource "aws_sqs_queue" "pipes_dlq" {
name = "orders-pipes-dlq"
message_retention_seconds = 1209600 # 14日
visibility_timeout_seconds = 300
tags = {
Environment = "production"
}
}
- DLQ は Pipes Source ごとに独立して設定:
dead_letter_configを省略すると、Target (Fargate Task) 失敗時のイベントがサイレントに消える。本番では必ず SQS DLQ を設定すること。 - maximum_retry_attempts は 3 が基準: 一時的なネットワーク障害・Fargate キャパシティ不足に対応。処理の冪等性 (idempotency) を実装した上で設定する。
- DLQ のメッセージ保持期間は14日: 障害発生から分析・修正・リプレイまでの猶予として14日 (1209600秒) が実運用での推奨値。
- DLQ アラーム設定:
ApproximateNumberOfMessagesVisible > 0で CloudWatch Alarm を設定し、失敗イベントの蓄積を即座に検知する。
EventBridge Scheduler — cron + Group + DLQ + Retry 設計
EventBridge Scheduler は従来の CloudWatch Events Schedule Rules の後継で、タイムゾーン対応・Group管理・フレキシブルウィンドウ・DLQが追加されています。
resource "aws_scheduler_schedule_group" "batch" {
name = "batch-jobs-production"
tags = {
Environment = "production"
}
}
resource "aws_scheduler_schedule" "nightly_batch" {
name = "nightly-order-aggregation"
group_name = aws_scheduler_schedule_group.batch.name
flexible_time_window {
mode = "FLEXIBLE"
maximum_window_in_minutes = 15
}
schedule_expression = "cron(0 2 * * ? *)"
schedule_expression_timezone = "Asia/Tokyo"
target {
arn= "arn:aws:ecs:${var.region}:${var.account_id}:cluster/${aws_ecs_cluster.app.name}"
role_arn = aws_iam_role.scheduler.arn
ecs_parameters {
task_definition_arn = aws_ecs_task_definition.aggregation.arn
launch_type= "FARGATE"
network_configuration {
assign_public_ip = false
security_groups = [aws_security_group.fargate_task.id]
subnets = var.private_subnet_ids
}
task_count = 1
}
retry_policy {
maximum_retry_attempts = 3
maximum_event_age_in_seconds = 3600
}
dead_letter_config {
arn = aws_sqs_queue.scheduler_dlq.arn
}
}
}
resource "aws_sqs_queue" "scheduler_dlq" {
name = "scheduler-dlq-production"
message_retention_seconds = 1209600
tags = { Environment = "production" }
}
Scheduler 本番設計のポイント:
– flexible_time_window で最大15分のずれを許容することで、同時刻起動によるリソース競合を回避
– schedule_expression_timezone = "Asia/Tokyo" で JST ベースのスケジュール指定 (UTC 変換不要)
– retry_policy.maximum_event_age_in_seconds = 3600 でスケジュール起動から1時間以内のリトライに制限
Fargate Task Target 統合 — TaskOverride でイベントペイロード受渡
EventBridge Rule から Fargate Task を起動する際、イベントの内容をコンテナに渡す唯一の手段が ECS Task Override の環境変数です。イベントペイロードを S3 や DynamoDB に書き込んで Fargate から参照するパターンも存在しますが、シンプルな構成では環境変数経由が推奨です。
resource "aws_cloudwatch_event_target" "fargate" {
rule = aws_cloudwatch_event_rule.order_fargate.name
event_bus_name = aws_cloudwatch_event_bus.app.name
target_id= "fargate-order-processor"
arn= aws_ecs_cluster.app.arn
role_arn = aws_iam_role.eventbridge_ecs.arn
ecs_target {
task_definition_arn = aws_ecs_task_definition.order_processor.arn
launch_type= "FARGATE"
task_count = 1
network_configuration {
subnets = var.private_subnet_ids
security_groups = [aws_security_group.fargate_task.id]
assign_public_ip = false
}
}
input_transformer {
input_paths = {
order_id= "$.detail.orderId"
amount = "$.detail.amount"
event_id= "$.id"
event_time = "$.time"
}
input_template = jsonencode({
containerOverrides = [{
name = "order-processor"
environment = [
{ name = "ORDER_ID", value = "<order_id>" },
{ name = "AMOUNT",value = "<amount>" },
{ name = "EVENT_ID", value = "<event_id>" },
{ name = "EVENT_TIME", value = "<event_time>" }
]
}]
})
}
}
resource "aws_iam_role" "eventbridge_ecs" {
name = "eventbridge-ecs-execution"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "events.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy" "eventbridge_ecs" {
name = "ecs-run-task"
role = aws_iam_role.eventbridge_ecs.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect= "Allow"
Action= ["ecs:RunTask"]
Resource = aws_ecs_task_definition.order_processor.arn
},
{
Effect= "Allow"
Action= ["iam:PassRole"]
Resource = [
aws_iam_role.ecs_task_execution.arn,
aws_iam_role.ecs_task_role.arn
]
}
]
})
}
- ecs:RunTask だけでは不十分: EventBridge の IAM Role には
ecs:RunTaskに加えてiam:PassRoleが必要。Task Execution Role と Task Role の両方に PassRole を付与しないとAccessDeniedExceptionが発生する。 - Resource は Task Definition ARN まで絞り込む:
ecs:RunTaskの Resource に*を使うと最小権限原則違反。Task Definition ARN (リビジョン指定 or:*で任意リビジョン) を指定する。 - Fargate awsvpc モードで assign_public_ip = false 必須: Private Subnet に NAT Gateway + VPC Endpoint 構成が前提。Public IP を付与すると VPC Lattice Auth Policy の IP ベース制御が破綻する。
Dead Letter Queue + Retry Policy 設計
EventBridge の DLQ とリトライポリシーは、Rule レベルと Scheduler レベルで独立して設定が必要です。
# Rule レベルの DLQ
resource "aws_cloudwatch_event_target" "fargate_with_dlq" {
rule = aws_cloudwatch_event_rule.order_fargate.name
event_bus_name = aws_cloudwatch_event_bus.app.name
target_id= "fargate-order-processor"
arn= aws_ecs_cluster.app.arn
role_arn = aws_iam_role.eventbridge_ecs.arn
retry_policy {
maximum_retry_attempts = 3
maximum_event_age_in_seconds = 3600
}
dead_letter_config {
arn = aws_sqs_queue.eventbridge_dlq.arn
}
ecs_target {
task_definition_arn = aws_ecs_task_definition.order_processor.arn
launch_type= "FARGATE"
task_count = 1
network_configuration {
subnets = var.private_subnet_ids
security_groups = [aws_security_group.fargate_task.id]
assign_public_ip = false
}
}
}
resource "aws_sqs_queue" "eventbridge_dlq" {
name = "eventbridge-fargate-dlq"
message_retention_seconds = 1209600
visibility_timeout_seconds = 300
redrive_allow_policy = jsonencode({
redrivePermission = "allowAll"
})
tags = { Environment = "production" }
}
# DLQ メッセージ蓄積アラーム
resource "aws_cloudwatch_metric_alarm" "eventbridge_dlq_alarm" {
alarm_name = "eventbridge-fargate-dlq-not-empty"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 1
metric_name= "ApproximateNumberOfMessagesVisible"
namespace = "AWS/SQS"
period = 300
statistic = "Sum"
threshold = 0
alarm_description= "EventBridge Fargate DLQ にメッセージが蓄積しています"
alarm_actions = [aws_sns_topic.alerts.arn]
dimensions = {
QueueName = aws_sqs_queue.eventbridge_dlq.name
}
}
mermaid01: EventBridge Rule → Fargate Task 起動フロー
flowchart LR
subgraph Sources["イベントソース"]
APP["アプリケーション\n(PutEvents)"]
DDB["DynamoDB Streams\n(変更データ)"]
SCHED["Scheduler\n(cron / one-time)"]
end
subgraph EventBridge["EventBridge レイヤー"]
BUS["カスタム EventBus\n(myapp-production)"]
RULE["EventBridge Rule\n(Event Pattern Match)"]
PIPES["EventBridge Pipes\n(Filter → Transform)"]
end
subgraph ECS["ECS / Fargate レイヤー"]
CLUSTER["ECS Cluster\n(Fargate)"]
TASKDEF["Task Definition\n(awsvpc モード)"]
TASK["Fargate Task\n(コンテナ実行)"]
end
subgraph Result["処理結果"]
SUCCESS["正常完了\n(Exit Code 0)"]
DLQ["SQS DLQ\n(失敗イベント保持)"]
ALARM["CloudWatch Alarm\n(DLQ 蓄積検知)"]
end
APP -->|PutEvents| BUS
BUS -->|Route| RULE
DDB -->|Stream| PIPES
SCHED -->|RunTask| CLUSTER
RULE -->|ECS RunTask\n+ TaskOverride| CLUSTER
PIPES -->|ECS RunTask\n+ ContainerOverride| CLUSTER
CLUSTER --> TASKDEF
TASKDEF --> TASK
TASK -->|Exit 0| SUCCESS
TASK -->|Exit != 0\nmax retry 3| DLQ
DLQ -->|ApproximateMessages > 0| ALARM
- ✅ カスタム EventBus でアプリケーションイベントを分離 (Default EventBus との混在なし)
- ✅ Rule Event Pattern に
source+detail-typeを必ず指定 (過剰マッチ防止) - ✅ EventBridge IAM Role に
ecs:RunTask+iam:PassRole(Task Execution Role + Task Role 両方) - ✅ Fargate Task は
awsvpcネットワークモード + Private Subnet + NAT Gateway 構成 - ✅ Rule / Pipes / Scheduler すべてに DLQ + Retry Policy (maximum_retry_attempts=3) を設定
- ✅ DLQ に CloudWatch Alarm (ApproximateNumberOfMessagesVisible > 0) を設定
- ✅ TaskOverride の環境変数でイベントペイロードをコンテナに受渡
- ✅ Scheduler は cron + JST タイムゾーン + flexible_time_window で競合回避
3. VPC Lattice本番運用 — Service Network × TargetGroup × Auth Policy × Listener
- 原則1: Service Network は組織単位で分離 (prod/staging/dev 環境別)
- 原則2: TargetGroup は IP type (Fargate awsvpc互換) を第一選択
- 原則3: Auth Policy は IAM-based 必須 (No Authentication は本番禁止)
- 原則4: Service Discovery はVPC Lattice 自動DNS活用 (FQDN変更不要)
- 原則5: Multi-Account共有は RAM 経由+Allowed Principals でOU指定
3-1. VPC Lattice アーキテクチャ全体像 — 5層構造
VPC Lattice は 5 層の論理コンポーネントで構成される。最上位の Service Network を起点に、Service → TargetGroup → Listener → Auth Policy という階層が積み重なり、VPC・アカウント境界を越えた L7 サービスメッシュを実現する。
[VPC Lattice 5層構造]
Layer 1 Service Network
├── VPC Association (複数VPCをアタッチ)
└── Service Association (ServiceをService Networkに紐付け)
Layer 2 Service
├── DNS Name (自動FQDN: <svc-id>.vpce.lattice.aws.dev)
└── Auth Policy (Service単位)
Layer 3 TargetGroup
├── Type: Instance / IP / Lambda / ALB
└── Health Check (HTTP/HTTPS/gRPC)
Layer 4 Listener
├── Port / Protocol (HTTP:80 / HTTPS:443 / TLS Pass-through)
└── Default Action (Forward to TargetGroup)
Layer 5 Auth Policy
├── IAM-based (Principal: AWS IAM Role / IRSA)
└── Condition (aws:PrincipalOrgID / aws:SourceVpc)
各層の責務を明確に分離することで、サービス間通信の認証・ルーティング・ヘルスチェックを一元管理できる。特に Auth Policy は Service Network レベルと Service レベルの 2 箇所に設定でき、多段防御を実現する。
3-2. Service Network 階層設計 — 環境別分離とTerraform実装
Service Network は「どのVPCとServiceを束ねるか」を定義する論理グループである。本番運用では 環境 (prod/staging/dev) ×組織単位 (OU) の2軸で設計するのが標準パターンだ。
設計パターン: 環境別 Service Network
| Service Network | 用途 | VPC Association | Service数上限 |
|---|---|---|---|
sn-prod | 本番環境 | prod-vpc, shared-vpc | 500 |
sn-staging | ステージング | staging-vpc | 500 |
sn-dev | 開発環境 | dev-vpc-{n} | 500 |
環境をまたぐ通信(staging → prod)はデフォルトで遮断される。同一 Service Network 内でのみ Service Discovery が機能するため、環境間の意図しない通信を構造的に防止できる。
Terraform 実装: aws_vpclattice_service_network
# Service Network (環境別)
resource "aws_vpclattice_service_network" "prod" {
name= "sn-${var.env}-${var.project}"
auth_type = "AWS_IAM"
tags = {
Environment = var.env
ManagedBy= "terraform"
}
}
# VPC Association — Fargate Task が稼働するVPCをアタッチ
resource "aws_vpclattice_service_network_vpc_association" "fargate_vpc" {
vpc_identifier = aws_vpc.fargate.id
service_network_identifier = aws_vpclattice_service_network.prod.id
security_group_ids = [aws_security_group.lattice_ingress.id]
}
# Service Association — ServiceをService Networkに登録
resource "aws_vpclattice_service_network_service_association" "app" {
service_identifier= aws_vpclattice_service.app.id
service_network_identifier = aws_vpclattice_service_network.prod.id
}
auth_type = "AWS_IAM" を必ず指定する。NONE (No Authentication) は検証環境専用であり、本番では設定してはならない。VPC Association に紐付ける Security Group は、Lattice の送信元 IP プレフィックス 169.254.171.0/24(link-local)を許可するルールを含むこと。
- Service Network per Account: デフォルト 20 (上限緩和申請可)
- VPC Association per Service Network: 5 VPC per AZ が下限保証。AZ跨ぎでは各AZに1つ以上のVPC AssociationがあればOK
- Service Association per Service Network: 500 Service
- 注意: Service Network削除はVPC Association / Service Association を全解除してから。順序違反はAPI 409エラー
3-3. TargetGroup種別比較とFargate IP type選定
VPC Lattice の TargetGroup は 4 種類あり、ターゲットの種類によって選択する。
TargetGroup種別比較表
| Type | ターゲット | Fargate互換 | ヘルスチェック | 主な用途 |
|---|---|---|---|---|
| Instance | EC2 Instance ID | 非推奨 | HTTP/HTTPS | EC2 Auto Scaling Group |
| IP | VPC内 Private IP | ◎ 推奨 | HTTP/HTTPS/gRPC | Fargate (awsvpc) / Lambda ENI |
| Lambda | Lambda Function ARN | N/A | N/A (Lambda側で処理) | Lambda Function URL代替 |
| ALB | ALB ARN | △ 経由 | HTTP/HTTPS | 既存ALB前段にLattice配置 |
Fargate に IP type を選ぶ理由
Fargate は awsvpc Network Mode 使用時、各 Task に独立した ENI(Elastic Network Interface)が割り当てられ、VPC 内 Private IP が動的に付与される。Instance type TargetGroup は EC2 Instance ID による登録を前提とするため、ENI ベースの Fargate Task を直接登録できない。IP type TargetGroup はこの Private IP を直接登録するため、Fargate との相性が最も良い。
Terraform 実装: aws_vpclattice_target_group
# TargetGroup — IP type (Fargate awsvpc 対応)
resource "aws_vpclattice_target_group" "fargate_api" {
name = "tg-${var.env}-fargate-api"
type = "IP"
config {
port = 8080
protocol= "HTTP"
vpc_identifier= aws_vpc.fargate.id
protocol_version = "HTTP1"
health_check {
enabled = true
protocol = "HTTP"
protocol_version = "HTTP1"
path = "/health"
port = 8080
healthy_threshold_count = 2
unhealthy_threshold_count = 3
health_check_interval_seconds = 30
health_check_timeout_seconds = 5
matcher {
value = "200"
}
}
}
tags = {
Environment = var.env
Service = "fargate-api"
}
}
# TargetGroup へ Fargate Task IP を登録 (ECS Service稼働後)
# 実運用では aws_ecs_service の network_configuration.subnets と
# ECS Task ENI の Private IP を動的に取得して登録する
resource "aws_vpclattice_target_group_attachment" "fargate_task" {
target_group_identifier = aws_vpclattice_target_group.fargate_api.id
target {
id= var.fargate_task_private_ip # Task ENI Private IP
port = 8080
}
}
TargetGroup の protocol_version は HTTP1 / HTTP2 / GRPC を選択できる。gRPC を使用する Fargate サービスには GRPC を指定し、ヘルスチェックプロトコルも gRPC に揃えること。
Instance type TargetGroup は EC2 Instance ID 紐付け前提のため、Fargate Task(ENI動的割当)では登録不可。登録試行時は
InvalidTargetException が返る。IP type TargetGroup + Fargate awsvpc Network Mode の組み合わせが正解。Task IP変動(スケールイン/アウト)時は ECS Service Events を EventBridge 経由でキャッチし、TargetGroup の登録/解除を自動化するか、AWS Cloud Map + Service Connect との併用を検討する。3-4. Listener設定 — プロトコル×ルーティングルール
Listener は Service の「入口」であり、受信プロトコル・ポートとトラフィックの転送先(TargetGroup)を定義する。
Listener プロトコル一覧
| プロトコル | ポート | 主な用途 | TLS終端 |
|---|---|---|---|
| HTTP | 80 (任意) | 内部マイクロサービス | なし |
| HTTPS | 443 (任意) | 本番外部公開 | Lattice側で終端 |
| TLS Pass-through | 443 (任意) | E2E暗号化必須 | ターゲット側で終端 |
Listener ルーティングルール
Listener に複数のルールを設定することで、パスベース・ヘッダーベースのルーティングが可能だ。
# Listener — HTTPS with weighted routing
resource "aws_vpclattice_listener" "api" {
name= "listener-api-https"
protocol = "HTTPS"
port= 443
service_identifier = aws_vpclattice_service.app.id
default_action {
forward {
target_groups {
target_group_identifier = aws_vpclattice_target_group.fargate_api.id
weight= 100
}
}
}
}
# Listener Rule — Blue/Green デプロイ用 weighted routing
resource "aws_vpclattice_listener_rule" "canary" {
name = "canary-10pct"
listener_identifier = aws_vpclattice_listener.api.id
service_identifier = aws_vpclattice_service.app.id
priority= 10
match {
http_match {
path_match {
match {
prefix = "/api/v2/"
}
case_sensitive = false
}
}
}
action {
forward {
target_groups {
target_group_identifier = aws_vpclattice_target_group.fargate_api_v2.id
weight= 10
}
target_groups {
target_group_identifier = aws_vpclattice_target_group.fargate_api.id
weight= 90
}
}
}
}
weight は合計 100 になるよう設定する。カナリーデプロイでは v2 を 10% → 50% → 100% と段階的に増加させ、各フェーズで CloudWatch メトリクス(エラーレート・レイテンシ)を確認してから次フェーズに移行する。
3-5. Auth Policy設計 — IAM-based + IRSA連携
VPC Lattice の Auth Policy はリソースベースポリシーであり、誰が(Principal) 何を(Action) 許可するかを JSON で記述する。Service Network と Service の 2 箇所に設定でき、それぞれ独立して評価される。
Auth Policy 評価順序
リクエスト
↓
[Service Network Auth Policy] — ALLOW/DENY
↓ (ALLOW の場合のみ)
[Service Auth Policy] — ALLOW/DENY
↓ (両方 ALLOW の場合)
ターゲットへ転送
Service Auth Policy — IRSA連携パターン
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "vpc-lattice-svcs:Invoke",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-xxxxxxxxxxxx",
"vpc-lattice-svcs:RequestMethod": ["GET", "POST"]
},
"ArnLike": {
"aws:PrincipalArn": "arn:aws:iam::*:role/fargate-task-role-*"
}
}
}
]
}
aws:PrincipalOrgID により Organizations 配下のアカウントのみを許可し、aws:PrincipalArn で Fargate Task Role の命名規則に一致するロールのみに絞り込む。これにより IRSA(EKS の場合)または ECS Task Role 経由のリクエストのみが通過できる。
Terraform 実装: aws_vpclattice_auth_policy
# Service レベル Auth Policy
resource "aws_vpclattice_auth_policy" "service" {
resource_identifier = aws_vpclattice_service.app.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = { AWS = "*" }
Action = "vpc-lattice-svcs:Invoke"
Resource = "*"
Condition = {
StringEquals = {
"aws:PrincipalOrgID"= var.org_id
"vpc-lattice-svcs:RequestMethod"= ["GET", "POST", "PUT", "DELETE"]
}
ArnLike = {
"aws:PrincipalArn" = "arn:aws:iam::*:role/${var.task_role_prefix}-*"
}
}
}
]
})
}
# Service Network レベル Auth Policy (広めの許可 — Service側で絞り込み)
resource "aws_vpclattice_auth_policy" "service_network" {
resource_identifier = aws_vpclattice_service_network.prod.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = { AWS = "*" }
Action = "vpc-lattice-svcs:Invoke"
Resource = "*"
Condition = {
StringEquals = {
"aws:PrincipalOrgID" = var.org_id
}
}
}
]
})
}
Service Network 側は Organization 全体を許可し、Service 側で Task Role の命名規則による絞り込みを行う。この 2 段階設計により、新しい Service を追加する際に Service Network ポリシーを変更せずに済む。
3-6. Service Discovery — DNS-based FQDN × VPC内アクセス
VPC Lattice は Service 作成時に自動的に FQDN(Fully Qualified Domain Name)を払い出す。この DNS 名は Service の ARN から導出される固定値であり、Service の設定変更(Listener追加・TargetGroup差し替え)後も変わらない。
DNS 名の形式
<service-id>.vpce.lattice.aws.dev
例: svc-01234567890abcdef.7d67968.vpce.lattice.aws.dev
この FQDN は VPC Association を持つ VPC 内でのみ名前解決できる。VPC Association に紐付ける Security Group が DNS クエリ(UDP 53)と HTTPS(TCP 443)を許可していることを確認する。
VPC内アクセス設計
# Fargate Task からのアクセス確認
# Task内で以下のコマンドを実行して疎通確認
# 1. DNS解決確認
nslookup svc-01234567890abcdef.7d67968.vpce.lattice.aws.dev
# 2. Sigv4署名付きリクエスト (IAM認証が有効な場合は署名必須)
curl -v \
--aws-sigv4 "aws:amz:ap-northeast-1:vpc-lattice-svcs" \
--user "${AWS_ACCESS_KEY_ID}:${AWS_SECRET_ACCESS_KEY}" \
-H "x-amz-security-token: ${AWS_SESSION_TOKEN}" \
https://svc-01234567890abcdef.7d67968.vpce.lattice.aws.dev/health
Fargate Task からの呼び出しには AWS Signature Version 4 (SigV4) 署名が必要だ。Task Role に vpc-lattice-svcs:Invoke 権限を付与し、AWS SDK の HTTP クライアントで自動署名を行うか、上記のように curl --aws-sigv4 オプションを使用する。
カスタムドメイン設定
# Route53 ALIAS で独自ドメインを割り当て
resource "aws_route53_record" "lattice_service" {
zone_id = aws_route53_zone.internal.zone_id
name = "api.internal.example.com"
type = "CNAME"
ttl = 60
records = [aws_vpclattice_service.app.dns_entry[0].domain_name]
}
内部ドメイン(*.internal.example.com)を Route 53 Private Hosted Zone に登録することで、可読性の高いエンドポイントを提供できる。VPC Lattice の自動 FQDN は変わらないため、CNAME の向き先を更新する必要はない。
3-7. Multi-Account Lattice — RAM経由 Service Network共有
大規模組織では複数 AWS アカウントにまたがってサービスを管理する。VPC Lattice は AWS Resource Access Manager (RAM) を使用して Service Network をアカウント間で共有できる。
共有パターン: 中央 Service Network
[Hub Account (Network Account)]
Service Network: sn-prod-central
↓ RAM共有
[Spoke Account A (App Account)] ← VPC Association
[Spoke Account B (App Account)] ← VPC Association + Service Association
[Spoke Account C (Security Account)] ← 監視専用 VPC Association
Hub アカウントが Service Network を所有し、各 Spoke アカウントに RAM で共有する。Spoke アカウントは RAM の共有を受け入れることで、自身の VPC を Service Network にアタッチできる。
Terraform 実装: RAM共有 + Organizations OU許可
# Hub Account: Service Network をRAM共有
resource "aws_ram_resource_share" "lattice_network" {
name = "lattice-sn-prod-share"
allow_external_principals = false # Organizations外への共有禁止
tags = {
Environment = "prod"
}
}
resource "aws_ram_resource_association" "service_network" {
resource_arn = aws_vpclattice_service_network.prod.arn
resource_share_arn = aws_ram_resource_share.lattice_network.arn
}
# Organizations OU全体に共有 (個別アカウント管理不要)
resource "aws_ram_principal_association" "org_unit" {
principal = "arn:aws:organizations::123456789012:ou/o-xxxx/ou-yyyy-zzzzzzzz"
resource_share_arn = aws_ram_resource_share.lattice_network.arn
}
# Spoke Account: 共有を受け入れて VPC Association
resource "aws_ram_resource_share_accepter" "lattice" {
share_arn = data.aws_ram_resource_share.from_hub.arn
}
resource "aws_vpclattice_service_network_vpc_association" "spoke" {
vpc_identifier = aws_vpc.spoke.id
service_network_identifier = data.aws_vpclattice_service_network.shared.id
security_group_ids = [aws_security_group.lattice_spoke.id]
depends_on = [aws_ram_resource_share_accepter.lattice]
}
OU 単位で RAM 共有することで、新規アカウントを OU に追加するだけで自動的に共有が適用される。個別アカウントへの共有追加作業が不要になるため、Landing Zone 展開時の運用負荷を大幅に削減できる。
- Hub Account の Service Network Auth Policy に全 Spoke アカウントの OU ID を含める
- RAM共有は
allow_external_principals = falseで Organizations内限定に制限 - Spoke Account でのVPC Associationには専用 Security Group を作成し、Lattice link-local (
169.254.171.0/24) を明示許可 - Service Association はサービスオーナーの Spoke Account から実行 (Hub Account では代理実行しない)
- CloudTrail で
vpc-lattice:CreateServiceNetworkVpcAssociationイベントを監視し、不正アタッチを検出
3-8. 本番Quota対策
VPC Lattice には Service Quota による上限が存在する。本番稼働前に必ず確認し、必要に応じて上限緩和申請を行う。
主要 Quota 一覧
| リソース | デフォルト上限 | 上限緩和 | 注意点 |
|---|---|---|---|
| Service Networks per Region | 20 | 可 | 環境×プロジェクト数で計算 |
| Services per Account | 500 | 可 | Microservice数が多い場合は早めに申請 |
| TargetGroups per Account | 500 | 可 | Service × Listener数分が必要 |
| Targets per TargetGroup | 1,000 | 可 | Fargate Task数がスケール時に超過するリスク |
| VPC Associations per Service Network | 20 | 可 | Multi-Account構成で消費が早い |
| Service Associations per Service Network | 500 | 可 | Service Networksと共に設計 |
| Listener Rules per Listener | 100 | 不可 | A/Bテスト・カナリー数に影響 |
Quota監視の自動化
# 現在のQuota使用量を確認
aws service-quotas get-service-quota \
--service-code vpc-lattice \
--quota-code L-F5093E9C \
--region ap-northeast-1
# TargetGroup内のTarget数確認 (1000上限接近チェック)
aws vpc-lattice list-targets \
--target-group-identifier tg-01234567890abcdef \
--query 'length(items)' \
--output text
Fargate Auto Scaling により Task 数が急増すると TargetGroup の登録数が上限に近づく可能性がある。CloudWatch で vpc-lattice:TargetCount メトリクスを監視し、800 件でアラートを発報する設定を入れておく。上限緩和申請は承認まで数営業日かかるため、リリース 2 週間前には申請を完了させること。
3-9. Terraform実装まとめ — aws_vpclattice_service
§3-2〜3-7 のコード例を補完する形で、aws_vpclattice_service リソースの完全な実装例を示す。
Terraform 実装: aws_vpclattice_service
# Service 定義 — Fargate API サービス
resource "aws_vpclattice_service" "app" {
name= "svc-${var.env}-${var.project}-api"
auth_type = "AWS_IAM"
# カスタムドメイン設定 (ACM証明書が必要)
certificate_arn = var.acm_certificate_arn
tags = {
Environment = var.env
Project = var.project
ManagedBy= "terraform"
}
}
# Service の完全な出力値
output "service_dns" {
description = "VPC Lattice Service の自動生成DNS名"
value = aws_vpclattice_service.app.dns_entry[0].domain_name
}
output "service_arn" {
description = "VPC Lattice Service ARN (Auth Policy設定で使用)"
value = aws_vpclattice_service.app.arn
}
# 全リソースをまとめたモジュール呼び出し例
module "vpc_lattice" {
source = "./modules/vpc-lattice"
env = var.env
project = var.project
org_id = var.org_id
fargate_vpc_id= module.vpc.fargate_vpc_id
task_role_prefix = "fargate-task-role"
acm_certificate_arn = module.acm.certificate_arn
# TargetGroup設定
target_port = 8080
target_protocol = "HTTP"
health_path = "/health"
# RAM共有 (Multi-Account構成の場合)
ram_share_ou_arn = "arn:aws:organizations::${data.aws_caller_identity.current.account_id}:ou/${var.org_id}/${var.app_ou_id}"
}
依存関係グラフ (Terraform apply 順序)
aws_vpc → aws_vpclattice_service_network
↓
aws_vpclattice_service_network_vpc_association (VPCアタッチ)
↓
aws_vpclattice_service (Service作成)
↓
aws_vpclattice_service_network_service_association (Service登録)
↓
aws_vpclattice_target_group (TargetGroup作成)
↓
aws_vpclattice_listener (Listener作成)
↓
aws_vpclattice_auth_policy (Auth Policy適用)
terraform apply では上記の依存関係が depends_on または暗黙的な参照により自動解決される。ただし Spoke Account から実行する aws_vpclattice_service_network_vpc_association は Hub Account の RAM 共有受け入れ (aws_ram_resource_share_accepter) に明示的な depends_on が必要だ。
4. Fargate本番運用 — ECS Task × Service Connect × Container Insights × IRSA

- 原則1: awsvpc Network Mode 必須 (Task毎ENI / SG / VPC Lattice IP登録対応)
- 原則2: Task Role + Task Execution Role を厳格分離 (権限の最小化)
- 原則3: ARM Graviton 第一選択 (x86_64より20%安・性能同等)
- 原則4: Container Insights enhanced で Task/Container metric統合監視
- 原則5: Service Connect or VPC Lattice 単独運用 (重複構成回避)
4-1. ECS Fargate基礎 — Task Definition / Cluster / Service設計
ECS Fargateは、サーバーレスコンテナ実行環境として「インフラ管理ゼロ」を実現する。EC2インスタンスのプロビジョニング不要で、Taskが起動するたびにAWSがマネージドな基盤を自動割り当てする。
Task Definitionの設計要点
Task Definitionはコンテナのブループリントであり、CPU/Memory・ネットワークモード・ログ設定・IAMロールを一括定義する。Fargate必須事項として networkMode: awsvpc を設定し、Task毎にENIが割り当てられることで独立したネットワーク空間を得る。
# task-definition.yaml (抜粋)
family: app-backend
networkMode: awsvpc
requiresCompatibilities:
- FARGATE
cpu: "512"# 0.5 vCPU
memory: "1024" # 1 GB
executionRoleArn: arn:aws:iam::123456789012:role/ecsTaskExecutionRole
taskRoleArn: arn:aws:iam::123456789012:role/ecsAppTaskRole
containerDefinitions:
- name: app
image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/app:latest
portMappings:
- containerPort: 8080
name: app-http# Service Connect用の名前付きポート
appProtocol: http
logConfiguration:
logDriver: awslogs
options:
awslogs-group: /ecs/app-backend
awslogs-region: ap-northeast-1
awslogs-stream-prefix: ecs
environment:
- name: APP_ENV
value: production
healthCheck:
command: ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"]
interval: 30
timeout: 5
retries: 3
startPeriod: 60
Capacity Provider戦略
Fargateには FARGATE(標準)と FARGATE_SPOT(最大70%割引・中断あり)の2種がある。本番ワークロードには以下の比率が推奨される。
# Cluster Capacity Provider設定
capacityProviders:
- FARGATE
- FARGATE_SPOT
defaultCapacityProviderStrategy:
- capacityProvider: FARGATE
weight: 1
base: 1 # 最低1Taskは標準Fargateで確保
- capacityProvider: FARGATE_SPOT
weight: 3 # 残り75%はSpotで実行
バースト耐性が必要なAPIサービスは base: 2 以上、非同期バッチ処理は FARGATE_SPOT 100%で大幅なコスト削減が可能。
4-2. Service Connect実装 — ECS Native Service Mesh
Service ConnectはECS 2022年11月GA以降の公式サービスメッシュ実装で、App Meshの設定複雑性を解消しECSネイティブに統合された。Envoyプロキシが各Taskのサイドカーとして自動注入され、サービス間通信のロードバランシング・リトライ・サーキットブレーカーを提供する。
- Service Connect推奨: ECS Cluster内のService間通信 / 設定工数最小 / ECSマネージド
- App Mesh (廃止予定): 2025年3月AWS公式廃止アナウンス / 新規利用禁止
- VPC Lattice推奨: Cross-VPC / Cross-Account通信 / IAM認証ポリシー必要時
- 移行パス: App Mesh → Service Connect (同Cluster内) / App Mesh → VPC Lattice (Cross-Account)
Service Connect Namespace / Service設定
# ecs-service-connect.yaml
services:
- name: app-backend-svc
cluster: production-cluster
taskDefinition: app-backend:latest
desiredCount: 3
launchType: FARGATE
networkConfiguration:
awsvpcConfiguration:
subnets: [subnet-aaa, subnet-bbb]
securityGroups: [sg-app]
assignPublicIp: DISABLED
serviceConnectConfiguration:
enabled: true
namespace: production.local# CloudMap Private DNS Namespace
services:
- portName: app-http # Task DefinitionのportMappings.name
discoveryName: app-backend# CloudMap サービス名
clientAliases:
- port: 80
dnsName: app-backend # 他ServiceからはHTTP://app-backend:80 でアクセス
logConfiguration:
logDriver: awslogs
options:
awslogs-group: /ecs/service-connect
awslogs-region: ap-northeast-1
awslogs-stream-prefix: sc
Terraform実装 — ECS Service + Service Connect
# ecs.tf
resource "aws_ecs_cluster" "main" {
name = "production-cluster"
service_connect_defaults {
namespace = aws_service_discovery_private_dns_namespace.main.arn
}
setting {
name = "containerInsights"
value = "enhanced"# Container Insights enhanced モード有効化
}
}
resource "aws_service_discovery_private_dns_namespace" "main" {
name = "production.local"
description = "ECS Service Connect Namespace"
vpc= var.vpc_id
}
resource "aws_ecs_task_definition" "app" {
family = "app-backend"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = 512
memory = 1024
execution_role_arn = aws_iam_role.ecs_execution.arn
task_role_arn= aws_iam_role.ecs_task.arn
runtime_platform {
operating_system_family = "LINUX"
cpu_architecture = "ARM64"# Graviton (ARM64) 優先
}
container_definitions = jsonencode([{
name = "app"
image = "${var.ecr_repository_url}:${var.image_tag}"
portMappings = [{
containerPort = 8080
name = "app-http"
appProtocol= "http"
}]
logConfiguration = {
logDriver = "awslogs"
options = {
"awslogs-group"= "/ecs/app-backend"
"awslogs-region" = var.aws_region
"awslogs-stream-prefix" = "ecs"
}
}
}])
}
resource "aws_ecs_service" "app" {
name= "app-backend-svc"
cluster= aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.app.arn
desired_count= 3
capacity_provider_strategy {
capacity_provider = "FARGATE"
weight= 1
base = 1
}
capacity_provider_strategy {
capacity_provider = "FARGATE_SPOT"
weight= 3
}
network_configuration {
subnets = var.private_subnet_ids
security_groups = [aws_security_group.app.id]
assign_public_ip = false
}
service_connect_configuration {
enabled= true
namespace = aws_service_discovery_private_dns_namespace.main.arn
service {
port_name= "app-http"
discovery_name = "app-backend"
client_alias {
port = 80
dns_name = "app-backend"
}
}
log_configuration {
log_driver = "awslogs"
options = {
"awslogs-group"= "/ecs/service-connect"
"awslogs-region" = var.aws_region
"awslogs-stream-prefix" = "sc"
}
}
}
}
4-3. VPC Lattice統合パターン — Service Connect併用 vs 単独選定
VPC LatticeをFargateと組み合わせる場合、Service Connectとの役割分担が設計の核心となる。
- Service Connect: ECS Cluster内Service間通信 / シンプル設定 / ECS Native / CloudMapベース
- VPC Lattice: Cross-VPC/Cross-Account通信 / IAM Auth Policy / Lambda・EC2・ECSを横断
- 両併用: ECS内=Service Connect / Cross-Account=VPC Lattice (レイヤー分離)
- 判断軸: 同Cluster内 → Service Connect / 異Account/VPC → VPC Lattice
VPC Lattice TargetGroup — IP Targetタイプ設定
FargateのTask IPをVPC Lattice TargetGroupに登録する場合、ip タイプを使用する。ECSサービス起動時にTask ENIのIPが動的にTargetGroupへ登録・削除される。
# vpc-lattice-target.tf
resource "aws_vpclattice_target_group" "fargate" {
name = "fargate-app-tg"
type = "IP"
config {
port = 8080
protocol= "HTTP"
protocol_version = "HTTP1"
vpc_identifier= var.vpc_id
health_check {
enabled = true
path = "/health"
protocol= "HTTP"
healthy_threshold= 3
unhealthy_threshold = 2
interval_seconds = 30
timeout_seconds = 5
}
}
}
# ECS Service とVPC Lattice連携 (EventBridge Pipes or Lambda経由でIP登録)
# Fargate Task起動イベント → EventBridge → Lambda → TargetGroup IP登録
resource "aws_lambda_function" "lattice_registrar" {
function_name = "fargate-lattice-ip-registrar"
role = aws_iam_role.lambda_lattice.arn
handler = "index.handler"
runtime = "python3.12"
architectures = ["arm64"]
environment {
variables = {
TARGET_GROUP_ARN = aws_vpclattice_target_group.fargate.arn
}
}
}
4-4. Container Insights Enhanced — Task/Container レベル監視
Container Insights enhancedモードでは、標準モードの ECS/ContainerInsights に加えて、Task・Containerレベルのメトリクスが取得できる。
# Container Insights enhanced 有効化 (AWS CLI)
aws ecs update-cluster-settings \
--cluster production-cluster \
--settings name=containerInsights,value=enhanced \
--region ap-northeast-1
取得可能メトリクス一覧
| メトリクス | 粒度 | 用途 |
|---|---|---|
CpuUtilized | Task / Container | CPU使用量(vCPU) |
MemoryUtilized | Task / Container | メモリ使用量(MiB) |
StorageReadBytes | Task | ストレージ読み取り |
NetworkRxBytes | Task | ネットワーク受信 |
RunningTaskCount | Service | 稼働Task数 |
PendingTaskCount | Service | 起動待ちTask数 |
CloudWatch Dashboard設定
# cloudwatch-dashboard.tf
resource "aws_cloudwatch_dashboard" "ecs_insights" {
dashboard_name = "ecs-container-insights"
dashboard_body = jsonencode({
widgets = [
{
type = "metric"
properties = {
title = "Task CPU Utilization"
period = 60
stat= "Average"
metrics = [
["ECS/ContainerInsights", "CpuUtilized",
"ClusterName", "production-cluster",
"ServiceName", "app-backend-svc"]
]
}
},
{
type = "metric"
properties = {
title = "Task Memory Utilization"
period = 60
stat= "Average"
metrics = [
["ECS/ContainerInsights", "MemoryUtilized",
"ClusterName", "production-cluster",
"ServiceName", "app-backend-svc"]
]
}
},
{
type = "metric"
properties = {
title= "Running vs Pending Tasks"
period = 60
view = "timeSeries"
metrics = [
["ECS/ContainerInsights", "RunningTaskCount",
"ClusterName", "production-cluster",
"ServiceName", "app-backend-svc"],
["ECS/ContainerInsights", "PendingTaskCount",
"ClusterName", "production-cluster",
"ServiceName", "app-backend-svc"]
]
}
}
]
})
}
4-5. IRSA実装 — Task Role × Task Execution Role厳格分離
FargateにおけるIAM設計の最重要原則は、Task RoleとTask Execution Roleを絶対に混在させないことである。
| ロール | 用途 | 代表的な権限 |
|---|---|---|
| Task Execution Role | ECS エージェントが使用 | ECRイメージPull / CloudWatch Logs書き込み / Secrets Manager読み取り |
| Task Role | アプリケーションが使用 | DynamoDB / S3 / SQS / 業務ロジックに必要なAWSサービス |
Task Execution Role (Terraform)
# iam-execution-role.tf
data "aws_iam_policy_document" "ecs_execution_assume" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ecs-tasks.amazonaws.com"]
}
}
}
resource "aws_iam_role" "ecs_execution" {
name= "ecsTaskExecutionRole"
assume_role_policy = data.aws_iam_policy_document.ecs_execution_assume.json
}
resource "aws_iam_role_policy_attachment" "ecs_execution_managed" {
role = aws_iam_role.ecs_execution.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}
# Secrets Manager読み取り (Task Definitionのsecrets参照用)
resource "aws_iam_role_policy" "ecs_execution_secrets" {
name = "ecs-secrets-policy"
role = aws_iam_role.ecs_execution.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect= "Allow"
Action= ["secretsmanager:GetSecretValue"]
Resource = ["arn:aws:secretsmanager:ap-northeast-1:*:secret:app/*"]
}]
})
}
Task Role — OIDC不要のネイティブIRSA
FargateのTask RoleはKubernetesのIRSAと異なり、OIDC Providerなしでネイティブに機能する。Task定義に taskRoleArn を指定するだけで、コンテナ内のAWS SDKが自動的にTask Roleで認証される。
# iam-task-role.tf
resource "aws_iam_role" "ecs_task" {
name= "ecsAppTaskRole"
assume_role_policy = data.aws_iam_policy_document.ecs_execution_assume.json
}
resource "aws_iam_role_policy" "ecs_task_app" {
name = "ecs-app-policy"
role = aws_iam_role.ecs_task.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:Query",
"dynamodb:UpdateItem"
]
Resource = ["arn:aws:dynamodb:ap-northeast-1:*:table/app-*"]
},
{
Effect= "Allow"
Action= ["sqs:ReceiveMessage", "sqs:DeleteMessage", "sqs:GetQueueAttributes"]
Resource = [var.sqs_queue_arn]
}
]
})
}
4-6. ENI Trunking — Task密度向上
ENI Trunkingは、Fargateホストに対して「トランクENI」を1本割り当て、その上に複数の「ブランチENI」を束ねる技術。これにより1ホストあたりのTask実行数が大幅に増加する。
- 通常モード: インスタンスタイプごとに上限あり (例: m5.xlarge → 最大15 ENI)
- ENI Trunkingモード: 同インスタンスで最大120 Taskまで実行可能 (aws-vpc-cni設定で制御)
# ENI Trunking 有効化 (ECS Cluster Account Setting)
aws ecs put-account-setting \
--name awsvpcTrunking \
--value enabled \
--region ap-northeast-1
# 確認
aws ecs list-account-settings \
--name awsvpcTrunking \
--effective-settings \
--region ap-northeast-1
4-7. Cold Start特性とPre-warming戦略
Fargateの起動レイテンシは15〜30秒が標準的で、コンテナイメージサイズと初期化処理に依存する。
Cold Start短縮テクニック
# 効果的なDockerfile最適化
# ① マルチステージビルドで最終イメージを最小化
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o main ./cmd/app
FROM alpine:3.19# 最終イメージは alpine のみ
RUN apk add --no-cache ca-certificates
COPY --from=builder /app/main /usr/local/bin/main
ENTRYPOINT ["main"]
Provisioned Capacity (Reserved Concurrency相当)
バーストトラフィックに備えるProvisioned Capacityは、EventBridge Schedulerと組み合わせてピーク前に事前スケールアウトする戦略が有効。
# eventbridge-prewarm.tf (Scheduled Scale-out)
resource "aws_scheduler_schedule" "prewarm" {
name = "fargate-prewarm"
group_name = "default"
flexible_time_window {
mode = "OFF"
}
schedule_expression = "cron(45 8 ? * MON-FRI *)" # 平日9時前にスケールアウト
target {
arn= "arn:aws:ecs:ap-northeast-1:${var.account_id}:cluster/production-cluster"
role_arn = aws_iam_role.scheduler.arn
ecs_parameters {
task_definition_arn = aws_ecs_task_definition.app.arn
launch_type= "FARGATE"
task_count = 5
network_configuration {
aws_vpc_configuration {
subnets = var.private_subnet_ids
security_groups = [aws_security_group.app.id]
assign_public_ip = "DISABLED"
}
}
}
}
}
4-8. Multi-Architecture — ARM Graviton選定基準
AWS Graviton3 (ARM64) はx86_64と比較して、Fargateコストを最大20%削減しながら同等以上の性能を発揮する。
| 項目 | x86_64 (Intel/AMD) | ARM64 (Graviton3) |
|---|---|---|
| Fargate vCPU単価 | $0.04048/vCPU時 | $0.03238/vCPU時 (20%安) |
| メモリ単価 | $0.004445/GB時 | $0.00356/GB時 (20%安) |
| 適合ワークロード | レガシー依存ライブラリ | 新規Goland/Python/Java/Node.js |
| コンテナイメージ | linux/amd64 | linux/arm64 必須 |
# Graviton(ARM64)選択
runtime_platform {
operating_system_family = "LINUX"
cpu_architecture = "ARM64"
}
ECRへのマルチアーキテクチャイメージプッシュにはDocker Buildxが必要:
# マルチアーキテクチャビルド
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/app:latest \
--push .
mermaid02: Fargate Task ENI割当 + VPC Lattice TargetGroup登録フロー
以下のシーケンス図は、ECS Serviceが新しいFargate Taskを起動してからVPC Lattice TargetGroupへのIP登録が完了するまでの内部フローを示す。
sequenceDiagram
autonumber
participant User as オペレーター / Auto Scaling
participant ECS as ECS Control Plane
participant Fargate as Fargate Runtime
participant ENI as VPC ENI (AWS Hyperplane)
participant CM as CloudMap (Service Connect)
participant Lattice as VPC Lattice TargetGroup
participant CW as CloudWatch Container Insights
User->>ECS: UpdateService (desiredCount++)
ECS->>Fargate: Task起動要求 (TaskDefinition ARN)
Fargate->>ENI: ENI動的プロビジョニング要求
ENI-->>Fargate: ENI割当完了 (Private IP: 10.0.x.y)
Fargate->>Fargate: コンテナイメージPull (ECR)
Fargate->>Fargate: コンテナ起動 / HealthCheck開始
alt Service Connect有効
Fargate->>CM: ServiceDiscovery登録 (DNS: app-backend.production.local → 10.0.x.y:80)
CM-->>Fargate: 登録完了
end
alt VPC Lattice IP Target有効
Fargate->>Lattice: TargetGroup IP登録 (10.0.x.y:8080)
Lattice->>Lattice: HealthCheck実行 (GET /health)
Lattice-->>Fargate: HealthCheck HEALTHY
end
Fargate->>CW: Container Insightsメトリクス送信開始
CW-->>ECS: Task稼働確認 (RunningTaskCount++)
Note over ECS,Lattice: Task終了時はENI解放 + CloudMap/TargetGroup自動登録削除
- Task Role/Execution Role混同: Execution Roleにアプリ権限を追加しがちだが、アプリの認証は必ずTask Roleで行う。混同すると最小権限原則が崩壊する
- awsvpcモード必須: Fargate + VPC Lattice構成でhostやbridgeネットワークモードを指定するとENIが割り当てられずIP登録が不可能になる
- Service Connect + VPC Lattice二重設定: 同一Serviceに両方を設定すると通信経路が二重になりレイテンシが増加する。役割を明確に分離すること
- Cold Start無視のDesiredCount=0設定: Traffic spike時に15〜30秒の起動遅延でタイムアウトが発生する。最低1Task常時起動 + Auto Scalingが基本
- ARM64イメージ未対応: Gravitonを選択してx86_64イメージをデプロイするとTaskが即終了する。必ずlinux/arm64またはマルチアーキイメージを使用する
5. 3層統合本番運用 — Event Pattern × Auth Policy × Distributed Trace × Multi-Account設計

EventBridge × VPC Lattice × Fargate の3層統合は、個々のサービスを組み合わせるだけでなく、イベント駆動型のサービスメッシュとして機能させることが本番運用の核心である。本セクションでは、Event Pattern設計からIAM権限統合、Multi-Account展開、分散トレース3層接続、Cost Allocation、Auto Scaling、障害時Failoverまでを体系的に解説する。
- 原則1: IAM Auth Policy + IRSA は同一Roleで統一 (二重認証回避)
- 原則2: Multi-Account共有は Organizations OU + RAM経由 (個別Account許可禁止)
- 原則3: X-Ray Trace 3層 (EventBridge → Lattice → Fargate) を必ず接続
- 原則4: Auto Scaling は Fargate Service Auto Scaling + EventBridge Schedule で予測+反応両立
- 原則5: DLQ + Retry + Circuit Breaker の3点セットで障害耐性確保
5-1. 3層統合パターン全体フロー
3層統合の全体像は「EventBridge がイベントを捕捉・ルーティング → VPC Lattice が認証済みの内部HTTP通信を仲介 → Fargate Task が実際の処理を実行」という流れになる。
Producer (AWS Service/Custom Source)
│ PutEvents (JSON Event)
▼
EventBridge Custom EventBus
│ Rule: Event Pattern Match (source + detail-type)
│ Target: HTTP API (VPC Lattice Service URL)
▼
VPC Lattice Service Network
│ Listener (HTTPS:443) → Listener Rule (Path/Header Match)
│ Auth Policy: IAM SigV4 認証 (Fargate Task IRSA Role)
▼
VPC Lattice Target Group (IP type)
│ Target: Fargate Task ENI IP:Port
▼
Fargate Task (ECS Service / awsvpc Network Mode)
│ 処理実行 → CloudWatch Logs / X-Ray Trace
▼
Response (同期: HTTP Response / 非同期: SQS DLQ)
EventBridge Rule の Event Pattern は source と detail-type を厳密に指定する。ワイルドカード放置はセキュリティリスクと誤発火の温床になるため、本番では以下のような明示的なパターンを使用する。
{
"source": ["com.myapp.orders"],
"detail-type": ["OrderCreated"],
"detail": {
"status": ["PENDING"],
"amount": [{ "numeric": [">", 1000] }]
}
}
detail 内のフィルタリングも活用することで、Fargate側の余分な処理を排除できる。EventBridge Rule Test機能を使ってパターン検証を事前に実施することが必須となる。
VPC Lattice への HTTP連携では、EventBridge Rule の Target に HTTP endpoint を指定し、Input Transformer でHTTPリクエストボディを整形する。
{
"inputTemplate": "{\"orderId\": \"<orderId>\", \"amount\": <amount>, \"userId\": \"<userId>\"}",
"inputPathsMap": {
"orderId": "$.detail.orderId",
"amount": "$.detail.amount",
"userId": "$.detail.userId"
}
}
5-2. IAM Auth Policy + IRSA 統合権限設計
VPC Lattice の Auth Policy と ECS Fargate の IRSA(IAM Roles for Service Accounts)を同一IAM Roleで統合することが、二重認証回避の要点である。
統合IAM Role設計
# Fargate Task Role (IRSA + Lattice Auth Policy 統合)
resource "aws_iam_role" "fargate_task_role" {
name = "fargate-task-lattice-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = { Service = "ecs-tasks.amazonaws.com" }
Action = "sts:AssumeRole"
Condition = {
StringEquals = {
"aws:SourceAccount" = var.account_id
}
}
}
]
})
}
resource "aws_iam_role_policy" "fargate_task_policy" {
name = "fargate-task-lattice-policy"
role = aws_iam_role.fargate_task_role.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect= "Allow"
Action= ["vpc-lattice-svcs:Invoke"]
Resource = "arn:aws:vpc-lattice:${var.region}:${var.account_id}:service/${var.lattice_service_id}/*"
},
{
Effect= "Allow"
Action= [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"xray:PutTraceSegments",
"xray:PutTelemetryRecords",
"xray:GetSamplingRules",
"xray:GetSamplingTargets"
]
Resource = "*"
}
]
})
}
VPC Lattice Auth Policy
Auth Policy は Fargate Task Role ARN を Principal に指定する。Organizations OU を使ったグループ単位での許可が推奨されるが、単一Account構成では Account + Role ARN で最小権限を実現する。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_ID:role/fargate-task-lattice-role"
},
"Action": "vpc-lattice-svcs:Invoke",
"Resource": "*",
"Condition": {
"StringEquals": {
"vpc-lattice:RequestMethod": ["GET", "POST"],
"vpc-lattice:SourceVpc": "vpc-xxxxxxxx"
}
}
}
]
}
vpc-lattice:RequestMethod や vpc-lattice:SourceVpc の条件キーを組み合わせることで、Lattice経由のみ・特定VPCからのみのアクセスに絞り込める。
- ✅ Fargate Task Role と Lattice Auth Policy Principal を同一ARNに統一
- ✅
vpc-lattice:SourceVpc条件でVPC外アクセスを遮断 - ✅
vpc-lattice-svcs:InvokeResource を特定Lattice ServiceのARNに絞り込み - ✅
ecs:tasks.amazonaws.comの Assume Role Condition にaws:SourceAccount追加 - ✅ IAM Policy Simulator で権限検証後にデプロイ
5-3. Multi-Account本番設計 — Organizations OU + RAM共有 + Cross-Account EventBridge
本番環境では複数AWSアカウントにまたがる3層統合が求められる。Organizations OU と RAM(Resource Access Manager)を組み合わせることで、Account単位の個別許可ではなくOU単位のグループ管理を実現する。
Account役割分担
Organizations Root
├── Production OU
│├── Producer Account (EventBridge Custom EventBus + Rule)
│├── Hub Account (VPC Lattice Service Network + RAM Share)
│└── Consumer Account (Fargate Service + Target Group登録)
└── Shared Services OU
├── ECR Account (Pull-Through Cache + KMS Key)
└── Logging Account (CloudWatch Logs Cross-Account / X-Ray)
RAM共有 (Hub Account → Consumer Account)
resource "aws_ram_resource_share" "lattice_network_share" {
name = "lattice-service-network-share"
allow_external_principals = false
tags = {
Environment = "production"
}
}
resource "aws_ram_resource_association" "lattice_network" {
resource_arn = aws_vpclattice_service_network.main.arn
resource_share_arn = aws_ram_resource_share.lattice_network_share.arn
}
resource "aws_ram_principal_association" "ou_principal" {
principal = "arn:aws:organizations::ROOT_ACCOUNT_ID:ou/o-xxxxxxxxxx/ou-xxxx-xxxxxxxx"
resource_share_arn = aws_ram_resource_share.lattice_network_share.arn
}
RAM共有の principal には個別Account ARNではなく Organizations OU ARN を指定する。OU ARN形式は arn:aws:organizations::ROOT_ACCOUNT_ID:ou/o-xxx/ou-yyy である。
Cross-Account EventBridge (Producer → Hub)
Producer AccountのEventBridge RuleからHub AccountのEventBusへクロスアカウント転送する。
# Hub Account: EventBus Policy (Producer Accountからの受信許可)
resource "aws_cloudwatch_event_bus_policy" "cross_account_policy" {
event_bus_name = aws_cloudwatch_event_bus.hub.name
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AllowProducerAccountEvents"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::PRODUCER_ACCOUNT_ID:root"
}
Action= "events:PutEvents"
Resource = aws_cloudwatch_event_bus.hub.arn
Condition = {
StringEquals = {
"aws:PrincipalOrgID" = "o-xxxxxxxxxx"
}
}
}
]
})
}
# Producer Account: Rule Target = Hub Account EventBus
resource "aws_cloudwatch_event_rule" "cross_account_rule" {
name = "forward-to-hub-account"
event_bus_name = "default"
event_pattern = jsonencode({
source= ["com.myapp.orders"]
detail-type = ["OrderCreated"]
})
}
resource "aws_cloudwatch_event_target" "hub_event_bus" {
rule = aws_cloudwatch_event_rule.cross_account_rule.name
arn= "arn:aws:events:ap-northeast-1:HUB_ACCOUNT_ID:event-bus/hub-event-bus"
role_arn = aws_iam_role.event_bridge_cross_account_role.arn
}
Condition に aws:PrincipalOrgID を追加することで、Organizations外のアカウントからの不正なPutEventsを防ぐ。
ECR Pull-Through Cache + KMS Replica Key
Consumer AccountがHub Account管理のECRイメージを使用する場合、Pull-Through Cacheを経由する。
# ECR Account: KMS Key (Multi-Region Key)
resource "aws_kms_key" "ecr_encryption_key" {
description = "ECR image encryption key"
multi_region= true
enable_key_rotation = true
deletion_window_in_days = 30
}
# Consumer Account: KMS Replica Key
resource "aws_kms_replica_key" "ecr_replica" {
description = "Replica key for ECR images"
primary_key_arn= "arn:aws:kms:us-east-1:ECR_ACCOUNT_ID:key/KEY_ID"
deletion_window_in_days = 30
}
# Consumer Account: ECR Pull-Through Cache Rule
resource "aws_ecr_pull_through_cache_rule" "hub_ecr" {
ecr_repository_prefix = "hub-cache"
upstream_registry_url = "ECR_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com"
credential_arn = aws_secretsmanager_secret.ecr_credentials.arn
}
5-4. Distributed Trace 3層統合 — X-Ray + ADOT Collector
3層間のTrace IDを途切れさせないことが、本番障害の根本原因特定を可能にする。EventBridge → VPC Lattice → Fargate の全層でX-Ray Trace IDを伝播させる。
ADOT Collector設定 (Fargate Sidecar)
# adot-config.yaml (ECS Task Definition でMountしてsidecar起動)
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
awsxray:
endpoint: 0.0.0.0:2000
transport: udp
processors:
batch:
timeout: 1s
send_batch_size: 50
resourcedetection:
detectors: [env, ecs, ec2]
timeout: 2s
exporters:
awsxray:
region: ap-northeast-1
indexed_attributes:
- aws.ecs.task.family
- http.method
- http.status_code
service:
pipelines:
traces:
receivers: [otlp, awsxray]
processors: [batch, resourcedetection]
exporters: [awsxray]
Trace ID伝播設定 (HTTP Header)
EventBridge → VPC Lattice → Fargate 間でTrace IDを伝播するため、X-Amzn-Trace-Id ヘッダーを各層で引き継ぐ。
import boto3
import requests
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch_all
patch_all() # boto3, requests を自動インストルメント
def invoke_lattice_service(lattice_url: str, payload: dict, trace_id: str):
headers = {
"Content-Type": "application/json",
"X-Amzn-Trace-Id": trace_id, # Trace ID を次層へ伝播
}
with xray_recorder.in_segment("fargate-to-lattice-call"):
xray_recorder.current_segment().put_annotation("lattice_url", lattice_url)
response = requests.post(lattice_url, json=payload, headers=headers)
xray_recorder.current_segment().put_metadata("response_status", response.status_code)
return response
ECS Task Definition (ADOT Sidecar統合)
{
"family": "order-processor",
"networkMode": "awsvpc",
"containerDefinitions": [
{
"name": "app",
"image": "ECR_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/hub-cache/order-processor:latest",
"environment": [
{ "name": "AWS_XRAY_DAEMON_ADDRESS", "value": "127.0.0.1:2000" },
{ "name": "OTEL_EXPORTER_OTLP_ENDPOINT", "value": "http://127.0.0.1:4317" }
],
"dependsOn": [{ "containerName": "adot-collector", "condition": "START" }]
},
{
"name": "adot-collector",
"image": "public.ecr.aws/aws-observability/aws-otel-collector:latest",
"command": ["--config=/etc/ecs/ecs-xray.yaml"],
"portMappings": [
{ "containerPort": 4317, "protocol": "tcp" },
{ "containerPort": 2000, "protocol": "udp" }
]
}
]
}
CloudWatch ServiceLens でService Mapを確認する際、EventBridge Span・Lattice Span・Fargate Spanが1本のTraceとして連結されていることを検証する。断絶が発生している場合はADOT Collectorのログ (/aws/ecs/adot-collector) でSpan Contextの伝播エラーを確認する。
- ① CloudWatch → ServiceLens → Service Map で3ノード (EventBridge/Lattice/Fargate) が連結表示されることを確認
- ② X-Ray → Traces → Filter:
annotation.aws.ecs.task.family = "order-processor"でFargate起点のTraceを絞り込み - ③ Trace Detail で EventBridge Segment → Lattice Segment → Fargate Segment の親子関係を確認
- ④ 断絶時: ADOT Collector の CloudWatch Logs で
SpanContextエラーを検索 - ⑤ Header伝播漏れ: EventBridge → Lattice の HTTP Target設定で
X-Amzn-Trace-Idヘッダーが含まれているかInput Transformerを確認
5-5. Cost Allocation — 3層統合のコスト構造
EventBridge × VPC Lattice × Fargate の3層統合ではコスト構造が複雑になる。各サービスの課金単位を把握し、Cost Allocation Tagで按分する。
課金単位一覧
EventBridge:
- Custom EventBus: $1.00 / 1M events (PUT)
- EventBridge Pipes: $0.40 / 1M events (処理)
- Scheduler: $1.00 / 1M invocations (スケジュール実行)
※ Default EventBus経由は無料
VPC Lattice:
- Service-hour: $0.025 / hour / Service (1 Service = 約 $18/month)
- Lattice Data Processing: $0.025 / GB (送受信合計)
※ Service Network自体に課金なし
Fargate:
- vCPU: $0.04048 / vCPU-hour (ap-northeast-1)
- Memory: $0.004445 / GB-hour (ap-northeast-1)
- Ephemeral Storage: $0.000111 / GB-hour (20GiB超過分)
Cost Allocation Tagによる按分
# 3層統合のリソースに共通タグを付与
locals {
common_tags = {
Project = "order-processing"
Layer = "event-driven-mesh"
CostCenter = "backend-platform"
Environment = "production"
}
}
resource "aws_cloudwatch_event_bus" "main" {
name = "order-event-bus"
tags = merge(local.common_tags, { Component = "eventbridge" })
}
resource "aws_vpclattice_service" "order_service" {
name = "order-service"
tags = merge(local.common_tags, { Component = "lattice" })
}
resource "aws_ecs_service" "order_processor" {
name= "order-processor"
cluster= aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.order_processor.arn
tags= merge(local.common_tags, { Component = "fargate" })
}
AWS Cost Explorer の「Group by: Tag」でComponent別コストを可視化し、3層ごとの按分を月次レポートに組み込む。
5-6. Auto Scaling統合 — 予測×反応の2軸設計
Fargate の Auto Scaling は「EventBridge Schedule による予測スケール」と「Target Tracking による反応スケール」の2軸を組み合わせる。
Application Auto Scaling (Target Tracking)
resource "aws_appautoscaling_target" "fargate_target" {
max_capacity = 20
min_capacity = 2
resource_id = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.order_processor.name}"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
}
# CPU使用率 70% でスケールアウト
resource "aws_appautoscaling_policy" "cpu_tracking" {
name= "cpu-target-tracking"
policy_type = "TargetTrackingScaling"
resource_id = aws_appautoscaling_target.fargate_target.resource_id
scalable_dimension = aws_appautoscaling_target.fargate_target.scalable_dimension
service_namespace = aws_appautoscaling_target.fargate_target.service_namespace
target_tracking_scaling_policy_configuration {
predefined_metric_specification {
predefined_metric_type = "ECSServiceAverageCPUUtilization"
}
target_value = 70.0
scale_in_cooldown = 300
scale_out_cooldown = 60
}
}
EventBridge Scheduler による予測スケール
ピーク時間帯(例: 平日9-18時)に事前にスケールアウトし、Cold Start遅延を排除する。
resource "aws_scheduler_schedule" "scale_out_morning" {
name = "order-processor-scale-out-morning"
group_name = "fargate-scaling"
flexible_time_window { mode = "OFF" }
schedule_expression = "cron(0 8 ? * MON-FRI *)"
schedule_expression_timezone = "Asia/Tokyo"
target {
arn= "arn:aws:scheduler:::aws-sdk:applicationautoscaling:registerScalableTarget"
role_arn = aws_iam_role.scheduler_role.arn
input = jsonencode({
ServiceNamespace = "ecs"
ResourceId = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.order_processor.name}"
ScalableDimension = "ecs:service:DesiredCount"
MinCapacity = 5
MaxCapacity = 20
})
}
}
resource "aws_scheduler_schedule" "scale_in_night" {
name = "order-processor-scale-in-night"
group_name = "fargate-scaling"
flexible_time_window { mode = "OFF" }
schedule_expression = "cron(0 20 ? * MON-FRI *)"
schedule_expression_timezone = "Asia/Tokyo"
target {
arn= "arn:aws:scheduler:::aws-sdk:applicationautoscaling:registerScalableTarget"
role_arn = aws_iam_role.scheduler_role.arn
input = jsonencode({
ServiceNamespace = "ecs"
ResourceId = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.order_processor.name}"
ScalableDimension = "ecs:service:DesiredCount"
MinCapacity = 2
MaxCapacity = 20
})
}
}
5-7. Service Mesh代替パターン — App Mesh廃止 → VPC Lattice移行
AWS App Mesh は2025年9月に廃止(新規作成停止)となり、VPC Lattice が後継のService Mesh代替として位置づけられている。
App Mesh → VPC Lattice 移行判断マトリクス
App Mesh (廃止済み) VPC Lattice (推奨)
─────────────────────────────────────────────────
Envoy Proxy必須Proxy不要 (AWSマネージド)
EKS/ECS両対応 ECS/Lambda/EC2対応 (EKS=VPC CNI経由)
mTLS必須設定IAM Auth Policy (SigV4) 標準
Virtual Service/Node抽象Service/Listener/Target Group
Cross-Account: 複雑RAM共有でシンプル
コスト: Proxy分の追加 Service-hour $0.025/h + Data
App Meshからの移行では、Virtual ServiceをVPC Lattice Serviceに、Virtual NodeをTarget Groupに対応付ける。
Service Connect との使い分け
同一ECSクラスタ内の East-West通信は ECS Service Connect が適切で、クラスタ・Account間にまたがる通信は VPC Lattice を選択する。
ECS Service Connect: 同一クラスタ内 Microservice間 (低レイテンシ・プロキシ自動管理)
VPC Lattice:Cross-Cluster / Cross-Account / Lambda連携 (IAM Auth必須の外部公開)
ALB Internal: VPC内 HTTP負荷分散 (Lattice不要な単純ルーティング)
5-8. 障害時Failover — DLQ + Retry + Circuit Breaker
- DLQ (Dead Letter Queue): EventBridge Pipes / Rule で処理失敗したイベントをSQS DLQへ退避。RetryAttempts=3 / MaximumRecordAge=86400秒
- Retry with Backoff: EventBridge Rule の RetryPolicy で exponential backoff + jitter を適用。最大24時間リトライ
- Circuit Breaker: Fargate Task側でAWS SDK Retry設定 + CloudWatch Alarm → EventBridge Rule でサーキットブレーカー状態遷移を管理
- Lattice Health Check: Target GroupのHealth Check周期を30秒以内に設定。異常Target自動除外で可用性を維持
- EventBridge Replay: 障害期間中のイベントを Archive + Replay機能で再処理。最長90日保持
DLQ + Retry設定 (Terraform)
resource "aws_sqs_queue" "order_dlq" {
name = "order-events-dlq"
message_retention_seconds = 1209600 # 14日
kms_master_key_id= aws_kms_key.sqs_key.key_id
tags = {
Component = "dlq"
Layer = "eventbridge"
}
}
resource "aws_cloudwatch_event_target" "lattice_target" {
rule = aws_cloudwatch_event_rule.order_rule.name
arn = var.lattice_service_url
retry_policy {
maximum_event_age_in_seconds = 86400 # 24時間
maximum_retry_attempts = 3
}
dead_letter_config {
arn = aws_sqs_queue.order_dlq.arn
}
}
Circuit Breaker Pattern (CloudWatch Alarm + EventBridge)
# Fargate Task エラー率 20% 超でCircuit OPEN
resource "aws_cloudwatch_metric_alarm" "task_error_rate" {
alarm_name = "fargate-task-error-rate-high"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 2
metric_name= "5XXError"
namespace = "AWS/ApplicationELB"
period = 60
statistic = "Average"
threshold = 20
alarm_actions = [aws_sns_topic.ops_alerts.arn]
dimensions = {
TargetGroup = aws_lb_target_group.fargate_tg.arn_suffix
LoadBalancer = aws_lb.internal_alb.arn_suffix
}
}
# Circuit OPEN時: EventBridge Ruleを一時無効化
resource "aws_cloudwatch_event_rule" "circuit_breaker_open" {
name = "circuit-breaker-open"
description = "Disable order rule when Fargate error rate is high"
event_pattern = jsonencode({
source= ["aws.cloudwatch"]
detail-type = ["CloudWatch Alarm State Change"]
detail = {
alarmName = ["fargate-task-error-rate-high"]
state = { value = ["ALARM"] }
}
})
}
resource "aws_cloudwatch_event_target" "disable_order_rule" {
rule = aws_cloudwatch_event_rule.circuit_breaker_open.name
arn = "arn:aws:events:${var.region}:${var.account_id}:rule/${aws_cloudwatch_event_rule.order_rule.name}"
input = jsonencode({ State = "DISABLED" })
}
EventBridge Archive + Replay設定
resource "aws_cloudwatch_event_archive" "order_archive" {
name = "order-events-archive"
event_source_arn = aws_cloudwatch_event_bus.main.arn
retention_days= 90
event_pattern = jsonencode({
source = ["com.myapp.orders"]
})
}
障害復旧後のReplayはAWS CLIまたはコンソールから実行する。
aws events start-replay \
--replay-name "order-events-replay-2026-01-15" \
--source-arn "arn:aws:events:ap-northeast-1:ACCOUNT_ID:archive/order-events-archive" \
--event-start-time "2026-01-15T00:00:00Z" \
--event-end-time "2026-01-15T06:00:00Z" \
--destination '{"Arn": "arn:aws:events:ap-northeast-1:ACCOUNT_ID:event-bus/order-event-bus"}'
Replayは本番EventBusに向けて実行するため、Fargate側で冪等性(Idempotency)の確保(処理済みイベントのDynamoDB記録)が前提となる。
6. 詰まりポイント7選 — 3層統合本番運用の地雷とフィックス
詰まり①: EventBridge Rule Event Pattern マッチ失敗
原因: Event Pattern の source や detail-type フィールドに誤りがあると、EventBridge Rule はサイレントにスキップする。CloudWatch Logs に "matchedRuleCount": 0 が記録される。末尾の s 抜けや大文字・小文字の相違など、1 文字の誤字でマッチが全件ゼロになる。
CloudWatch Logs エラー例:
{
"version": "0",
"id": "abc-123",
"source": "com.myapp.orders",
"detail-type": "OrderCreated",
"detail": { "orderId": "ORD-001" }
}
Rule Pattern で "source": ["com.myapp.order"] (末尾 s 抜け) → マッチ 0 件。
診断手順:
# EventBridge Rule の Event Pattern 確認
aws events describe-rule \
--name my-rule \
--event-bus-name my-event-bus \
--query 'EventPattern'
# Event Pattern テスト (source/detail-type が一致するか即時検証)
aws events test-event-pattern \
--event-pattern '{"source":["com.myapp.orders"]}' \
--event '{"source":"com.myapp.orders","detail-type":"OrderCreated","detail":{}}'
フィックス (Terraform):
resource "aws_cloudwatch_event_rule" "order_rule" {
name = "order-rule"
event_bus_name = aws_cloudwatch_event_bus.main.name
event_pattern = jsonencode({
source= ["com.myapp.orders"] # 厳密一致・末尾 s まで含める
detail-type = ["OrderCreated"]# 大文字小文字を区別
})
}
再発防止: aws events test-event-pattern を CI/CD パイプラインに組み込み、Rule デプロイ前に自動検証する。EventBridge Schema Registry で Event Schema を登録し、型安全な Event 生成を強制することで送信側の誤字を根絶する。
詰まり②: VPC Lattice TargetGroup Type 違いで Fargate Task 登録不可
原因: VPC Lattice TargetGroup の type が INSTANCE の場合、Fargate (awsvpc ネットワークモード) のタスク IP を直接登録できない。Fargate は ENI に IP が割り当てられるため IP type が必須。この組み合わせを間違えると ECS Service の起動時に InvalidParameterException が発生し、タスクが一切登録されない。
エラーメッセージ:
InvalidParameterException: The target type 'instance' does not support
targets with VPC networking mode 'awsvpc'. Use target type 'ip'.
診断手順:
# TargetGroup の type 確認
aws vpc-lattice list-target-groups \
--query 'items[?name==`my-tg`].{type:type,status:status}'
# 登録済みターゲット確認 (空なら登録失敗)
aws vpc-lattice list-targets \
--target-group-identifier my-tg-id
フィックス (Terraform):
resource "aws_vpclattice_target_group" "fargate_tg" {
name = "fargate-tg"
type = "IP" # Fargate awsvpc モードには IP type 必須
config {
port= 8080
protocol = "HTTP"
vpc_identifier = aws_vpc.main.id
ip_address_type = "IPV4"
health_check {
enabled = true
path = "/health"
protocol= "HTTP"
healthy_threshold= 3
unhealthy_threshold = 3
interval_seconds = 30
}
}
}
再発防止: Fargate サービスを VPC Lattice に登録する場合、ECS Task Definition の network_mode = "awsvpc" と Lattice TargetGroup type = "IP" のセットを Terraform module で強制し、INSTANCE type を variable validation でエラーにする。
詰まり③: EventBridge Pipes Source=DynamoDB Streams で DLQ 未設定によるイベント消失
原因: DLQ 未設定の EventBridge Pipes は処理失敗イベントを DROP する。MaximumRetryAttempts のデフォルト値はゼロ(リトライなし)のため、Fargate タスクが一時的に起動不能になっている間のストリームレコードが全件消失する。DynamoDB Streams の Shard Iterator が先に進んでしまうと復旧不可能。
CloudWatch Metrics シグナル:
EventBridgePipes/ExecutionFailed: Count > 0
DynamoDB/SystemErrors:Count > 0
SQS/ApproximateNumberOfMessagesVisible (DLQ): Count = 0 ← DLQ が空 → DROP されている
診断手順:
# Pipe の DLQ 設定を確認
aws pipes describe-pipe \
--name my-pipe \
--query 'Pipe.SourceParameters.DynamoDBStreamParameters.DeadLetterConfig'
# 失敗ログを確認
aws logs filter-log-events \
--log-group-name /aws/pipes/my-pipe \
--filter-pattern '"status":"FAILED"' \
--limit 20
フィックス (Terraform):
resource "aws_sqs_queue" "pipe_dlq" {
name = "fargate-pipe-dlq"
message_retention_seconds = 1209600 # 14 日間保持
}
resource "aws_pipes_pipe" "ddb_to_fargate" {
name = "ddb-to-fargate-pipe"
role_arn = aws_iam_role.pipe_role.arn
source= aws_dynamodb_table.events.stream_arn
target= aws_ecs_cluster.main.arn
source_parameters {
dynamodb_stream_parameters {
starting_position = "LATEST"
maximum_retry_attempts = 3# 最大 3 回リトライ後 DLQ へ
maximum_record_age_in_seconds = 86400 # 24 時間超の古いレコードは SKIP
dead_letter_config {
arn = aws_sqs_queue.pipe_dlq.arn # 必須
}
}
}
}
再発防止: DLQ SQS への CloudWatch アラーム (ApproximateNumberOfMessagesVisible ≥ 1) を設定し、イベント消失を即座に検知する。Pipe の Terraform module に DLQ を必須パラメータとして組み込む。
詰まり④: Auth Policy IAM + IRSA 権限重複で認証失敗 (403 Unauthorized)
原因: VPC Lattice Auth Policy で設定した Principal IAM Role と、ECS タスクが実際に使う Task Role が異なる場合、Lattice は呼び出し元の Assumed Role ARN が Auth Policy に含まれないと判断して 403 Unauthorized を返す。Task Execution Role と Task Role を混同するケースが最多。
エラーメッセージ (CloudWatch Logs):
{
"httpStatusCode": 403,
"message": "User: arn:aws:sts::123456789012:assumed-role/task-role/task-id
is not authorized to perform: vpc-lattice-svcs:Invoke
on resource: arn:aws:vpc-lattice:ap-northeast-1:..."
}
診断手順:
# ECS Task が使っている実際の Role ARN を確認
aws ecs describe-tasks \
--cluster my-cluster \
--tasks task-id-xxx \
--query 'tasks[0].overrides.taskRoleArn'
# Lattice Auth Policy の Principal と照合
aws vpc-lattice get-auth-policy \
--resource-identifier my-service-id
# IAM Policy Simulator で vpc-lattice-svcs:Invoke を検証
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:role/ecs-task-role \
--action-names vpc-lattice-svcs:Invoke \
--resource-arns arn:aws:vpc-lattice:ap-northeast-1:123456789012:service/svc-xxx
フィックス (Terraform):
# Task Role に Lattice Invoke 権限を付与
resource "aws_iam_role_policy" "task_lattice_invoke" {
name = "lattice-invoke"
role = aws_iam_role.task_role.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect= "Allow"
Action= ["vpc-lattice-svcs:Invoke"]
Resource = [aws_vpclattice_service.backend.arn]
}]
})
}
# Lattice Auth Policy: 実際の Task Role ARN を Principal に設定
resource "aws_vpclattice_auth_policy" "service_auth" {
resource_identifier = aws_vpclattice_service.backend.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { AWS = aws_iam_role.task_role.arn }
Action = "vpc-lattice-svcs:Invoke"
Resource = "*"
}]
})
}
再発防止: Terraform module で Task Role ARN と Lattice Auth Policy Principal を同じ変数から生成し、不一致を構造的に防ぐ。デプロイ後は IAM Policy Simulator を CI/CD で自動実行して権限検証を必須化する。
詰まり⑤: X-Ray Trace 3層断絶 (ADOT Collector 設定漏れ)
原因: EventBridge → VPC Lattice → Fargate の Trace ID が各ステージで新規生成される。ADOT Collector サイドカーなしでは X-Amzn-Trace-Id ヘッダが Fargate 内で引き継がれず、X-Ray Service Map に 3 つの独立したノードが表示される。エンドツーエンドのレイテンシ分析が不可能になる。
X-Ray Service Map の異常シグナル:
– EventBridge / Lattice / Fargate がそれぞれ独立したサービスノードとして表示
– Connected edges がゼロ
– aws xray get-service-graph の Edges リストが空
診断手順:
# Trace の断絶を確認 (Trace ID が各ステージで異なる場合は断絶)
aws xray get-traces \
--filter-expression 'service("my-fargate-service")' \
--query 'Traces[0].Segments[*].Document' | jq '.[].trace_id'
# ADOT Collector のログ確認
aws logs filter-log-events \
--log-group-name /ecs/adot-collector \
--filter-pattern '"X-Amzn-Trace-Id"' \
--limit 10
フィックス (Terraform):
resource "aws_ecs_task_definition" "app_with_adot" {
family = "app-with-adot"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
task_role_arn= aws_iam_role.task_role.arn
container_definitions = jsonencode([
{
name = "app"
image = "my-app:latest"
environment = [
{ name = "AWS_XRAY_DAEMON_ADDRESS", value = "localhost:2000" },
{ name = "OTEL_PROPAGATORS", value = "xray,tracecontext" }
]
dependsOn = [{ containerName = "adot-collector", condition = "START" }]
},
{
name = "adot-collector"
image= "public.ecr.aws/aws-observability/aws-otel-collector:latest"
command = ["--config=/etc/ecs/otel-instance-metrics-config.yaml"]
portMappings = [
{ containerPort = 2000, protocol = "udp" },
{ containerPort = 4317, protocol = "tcp" }
]
}
])
}
再発防止: ADOT Collector サイドカーを Fargate Terraform module の必須コンポーネントとして組み込む。デプロイ後は X-Ray Service Map で 3 層の Connected edges を目視確認する手順を運用チェックリストに追加する。
詰まり⑥: Multi-Account RAM 共有で Allowed Principals に個別 Account ARN を指定
原因: AWS RAM で VPC Lattice Service Network を共有する際、個別 Account ARN を Allowed Principals に指定すると、Organizations に新規アカウントが追加されるたびに手動更新が必要になる。Organizations Unit (OU) ARN で一括管理しないと運用が破綻する。
エラーメッセージ:
ResourceShareInvitationArnNotFoundException: The specified resource share
invitation ARN does not exist or it has been deleted.
診断手順:
# RAM Resource Share の Principal を確認
aws ram list-principals \
--resource-share-arns arn:aws:ram:ap-northeast-1:123456789012:resource-share/xxx \
--query 'principals[*].{id:id,type:type,status:status}'
# Organizations の OU ARN を確認
aws organizations list-organizational-units-for-parent \
--parent-id r-xxxx \
--query 'OrganizationalUnits[*].{id:Id,name:Name,arn:Arn}'
フィックス (Terraform):
resource "aws_ram_resource_share" "lattice_share" {
name = "lattice-service-network-share"
allow_external_principals = false # 外部アカウント禁止
}
resource "aws_ram_principal_association" "ou_association" {
resource_share_arn = aws_ram_resource_share.lattice_share.arn
# OU ARN で一括管理 (個別 Account ARN の直接指定を禁止)
principal = "arn:aws:organizations::123456789012:ou/o-xxx/ou-xxx-yyyyzzzz"
}
再発防止: RAM Allowed Principals に Account ARN を直接指定することを Terraform validation ブロックまたは AWS Config ルールで禁止し、OU ARN のみを受け付ける設計を標準化する。
詰まり⑦: Fargate Cold Start 15-30 秒で SLA 違反
原因: EventBridge からトリガーされた Fargate タスクの起動に 15-30 秒かかり、SLA (例: 10 秒以内レスポンス) を達成できない。desired_count = 0 の状態からのコールドスタートや、ECR からのイメージプルが主な遅延要因となる。
CloudWatch Metrics シグナル:
ECS/RunningTaskCount: 0 → 突発 Spike (コールドスタート発生)
ALB/TargetResponseTime P99: 30 秒超
ECS/CPUUtilization:急激なピークスパイク
診断手順:
# ECS タスクの起動時間を分析
aws ecs describe-tasks \
--cluster my-cluster \
--tasks task-id-xxx \
--query 'tasks[0].{startedAt:startedAt,createdAt:createdAt,pullStartedAt:pullStartedAt}'
# EventBridge Scheduler による予測スケール設定を確認
aws scheduler list-schedules \
--query 'Schedules[?Target.Arn==`arn:aws:ecs:ap-northeast-1:123456789012:cluster/my-cluster`]'
フィックス (Terraform):
# ECS Service: 最小 2 タスク常時起動で Cold Start を排除
resource "aws_ecs_service" "app" {
name = "app"
cluster = aws_ecs_cluster.main.id
desired_count = 2 # 常時 2 タスク以上
capacity_provider_strategy {
capacity_provider = "FARGATE"
weight= 1
base = 2 # 最低保証タスク数
}
}
# EventBridge Scheduler: 業務ピーク前に予測スケール
resource "aws_scheduler_schedule" "pre_scale" {
name = "pre-scale-before-peak"
flexible_time_window { mode = "OFF" }
schedule_expression = "cron(50 8 * * ? *)" # 9:00 ピーク前の 8:50 に発動
target {
arn= "arn:aws:scheduler:::aws-sdk:ecs:updateService"
role_arn = aws_iam_role.scheduler_role.arn
input = jsonencode({
Cluster= aws_ecs_cluster.main.name
Service= aws_ecs_service.app.name
DesiredCount = 10 # ピーク時は 10 タスクに拡張
})
}
}
再発防止: Provisioned Capacity + EventBridge Scheduler 予測スケールをデフォルトアーキテクチャとして採用し、Cold Start リスクを設計時に排除する。SLA 要件がある場合は P99 レイテンシアラームを必須設定にする。
- EventBridge Rule 発火せず: CloudWatch Logs で
matchedRuleCountを確認 →aws events test-event-patternで Event Pattern を実機検証 → Schema Registry で型定義を追加 - Fargate TargetGroup 未登録:
aws vpc-lattice list-targetsで登録状態確認 → Task awsvpc + TargetGroup type=IP + Subnet Tag + Security Group の 4 点セットを再確認 - Auth Policy deny エラー: IAM Policy Simulator で
vpc-lattice-svcs:Invokeをシミュレート → Task Role と Lattice Auth Policy Principal の ARN 一致を確認 - X-Ray Service Map 断絶: ADOT Collector サイドカーログ確認 →
X-Amzn-Trace-Idヘッダ伝播を curl で手動テスト → ADOT Collector config を再適用
7. アンチパターン→正解パターン変換演習5問
- 各演習は「現場でよく見るアンチパターン」を起点に、正解パターンへの移行手順と Trade-off を解説します。
- Terraform 実装例はそのまま本番環境に適用可能な形式で提示します。
演習1: EventBridge Rule Event Pattern ワイルドカード放置 → 厳密化
問題設定: EventBridge Rule の Event Pattern に "source": [{"prefix": "com.myapp"}] を使用している。新たに追加された com.myapp.debug イベントも本番 Fargate を起動してしまい、コストが 3 倍に膨らんだ。デバッグ用イベントと本番用イベントを分離したいが、現状の prefix マッチでは区別できない。
何が問題か: prefix マッチは将来追加されるイベントソースを全て捕捉する。本番環境では許可ソースを厳密にリスト化しないと、予期しないイベントが Fargate タスクを起動してコストとセキュリティリスクを生む。
正解パターン (Terraform):
# アンチパターン: prefix マッチで全 com.myapp.* を許可
# event_pattern = jsonencode({ source = [{ prefix = "com.myapp" }] })
# 正解: 許可ソースを明示的にリスト化
resource "aws_cloudwatch_event_rule" "production_rule" {
name = "production-order-rule"
event_bus_name = aws_cloudwatch_event_bus.production.name
event_pattern = jsonencode({
source= ["com.myapp.orders", "com.myapp.payments"] # 許可リスト
detail-type = ["OrderCreated", "PaymentCompleted"]# イベント種別も制限
detail = {
environment = ["production"] # 本番イベントのみを捕捉
}
})
}
移行手順:
# Step1: 現在の Event Pattern から実際に発火しているイベントソースを集計
aws logs filter-log-events \
--log-group-name /aws/events/my-bus \
--filter-pattern '{ $.source = "com.myapp*" }' \
--limit 1000 | jq '.events[].message | fromjson | .source' | sort | uniq -c
# Step2: 許可リストを確定し Rule を更新
aws events put-rule \
--name production-order-rule \
--event-bus-name production-bus \
--event-pattern '{"source":["com.myapp.orders","com.myapp.payments"]}'
Trade-off: 厳密化により新規イベントソースを追加するたびに Rule の更新が必要になる。Schema Registry で Event Schema を事前登録し、CI/CD で Rule の許可リストを自動生成する運用が推奨される。
演習2: VPC Lattice TargetGroup INSTANCE type → IP type + awsvpc 移行
問題設定: EC2 ベースのアプリを Fargate に移行した際、既存の VPC Lattice TargetGroup (type=INSTANCE) をそのまま流用しようとした。Fargate タスクを登録しようとすると InvalidParameterException が発生し、サービス移行が止まっている。移行期限まで 2 日しかない状況で判断が迫られている。
何が問題か: type=INSTANCE TargetGroup は EC2 インスタンス ID でターゲットを管理する。Fargate の awsvpc ネットワークモードでは ENI に IP が割り当てられるため、IP ベースの登録が必要。INSTANCE type では物理的に Fargate タスクを登録できない。
正解パターン (Terraform):
# 既存 INSTANCE type を廃止し IP type を新規作成
resource "aws_vpclattice_target_group" "fargate_ip_tg" {
name = "fargate-ip-tg"
type = "IP" # Fargate awsvpc モードに必須
config {
port= 8080
protocol = "HTTP"
vpc_identifier = aws_vpc.main.id
ip_address_type = "IPV4"
health_check {
enabled = true
path = "/health"
protocol = "HTTP"
healthy_threshold_count = 3
unhealthy_threshold_count = 3
health_check_interval_seconds = 30
health_check_timeout_seconds = 5
}
}
}
# ECS Service: awsvpc + 新 TargetGroup に切り替え
resource "aws_ecs_service" "app" {
task_definition = aws_ecs_task_definition.app.arn
network_configuration {
subnets = aws_subnet.private[*].id
security_groups = [aws_security_group.app.id]
assign_public_ip = false
}
load_balancer {
target_group_arn = aws_vpclattice_target_group.fargate_ip_tg.arn
container_name= "app"
container_port= 8080
}
}
移行手順:
# Step1: 新 IP type TargetGroup を作成
# Step2: ECS Service をローリング更新 (無停止)
aws ecs update-service \
--cluster my-cluster \
--service my-service \
--task-definition my-task:NEW_REVISION
# Step3: 旧 INSTANCE type TG を削除
aws vpc-lattice delete-target-group \
--target-group-identifier old-instance-tg-id
Trade-off: IP type TargetGroup では ECS Service の rolling update 時にタスク IP が変わるたびに自動登録/解除される。Deregistration Delay を短くしすぎると接続中リクエストが切断されるため、30 秒以上の猶予を設けることが推奨される。
演習3: EventBridge Pipes DLQ 未設定 → DLQ + RetryAttempts 追加
問題設定: DynamoDB Streams をソースにした EventBridge Pipes で Fargate タスクを起動している。先週の障害でタスクが一時的に起動不能になり、その間の 500 件のストリームイベントが全て消失した。DynamoDB Streams の保持期間は 24 時間だったが、Pipes がリトライせず即時 DROP していた。イベントの消失に気づいたのは翌朝の業務開始時だった。
何が問題か: DLQ 未設定の Pipes は処理失敗イベントを MaximumRetryAttempts = 0 (デフォルト) でそのまま破棄する。DynamoDB Streams の Shard Iterator が先に進んでしまい、イベントは永久に失われる。
正解パターン (Terraform):
resource "aws_sqs_queue" "pipe_dlq" {
name = "fargate-pipe-dlq"
message_retention_seconds = 1209600 # 14 日間保持
visibility_timeout_seconds = 300
tags = { Purpose = "EventBridge-Pipe-DLQ" }
}
resource "aws_pipes_pipe" "ddb_to_fargate" {
name = "ddb-to-fargate-pipe"
role_arn = aws_iam_role.pipe_role.arn
source= aws_dynamodb_table.events.stream_arn
target= aws_ecs_cluster.main.arn
source_parameters {
dynamodb_stream_parameters {
starting_position = "LATEST"
maximum_retry_attempts = 3# 最大 3 回リトライ後 DLQ へ
maximum_record_age_in_seconds = 86400 # 24 時間超のレコードは SKIP
dead_letter_config {
arn = aws_sqs_queue.pipe_dlq.arn # 必須
}
}
}
}
# DLQ 監視アラーム
resource "aws_cloudwatch_metric_alarm" "pipe_dlq_alarm" {
alarm_name = "pipe-dlq-messages"
metric_name= "ApproximateNumberOfMessagesVisible"
namespace = "AWS/SQS"
statistic = "Maximum"
threshold = 1
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 1
period = 60
dimensions = { QueueName = aws_sqs_queue.pipe_dlq.name }
}
移行手順:
# Step1: DLQ SQS Queue を作成
# Step2: Pipe を無停止で更新 (DLQ 追加は設定変更のみ)
aws pipes update-pipe \
--name ddb-to-fargate-pipe \
--source-parameters '{
"DynamoDBStreamParameters": {
"MaximumRetryAttempts": 3,
"DeadLetterConfig": { "Arn": "arn:aws:sqs:ap-northeast-1:123456789012:fargate-pipe-dlq" }
}
}'
Trade-off: DLQ に積まれたメッセージの再処理 (Redrive) は手動または Lambda による自動化が必要。Redrive 時に Fargate タスクが二重起動する可能性があるため、タスク処理は冪等性を保証する設計が前提となる。
演習4: IAM Auth Policy + Task Role の別 Role 運用 → 同一 IAM Role 統合
問題設定: VPC Lattice Auth Policy で frontend-task-role を Principal に設定し、ECS Task Definition の taskRoleArn には ecs-task-execution-role を指定している。本番 Fargate タスクから Lattice サービスを呼び出すと一貫して 403 Unauthorized が発生する。ロールの権限を見直しても解決しない状況が続いている。
何が問題か: Lattice Auth Policy の Principal (frontend-task-role) と実際に Fargate タスクが Assume する IAM Role (ecs-task-execution-role) が異なる。Lattice は呼び出し元の Assumed Role ARN を検証するため、実際の Task Role が Auth Policy に登録されていないと拒否される。
正解パターン (Terraform):
# 統合 Task Role: Lattice Invoke 権限 + タスク実行権限を一本化
resource "aws_iam_role" "unified_task_role" {
name = "unified-fargate-task-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "ecs-tasks.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy" "lattice_invoke" {
name = "lattice-invoke"
role = aws_iam_role.unified_task_role.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect= "Allow"
Action= ["vpc-lattice-svcs:Invoke"]
Resource = [aws_vpclattice_service.backend.arn]
}]
})
}
# Lattice Auth Policy: 統合 Task Role を Principal に設定
resource "aws_vpclattice_auth_policy" "service_auth" {
resource_identifier = aws_vpclattice_service.backend.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { AWS = aws_iam_role.unified_task_role.arn }
Action = "vpc-lattice-svcs:Invoke"
Resource = "*"
}]
})
}
移行手順:
# Step1: IAM Policy Simulator で現状の権限ギャップを確認
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::123456789012:role/ecs-task-execution-role \
--action-names vpc-lattice-svcs:Invoke \
--resource-arns arn:aws:vpc-lattice:ap-northeast-1:123456789012:service/svc-xxx
# Step2: 新 Task Definition (統合 Role) でローリング更新
aws ecs update-service \
--cluster my-cluster \
--service my-service \
--task-definition my-task:NEW_REVISION
# Step3: 動作確認後に旧 Role を削除
Trade-off: Task Role に複数のサービス呼び出し権限を集約すると最小権限原則から外れる可能性がある。サービスごとに個別の Task Role を作成し Lattice Auth Policy に複数 Principal を登録する設計も有効だが、Role 数の増加で管理コストが上がる。
演習5: X-Ray Trace 3層断絶 → ADOT Collector で Trace ID 伝播
問題設定: EventBridge → VPC Lattice → Fargate の 3 層アーキテクチャを本番運用しているが、X-Ray Service Map を確認すると EventBridge / Lattice / Fargate がそれぞれ独立したサービスとして表示される。エンドツーエンドのレイテンシが把握できず、ボトルネック調査に毎回数時間かかっている。チームからは「どのステージで遅くなっているか分からない」という声が上がっている。
何が問題か: X-Ray の Trace ID 伝播には、各コンポーネントが X-Amzn-Trace-Id ヘッダを受け取り、アウトバウンドリクエストに同じヘッダを付与する必要がある。ADOT Collector サイドカーなしでは Fargate 内のリクエストで Trace ID が新規生成され、3 層の Span が断絶する。
正解パターン (Terraform):
resource "aws_ecs_task_definition" "app_with_adot" {
family = "app-with-adot"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
task_role_arn= aws_iam_role.task_role.arn
container_definitions = jsonencode([
{
name = "app"
image = "my-app:latest"
environment = [
{ name = "AWS_XRAY_DAEMON_ADDRESS", value = "localhost:2000" },
{ name = "OTEL_PROPAGATORS", value = "xray,tracecontext" }
]
dependsOn = [{ containerName = "adot-collector", condition = "START" }]
},
{
name = "adot-collector"
image= "public.ecr.aws/aws-observability/aws-otel-collector:latest"
command = ["--config=/etc/ecs/otel-instance-metrics-config.yaml"]
portMappings = [
{ containerPort = 2000, protocol = "udp" },
{ containerPort = 4317, protocol = "tcp" }
]
}
])
}
移行手順:
# Step1: Task Role に X-Ray 書き込み権限を追加
aws iam attach-role-policy \
--role-name my-task-role \
--policy-arn arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess
# Step2: ADOT Collector サイドカー追加後に ECS Service をローリング更新
# Step3: X-Ray Service Map で 3 層が Connected edges で接続されていることを確認
aws xray get-service-graph \
--start-time $(date -v -1H +%s) \
--end-time $(date +%s) \
--query 'Services[*].{name:Name,edgeCount:length(Edges)}'
Trade-off: ADOT Collector サイドカーは各 Fargate タスクに 128MB 以上のメモリを追加消費する。コスト制約がある場合は X-Ray SDK をアプリに直接組み込む軽量な選択肢もある。ただし ADOT Collector はメトリクスとトレースを統合管理できるため、可観測性プラットフォームとしての拡張性が高い。
8. まとめ + 隣接3シリーズ双方向リンク + 全クロスリンク
3層統合本番運用パターン 総括
本記事では EventBridge × VPC Lattice × Fargate の 3 層統合アーキテクチャを本番運用する際の核心技術を解説してきた。設計から詰まりポイントの解消、アンチパターンの修正まで一貫して習得できる構成とした。
本記事で習得した本番運用パターン:
- EventBridge 4本柱統合: Rule / EventBus / Pipes / Scheduler を組み合わせ、Fargate を Target としたイベント駆動 Microservice の基盤を構築する設計パターン
- VPC Lattice Service Mesh: Service Network → Service → Listener → Rule → TargetGroup の階層を IP type TargetGroup + Auth Policy IAM で本番グレードに構成するアーキテクチャ
- Fargate 本番デプロイ: awsvpc + Service Connect / Lattice 併用で Cross-Account Microservice を実現し、Provisioned Capacity + Scheduler 予測スケールで Cold Start を排除する手法
- 3層 Distributed Trace: ADOT Collector サイドカーで EventBridge → Lattice → Fargate の Trace ID を伝播し、X-Ray Service Map でエンドツーエンドの可視化を実現する構成
- Multi-Account 運用: Organizations RAM 共有 + OU ARN 指定で Lattice Service Network を複数アカウントに安全に展開し、Organizations の拡張に自動追随する仕組み
落とし穴チェックリスト10選 (3層統合横断)
- ✅ EventBridge Event Pattern:
aws events test-event-patternで全パターンを CI/CD で自動検証している - ✅ Lattice TargetGroup type: Fargate (awsvpc) に対して type=IP を使用し、type=INSTANCE を排除している
- ✅ Pipes DLQ: EventBridge Pipes の全 Source に DLQ SQS を設定し、CloudWatch アラームで監視している
- ✅ Auth Policy Principal: Lattice Auth Policy の Principal と ECS Task Role ARN が同一であることを IAM Policy Simulator で検証している
- ✅ ADOT Collector サイドカー: Fargate Task Definition に ADOT サイドカーを追加し、X-Ray Service Map で 3 層の Connected edges を確認している
- ✅ RAM Allowed Principals: Organizations OU ARN を使用し、個別 Account ARN の直接指定を禁止している
- ✅ Fargate Cold Start 対策: 最小 desired_count ≥ 2 + Provisioned Capacity で SLA 要件を保証している
- ✅ Security Group 最小権限: Fargate タスク ↔ Lattice TargetGroup 間の Ingress/Egress を最小権限で設定している
- ✅ DynamoDB Streams MaximumRecordAgeInSeconds: Pipes で DynamoDB Streams を使う場合、古すぎるレコードをスキップする閾値を設定している
- ✅ EventBridge Schema Registry: 全 Event Source のスキーマを Schema Registry に登録し、型安全な Event 生成を CI/CD で強制している
隣接3シリーズ連携 — 本記事の位置付け
本記事が扱う「3層統合本番運用」は、以下の 3 シリーズの応用編に位置する。各シリーズとの連携ポイントを理解することで、より大規模なアーキテクチャへの拡張が可能になる。
Serverless Vol2 との連携:
EventBridge × SQS × SNS × Kinesis のメッセージング基盤を習得してから本記事の EventBridge 4 本柱を学ぶと、Pipes の Source として SQS / Kinesis / DynamoDB Streams を選ぶ設計判断軸が明確になる。Serverless Vol2 はイベント駆動アーキテクチャの基礎として本記事の前提知識となる。
Network Vol2 との連携:
VPC Lattice の Cross-Account Service Mesh は Transit Gateway や PrivateLink と組み合わせて使う場面が多い。Multi-Account ネットワーク設計の全体像は Network Vol2 のマルチアカウント網編で解説しており、本記事の Multi-Account RAM 共有と合わせて習得することでエンタープライズ規模の設計が可能になる。
Container Vol1 + Vol2 (GitOps) との連携:
Fargate の awsvpc / ECR イメージ管理 / Service Connect の基礎は Container Vol1 で習得する。ArgoCD × Kustomize を用いた GitOps パイプラインで Fargate Task Definition を自動デプロイし、Lattice Service Mesh と統合する手法は Container Vol2 で詳解している。
- EventBridge Rule/EventBus/Pipes/Scheduler の4本柱を Fargate Target統合で本番運用
- VPC Lattice Service Network 階層 + IP type TargetGroup + Auth Policy で本番Service Mesh
- Fargate awsvpc + Service Connect/Lattice 併用で Cross-Account Microservice
- 3層 (EventBridge/Lattice/Fargate) Distributed Trace 統合 X-Ray Service Map
- Multi-Account Organizations + RAM共有で本番Cross-Account 3層統合
- IAM: Vol1 IAM ポリシー設計
- EKS: Vol1 クラスタ設計
- 復旧: 復旧運用編 Vol1
- AI Bedrock: Vol1 Bedrock Agents
- ML/AI Vol2: Vol2 Bedrock Embedding×RAG
- セキュリティ: Vol1 セキュリティ運用
- コスト: Vol1 Cost Optimization
- マルチアカウント: Vol1 Multi-Account
- Observability: Vol1 分散トレース実践 / Vol2 Logs深掘り
- Network: VPC基礎 / Hybrid専門 / Vol2 マルチアカウント網編
- DevOps: Vol1 CodePipeline
- Database: Vol1 RDS×Aurora / Vol2 DMS / Vol3 ElastiCache×DAX
- Serverless Vol1: Vol1 Lambda×API GW×SF
- Serverless Vol2 (主軸): Vol2 EventBridge×SQS×SNS×Kinesis
- Container Vol1 (主軸): Vol1 ECS×Fargate×ECR
- Container Vol2: Vol2 GitOps編 ArgoCD×Kustomize×Argo Rollouts
- Storage Vol1: Vol1 S3×EFS×FSx / Vol2 S3 Advanced
- Analytics: Vol1 Glue×Athena×Redshift
- Migration: Vol1 DMS×MGN×Snow Family×AMS
- Step Functions: 入門 ASL×Standard/Express×Catch/Retry
Container本番運用 Vol1 — ECS×Fargate×ECR (Fargate本番基礎)