AWS Container本番運用Vol1|ECS×Fargate×ECR×ECS Exec

目次

Container本番運用 Vol1: ECS × Fargate × ECR × ECS Exec × Service Connect 完全ガイド

fig01: Container本番運用 5本柱全体アーキテクチャ (ECS / Fargate / ECR / ECS Exec / Service Connect)

AWS本番運用 第14軸 Container本番運用 シリーズ起点 Vol1 ECS編
本記事は AWS本番運用 全13軸を完遂した中堅エンジニアに向けた、第14軸 = Container本番運用 の起点記事です。ECS × Fargate × ECR × ECS Exec × Service Connect の5本柱を全13軸統合視点で再統合し、EKS過剰層 (Kubernetes不要のチーム) 向けの本番品質 Container 運用パターンを確立します。

EKS Vol1-3 シリーズとの住み分け

  • EKS Vol1-3 = Kubernetes本番運用 (IRSA / Fluent Bit / GitOps ArgoCD): K8s文化必須・複雑性高
  • Container本番運用 Vol1 ECS = AWS Native コンテナ運用: シンプル運用・Fargate前提・小〜中規模最適

選定基準: チーム規模 50名以下 / マルチクラウドなし / Kubernetes専任者なし → ECS推奨。


§ 1 なぜContainer本番運用 Vol1 ECS編か — 全13軸からの架橋 + ECS vs EKS選定の現実解

全13軸を習得したエンジニアが次に直面するのは「Container本番運用をどのレイヤーで実装するか」という判断だ。EKS (Kubernetes) は強力だが、チーム規模や運用リソースを考慮すると ECS が現実解となるケースが多い。本節では全13軸の知識を Container 本番運用へ架橋し、ECS vs EKS の選定根拠を整理する。

全13軸完遂後にContainer運用で直面する5つの壁

痛点5選: 全13軸完遂者がContainer本番運用で直面する地雷

  • 痛点1 EKS過剰投資: チーム5名でK8s運用すると、ノード管理・アドオン更新・RBAC設計で月40〜80時間の保守工数が発生し実質赤字になる。ECS Fargate なら同等ワークロードを1/3の工数で運用できる。
  • 痛点2 Fargate cold start遅延: cold start 15〜30秒が API SLA (p99 < 2秒) に抵触する。Pre-warming / Reserved Capacity / Application Start Optimization の3段階対策が必要。
  • 痛点3 ECR脆弱性スキャン放置: ECR Basic スキャンはOS層のみ検出。Language-level CVE (Log4Shell相当) が本番Image に流入するリスクがある。Enhanced Scan (Inspector V2) への移行判断が求められる。
  • 痛点4 ECS Service Auto Scaling 設定漏れ: Target Tracking のみでは急激なスパイク (10倍超) に対応できず Black Friday 落ちを引き起こす。Step Scaling + Scheduled Scaling の併用が必要。
  • 痛点5 Service Discovery未設定: マイクロサービス間通信を IP ハードコードすると、Task 再起動の度に接続先が変わり通信断が発生する。Service Connect (Cloud Map) による動的 Discovery が必須。

ECS vs EKS 選定の現実解 — 4軸マトリクス

全13軸完遂者が最初に判断すべきは「ECS か EKS か」だ。以下の4軸マトリクスで判断する。

判断軸ECS 推奨EKS 推奨
チーム規模50名以下 / 専任インフラ不在100名超 / SRE専任チームあり
Kubernetes専任者なし (K8s学習コスト吸収不可)あり (K8s運用経験3年以上)
マルチクラウド要件なし (AWS集中運用)あり (GKE/AKS との統合が必要)
運用コスト優先度コスト最小化・Fargate Spot活用機能優先・複雑なワークロード対応

ECS を選ぶ理由は「シンプルさ」だ。ECS は AWS 内で完結する Native Container オーケストレーターであり、Cluster / Service / Task Definition の3層構造のみを習得すれば本番運用に到達できる。K8s の Controller / CRD / Operator といった概念は不要で、Fargate を選択すればノード管理 (EC2パッチ適用・ノードグループ更新) も不要になる。

本Vol1で得られる4成果

  1. ECS Cluster/Service/Task Definition 本番設計: Launch Type選定・Capacity Provider Strategy・Auto Scaling 3方式を習得し、本番品質の ECS 基盤を構築できる。Cluster を環境別 (dev/staging/prod) に分離し、Service ごとに ALB Target Group を紐付けた本番アーキテクチャの設計判断が自分でできるようになる。

  2. Fargate 最適化運用: Graviton (ARM) 移行・Fargate Spot 混在・cold start 対策を実装し、コスト20〜30%削減と SLA 維持を両立できる。Capacity Provider Strategy による Spot 30〜50% 混在はコスト最適化の核心であり、本番での実装パターンを習得できる。

  3. ECR セキュリティ強化: 脆弱性スキャン (Basic→Enhanced) / Pull-Through Cache / Lifecycle Policy / Cross-Region Replication を設定し、Image セキュリティ体制を確立できる。ECR Lifecycle Policy によるストレージ管理と、Inspector V2 連携による CVE 自動検出フローを本番に適用できる。

  4. ECS Exec + Service Connect 本番運用: SSH/Bastion を廃止し ECS Exec + Session Manager で監査対応、Service Connect で動的 Service Discovery を実現できる。全コマンド実行履歴を S3 に保存し、規制要件 (PCI-DSS / SOC2) に対応した Container 運用体制を構築できる。

Container本番運用5原則

ECS/Fargate の本番設計を支える根本原則を先に確認しておく。

  1. ステートレス徹底: Container は状態を持たない設計とし、状態は EFS / DynamoDB / ElastiCache に外部化する。
  2. イミュータブルImage: Task Definition は revision 毎に新規作成し、既存 Task Definition を上書き変更しない。ECR タグは latest 禁止・GitSHA タグ固定を徹底する。
  3. Secrets Manager連携: 機密情報 (DB パスワード / API キー) を環境変数に直書きしない。Task Definition の secrets フィールドで Secrets Manager / Parameter Store から動的注入する。
  4. Auto Scaling予算化: ECS Service Auto Scaling は予算枠 (最大タスク数) を設定し、スパイク時のコスト爆増を防ぐ。Target Tracking の scaleInCooldown / scaleOutCooldown を適切に設定する。
  5. Observability優先: CloudWatch Container Insights Enhanced を Cluster 作成時から必ず有効化する。後付けでの有効化は過去メトリクスが欠落しトラブルシュートが困難になる。
ECS vs EKS 住み分け: チーム50名以下/K8s専任者なし → ECS推奨

  • ECS = AWS Native / 学習コスト低 / Fargate で ノード管理ゼロ / 小〜中規模最適
  • EKS = Kubernetes標準 / 高度なワークロード / マルチクラウド統合 / 大規模組織向け
  • 判断基準: K8s専任者がいない & チーム50名以下 & マルチクラウド不要 → ECS Fargate が現実最適解
  • EKS比較: EKS は ECS 比で学習コスト3〜5倍・運用工数2〜3倍。ROI が出るのはチーム規模100名超かつ K8s専任SREがいる場合のみ

EKS本番運用との詳細比較は EKS Vol1 — Kubernetes本番運用との対比 を参照されたい。EKS の IRSA / ALB Ingress / Fluent Bit 設定は ECS では不要となる差分を理解することで、ECS の選定根拠がより明確になる。

EKS Vol1 — Kubernetes本番運用との対比


§ 2 ECS基盤本番運用 — Cluster / Service / Task Definition / Launch Type選定

fig02: ECS Cluster + Service + Task Definition 選定マトリクス

ECS の基盤設計は「Cluster → Service → Task Definition」の3層構造を理解することから始まる。この3層の役割と設定方針を確定させてから Launch Type・Auto Scaling・Capacity Provider Strategy の詳細設計に進む。

ECS 3層構造の役割定義

レイヤー役割設計方針
ClusterContainer の実行環境 (論理グループ)環境別 (dev/staging/prod) に分離。1 Cluster = 1 環境が原則
Service常駐 Container の管理 (希望タスク数・ロードバランサー連携)ALB Target Group と 1:1 紐付け。Auto Scaling は Service 単位で設定
Task DefinitionContainer の仕様書 (Image URI / CPU / Memory / IAM Role / Logging)Immutable 運用。変更の度に新 revision を作成し、既存 revision を編集しない

Cluster は名前空間の役割を担い、VPC・Subnet・Security Group は Cluster ではなく Task Definition (awsvpc モード) のレベルで設定する。Service は Cluster 内で複数定義でき、マイクロサービスごとに 1 Service を割り当てる構成が標準だ。

Cluster 設計: 環境分離とネーミング規約

Cluster の設計で最も重要な判断は「環境分離戦略」だ。推奨する構成は以下の通り。

  • 本番 (prod): myapp-prod-cluster — 本番専用 VPC / Private Subnet のみ / Cluster-level CloudWatch Container Insights Enhanced 必須
  • ステージング (staging): myapp-staging-cluster — 本番 VPC と分離 / Fargate Spot 100%で可
  • 開発 (dev): myapp-dev-cluster — Fargate Spot 100% / 夜間 Scheduled Scale-in (タスク数ゼロ) でコスト最小化

Cluster 名に環境を含めることで、AWS Console・CloudWatch Logs・IAM Policy の全レイヤーで環境誤操作を防ぐ。ECS Exec で本番 Task にアクセスする際も Cluster 名に prod を含むリソースへの操作を IAM Condition で制限できる。

Launch Type選定: EC2 vs Fargate vs Fargate Spot — 5軸マトリクス

選定軸EC2FargateFargate Spot
ノード管理自己管理 (パッチ/スケール)不要 (AWS管理)不要 (AWS管理)
コスト予約購入で低コストオンデマンドより20%高めFargate比70%削減
中断リスクなしなしあり (2分前通知)
GPU / 大容量Memory対応 (>120GB)最大120GB最大120GB
適用ワークロードGPU推論 / 大容量DB標準API / Webバッチ / 開発環境

新規構築では Fargate 第一選択 を推奨する。ノード管理工数ゼロ・OS パッチ自動適用・awsvpc モードによる Task 単位 Security Group の3点が本番運用品質を最小コストで実現する。GPU ワークロードや 120GB 超のメモリ要件がある場合のみ EC2 Launch Type に切り替える。

Fargate Spot の中断ハンドリングは本番採用の前提条件だ。Spot 中断は 2 分前に SIGTERM が送信される。アプリケーションは SIGTERM 受信後 120 秒以内にインフライト処理を完了し graceful shutdown する実装が必要だ。ECS Service の minimumHealthyPercent: 50maximumPercent: 200 の設定により、中断時も最低タスク数が維持され SLA を守れる。Spot 中断率は時間帯・vCPU 構成・リージョンによって 3〜15% 変動するため、本番では Base タスク数を Fargate (オンデマンド) で確保したうえで Spot を上乗せする設計を徹底する。

Task Definition 本番品質設定

Task Definition の核心は CPU/Memory 単位、IAM Role 分離、awsvpc Network Mode、FireLens Logging の4点だ。以下に本番品質の Task Definition JSON を示す。

json
{
"family": "myapp-prod",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "1024",
"memory": "2048",
"taskRoleArn": "arn:aws:iam::123456789012:role/myapp-task-role",
"executionRoleArn": "arn:aws:iam::123456789012:role/myapp-execution-role",
"containerDefinitions": [
{
"name": "myapp",
"image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:abc1234",
"portMappings": [{ "containerPort": 8080, "protocol": "tcp" }],
"secrets": [
{ "name": "DB_PASSWORD", "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:myapp/db-password" }
],
"logConfiguration": {
"logDriver": "awsfirelens",
"options": { "Name": "cloudwatch", "region": "ap-northeast-1", "log_group_name": "/ecs/myapp-prod" }
},
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"],
"interval": 30, "timeout": 5, "retries": 3, "startPeriod": 60
}
}
]}
text
taskRoleArn (Container が AWS API を呼ぶための Role) と executionRoleArn (ECS が ECR から Image を pull し CloudWatch Logs に書き込むための Role) は必ず分離する。混用すると最小権限原則が崩れ、セキュリティ監査で指摘を受ける。

Terraform で同等設定を管理する場合は以下のように記述する。

“`hcl
resource “aws_ecs_task_definition” “myapp” {
family = “myapp-prod”
network_mode = “awsvpc”
requires_compatibilities = [“FARGATE”] cpu = 1024
memory = 2048
task_role_arn= aws_iam_role.task_role.arn
execution_role_arn = aws_iam_role.execution_role.arn

container_definitions = jsonencode([{
name = “myapp”
image = “${aws_ecr_repository.myapp.repository_url}:${var.image_tag}”
portMappings = [{ containerPort = 8080, protocol = “tcp” }] secrets = [
{ name = “DB_PASSWORD”, valueFrom = aws_secretsmanager_secret.db_password.arn }
] logConfiguration = {
logDriver = “awslogs”
options = {
“awslogs-group” = “/ecs/myapp-prod”
“awslogs-region” = “ap-northeast-1”
“awslogs-stream-prefix” = “myapp”
}
}
}])

lifecycle {
create_before_destroy = true
}
}
``textlifecycle { create_before_destroy = true }` を指定することで、Task Definition 更新時に新 revision が先に作成され、古い revision が残存するため Blue/Green デプロイと相性がよい。

Service Auto Scaling — 3方式選定

ECS Service Auto Scaling は以下の3方式を用途に応じて組み合わせる。

方式仕組み適用シーン
Target TrackingCPU使用率 / ALBリクエスト数を目標値に維持常時稼働 API の標準設定 (第一選択)
Step ScalingCloudWatch Alarm トリガーでステップ増減急激スパイク対応 (Target Tracking 補完)
Scheduled Scaling時刻・曜日で事前にスケールバッチ前タスク増強 / 夜間縮退

本番構成では Target Tracking を基本とし、急激なスパイク (10倍超) に備えて Step Scaling を補完として設定する。以下に AWS CLI での Target Tracking 設定例を示す。

“`bash
aws application-autoscaling register-scalable-target \
–service-namespace ecs \
–resource-id “service/myapp-prod-cluster/myapp-service” \
–scalable-dimension ecs:service:DesiredCount \
–min-capacity 2 \
–max-capacity 50

aws application-autoscaling put-scaling-policy \
–service-namespace ecs \
–resource-id “service/myapp-prod-cluster/myapp-service” \
–scalable-dimension ecs:service:DesiredCount \
–policy-name myapp-cpu-target-tracking \
–policy-type TargetTrackingScaling \
–target-tracking-scaling-policy-configuration ‘{
“TargetValue”: 60.0,
“PredefinedMetricSpecification”: {
“PredefinedMetricType”: “ECSServiceAverageCPUUtilization”
},
“ScaleInCooldown”: 300,
“ScaleOutCooldown”: 60
}’
``textScaleOutCooldown: 60(スケールアウト冷却60秒) とScaleInCooldown: 300` (スケールイン冷却5分) の非対称設定が重要だ。スパイク時に素早くスケールアウトし、負荷が下がっても急いでスケールインしないことで、チャタリング (頻繁なスケール往復) を防ぐ。

Capacity Provider Strategy で Fargate + Fargate Spot 混在最適化

Capacity Provider Strategy を使うと、Fargate (オンデマンド) と Fargate Spot の比率を Service 単位で制御できる。

bash
aws ecs create-service \
--cluster myapp-prod-cluster \
--service-name myapp-service \
--task-definition myapp-prod:5 \
--desired-count 10 \
--capacity-provider-strategy \
capacityProvider=FARGATE,weight=1,base=2 \
capacityProvider=FARGATE_SPOT,weight=3 \
--deployment-configuration \
"deploymentCircuitBreaker={enable=true,rollback=true},maximumPercent=200,minimumHealthyPercent=50"
text
base=2 は「最低2タスクは必ず Fargate (オンデマンド) で確保する」という設定だ。Spot の中断が発生しても base タスクが残存し、Service の最低稼働を保証する。weight の比率 (Fargate:Spot = 1:3) で残りのタスクを Spot 優先で起動し、コストを約30〜40%削減できる。

deploymentCircuitBreaker は必ず有効化する。デプロイ失敗時に自動で前の revision に rollback するため、障害の影響時間を最小化できる。

mermaid01: ECS Service Deployment ライフサイクル

ECS Service の Rolling Update と Blue/Green Deployment の切り替えフローを sequenceDiagram で示す。

“`mermaid
sequenceDiagram
participant Dev as Developer
participant ECR as ECR Registry
participant ECS as ECS Service
participant ALB as ALB Target Group
participant Old as Old Tasks (v1)
participant New as New Tasks (v2)

Dev->>ECR: docker push myapp:v2 (GitSHA tag)
Dev->>ECS: update-service --task-definition myapp-prod:6

Note over ECS: Rolling Update 開始 (maximumPercent=200)
ECS->>New: 新 Task 起動 (v2) × N
New-->>ALB: HealthCheck 通過
ALB->>New: トラフィック切替開始

Note over ECS: Circuit Breaker 監視中
alt HealthCheck 成功
 ECS->>Old: 旧 Task 停止 (v1) × N
 ECS-->>Dev: deployment COMPLETED
else HealthCheck 失敗 (Circuit Breaker 発動)
 ECS->>New: 新 Task 停止 (v2)
 ECS-->>Old: 旧 Task 継続稼働 (v1)
 ECS-->>Dev: deployment FAILED → auto rollback
end

Note over ALB,New: Blue/Green (CodeDeploy) の場合はトラフィックを段階的に切替

“`text
Rolling Update は ECS ネイティブ機能で追加コストなし、Blue/Green は CodeDeploy 連携が必要だが Canary リリース (10%→100% の段階切替) が可能だ。API の SLA 要件が厳しい場合は Blue/Green を選択し、リリース失敗時の即時 rollback 能力を確保する。

ECS基盤 本番運用5原則

  • 原則1 awsvpc Network Mode 必須: Task ごとに ENI と Security Group を付与し、Service 間通信を最小権限で制御する。bridge モードは新規構築禁止。
  • 原則2 Task Definition は Immutable: revision ごとに新規作成・既存編集禁止。rollback は前 revision を指定して update-service するだけで完了する。
  • 原則3 Service Auto Scaling は Target Tracking 第一選択: CPU使用率60%目標・ScaleOut冷却60秒・ScaleIn冷却300秒を基本値とし、スパイク対応は Step Scaling で補完する。
  • 原則4 Capacity Provider Strategy で Spot 30〜50% 混在: base=2 でオンデマンド最低稼働を保証し、残りを Fargate Spot で起動してコスト最適化を図る。
  • 原則5 deployment_circuit_breaker 必ず有効化: デプロイ失敗時の自動 rollback で MTTR (平均復旧時間) を最小化する。enable=true / rollback=true を Service 作成時から設定する。
Launch Type 選定マトリクス: 迷ったらこの表で決める

  • Fargate (第一選択): 標準API・Web・バックグラウンドワーカー / 運用負荷最小 / OS パッチ自動 / awsvpc必須 → 新規構築はすべて Fargate から開始
  • Fargate Spot: バッチ処理 / CI/CD Runner / 開発・ステージング環境 / 中断許容あり → コスト70%削減・本番では Capacity Provider で30〜50%混在
  • EC2: GPU推論 (p3/g4 インスタンス) / メモリ120GB超 / 既存 EC2 運用資産継承 → 上記2つで対応不可の場合のみ採用
アンチパターン: Task Definition を EC2 Launch Type で新規構築する
EC2 Launch Type で新規構築すると、ノード管理 (AMI更新 / Security Group 設定 / ECS Agent 更新) が常に必要になり、運用コストが Fargate の約2倍になる。加えて、bridge Network Mode を選択した場合は Task 単位の Security Group が使えず、ネットワーク分離が Cluster レベルのみとなりセキュリティ設計が困難になる。新規構築は Fargate + awsvpc から始め、GPU/大容量メモリの要件が明確になった段階で EC2 に切り替える。

ECS 基盤の Observability 設定については Observability Vol1 — Application Signals 完全ガイド で CloudWatch Container Insights Enhanced の設定手順を詳解している。コスト最適化については Cost Optimization Vol1 で Fargate Spot と Savings Plans の組み合わせ戦略を参照されたい。CI/CD パイプラインとの連携は DevOps Vol1 — CodePipeline×ECS デプロイ で Blue/Green デプロイの実装手順を確認できる。また、ECS Task の IAM 設計 (Task Role / Execution Role 最小権限設定) は IAM Vol1 — ポリシー設計の基礎 と合わせて習得することで、Task 単位の最小権限アーキテクチャを確立できる。第14軸 Container 本番運用は全13軸の IAM / Network / Observability / コスト / DevOps の集大成であり、これらの軸の設計パターンを ECS レイヤーで統合するのが本シリーズの狙いだ。

§ 2 チェックリスト: ECS基盤 本番構築前確認5項目

§ 2 の内容を踏まえ、ECS 基盤を本番環境に適用する前に以下の5点を必ず確認する。

  1. Task Definition の networkModeawsvpc になっているか (bridge モード禁止)
  2. taskRoleArnexecutionRoleArn が分離されているか (混用禁止)
  3. secrets フィールドで DB パスワード / API キーを Secrets Manager から動的注入しているか (環境変数直書き禁止)
  4. Service の deploymentCircuitBreakerenable=true, rollback=true になっているか
  5. Cluster に CloudWatch Container Insights Enhanced が有効化されているか (後付け不可・作成時から必須)

この5項目を確認してから § 3 Fargate 最適化運用に進むことで、基盤層の設計ミスによる手戻りを防ぐ。


3. Fargate本番運用 — vCPU/Memory選定 / Spot活用 / ARM (Graviton) / cold start特性

fig03: Fargate Spot + Graviton 構成 + cold start計測フロー

AWS Fargateはサーバーレスコンテナ実行基盤として、EC2インスタンス管理の煩雑さを排除しながら本番グレードのコンテナ運用を実現する。しかし「サーバーレスだから管理不要」という誤解が本番障害を招く。vCPU/Memoryの適正選定、Fargate Spotの冗長設計、Gravitonへの移行、cold startの吸収戦略——これらを体系的に理解することで、コストと可用性の最適バランスを実現できる。

本セクションではEKS本番クラスター設計との比較も踏まえながら、Fargateならではの本番設計パターンを解説する。

Fargate 本番運用5原則

  • 原則1: 右サイジングファースト — vCPU/Memory使用率70-80%目標でTask Definitionを調整。過剰プロビジョニングは即座にコスト増に直結する
  • 原則2: ARM (Graviton) 第一選択 — x86_64比で約20%コスト削減・性能同等。新規ワークロードはGraviton前提で設計する
  • 原則3: Fargate Spot は本番でも30%混在可能 — Capacity Provider StrategyでFARGATE:70 / FARGATE_SPOT:30の冗長構成を前提に活用する
  • 原則4: cold start 15-30秒をSLA設計に織り込む — VPC Endpoint + イメージ軽量化で短縮。SLA文書に初回起動時の遅延許容を明記する
  • 原則5: Secrets Manager + Parameter Store 必須 — 環境変数にシークレットをハードコードしない。Task DefinitionのsecretsフィールドでSecrets Manager ARNを参照する

3.1 vCPU/Memory 組み合わせ選定 — 制約マトリクスと右サイジング

FargateのvCPUとメモリ組み合わせはEC2と異なり、AWS定義の制約マトリクスに従う。この制約を理解しないと「指定した組み合わせが使えない」エラーに直面する。

vCPU使用可能メモリ範囲主なユースケース
0.25 vCPU0.5 GB、1 GB、2 GB軽量API / サイドカー / 小規模バッチ
0.5 vCPU1 GB、2 GB、3 GB、4 GB小規模Webアプリ / キュー処理
1 vCPU2 GB 〜 8 GB(1 GB刻み)標準Webサービス / Node.js / Python
2 vCPU4 GB 〜 16 GB(1 GB刻み)Java Spring Boot / PHP Laravel
4 vCPU8 GB 〜 30 GB(1 GB刻み)中規模バッチ / ML推論 / Go
8 vCPU16 GB 〜 60 GB(4 GB刻み)大規模バッチ / Spark / データ集計
16 vCPU32 GB 〜 120 GB(8 GB刻み)高負荷ML / 動画処理 / 大規模並列

右サイジングの実践手順:

CloudWatch Container InsightsでTask-level CPUUtilization/MemoryUtilizationを7日間計測する。P95値の1.3倍を必要vCPU/Memoryの目安とし、上記マトリクスで次のサイズを選択する。

“`bash

Container Insightsでタスク使用率を確認(過去7日間)

aws cloudwatch get-metric-statistics \
–namespace ECS/ContainerInsights \
–metric-name CpuUtilized \
–dimensions \
Name=ClusterName,Value=production-cluster \
Name=TaskDefinitionFamily,Value=myapp \
–start-time $(date -u -v-7d +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
|| date -u –date=’7 days ago’ +%Y-%m-%dT%H:%M:%SZ) \
–end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
–period 3600 \
–statistics p95 \
–output table
“`text
P95 CPU使用率が例えば350 CPU units(0.35 vCPU相当)であれば、1.3倍で0.455 vCPU → 0.5 vCPUを選択する。メモリも同様にP95の1.3倍で算出し、上記マトリクスの制約内で最小サイズを選ぶ。2週間ごとに見直しを行い、使用率が継続して50%未満ならダウンサイジングを検討する。


3.2 Fargate Spot 中断ハンドリング — 2分前通知 / SIGTERM処理 / Auto Scaling冗長化

Fargate Spotは通常のFargateより最大70%のコスト削減を実現するが、AWSインフラの余剰キャパシティを利用するため中断が発生する。中断ハンドリングを適切に実装することで本番環境でも安全に活用できる。

中断フロー(2分猶予):

  1. AWS側がSpotキャパシティを回収する2分前にSIGTERMをコンテナへ送信
  2. アプリがSIGTERMを受信して処理中リクエストを完了しグレースフルシャットダウン
  3. 2分経過後にSIGKILLで強制終了(未処理リクエストは失われる)

SIGTERMハンドリングを実装しないアプリはリクエスト途中で強制終了され、エラーレスポンスをクライアントに返してしまう。以下のentrypoint.shで確実にSIGTERMを捕捉する。

“`bash

!/bin/bash

entrypoint.sh — Fargate Spot SIGTERM graceful shutdown

APP_PID=””

cleanup() {
echo “[$(date -u +%Y-%m-%dT%H:%M:%SZ)] SIGTERM received – initiating graceful shutdown”
if [ -n “$APP_PID” ]; then
# アプリにSIGTERMを転送
kill -TERM “$APP_PID” 2>/dev/null
# 最大90秒待機(2分猶予のうち余裕を持たせる)
for i in $(seq 1 90); do
if ! kill -0 “$APP_PID” 2>/dev/null; then
echo “[$(date -u +%Y-%m-%dT%H:%M:%SZ)] Graceful shutdown completed in ${i}s”
exit 0
fi
sleep 1
done
echo “[$(date -u +%Y-%m-%dT%H:%M:%SZ)] Timeout reached – forcing shutdown”
kill -KILL “$APP_PID” 2>/dev/null
fi
exit 0
}

trap cleanup SIGTERM SIGINT

アプリをバックグラウンドで起動してPIDを取得

exec node server.js &
APP_PID=$!
wait “$APP_PID”
``text
**Capacity Provider Strategy** で FARGATE/FARGATE_SPOT を混在させる。
base`が最低保証タスク数となるため、SLA維持に必要なタスク数をbaseに設定することが重要となる。

“`hcl
resource “aws_ecs_service” “production_api” {
name= “production-api”
cluster= aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.api.arn
desired_count= 10

capacity_provider_strategy {
# FARGATE: 最低3タスクは常時確保(Spot中断時の保証)
capacity_provider = “FARGATE”
base = 3
weight= 30
}

capacity_provider_strategy {
# FARGATE_SPOT: 残り70%をSpotで補完(コスト最適化)
capacity_provider = “FARGATE_SPOT”
base = 0
weight= 70
}

deployment_minimum_healthy_percent = 100
deployment_maximum_percent= 200

# Auto Scalingが管理するためdesired_countの変更を無視
lifecycle {
ignore_changes = [desired_count] }
}
“`text

アンチパターン: Fargate Spot を本番Production 100%適用
Fargate Spot中断率は時間帯・vCPU構成・リージョンによって 5〜15%/時間 で変動する。本番APIを100% Spot構成にすると、中断発生時に全タスクが同時に再起動し、数十秒〜数分のAPI停止が発生するリスクがある。

特に危険な3つのシナリオ:

  • 夜間バッチ中断 — Spot全中断でバッチ処理が途中失敗→データ不整合。冪等性設計とチェックポイント保存が必須
  • トラフィックスパイク時のキャパシティ枯渇 — Spotキャパシティが枯渇すると新規タスク起動がFARGATEに切り替わり、起動まで20-30秒の空白が生じる
  • デプロイ中のRolling Update同時発生 — Spot中断とRolling Updateが重なるとHealthy Taskがdesired_count未満に低下し、ALBへの接続エラーが急増する

正しい構成: Capacity Provider Strategyで FARGATE base=N(SLA維持の最低タスク数)+ FARGATE_SPOT weight=70 を組み合わせる。baseはP99トラフィックを処理できる最低タスク数を設定し、スパイク分をSpotで補完する設計とする。


3.3 ARM (Graviton) 移行手順 — Multi-Arch Image / docker buildx / コスト20%削減

AWS Graviton3プロセッサ搭載のARMアーキテクチャは、x86_64比で約20%低コスト・同等以上の性能を提供する。FargateではruntimePlatform.cpuArchitecture: ARM64を指定するだけで切り替え可能だが、コンテナイメージのマルチアーキテクチャ対応が前提となる。

Serverlessとのコスト比較でも示す通り、Graviton採用はコスト最適化の最初の一手として最も費用対効果が高い選択となる。

Multi-Arch Imageビルドと本番デプロイの完全手順:

“`bash

1. buildxのMulti-platformビルダーを作成(初回のみ)

docker buildx create \
–name multiarch-builder \
–driver docker-container \
–use

2. ECRへの認証

ACCOUNT_ID=$(aws sts get-caller-identity –query Account –output text)
REGION=”ap-northeast-1″
REPO=”${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/production-api”

aws ecr get-login-password –region “${REGION}” \
| docker login –username AWS –password-stdin \
“${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com”

3. AMD64+ARM64のマルチアーキテクチャイメージをビルド&ECRにプッシュ

GIT_SHA=$(git rev-parse –short HEAD)
docker buildx build \
–platform linux/amd64,linux/arm64 \
–tag “${REPO}:latest” \
–tag “${REPO}:${GIT_SHA}” \
–push \
–cache-from “type=registry,ref=${REPO}:buildcache” \
–cache-to “type=registry,ref=${REPO}:buildcache,mode=max” \
.

4. Task DefinitionをARM64で登録(既存定義のruntimePlatformのみ変更)

aws ecs register-task-definition \
–cli-input-json “$(aws ecs describe-task-definition \
–task-definition production-api \
–query ‘taskDefinition’ \
| jq ‘.runtimePlatform.cpuArchitecture = “ARM64″ | del(.taskDefinitionArn,.revision,.status,.requiresAttributes,.compatibilities,.registeredAt,.registeredBy)’)”
“`text
アーキテクチャ別移行難易度:

言語/ランタイム移行難易度注意事項
GoGOARCH=arm64 GOOS=linux go build でクロスコンパイル可
Node.js (Pure JS)変更不要。ただしsharpbcrypt等のネイティブモジュールは要ARM64リビルド
Python (Pure Python)変更不要。numpyPillow等のC拡張はARM64ホイールを確認
Java / Kotlin低〜中JDK 11+はGraviton最適化済み。GraalVM Native ImageはARM64向け再コンパイル必須
Rust--target aarch64-unknown-linux-musl でクロスコンパイル可
C/C++ (カスタム)中〜高CPU依存命令セット(SSE/AVX等)をNEONで置き換え要検討

3.4 cold start特性と対策 — 15-30秒の実態とPre-warming戦略

Fargateのcold startはインフラプロビジョニング + イメージPull + アプリ初期化の合計となる。EC2上のECSと異なりFargateはインフラ起動も含むため、cold startが長くなる特性がある。

cold startの内訳(目安):

  1. Fargateインフラプロビジョニング: 5-10秒 — ENI割り当て・セキュリティグループ設定・仮想マシン起動
  2. ECRからのイメージPull: 5-15秒 — イメージサイズに依存。VPC Endpointで短縮可能
  3. コンテナ起動 + アプリ初期化: 5-30秒 — JVM起動・DB接続プール初期化・依存関係ロード

合計として15-55秒が現実的な範囲となる。JVMアプリや大規模イメージでは60秒を超えるケースも存在する。

cold start対策チェックリスト

  • VPC Endpoint設定 — ECR (ecr.dkr / ecr.api) のVPC Endpointを設定しNAT Gateway経由を回避。イメージPull時間を最大50%短縮できる
  • イメージ軽量化 — distroless / Alpine ベースイメージで200MB以下を目標。不要なパッケージ・開発ツールを除去しMulti-stage Buildを徹底する
  • レイヤーキャッシュ最適化 — Dockerfileで変更頻度の低いレイヤー(OSパッケージ・依存ライブラリ)を上位に配置。アプリコードだけのレイヤー変更で済む構成にする
  • アプリ起動の非同期化 — DB接続プール初期化・外部API疎通確認をバックグラウンドで実行。ヘルスチェック(/health)は最短で200を返せる状態で応答開始する
  • ALBヘルスチェックgrace period調整 — ECS ServiceのhealthCheckGracePeriodSecondsをcold start時間の1.5倍に設定(例:cold start 30秒 → grace period 45秒)。短すぎるとタスクがUnhealthyと判定され再起動ループに入る
  • 最小タスク数でzero-scale回避 — Auto Scaling minimum=2以上に設定。全タスクがスケールインされるとスパイク時に全タスクがcold startとなり、集中的な遅延が発生する
  • SLAへの明示的な織り込み — 「スケールアウト時の初回リクエストは最大X秒の応答遅延が発生する」をSLA文書に記載し、監視アラートの閾値を調整する

3.5 Ephemeral Storage Volume サイズ調整

FargateのEphemeral Storage(一時ストレージ)はデフォルト20 GBだが、最大200 GBまで拡張できる。MLモデルファイル・動画処理・大規模バッチデータを扱う場合は明示的な設定が必要となる。

“`bash

Ephemeral Storage 200GBを指定したTask Definitionを登録

aws ecs register-task-definition \
–family ml-inference-task \
–cpu 4096 \
–memory 30720 \
–requires-compatibilities FARGATE \
–network-mode awsvpc \
–ephemeral-storage ‘{“sizeInGiB”: 200}’ \
–runtime-platform ‘{“cpuArchitecture”:”ARM64″,”operatingSystemFamily”:”LINUX”}’ \
–cli-input-json file://ml-task-definition.json
“`text
Ephemeral Storageの設計上の注意点:

  • Task終了時に完全削除される — 永続化が必要なデータはTask完了前にS3またはEFSへ書き出す
  • 同一Task内の全コンテナが共有する — アプリコンテナ・FireLensサイドカーが同一ストレージを使用。大量ログを/tmpに書き出すサイドカーがストレージを圧迫するケースに注意
  • 追加料金が発生する — 20GBを超えた分は約$0.000111/GB-hour。200GBを1ヶ月維持すると約$12.77/Task(180GB × 720時間)

3.6 本番品質設定 — FireLens ロギング + Secrets Manager 環境変数注入

本番FargateタスクにはFireLens(Fluent Bitサイドカー)によるログ集約とSecrets Managerによるシークレット管理が不可欠となる。ハードコードされた認証情報はセキュリティリスクの温床であり、CloudWatch Logsへの直接送信はコスト効率も低い。

AWSコスト最適化の観点から見ても、FireLensによるログフィルタリング・バッファリングはCloudWatch直接送信と比較してログコストを30-50%削減できるケースがある。

json
{
"family": "production-api",
"cpu": "1024",
"memory": "2048",
"requiresCompatibilities": ["FARGATE"],
"networkMode": "awsvpc",
"runtimePlatform": {
"cpuArchitecture": "ARM64",
"operatingSystemFamily": "LINUX"
},
"ephemeralStorage": {
"sizeInGiB": 21
},
"executionRoleArn": "arn:aws:iam::123456789:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789:role/ecsTaskRole",
"containerDefinitions": [
{
"name": "app",
"image": "123456789.dkr.ecr.ap-northeast-1.amazonaws.com/production-api:latest",
"essential": true,
"portMappings": [
{
"containerPort": 8080,
"protocol": "tcp"
}
],
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789:secret:prod/db/password"
},
{
"name": "API_SECRET_KEY",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789:secret:prod/api/secret-key"
}
],
"logConfiguration": {
"logDriver": "awsfirelens",
"options": {
"Name": "cloudwatch",
"region": "ap-northeast-1",
"log_group_name": "/ecs/production-api",
"log_stream_prefix": "app/",
"auto_create_group": "true"
}
},
"healthCheck": {
"command": ["CMD-SHELL", "curl -sf http://localhost:8080/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 60
},
"linuxParameters": {
"initProcessEnabled": true
}
},
{
"name": "log_router",
"image": "public.ecr.aws/aws-observability/aws-for-fluent-bit:stable",
"essential": true,
"firelensConfiguration": {
"type": "fluentbit",
"options": {
"enable-ecs-log-metadata": "true"
}
},
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/firelens-router",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "firelens"
}
},
"cpu": 0,
"memoryReservation": 50,
"user": "0"
}
]}
text
Secrets Manager運用の3つのポイント:

  1. 権限はTask Execution Roleに付与する — Task RoleではなくecsTaskExecutionRoleにSecrets Manager GetSecretValue権限が必要。混同するとタスク起動時に「ResourceNotFoundException」でコンテナが起動しない
  2. 自動ローテーションを有効化する — RDS/Redshiftは専用ローテーションLambdaが用意されており、ワンクリックで設定可能。アプリはSecrets Managerからの取得タイミングで最新値を受け取るため、RotationによるDB接続断を考慮した再接続ロジックが必要
  3. 複数環境のパス規約を統一する/環境/サービス/シークレット名(例:/prod/api/db-password)の規約でIAM PolicyのResourceをワイルドカード指定できる:arn:aws:secretsmanager:*:*:secret:/prod/*

linuxParameters.initProcessEnabledのポイント:

initProcessEnabled: trueを設定するとコンテナ内でtini(軽量initプロセス)が起動し、SIGTERMのゾンビプロセス問題を回避できる。Fargate Spot環境ではSIGTERM処理が重要なため、設定を推奨する。


3節まとめ — Fargate本番運用の設計チェックポイント

本節で解説したFargate本番運用の要点を整理する。

  1. vCPU/Memory: AWSの制約マトリクスを確認し、Container InsightsのP95の1.3倍でサイジング。2週間ごとに見直す
  2. Fargate Spot: base=N(最低保証タスク数)+ weight=70(Spot比率)のCapacity Provider Strategyで本番活用。SIGTERMハンドリングは必須
  3. Graviton: 新規ワークロードはARM64第一選択。Multi-stage Build + Multi-Arch Imageで移行コストを最小化し、約20%コスト削減を実現する
  4. cold start: VPC Endpoint + イメージ軽量化 + minimum=2以上で影響を最小化。ALBヘルスチェックgrace periodを適切に設定しないと再起動ループに陥る
  5. 本番品質: FireLens + Secrets Managerをデフォルト構成とし、ハードコードシークレット・CloudWatch直接送信を廃止する

ECS Exec本番運用(SSH置き換え)は次節§4で解説する。

4. ECR本番運用 — 脆弱性スキャン / Pull-Through Cache / Cross-Region Replication / Lifecycle Policy

ECR (Elastic Container Registry) は ECS×Fargate の Image 配布基盤であり、本番運用の品質はここで決まる。脆弱なImageをそのまま本番にデプロイするリスク、CI/CDのImage蓄積によるストレージ費爆増、Single-Regionでの可用性リスク — これら3つの地雷を潰す実装パターンを示す。

ECR Enhanced Scan 採用判断フレームワーク

  • Basic Scan: 1スキャン無料 / Inspector V2非連携 / OSパッケージのみ検出 / push時1回のみ実行
  • Enhanced Scan (Inspector V2連携): 月額$0.09/Image / OS+言語パッケージCVE両対応 / 継続スキャン(新CVE自動検知)/ EventBridge通知対応
  • 採用判断基準:
    • 規制対応必須 (PCI-DSS / SOC2 / HIPAA) → Enhanced一択(継続スキャン+CVE通知必須)
    • SaaS/エンタープライズ向けAPI → Enhanced推奨(言語パッケージCVEはBasicでは検知不可)
    • 内部ツール/社内システム / スタートアップ初期 → Basic + 定期Image更新で十分
  • コスト試算: リポジトリ10個×平均5 Image = 50 Image × $0.09 = 月額$4.50 → 規制対応コストとして許容範囲

4-1. ECR脆弱性スキャン設定 — Basic vs Enhanced 比較と実装

Basic Scan 有効化 (Terraform)

“`hcl
resource “aws_ecr_repository” “app” {
name = “myapp/backend”
image_tag_mutability = “IMMUTABLE”

image_scanning_configuration {
scan_on_push = true # push時に自動スキャン
}

encryption_configuration {
encryption_type = “KMS”
kms_key= aws_kms_key.ecr.arn
}

tags = {
Environment = “production”
Service = “backend”
}
}
“`text
Enhanced Scan (Inspector V2) 有効化

“`bash

Inspector V2 を ECR Enhanced Scan として有効化

aws inspector2 enable \
–resource-types ECR \
–region ap-northeast-1

リポジトリ単位でEnhanced Scan設定確認

aws ecr describe-repositories \
–repository-names myapp/backend \
–query ‘repositories[].imageScanningConfiguration’

スキャン結果確認 (CRITICAL以上のみ)

aws ecr describe-image-scan-findings \
–repository-name myapp/backend \
–image-id imageTag=latest \
–query ‘imageScanFindings.findings[?severity==CRITICAL]’
“`text
CVE検知時の自動通知 (EventBridge → SNS)

“`hcl
resource “aws_cloudwatch_event_rule” “ecr_scan_finding” {
name = “ecr-inspector-critical-finding”
description = “ECR Enhanced Scan CRITICAL/HIGH CVE検知”

event_pattern = jsonencode({
source= [“aws.inspector2”] detail-type = [“Inspector2 Finding”] detail = {
severity = [“CRITICAL”, “HIGH”]resources = {
type = [“AWS_ECR_CONTAINER_IMAGE”]}
}
})
}

resource “aws_cloudwatch_event_target” “sns_alert” {
rule= aws_cloudwatch_event_rule.ecr_scan_finding.name
target_id = “SendToSNS”
arn = aws_sns_topic.security_alert.arn
}
“`text
Basic vs Enhanced 機能比較表

項目Basic ScanEnhanced Scan (Inspector V2)
費用無料$0.09/Image/月
スキャン対象OSパッケージOS + 言語パッケージ (pip/npm/gem等)
実行タイミングpush時1回継続スキャン (新CVE自動検知)
EventBridge連携限定的フル対応
SBOM出力なしあり
規制対応不可PCI-DSS / SOC2 対応

4-2. Pull-Through Cache — Docker Hub / Quay / GitHub Container Registry

Pull-Through Cache は外部パブリックレジストリのImage を ECR 経由でキャッシュする機能。Docker Hub Rate Limit回避・転送コスト削減・内部Audit証跡確保の3メリットがある。

Pull-Through Cache 設定 (Terraform)

“`hcl

Docker Hub キャッシュ設定

resource “aws_ecr_pull_through_cache_rule” “dockerhub” {
ecr_repository_prefix = “dockerhub”
upstream_registry_url = “registry-1.docker.io”
credential_arn = aws_secretsmanager_secret.dockerhub_creds.arn
}

GitHub Container Registry キャッシュ設定

resource “aws_ecr_pull_through_cache_rule” “ghcr” {
ecr_repository_prefix = “ghcr”
upstream_registry_url = “ghcr.io”
credential_arn = aws_secretsmanager_secret.ghcr_creds.arn
}

Quay.io キャッシュ設定

resource “aws_ecr_pull_through_cache_rule” “quay” {
ecr_repository_prefix = “quay”
upstream_registry_url = “quay.io”
}

Docker Hub 認証情報 (Secrets Manager)

resource “aws_secretsmanager_secret” “dockerhub_creds” {
name = “ecr-pullthroughcache/dockerhub”
}

resource “aws_secretsmanager_secret_version” “dockerhub_creds” {
secret_id = aws_secretsmanager_secret.dockerhub_creds.id
secret_string = jsonencode({
username = var.dockerhub_username
accessToken = var.dockerhub_token
})
}
“`text
Pull-Through Cache 経由での Image Pull

“`bash

AWS アカウントID取得

ACCOUNT_ID=$(aws sts get-caller-identity –query Account –output text)
REGION=”ap-northeast-1″

Docker Hub の nginx:alpine を ECR キャッシュ経由で取得

docker pull ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/dockerhub/library/nginx:alpine

GitHub Container Registry の Image をキャッシュ経由で取得

docker pull ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/ghcr/org/repo:tag

ECS Task Definition での参照 (Docker Hub → ECR キャッシュ経由)

image: “123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/dockerhub/library/node:20-alpine”

“`text
Pull-Through Cache の利点

  • Docker Hub 匿名制限 (100回/6時間) → ECR経由で制限回避
  • VPC内閉域化: ECR VPC Endpoint 経由でインターネット非経由 pull 実現
  • Audit証跡: CloudTrail に全 pull 記録(Who/When/What)
  • コスト削減: 同一Imageの複数Task pull がキャッシュヒット

4-3. Cross-Region Replication — 本番東京→大阪DR設定

ECR Cross-Region Replication で Image を自動複製し、DR時の復旧時間を最小化する。

Cross-Region Replication 設定 (Terraform)

“`hcl
resource “aws_ecr_replication_configuration” “main” {
replication_configuration {
# 東京 → 大阪DR レプリケーション
rule {
destination {
region= “ap-northeast-3” # 大阪
registry_id = data.aws_caller_identity.current.account_id
}

  repository_filter {
 filter= "myapp/"# myapp/ prefix のリポジトリのみ
 filter_type = "PREFIX_MATCH"
  }
}

# 東京 → バージニア (グローバル展開時)
rule {
  destination {
 region= "us-east-1"
 registry_id = data.aws_caller_identity.current.account_id
  }

  repository_filter {
 filter= "myapp/global-"# グローバル向けImageのみ
 filter_type = "PREFIX_MATCH"
  }
}

}
}

data “aws_caller_identity” “current” {}
“`text
クロスアカウント + クロスリージョン レプリケーション

“`hcl

本番アカウント (東京) → DR アカウント (大阪) へのレプリケーション

resource “aws_ecr_replication_configuration” “cross_account” {
replication_configuration {
rule {
destination {
region= “ap-northeast-3”
registry_id = var.dr_account_id # DR専用AWSアカウント
}

  repository_filter {
 filter= "myapp/production/"
 filter_type = "PREFIX_MATCH"
  }
}

}
}

DR アカウント側: レプリケーション受け入れポリシー

resource “aws_ecr_registry_policy” “dr_replication_policy” {
provider = aws.dr_region

policy = jsonencode({
Version = “2012-10-17”
Statement = [
{
Sid = “AllowReplicationFromProd”
Effect = “Allow”
Principal = {
AWS = “arn:aws:iam::${var.prod_account_id}:root”
}
Action = [
“ecr:CreateRepository”,
“ecr:ReplicateImage”
] Resource = “arn:aws:ecr:ap-northeast-3:${var.dr_account_id}:repository/
}
] })
}
“`text
DR切り替え手順 (大阪リージョン)*

“`bash

DR切り替え時: 大阪リージョンのECRからImageを確認

aws ecr describe-repositories \
–region ap-northeast-3 \
–query ‘repositories[?contains(repositoryName, myapp/)].repositoryName’

DR用ECSクラスターでImageが利用可能か確認

aws ecr list-images \
–repository-name myapp/backend \
–region ap-northeast-3 \
–query ‘imageIds[?imageTag!=null]’
“`text


4-4. Lifecycle Policy — Image削除自動化で ECRストレージ費を制御

標準Lifecycle Policy (Terraform)

“`hcl
resource “aws_ecr_lifecycle_policy” “app” {
repository = aws_ecr_repository.app.name

policy = jsonencode({
rules = [
{
# ルール1: untagged Imageを7日後に削除
rulePriority = 1
description = “untagged Image: 7日後削除”
selection = {
tagStatus= “untagged”
countType= “sinceImagePushed”
countUnit= “days”
countNumber = 7
}
action = { type = “expire” }
},
{
# ルール2: tagged Imageは最新10件を保持 (それ以外削除)
rulePriority = 2
description = “tagged Image: 最新10件以外削除”
selection = {
tagStatus = “tagged”
tagPrefixList = [“v”, “release-“] countType = “imageCountMoreThan”
countNumber= 10
}
action = { type = “expire” }
},
{
# ルール3: latest タグは最新3件保持 (CI/CD上書き考慮)
rulePriority = 3
description = “latest tag: 最新3件保持”
selection = {
tagStatus = “tagged”
tagPrefixList = [“latest”] countType = “imageCountMoreThan”
countNumber= 3
}
action = { type = “expire” }
}
] })
}
“`text
環境別Lifecycle Policy 設定パターン

“`bash

本番: tagged 最新10件 / untagged 7日

ステージング: tagged 最新5件 / untagged 3日

開発: tagged 最新3件 / untagged 1日

Lifecycle Policy ドライラン (削除対象を確認してから適用)

aws ecr get-lifecycle-policy-preview \
–repository-name myapp/backend \
–image-ids imageTag=v1.0.0

既存リポジトリのストレージ使用量確認

aws ecr describe-repositories \
–query ‘repositories[].[repositoryName,createdAt]’ \
–output table
“`text

アンチパターン: Lifecycle Policy未設定でECRストレージ費爆増
Lifecycle Policy未設定のまま CI/CD が毎日Image push を継続すると、半年で以下の被害が発生する:

  • 蓄積量の試算: 1 Image = 200MB × 1日10 push × 180日 = 360GB / リポジトリ
  • 費用: 360GB × $0.10/GB = 月額$36 / リポジトリ。リポジトリ20個なら月額$720の無駄コスト
  • よくある見落とし: untaggedのみ削除設定で tagged が無限増殖するケース。semver tagを毎回付与するCI/CDパターンで特に発生
  • 正解パターン: untagged 7日後削除 + tagged 最新10件以外削除 をリポジトリ作成時に必ず設定。Terraformモジュール化で設定漏れを防ぐ
  • 発見方法: AWS Cost Explorer → ECR → リポジトリ別コスト確認。月額$10超のリポジトリはLifecycle Policy要確認

4-5. Image Signing — Notation によるサプライチェーン対策

Amazon ECR Image Signing (Notation) でイメージの完全性を保証し、署名なしImageのデプロイを防止する。

“`bash

Notation CLI インストール

brew install notation # macOS

または: curl -Lo notation.tar.gz https://github.com/notaryproject/notation/releases/…

AWS Signer で署名プロファイル作成

aws signer put-signing-profile \
–profile-name EcrImageSigningProfile \
–platform-id Notation-OCI-SHA384-ECDSA \
–signature-validity-period ‘{“value”: 365, “type”: “DAYS”}’

ECR にプッシュ済みImageに署名

notation sign \
–plugin com.amazonaws.signer.notation.plugin \
–id arn:aws:signer:ap-northeast-1:123456789012:/signing-profiles/EcrImageSigningProfile \
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp/backend:v1.2.0

署名検証

notation verify \
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp/backend:v1.2.0

ECS Task Definition での署名検証強制 (OPA/Admission Controller 連携)

→ 署名なしImageはデプロイ拒否するポリシーを CI/CD パイプラインに組み込む

“`text

4-6. 本番品質設定 — Repository Policy / KMS暗号化 / Encryption-at-Rest

Repository Policy (クロスアカウントアクセス制御)

“`hcl
resource “aws_ecr_repository_policy” “app” {
repository = aws_ecr_repository.app.name

policy = jsonencode({
Version = “2012-10-17”
Statement = [
{
# ECS タスク実行ロールのみ pull 許可
Sid = “AllowECSTaskExecution”
Effect = “Allow”
Principal = {
AWS = [
“arn:aws:iam::${var.account_id}:role/ecsTaskExecutionRole”,
“arn:aws:iam::${var.account_id}:role/myapp-task-execution-role”
] }
Action = [
“ecr:GetDownloadUrlForLayer”,
“ecr:BatchGetImage”,
“ecr:BatchCheckLayerAvailability”
]},
{
# CI/CD (CodeBuild) のみ push 許可
Sid = “AllowCodeBuildPush”
Effect = “Allow”
Principal = {
AWS = “arn:aws:iam::${var.account_id}:role/CodeBuildRole”
}
Action = [
“ecr:GetAuthorizationToken”,
“ecr:BatchCheckLayerAvailability”,
“ecr:GetDownloadUrlForLayer”,
“ecr:InitiateLayerUpload”,
“ecr:UploadLayerPart”,
“ecr:CompleteLayerUpload”,
“ecr:PutImage”
]}
] })
}

KMS キー (ECR 暗号化用)

resource “aws_kms_key” “ecr” {
description = “ECR Image暗号化キー”
deletion_window_in_days = 30
enable_key_rotation = true

policy = jsonencode({
Version = “2012-10-17”
Statement = [
{
Sid = “AllowECRUse”
Effect = “Allow”
Principal = {
Service = “ecr.amazonaws.com”
}
Action = [
“kms:GenerateDataKey”,
“kms:Decrypt”
] Resource = “*”
}
] })
}

resource “aws_kms_alias” “ecr” {
name = “alias/ecr-encryption”
target_key_id = aws_kms_key.ecr.key_id
}
“`text
VPC Endpoint 経由のプライベート ECR アクセス

“`hcl

ECR VPC Endpoint (インターネット非経由でECR接続)

resource “aws_vpc_endpoint” “ecr_api” {
vpc_id = aws_vpc.main.id
service_name = “com.amazonaws.ap-northeast-1.ecr.api”
vpc_endpoint_type= “Interface”
subnet_ids = aws_subnet.private[*].id
security_group_ids = [aws_security_group.vpc_endpoints.id] private_dns_enabled = true
}

resource “aws_vpc_endpoint” “ecr_dkr” {
vpc_id = aws_vpc.main.id
service_name = “com.amazonaws.ap-northeast-1.ecr.dkr”
vpc_endpoint_type= “Interface”
subnet_ids = aws_subnet.private[*].id
security_group_ids = [aws_security_group.vpc_endpoints.id] private_dns_enabled = true
}

S3 Gateway Endpoint (Layer データはS3経由)

resource “aws_vpc_endpoint” “s3” {
vpc_id= aws_vpc.main.id
service_name= “com.amazonaws.ap-northeast-1.s3”
vpc_endpoint_type = “Gateway”
route_table_ids= [aws_route_table.private.id]}
“`text

ECR本番運用5原則

  • 原則1: Image Tag Immutability 必須IMMUTABLE 設定でtag上書きによる意図しないImage入れ替えを防止。latest タグ運用は staging のみ許容
  • 原則2: KMS暗号化 必須 — デフォルトAES-256では規制対応不可。KMS CMKで鍵ローテーション+CloudTrail監査を確保
  • 原則3: Lifecycle Policy をリポジトリ作成時に必ず設定 — Terraform モジュール内でセットで定義し設定漏れを構造的に防止
  • 原則4: Enhanced Scan で言語パッケージCVEを継続監視 — OS脆弱性はBaseImage更新で対応できるが、pip/npm依存のCVEはEnhancedでしか検知不可
  • 原則5: VPC Endpoint 経由の閉域アクセス — ECR API + ECR DKR + S3 の3 Endpoint設定でFargateからインターネット非経由pull実現

4-7. ECR関連コストの最適化

“`bash

リポジトリ毎のImage数とストレージ確認スクリプト

aws ecr describe-repositories \
–query ‘repositories[].repositoryName’ \
–output text | \
tr ‘\t’ ‘\n’ | \
xargs -I {} sh -c \
‘COUNT=$(aws ecr list-images –repository-name {} –query “length(imageIds)” –output text); \
echo “{}: ${COUNT} images”‘

コスト最適化チェックリスト

[ ] Lifecycle Policy 設定済み (全リポジトリ)

[ ] Enhanced Scan は必要なリポジトリのみ有効化

[ ] Pull-Through Cache で Docker Hub Rate Limit 対策済み

[ ] VPC Endpoint 設定で Data Transfer コスト削減済み

[ ] Cross-Region Replication は production prefix のみ (開発ImageはReplication不要)

“`text
関連記事 — セキュリティ / DevOps / マルチアカウント統合

ECRのセキュリティ設定はAWS全体のセキュリティ基盤と連携する。以下のシリーズと組み合わせてContainer本番運用のセキュリティを完成させよ:

5. ECS Exec本番運用 — SSH置き換え + Session Manager連携

5-1. ECS Execとは — Containerへの直接アクセス革命

ECS Exec は、ECS Task 上で動作するコンテナに対して直接シェルセッションを開く機能です。AWS Systems Manager Session Manager をトランスポート層として活用し、SSH・踏み台サーバー不要でコンテナへの安全なアクセスを実現します。

従来の SSH ベース運用では以下の問題が発生していました。

  • 踏み台サーバー (Bastion Host) の維持管理コスト(EC2費用・パッチ管理・HA構成)
  • Port 22 の開放によるセキュリティリスク(インターネット向けSSHスキャン攻撃)
  • SSH キー管理の複雑さ(キーの発行・失効・ローテーション)
  • 接続ログの分散(誰がいつ何をしたか追跡困難、インシデント時の証跡不足)

ECS Exec はこれらを根本解決します。Session Manager 経由でセッションを確立し、CloudTrail が全操作を自動記録するため、監査証跡が完全に残ります。コンテナへのアクセスは IAM ポリシーで制御され、SSH キー管理は不要です。

ECS Exec 本番運用5原則

  • 原則1: ECS Exec 有効化で SSH/Bastion Host を完全廃止し、Port 22 を全Security Groupから削除
  • 原則2: Session録画を S3 + CloudWatch Logs に強制設定 (監査・コンプライアンス必須)
  • 原則3: IAM Policy に Condition (PrincipalTag / RequestedRegion) で本番アクセスをSREのみに制限
  • 原則4: Task Role と Task Execution Role を厳格分離 (Task RoleにSSM権限 / Execution RoleにECR権限)
  • 原則5: 緊急時のみ ECS Exec 使用 / 通常運用は ECS Service 経由デプロイで完結

5-2. ECS Exec有効化手順 — Task Definition + IAM Role + Service更新

ECS Exec を有効化するには3つのコンポーネントの設定が必要です。

Step 1: Task Role に Session Manager トランスポート権限を付与

ECS Exec は Session Manager をトランスポートとして利用するため、Task Role に ssmmessages の権限が必要です。

json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetEncryptionConfiguration"
],
"Resource": [
"arn:aws:s3:::prod-ecs-exec-audit",
"arn:aws:s3:::prod-ecs-exec-audit/*"
] },
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:ap-northeast-1:ACCOUNT_ID:log-group:/ecs-exec/*"
},
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": "arn:aws:kms:ap-northeast-1:ACCOUNT_ID:key/YOUR-KMS-KEY-ID"
}
]}
text
Step 2: Task Definition の linuxParameters と executeCommandConfiguration 設定

“`hcl
resource “aws_ecs_task_definition” “api” {
family = “api-task”
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

container_definitions = jsonencode([{
name = “api”
image = “${aws_ecr_repository.api.repository_url}:latest”
portMappings = [{ containerPort = 8080, protocol = “tcp” }]

linuxParameters = {
  initProcessEnabled = true
}

logConfiguration = {
  logDriver = "awslogs"
  options = {
 "awslogs-group"= "/ecs/api"
 "awslogs-region"  = "ap-northeast-1"
 "awslogs-stream-prefix" = "ecs"
  }
}

}])
}

resource “aws_ecs_cluster” “production” {
name = “production-cluster”

configuration {
execute_command_configuration {
kms_key_id = aws_kms_key.ecs_exec.arn
logging = “OVERRIDE”

  log_configuration {
 cloud_watch_encryption_enabled = true
 cloud_watch_log_group_name  = "/ecs-exec/sessions"
 s3_bucket_name  = aws_s3_bucket.ecs_exec_audit.bucket
 s3_bucket_encryption_enabled= true
 s3_key_prefix= "sessions/"
  }
}

}
}

resource “aws_ecs_service” “api” {
name= “api-service”
cluster= aws_ecs_cluster.production.id
task_definition = aws_ecs_task_definition.api.arn
desired_count= 2

enable_execute_command = true

capacity_provider_strategy {
capacity_provider = “FARGATE”
base = 1
weight= 70
}
capacity_provider_strategy {
capacity_provider = “FARGATE_SPOT”
weight= 30
}
}
“`text
Step 3: ECS Exec でコンテナへ接続

“`bash

稼働中のTask IDを取得

TASK_ARN=$(aws ecs list-tasks \
–cluster production-cluster \
–service-name api-service \
–query ‘taskArns[0]’ \
–output text)

ECS Exec でコンテナに接続 (Session Manager経由)

aws ecs execute-command \
–cluster production-cluster \
–task “${TASK_ARN}” \
–container api \
–interactive \
–command “/bin/sh”

接続確認 — 以下が実行されたら成功

The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.

Starting session with SessionId: ecs-execute-command-xxxxxxxx

“`text

5-3. Session Manager連携 — CloudTrail監査 + S3セッション録画

ECS Exec は Session Manager をトランスポートとして使用します。この連携により、コンテナへのアクセスに関する詳細な監査証跡が自動生成されます。

CloudTrail による ExecuteCommand 記録

ExecuteCommand API コールは CloudTrail Management Events に自動記録されます。ログには who(呼び出し元 IAM プリンシパル)・when(タイムスタンプ)・which task(Task ARN)が含まれます。

S3 セッション録画の確認

セッション録画は設定した S3 バケットに .log 形式で保存されます。

“`bash

セッション録画の一覧確認

aws s3 ls s3://prod-ecs-exec-audit/sessions/ –recursive

セッション内容の確認 (全コマンド・出力が記録)

aws s3 cp s3://prod-ecs-exec-audit/sessions/SESSION_ID.log – | less
“`text
録画ファイルには、コンテナ内で実行したすべてのコマンドとその出力が含まれます。PCI-DSS 要件の「特権アクセス全記録」や、SOC 2 の「アクセス制御証跡」に対応可能です。

5-4. SSH置き換え運用 — Bastion Host完全廃止への移行

ECS Exec 導入後、既存の SSH ベース運用から段階的に移行します。

移行ステップ

  1. ECS Exec の有効化と動作確認 (本番並行期間: 2週間)
    すべてのエンジニアが ECS Exec で接続できることを確認。Bastion Host は残したまま。

  2. 踏み台サーバーへのアクセス件数モニタリング
    CloudTrail で SSH 接続 (Bastion へのインバウンドフロー) が0件になるまで待機。

  3. エンジニア全員への ECS Exec 手順共有・トレーニング
    Runbook に ECS Exec 接続手順を記載。インシデント対応 Runbook — 復旧手順自動化ガイド のフォーマットで標準化。

  4. Security Group から Port 22 (inbound) を削除
    接続不能を確認後、全 Security Group の SSH inbound ルールを削除。

  5. 踏み台サーバーの停止・終了
    EC2 コスト削減 + 攻撃対象面 (Attack Surface) の縮小を達成。

5-5. 監査要件対応 — IAM Condition で Production アクセス制限

本番環境では、ECS Exec の使用を特定の IAM Principal と時間帯に制限することで、ゼロトラスト原則に基づくアクセス制御を実現します。

json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowECSExecSREOnly",
"Effect": "Allow",
"Action": "ecs:ExecuteCommand",
"Resource": "arn:aws:ecs:ap-northeast-1:ACCOUNT_ID:task/production-cluster/*",
"Condition": {
"StringEquals": {
"aws:PrincipalTag/Role": "SRE",
"aws:RequestedRegion": "ap-northeast-1"
}
}
},
{
"Sid": "DenyECSExecNonSRE",
"Effect": "Deny",
"Action": "ecs:ExecuteCommand",
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:PrincipalTag/Role": "SRE"
}
}
}
]}
text
この設定では Role=SRE タグを持つ IAM ユーザーのみが本番コンテナへ接続できます。緊急アクセスのたびに承認フローを経由させる Just-In-Time アクセス運用が可能になります。

セキュリティ設計の詳細はセキュリティ運用 Vol1 — IAM最小権限設計 + CloudFront WAF多層防御を参照してください。

ECS Exec 有効化チェックリスト

  • ☑ Task Role に ssmmessages 4権限 (CreateControlChannel / OpenControlChannel / CreateDataChannel / OpenDataChannel) を付与
  • ☑ Task Role に S3 PutObject 権限 (監査ログバケット対象) を付与
  • ☑ Task Role に KMS Decrypt / GenerateDataKey 権限を付与
  • ☑ Task Definition の linuxParameters.initProcessEnabled = true を設定
  • ☑ ECS Cluster の executeCommandConfiguration で S3 + CloudWatch Logs 録画先を設定
  • ☑ ECS Service の enable_execute_command = true を設定
  • ☑ S3 録画バケットに SSE-KMS 暗号化 + バケットポリシー (Task Role のみ PutObject 許可) を適用
  • ☑ IAM Policy の Condition で SRE 以外の ExecuteCommand を Deny
  • ☑ CloudTrail Management Events で ExecuteCommand ログ記録を確認
  • ☑ 既存 Security Group から Port 22 inbound ルールを削除完了

セキュリティ運用 Vol1 — IAM最小権限設計の詳細


6. Service Connect本番運用 — App Mesh後継 / Service Discovery / Observability

6-1. Service Connectとは — ECS Native Service Mesh

Service Connect は ECS に組み込まれた Service Mesh 機能です。App Mesh(AWS Managed Envoy ベース)の後継として 2022 年 re:Invent で一般提供が開始されました。App Mesh は廃止予告済みのため、新規採用は Service Connect 一択です。

Service Connect の主要特徴:

  • ECS Native 統合: ECS Service 設定のみで有効化。独立した Mesh リソースや CDK/CloudFormation カスタムリソースが不要
  • 透過的なトラフィック制御: Envoy ベースのサイドカーが自動注入。アプリケーションコードの変更ゼロ
  • Cloud Map 統合: DNS ベースの Service Discovery を Cloud Map が提供。サービス名でサービスを参照
  • Observability 標準搭載: CloudWatch へのメトリクス自動送信(追加エージェント不要)
  • mTLS サポート: ACM Private CA と連携したサービス間 mutual TLS 認証

従来のマイクロサービス間通信で発生していた問題(エンドポイント URL のハードコード・DNS 名変更時の障害・サービス間 TLS 実装コスト)を、Service Connect が透過的に解決します。

fig04: Service Connect Service Discovery + ALB Sidecar構成

6-2. Cloud Map Service Discovery統合 — DNS-based service-to-service通信

Service Connect は AWS Cloud Map と統合し、DNS ベースの Service Discovery を実現します。各 ECS Service が Cloud Map に自動登録され、サービス名で他のサービスから参照できます。

“`hcl
resource “aws_service_discovery_private_dns_namespace” “production” {
name = “production.local”
description = “Production ECS Service Connect namespace”
vpc= aws_vpc.main.id

tags = {
Environment = “production”
ManagedBy= “terraform”
}
}

resource “aws_ecs_service” “api” {
name= “api-service”
cluster= aws_ecs_cluster.production.id
task_definition = aws_ecs_task_definition.api.arn
desired_count= 3

service_connect_configuration {
enabled= true
namespace = aws_service_discovery_private_dns_namespace.production.arn

service {
  port_name= "api-http"
  discovery_name = "api"

  client_alias {
 port  = 8080
 dns_name = "api.production.local"
  }
}

log_configuration {
  log_driver = "awslogs"
  options = {
 "awslogs-group"= "/ecs/service-connect"
 "awslogs-region"  = "ap-northeast-1"
 "awslogs-stream-prefix" = "envoy"
  }
}

}

deployment_circuit_breaker {
enable= true
rollback = true
}
}
``text
この設定により
api.production.local:8080` でサービスに到達できます。IP アドレスや変動するエンドポイントをハードコードする必要がなくなります。Cloud Map がヘルスチェック結果に基づいて自動的に死活管理を行います。

6-3. mermaid02: Service Connect Service Discovery シーケンス

“`mermaid
sequenceDiagram
participant Frontend as Frontend Service
participant Envoy as Envoy Sidecar
(Service Connect)
participant CloudMap as AWS Cloud Map
participant Backend as Backend Service

Frontend->>Envoy: HTTP Request to backend.production.local:8080
Envoy->>CloudMap: DNS Query (backend.production.local)
CloudMap-->>Envoy: Resolve → 10.0.1.42:8080 (Backend Task IP)
Envoy->>Envoy: Apply policy (retry / circuit breaker / timeout)
Envoy->>Backend: Forward Request (mTLS encrypted)
Backend-->>Envoy: HTTP Response
Envoy-->>Frontend: Forward Response
Envoy->>Envoy: Emit metrics to CloudWatch
Note over Envoy: RequestCount / Latency(P50/P95/P99)<br/>ErrorRate → CloudWatch Container Insights

``text
フロントエンドサービスは
backend.production.local` という DNS 名でバックエンドにアクセスします。Envoy サイドカーが Cloud Map で名前解決し、mTLS 暗号化でトラフィックを転送します。サーキットブレーカー・リトライ・タイムアウトポリシーも Envoy が透過的に適用します。この全過程が CloudWatch に自動記録されます。

6-4. TLS暗号化 — mutual TLS とService-to-Service認証

Service Connect は mutual TLS (mTLS) をサポートします。サービス間通信を暗号化し、証明書ベースの相互認証を実現します。

mTLS を有効化すると、各 Envoy サイドカーに ACM Private CA から証明書が自動発行されます。証明書の更新は自動化されており、運用負荷なしにサービス間通信のセキュリティを維持できます。

mTLS 設定 (Terraform)

“`hcl
resource “aws_acmpca_certificate_authority” “production” {
certificate_authority_configuration {
key_algorithm = “RSA_2048”
signing_algorithm = “SHA256WITHRSA”

subject {
  common_name  = "production.local"
  organization = "MyCompany"
}

}

type = “ROOT”
}

resource “aws_ecs_service” “backend” {
name = “backend-service”
cluster = aws_ecs_cluster.production.id

service_connect_configuration {
enabled= true
namespace = aws_service_discovery_private_dns_namespace.production.arn

service {
  port_name= "backend-http"
  discovery_name = "backend"

  tls {
 issuer_cert_authority {
aws_pca_authority_arn = aws_acmpca_certificate_authority.production.arn
 }
 kms_key  = aws_kms_key.service_connect.arn
 role_arn = aws_iam_role.service_connect_tls.arn
  }

  client_alias {
 port  = 8080
 dns_name = "backend.production.local"
  }
}

}
}
“`text
mTLS により、未認証のサービスからの接続を Envoy レベルで拒否します。コンテナ侵害時の横展開 (Lateral Movement) リスクを大幅に低減できます。

6-5. Observability — CloudWatch Container Insights + ADOT統合

Service Connect は CloudWatch Container Insights と標準統合されており、サービス間通信の以下のメトリクスを自動収集します。

メトリクス説明推奨アラート閾値
RequestCount受信リクエスト総数急増検知 (5分で平常比300%)
RequestFailedCount4xx / 5xx エラー数ErrorRate > 5% で通知
TargetResponseTimeバックエンド応答時間P99 > 500ms で通知
ConnectionCount同時接続数上限の80%超で通知

Container Insights Enhanced 有効化 + CloudWatch Alarm 設定

“`bash

ECS Cluster レベルで Container Insights Enhanced を有効化

aws ecs update-cluster-settings \
–cluster production-cluster \
–settings name=containerInsights,value=enhanced

Service Connect エラー率アラームの作成

aws cloudwatch put-metric-alarm \
–alarm-name “ServiceConnect-ErrorRate-High” \
–alarm-description “Service Connect error rate exceeded 5%” \
–metric-name “RequestFailedCount” \
–namespace “ECS/ContainerInsights” \
–dimensions Name=ClusterName,Value=production-cluster \
Name=ServiceName,Value=api-service \
–statistic Sum \
–period 300 \
–evaluation-periods 2 \
–threshold 50 \
–comparison-operator GreaterThanThreshold \
–alarm-actions “arn:aws:sns:ap-northeast-1:ACCOUNT_ID:production-alerts”

P99 レイテンシアラームの作成

aws cloudwatch put-metric-alarm \
–alarm-name “ServiceConnect-P99Latency-High” \
–alarm-description “Service Connect P99 latency exceeded 500ms” \
–metric-name “TargetResponseTime” \
–namespace “ECS/ContainerInsights” \
–dimensions Name=ClusterName,Value=production-cluster \
Name=ServiceName,Value=api-service \
–extended-statistic p99 \
–period 300 \
–evaluation-periods 3 \
–threshold 0.5 \
–comparison-operator GreaterThanThreshold \
–alarm-actions “arn:aws:sns:ap-northeast-1:ACCOUNT_ID:production-alerts”
“`text
ADOT (AWS Distro for OpenTelemetry) と統合することで、トレースデータを X-Ray に送信し、サービス間の依存関係マップと分散トレーシングが実現します。

Observability の詳細設計はObservability Vol1 — CloudWatch Application Signals × ADOT統合を参照してください。

6-6. App Mesh移行手順 — 段階的移行パターン

既存の App Mesh 環境から Service Connect への移行は、以下の段階的アプローチを推奨します。App Mesh は廃止予告済みのため、早期移行が推奨されます。

移行フェーズ

Phase 1: 評価 (1〜2週間)
– Service Connect の機能要件確認(mTLS / Cloud Map / Observability)
– App Mesh で使用している Virtual Router / Virtual Service のマッピング整理
– 移行対象サービスの優先順位設定(非クリティカルサービスから開始)

Phase 2: 並行稼働 (2〜4週間)
– 新規サービスは Service Connect で構築
– 既存サービスは App Mesh のまま維持
– Service Connect サービス間の通信確認

Phase 3: 段階移行 (サービスごとにローリング)

“`bash

App Mesh Virtual Node を削除した新 Task Definition を作成

Terraform で service_connect_configuration を追加

ローリングデプロイで旧タスクを置き換え

aws ecs update-service \
–cluster production-cluster \
–service legacy-api-service \
–task-definition api-with-service-connect:3 \
–force-new-deployment

デプロイ完了確認 (全タスクが新 revision に置き換わったことを確認)

aws ecs wait services-stable \
–cluster production-cluster \
–services legacy-api-service

App Mesh Virtual Node 削除

aws appmesh delete-virtual-node \
–mesh-name production-mesh \
–virtual-node-name api-node
“`text
Phase 4: App Mesh 廃止
– すべてのサービスが Service Connect に移行完了
– App Mesh Mesh リソース全削除
– App Mesh の料金($0.009/インバウンドリクエスト 1,000 件)がゼロになる

IaC を活用した段階的移行の詳細はecspresso × Terraform 統合ガイドを参照してください。

Service Connect 本番運用5原則

  • 原則1: 全マイクロサービス間通信は Service Connect 経由 (ハードコード DNS / IP は禁止)
  • 原則2: Cloud Map namespace を環境別 (dev.local / staging.local / production.local) で完全分離
  • 原則3: mutual TLS 必須 — ACM Private CA で証明書自動発行・自動更新を実現
  • 原則4: CloudWatch Container Insights enhanced で RequestCount / Latency (P99) / ErrorRate を常時監視
  • 原則5: App Mesh は新規採用禁止 (廃止予告済み / Service Connect 一択)
アンチパターン: App Mesh 新規採用
App Mesh は廃止予告済みのサービスです。2023年以降、新機能の追加は停止されており、既存ユーザーへのサポートは継続されているものの、新規プロジェクトでの採用は避けるべきです。App Mesh を選択してしまうと、将来的な Service Connect への強制移行が必要になり、移行工数が発生します。新規プロジェクトは Service Connect を採用し、既存の App Mesh 環境は本ガイドの移行フェーズに沿って順次移行してください。なお、App Mesh 移行先として Amazon VPC Lattice も選択肢に挙がりますが、ECS ネイティブ統合の観点では Service Connect が最も運用コストが低い選択肢です。

Network Vol2 — VPC / Transit Gateway / PrivateLink 設計の詳細

Observability Vol1 — ADOT × CloudWatch Application Signals 統合

7. 詰まりポイント7選 + アンチパターン演習5問

ECS × Fargate × ECR × ECS Exec × Service Connect の5本柱を本番導入した際に、現場で直面する7つの詰まりポイントを体系化した。全13軸の知識を保有するエンジニアでも踏みやすい落とし穴であり、事前把握が本番インシデント防止の最短経路だ。各詰まりには「発生する具体的問題」と「本番実装の解決策」を対で示す。

詰まり1: Task Definition revision 履歴爆増 — Lifecycle戦略が必須

ECSのTask Definitionはデプロイのたびに新しいrevisionが生成される設計だ。Lifecycle Policyを未設定のまま運用を続けると、CI/CDパイプラインで毎日デプロイが走るシステムでは3か月で数百、半年で数千のrevisionが蓄積する。GitリポジトリはPRマージでコードが上書きされていくが、ECSのTask Definitionは一度作成したrevisionが削除されない設計になっている点がEC2やLambdaと大きく異なる。

発生する具体的問題:
list-task-definitions APIのレスポンスが数万件規模に膨張しタイムアウト頻発
– デプロイスクリプトがlatest revisionを特定できずオペレーションミスを誘発
– AWS Console上の一覧が長大すぎて目視確認が現実的でなくなる
– describe-task-definition の呼び出しがAPI Rate Limitに引っかかりCIが断続的に失敗する

解決策: Task Definition Lifecycle Policyによるrevision自動管理

ECS Task Definition Lifecycle Policy (2024年GA) を使い、非アクティブ状態のrevisionを指定期間後に自動アーカイブまたは削除する。推奨設定は「INACTIVE状態90日経過後に削除 / 最新10 revisionを常時保持」だ。Terraformでは専用リソースで宣言的に管理し、既存リポジトリにはCIパイプラインの初期ステップにLifecycle Policy適用を組み込む。

本番適用のポイント: ロールバック対象となるrevisionには明示的な「keep」タグを設定し削除対象から除外する。また、Lifecycle Policy設定前に既存のrevisionを棚卸しし、現在ACTIVEなrevisionのリストをCMDBまたはドキュメントとして保管しておくと移行時の混乱を防げる。デプロイスクリプトはLatest revisionではなく特定の revision番号を明示参照するよう設計することが、Lifecycle Policy導入後の安定運用につながる。

詰まり2: Fargate cold start 15-30秒でAPI SLA違反 — warm pool/SLA設計

FargateのスケールアウトはEC2インスタンス上のコンテナランタイム起動 + イメージpull + アプリケーション初期化のすべてを含むため、最短でも15秒、JVM系アプリや大容量イメージでは30〜60秒を要する。急激なトラフィック増加に対してCloudWatchアラームのevaluation periodとcold start遅延が加算される点が設計上の最大の罠だ。EC2 Auto Scalingとは異なり、FargateはインスタンスではなくTask単位でキャパシティが管理されるため、cold startの特性を設計に織り込むことが不可欠だ。

発生する具体的問題:
– CloudWatchアラームのevaluation period 2分 + cold start 30秒 = 約2.5分の空白期間が発生
– P99レイテンシがSLA (3秒以内) を大幅超過するスパイクが周期的に発生しSLAレポートを汚染する
– スケールアウト直後の新タスクにALBがヘルスチェック通過前にトラフィックを流入させてしまう
– 「Auto Scalingが機能していない」と誤解しスケールアウト閾値をさらに下げる悪循環に陥る

解決策: warm-up period設定 + SLA設計での吸収

Application Auto Scalingのターゲット追跡ポリシーでwarm-up period (300秒) を設定し、cold start中のタスクをScaling計算から除外する。ALBのターゲットグループではderegistration delay (60〜90秒) を適切に設定し、既存タスクの接続完結後にドレインする。SLA設計ではcold start 30秒をP99バッファとして吸収し、常時最低タスク数をdesiredCount × 1.2に設定する余剰確保が安定運用の現実解だ。

本番適用のポイント: コンテナイメージのサイズを最小化することでcold start時間を短縮できる。Multi-stage buildでビルド成果物のみを含むslimイメージを作成し、Graviton (ARM64) に切り替えることでコスト削減と起動速度改善を同時に達成する。イメージサイズは200MB以下を目標とし、ECR Pull-Through Cacheを活用することでDocker Hub rate limitを回避しながらpull時間を短縮する設計が推奨される。

詰まり3: ECR脆弱性スキャン放置でCVE本番流入 — Enhanced Scan自動アラート

ECRリポジトリのデフォルトはBasicスキャン (push時1回のみ) だ。新しいCVEは毎日数十件のペースで発見されるため、「push時にスキャン済み」という状態が数日後には深刻な脆弱性を抱えたイメージに変わる。Basicスキャンはpush時のOSパッケージのみを対象としており、Pythonパッケージ (pip) やNode.js (npm) 依存ライブラリのCVEは検出できない。

発生する具体的問題:
– push時にCVEゼロでも2週間後にOSパッケージの新CVEが発見され本番コンテナに残存し続ける
– PCI-DSS / SOC2の規制監査で「継続的スキャン」要件を満たせず指摘を受ける
– 脆弱性検出から対応完了までのリードタイムが測定不能でSLAが設定できない
– 複数リポジトリのスキャン結果を横断的に管理するダッシュボードが存在しない

解決策: Enhanced Scan + Inspector V2 + EventBridge自動アラート体制

Amazon Inspector V2との統合によるContinuous Scanning (Enhanced Scan) を全リポジトリで有効化する。CVSSスコア7.0以上をCriticalとしてEventBridge → SNS → PagerDuty通知を即時発報し、4.0〜6.9をHighとして週次レポートに集約する。CI/CDパイプライン内でInspectorスキャン結果をAPIで確認し、Critical CVEが存在する場合はデプロイをブロックするゲートを設ける。

本番適用のポイント: Enhanced Scanの費用は月額$0.09/イメージだが、CVEインシデント対応コスト (人件費・サービス停止損失) と比較すると投資対効果は明らかだ。スキャン対象を絞り込む場合は、本番デプロイに使用するタグ付きイメージのみをEnhanced Scan対象とし、開発中のuntaggedイメージはBasicスキャンで十分なケースが多い。また、Inspector Findingsを定期的にS3にエクスポートし、SIEMや一元管理ツールに取り込むことで組織横断の脆弱性管理ダッシュボードを構築できる。

詰まり4: Service Auto Scaling遅延でBlack Friday落ち — Target Tracking+Scheduled Scaling

Auto Scalingのデフォルト設定では、CPU使用率が閾値を超えてからCloudWatchアラーム → Scaling Policy実行 → タスク起動 → ヘルスチェック通過 → ALBトラフィック受信まで最低5〜10分かかる。段階的に増えるトラフィックには追いつくが、瞬間的なスパイク (セール開始・TV放映・ニュース流入) には間に合わない。

発生する具体的問題:
– Black Fridayのセール開始0秒でトラフィックが5倍に急増し5分間503エラーが累積する
– Scaling実行中に重ねてアラームが発報し意図した台数以上にタスクが増加するオーバーシュート
– スケールイン cooldown が短すぎてトラフィック変動のたびにタスク数がフラッピングしコストが増大
– Scheduled Scaling未設定でBlack Friday当日にSREが手動でdesiredCountを変更する属人対応に陥る

解決策: Target Tracking + Scheduled Scalingの2段構え

Target Tracking (目標CPU使用率60%) を基本ポリシーとし、需要パターンが既知のイベント (Black Friday / 月次バッチ) にはScheduled Scalingで事前にdesiredCountを引き上げる2段構えが有効だ。イベント開始1時間前に最低タスク数を通常の3倍に設定し、終了後に通常値に戻すScheduled Actionを事前に登録する。スケールアウトcooldown 180秒・スケールイン cooldown 300秒以上をPolicyに設定しフラッピングを防ぐ。

本番適用のポイント: Application Load Balancerのアクティブリクエスト数 (RequestCountPerTarget) をカスタムメトリクスとしてAuto Scalingのターゲットに追加することで、CPU使用率に先行してスケールアウトを開始できる。ALBのターゲット値を300リクエスト/Taskに設定し、急増時のレスポンス時間悪化前にキャパシティを補充する設計が、APIサービスの安定運用において有効だ。

詰まり5: Container Insights未有効化でTroubleshoot困難 — Cluster作成時から必須化

ECS Container InsightsはCluster作成後に有効化することは可能だが、有効化前のメトリクスは遡れない。本番稼働後にOOMKillが多発してContainer Insightsを有効化しても、「OOMKillが起き始めたのはいつか」「どのタスクがメモリを消費していたか」を確認する術がない。新規Clusterを立ち上げた際のContainer Insights有効化は「後からやればいい」ではなく「今すぐやる」が鉄則だ。

発生する具体的問題:
– タスクが突然OOMKillされてもメモリ使用量の推移グラフが残っていない
– Service内の各タスクのCPU/Memory偏差が可視化されておらず右サイジングが勘頼みになる
– コンテナログがCloudWatch Logsに集約されていないためデバッグにECS Exec頼りになる
– CloudWatch Dashboardで表示できるECSメトリクスがCluster/Service単位の基本値のみに留まる

解決策: Cluster作成時にenhanced Container Insightsを必須化

TerraformでECS Cluster作成時にcontainerInsights enhanced設定を宣言し、インフラコードのレビューゲートでContainer Insights設定の存在を必須チェックに加える。FireLensサイドカー (Fluent Bit) をTask Definitionの標準テンプレートに組み込み、全コンテナログをCloudWatch Logs + S3に集約する設定を共通化する。enhancedモードではタスクレベルのネットワーク・ストレージメトリクスも取得でき、右サイジングの精度が飛躍的に向上する。

本番適用のポイント: Container Insightsの費用は収集メトリクス量に応じて課金される (東京リージョン: $0.30/メトリクス/月) が、CloudWatch Dashboardのカスタムウィジェットと組み合わせることでSREダッシュボードを低コストで構築できる。Fluentbit設定でログの重要度に応じてCloudWatch Logs (高頻度アクセス用) とS3 (長期保存用) に振り分けるTiered Logging設計を採用し、CloudWatch Logsのコストを月20〜30%削減することが現実的だ。

詰まり6: ECS Exec監査ログ漏れで規制違反 — S3録画強制設定

ECS ExecはSSH置き換えとして強力な機能だが、executeCommandConfigurationのlogConfigurationを明示的に設定しない限り、Session内のコマンド実行履歴はどこにも保存されない。有効化したことに満足し監査ログ設定を後回しにする現場が多い。ECS Execを「Bastion廃止のツール」として導入しても、監査ログなしでは規制対応の観点でBastionと同等のリスクを抱えることになる。

発生する具体的問題:
– 本番コンテナ内でのコマンド実行内容がログとして残らずインシデント事後調査が不可能
– PCI-DSS / HIPAA監査で「誰が何時どのコマンドを実行したか」を証明できず是正指摘を受ける
– IAMポリシーで実行者を制限してもコマンド内容が追跡できないためフォレンジックが機能しない
– 開発者が本番データを誤って参照・削除しても記録が残らず原因特定に長時間を要する

解決策: S3録画 + CloudWatch Logs + Object Lock による強制設定

executeCommandConfigurationを logging: ENABLED に設定し、S3バケット (KMS暗号化 + Object Lock WORM) とCloudWatch Logsグループの両方にセッション録画を送信する。S3バケットにはObject Lock (Governance Mode / Retention 365日) で改ざんを防止する。IAM Conditionで aws:PrincipalTag/Team = SRE を条件とし、本番環境へのECS Exec実行者をSREチームのみに制限するポリシーが規制対応のベストプラクティスだ。

本番適用のポイント: ECS Exec使用時には必ずJIRA/ServiceNow等のチケットIDをセッションタグとして付与し、監査ログとインシデントチケットを紐付ける運用を徹底する。CloudTrailのECS APIログとECS Exec Sessionログを相互参照できるアーキテクチャを構築し、「誰が・いつ・なぜ」本番コンテナにアクセスしたかを24時間以内に追跡できる体制を確立する。月次の監査ログレビューをSREの定例タスクに組み込むことで、見落としを防ぐ。

詰まり7: Service Connect未採用でハードコードDNS — Cloud Map namespace戦略

マイクロサービス構成で各サービスが互いをハードコードされたDNS名で参照しているシステムは、サービス追加や環境複製のたびにDNS設定の変更が必要になり運用コストが増大する。App Meshが廃止予告された現在、新規採用はService Connectへの移行を最優先とすべきだ。ハードコードDNSはマイクロサービスの独立デプロイという最大のメリットを損ない、サービス間の密結合を生み出す技術的負債の典型だ。

発生する具体的問題:
– 開発/ステージング/本番でエンドポイントが異なりアプリコードに環境依存のハードコードが混入する
– サービス増加につれてDNS名管理が属人化しどのサービスがどのエンドポイントを参照しているか把握不能
– App Meshに依存したシステムはAWSの廃止スケジュールに追われ強制的に移行コストが発生する
– サービス間の通信メトリクスが取得できないためレイテンシの原因特定に時間がかかる

解決策: Service Connect + Cloud Map namespace戦略

ECS Clusterに紐づくCloud Map Private DNS namespaceを環境別 (dev.local / staging.local / prod.local) に分離し、Service ConnectのserviceClientAliasesで各サービスに一貫した短縮名を割り当てる。アプリケーションコードはエンドポイントを環境変数経由で参照する設計にし、環境切り替えをTask Definitionの環境変数のみで完結させる。App Meshからの移行は1サービスずつBlue/Green方式で実施し、通信ログで動作確認後に切り替えるリスク低減策を取る。

本番適用のポイント: Service Connectの通信メトリクス (接続数・エラー率・レイテンシ) はCloudWatch Container Insightsに自動収集される。これを活用してサービスマップを可視化し、ボトルネックサービスを特定するObservability基盤を構築する。Cloud Map namespaceのDNS TTLは60秒以下に設定しサービス再起動後のDNS反映遅延を最小化する。Service Connect採用後は旧来のELB内部ルーティングを段階的に廃止し、Service Connect一本に集約することでコストと複雑性を削減する。

アンチパターン演習5問 — Container本番運用の設計判断力を鍛える実践問題

  • 演習1: Fargate Spot 100% → Capacity Provider Strategy 70:30混在
    本番APIをFargate Spot 100%で構成したところ、中断率が高負荷時に12%に達しAPIが断続的に停止するインシデントが発生した。Capacity Provider Strategyを用いてFargate Base (70%) + Fargate Spot (30%) の混在構成に変更し、Spot中断時もBaseタスクがリクエストを継続処理できる可用性設計を実施せよ。スケールアウト時のCapacity Provider重み付けと、中断通知 (2分前SIGTERM) のSIGTERMハンドラー実装を含めること。Spot中断率が15%を超えた場合にBase比率を80%へ自動変更するEventBridge Ruleも設計すること。
  • 演習2: ECR Basic → Enhanced Scan移行 (PCI-DSS規制対応)
    PCI-DSS準拠が求められたが、現在のECRリポジトリ20個はBasicスキャン (push時1回) のみ対応。Inspector V2統合のEnhanced Scan (Continuous Scanning) を全リポジトリで有効化し、CVSSスコア7.0以上のCritical CVEが検出された際にEventBridge → SNS → PagerDutyへ即時通知されるパイプラインを構築せよ。CI/CDデプロイゲートにInspectorスキャン結果APIチェックを追加し、Critical CVE存在時のデプロイブロックと対応チームへのSlack通知も実装すること。月次の脆弱性棚卸しレポートを自動生成するLambda関数も設計に含めること。
  • 演習3: SSH/Bastion → ECS Exec全廃 (Session Manager S3録画)
    本番コンテナへのアクセスにBastionサーバ+SSHキー (20名分) を使用していた。セキュリティ監査でBastionサーバ廃止が勧告された。ECS Execへ完全移行し、全セッションをS3 Object Lock (WORM) + CloudWatch Logsに録画し、IAM Conditionで本番ECS Exec実行者をSREチームのみに制限する構成を設計・実装せよ。SSHキーの無効化スケジュールと移行期間中の並行運用計画、移行後の規制監査対応手順書の作成も含めること。
  • 演習4: App Mesh → Service Connect移行 (段階的traffic shift)
    既存マイクロサービス (10サービス、月間トラフィック1億リクエスト) がApp Meshで構成されている。AWSの廃止スケジュールに向け段階移行を開始したい。Service ConnectのCloud Map namespaceを環境別 (dev/staging/prod) に設計し、1サービスずつBlue/Green方式でApp Mesh依存を切り離してService Connectに移行する12週間計画を策定せよ。各週の移行対象サービス選定基準、通信ログによる動作確認チェックリスト、全面移行完了後のApp Mesh削除手順とロールバック計画を含めること。
  • 演習5: x86_64 → ARM (Graviton) マルチアーキ移行 (docker buildx)
    全コンテナイメージ (15リポジトリ、各5〜8個のサービス) がx86_64でビルドされている。コスト最適化のためGraviton (ARM64) 対応Fargateタスクへ移行したい。docker buildx buildkitでMulti-Arch Image (linux/amd64 + linux/arm64) をビルドしECRにManifest List形式でpushし、Task DefinitionのruntimeにARM64を指定してFargate ARM64タスクとして起動する移行手順を設計せよ。リポジトリごとの移行優先順位付け基準、パフォーマンス比較テスト計画 (レイテンシ/スループット/CPU使用率)、移行前後のコスト削減試算も含めること。

8. まとめ + Vol2予告 + 落とし穴10選 + 全14軸クロスリンク

Vol1 習得5本柱の統合: Container本番運用設計力の確立

Container本番運用 Vol1では、ECS Cluster/Service/Task Definitionの基盤設計から始まり、Fargate (Spot/Graviton/cold start対策)、ECR (脆弱性スキャン/Lifecycle Policy/Pull-Through Cache)、ECS Exec (SSH廃止/監査ログ)、Service Connect (App Mesh後継/Cloud Map統合) の5本柱を体系的に習得した。

この5本柱が統合されることで初めて本番品質のContainer運用が実現する。5本柱の依存関係を整理すると:

  • ECS基盤 × DevOps: Task Definitionのrevision管理 + Lifecycle PolicyがCI/CDパイプラインと連動して初めて自動化が完結する
  • Fargate × Observability: Container InsightsとFireLensが有効化されて初めてFargateの右サイジングが可能になる
  • ECR × DevOps: Enhanced ScanのデプロイゲートがCI/CDパイプラインに組み込まれて初めてセキュリティが保証される
  • ECS Exec × IAM: IAM Conditionによる実行者制限とS3録画が組み合わさって初めて規制対応が完成する
  • Service Connect × Network: Cloud Map namespaceとawsvpcモードが連動して初めてマイクロサービス間通信が本番品質化する

全13軸 (IAM / EKS / 復旧 / AI / セキュリティ / コスト / マルチアカウント / Observability / Network / DevOps / Database / Serverless / IaC) の知識をこの5本柱に統合することで、第14軸 Container本番運用のハブ機能が完成する。第14軸はECSという1つの技術レイヤではなく、全13軸の知識が統合的に発揮される複合領域だ。

ECS本番化 段階的ロードマップ: 0日目〜180日目

本番ECS運用を0から立ち上げる際の標準ロードマップを示す。各フェーズの完了基準をチェックリスト化し、フェーズゲートを設けることで品質を担保する。

フェーズ1 (0〜30日): 基盤確立
ECS Cluster + awsvpcモード + Task Definition テンプレート化 + Fargate Base起動 + ALB連携 + Container Insightsを有効化する。ECRリポジトリを環境別 (dev/staging/prod) に分離しLifecycle PolicyとEnhanced Scanを設定する。CI/CDパイプライン (CodePipeline/GitHub Actions) でTask Definition自動更新とECR push→scan→deployの流れを確立する。

フェーズ2 (30〜90日): セキュリティ強化
ECS ExecでBastion廃止 + S3録画強制 + IAM Condition設定を完了する。Fargate SpotのCapacity Provider Strategy (70:30) を有効化しコストを最適化する。Graviton移行を段階的に実施しx86_64比20%のコスト削減を達成する。

フェーズ3 (90〜180日): マイクロサービス本番化
Service Connectを全サービスに展開しApp Mesh依存を完全排除する。Auto ScalingにScheduled Scalingを追加しBlack Friday対応を自動化する。全13軸統合のContainer本番運用ダッシュボードをCloudWatchで構築し、SREチームの運用効率を最大化する。

フェーズゲート (フェーズ間の完了基準):

  • フェーズ1 → 2移行条件: 本番ECSサービスが72時間無停止で稼働し、Container Insightsダッシュボードで全タスクのCPU/メモリが可視化されていること。ECR Enhanced Scanで本番イメージのCritical CVEがゼロであること。
  • フェーズ2 → 3移行条件: ECS Exec監査ログのS3録画が30日分蓄積されBastionサーバーが停止済みであること。Fargate Spot混在構成で7日間の稼働実績があり中断率が5%以下であること。
  • フェーズ3完了条件: 全マイクロサービスがService Connect経由で相互通信し、App Mesh依存が完全ゼロになっていること。Scheduled ScalingでBlack Friday相当のトラフィックを自動処理できることをロードテストで検証済みであること。全13軸との統合ダッシュボードが完成し、SREチームが24時間以内にインシデント根本原因を特定できる体制が確立されていること。
Container本番運用5本柱 本番デプロイ前チェックリスト

  • [ECS基盤] deployment_circuit_breaker enable + rollback有効化を確認済み
  • [ECS基盤] Task Definition Lifecycle Policy: INACTIVE 90日後削除 + 最新10revision保持 設定済み
  • [Fargate] Capacity Provider Strategy: Fargate Base + Spot 70:30 設定済み
  • [Fargate] Container Insights enhanced をCluster作成時に有効化済み
  • [Fargate] Auto Scaling warm-up period 300秒 + スケールイン cooldown 300秒以上 設定済み
  • [ECR] Enhanced Scan (Continuous Scanning) を全リポジトリで有効化済み
  • [ECR] Lifecycle Policy: untagged 7日削除 + 最新10tagged以外削除 設定済み
  • [ECS Exec] logConfiguration: logging ENABLED + S3 Object Lock 録画 設定済み
  • [ECS Exec] IAM Condition: 本番ECS Exec実行者をSREチームのみに制限済み
  • [Service Connect] Cloud Map namespace: 環境別 (dev/staging/prod) 分離 設定済み
  • [監視] FireLens (Fluent Bit) サイドカー: 全Task Definitionに組み込み済み
  • [コスト] Graviton (ARM64) 移行完了 または 移行計画策定済み
Container本番運用 落とし穴10選 — 全14軸横断チェックリスト

  • 落とし穴1 [ECS基盤]: deployment_circuit_breaker未設定 → ロールアウト失敗が全タスク停止まで進行。対策: circuit_breaker enable + rollback有効化をTask Definition標準に組み込む
  • 落とし穴2 [Fargate]: Spot 100%本番運用 → 中断率12%でAPIが断続停止するインシデント。対策: Fargate Base + Spot 70:30のCapacity Provider Strategy必須化
  • 落とし穴3 [ECR]: Lifecycle Policy未設定 → 半年で数百GBのイメージ蓄積でストレージコスト爆増。対策: untagged 7日後削除 + 最新10tagged以外削除をデフォルトPolicyとして設定
  • 落とし穴4 [ECR]: Basicスキャンのみ → push後に新CVEが発見されても本番コンテナに残存し続ける。対策: Enhanced Scan + EventBridgeによるCritical CVE自動アラート体制
  • 落とし穴5 [ECS Exec]: logConfiguration未設定 → セッション内コマンドログが残らず規制監査不合格。対策: S3 Object Lock録画 + CloudWatch Logs強制設定
  • 落とし穴6 [Fargate]: cold start未考慮のSLA設計 → P99でSLA違反が常態化。対策: warm-up period 300秒 + SLAに30秒バッファ + 最低タスク数 × 1.2の常時余剰
  • 落とし穴7 [Service Connect]: App Mesh継続利用 → 廃止スケジュールで強制移行コスト発生。対策: 今すぐService Connect段階移行計画を策定し実行開始
  • 落とし穴8 [監視]: Container Insights後付け → 過去メトリクスが遡れず障害発生前の状態が把握不能。対策: Cluster作成時にenhancedモードを必須化しインフラコードレビューゲートに追加
  • 落とし穴9 [IAM]: Task RoleとTask Execution Roleの混同 → タスクが過剰なS3・Secrets Manager権限を保持しセキュリティリスク増大。対策: 役割を厳格分離しTask Roleを最小権限化
  • 落とし穴10 [Auto Scaling]: スケールイン cooldown 短すぎ → トラフィック変動のたびにタスク数がフラッピングしコスト増と不安定化を同時に引き起こす。対策: スケールアウト cooldown 180秒・スケールイン 300秒以上を標準設定

ECS vs EKS 設計判断フロー — 中堅エンジニアが迷う5シナリオ

Vol1を通じてECS 5本柱を習得した後も、「ECSで良かったのか/EKSにすべきだったのか」という判断に迷うシナリオが実際の現場では多く発生する。以下の5シナリオは、Container本番運用の設計判断で特に頻出する岐路だ。

シナリオ1: チーム規模が50名を超えてきた

50名超のエンジニア組織ではKubernetes専任チームを設ける余裕が生まれ、EKSへの移行投資が回収できるケースが出始める。ただし既存ECS資産 (Task Definition / Service Connect / ECR) の移行コストは想定以上にかかることが多い。移行判断の基準は「Kubernetes専任者を2名以上常駐できるか」だ。できない場合はECSを継続することを推奨する。

シナリオ2: マルチクラウド要件が発生した

GCP/Azureとの相互運用が求められる場合、Kubernetes (EKS/GKE/AKS) が共通基盤として機能する。ECSはAWS専用のオーケストレーターであるため、将来的なマルチクラウド移行が確定しているならEKSを選択する方が移行コストを抑えられる。ただし「検討している」程度であれば現時点ではECSで十分だ。

シナリオ3: Helm/ArgoCDによるGitOpsを導入したい

GitOpsはECSでも ecspresso + Terraform + CodePipeline で実現できるが、Helm Chartエコシステムを活用したい場合はEKSが優位だ。第13軸 IaC記事 (ecspresso×Terraform統合) でECS GitOpsパターンを確認し、Helm Chart依存のないシステムではECSで十分な水準に達することを検証してから判断する。

シナリオ4: サービスメッシュの高度な機能が必要

Service ConnectはApp Meshの後継として基本的なService Discovery・TLS・メトリクスを提供するが、高度なトラフィック制御 (カナリアリリース比率制御・回路遮断・リトライポリシー) が必要な場合はIstioベースのEKSが優位だ。Service Connectで実現可能なパターンかをまず検証し、不可能な場合にのみEKSを検討する。

シナリオ5: GPU/高性能コンピューティングが必要

機械学習推論やHPC用途ではGPUインスタンスが必要になる。FargateはGPUをサポートしないため、ECS + EC2起動タイプ (p3/p4インスタンス) またはEKS + GPU Node Groupを選択する必要がある。この場合はEC2専任の管理が必要になるため、インフラ運用体制を考慮してECS EC2かEKSかを判断する。

ECS継続を推奨する判断基準のまとめ:
以下の条件をすべて満たす組織では、ECS Fargateの継続運用が最適解だ。
– チーム規模50名以下でKubernetes専任者を確保できない
– マルチクラウド移行の計画が具体化していない (5年以内の移行計画なし)
– 高度なサービスメッシュ制御 (回路遮断・高精度カナリア) が不要
– GPU/HPC用途のワークロードを持たない
– AWS Nativeエコシステム (IAM / CloudWatch / ALB / ECR) への投資を最大化したい

これらの条件に当てはまる組織では、ECS Fargate + 5本柱 + 全13軸統合という本Vol1のアーキテクチャが5年以上の本番稼働に耐える設計として機能する。EKSへの移行を「技術的負債の解消」と捉えるのではなく、「組織規模とユースケースが要求する時に初めて検討する選択肢」として位置づけることが、Container本番運用の設計哲学として正しい。

Container本番運用 全14軸統合マトリクス — 各軸との連携パターン

第14軸 Container本番運用は、全13軸の知識が収束する統合領域だ。各軸との具体的な連携パターンを整理し、Vol1で習得した5本柱を全13軸エコシステムの中でどう活かすかを明確にする。

第1軸 IAM との連携: Task RoleとTask Execution Roleの分離がIAM最小権限設計の教科書的な適用例となる。ECS Exec IAM ConditionはSCPと組み合わせることで組織横断のアクセス制御を実現する。

第2軸 EKS との連携: 共通ECRリポジトリをECSとEKS両方から参照する設計でイメージ管理を一元化する。Container InsightsメトリクスをCloudWatch Dashboardで統合表示しECS/EKS横断の可視化を実現する。

第3軸 復旧 との連携: 自動復旧 RunbookをECS Serviceのrollback自動化に活用する。ECS Execによる本番調査手順をRunbookに組み込み復旧対応時間を短縮する。

第4軸 AI との連携: Bedrock InvokeModelをECS Task上のAPIサーバーから呼び出す構成が第4軸×第14軸の標準アーキテクチャだ。Task RoleにBedrock実行権限を付与しSecrets Manager経由でAPIキーを管理する。

第5軸 セキュリティ との連携: ECR Enhanced ScanのCVE検出をEventBridgeで第5軸のインシデント対応フローに接続する。ECS Exec監査ログをCloudWatch Logs → S3に集約し第5軸のフォレンジック基盤に統合する。

第6軸 コスト との連携: Fargate Spot + Graviton移行が第6軸コスト最適化の最大の貢献ポイントとなる。Savings Plans (Compute SP) でFargate費用を最大50%削減しコスト最適化の幹として機能させる。

第9軸 Network との連携: awsvpcモードでTask毎にENIを割り当てることで第9軸のVPC設計原則 (Security Group最小権限) をコンテナレベルで実現する。Service Connectの名前解決はVPC Private DNS Namespaceを基盤とし第9軸との深い連携が必要だ。

第10軸 DevOps との連携: CodePipeline + ECR push + ECS rolling/blue-greenが第10軸×第14軸の標準CI/CDパターンだ。Task Definition自動更新とLifecycle Policyの管理もパイプラインに組み込む。

第13軸 IaC との連携: ecspresso (Task Definition/Service管理) + Terraform (Cluster/ECR/IAM) の役割分担が第13軸×第14軸の推奨構成だ。ecspressoはJSON Task Definitionを直接管理しTerraformの state複雑化を防ぐ。

第11軸 Database との連携: RDS/Aurora への接続情報をSecrets Managerで管理し、Task Execution RoleがSecrets Managerから取得してコンテナ起動時に環境変数として注入するパターンが標準だ。Aurora Serverless v2とFargateの組み合わせでスケールアウト/スケールインが両レイヤで連動するサーバーレスに近い構成を実現できる。

第12軸 Serverless との連携: Lambda (第12軸) とECS Fargate (第14軸) の役割分担は「イベント駆動/短時間 → Lambda / 長時間/ステートフル → Fargate」が原則だ。EventBridgeからFargate Taskを起動するパターン (ECS RunTask API) でバッチジョブをServerlessな起動フローで実行する設計が第12軸×第14軸の典型的な統合パターンとなる。

第7軸 マルチアカウント との連携: AWS Organizationsで本番/ステージング/開発アカウントを分離する環境において、ECRリポジトリは共有サービスアカウントに集中管理し、各環境アカウントのECS TaskがCross-Account IAM Role経由でイメージをpullするパターンが第7軸×第14軸の標準設計だ。SCPでECS Exec実行を本番アカウントのSREロールのみに制限することで、マルチアカウント環境全体のセキュリティ統制を実現する。

第8軸 Observability との連携: ADOT CollectorサイドカーをTask Definitionに追加しX-Ray Tracingをコンテナレベルで収集する。CloudWatch Application SignalsでECSサービスのGolden Signals (レイテンシ/エラー率/スループット) を自動収集し、第8軸のObservabilityダッシュボードとECSメトリクスを一元化する。

Vol2予告: Container本番運用の次の地平

Vol1でECS 5本柱を確立した後、Vol2では以下のテーマを扱う。ECS Fargateで本番品質を確立したエンジニアが次に直面する「より高度なマネージドコンテナ実行環境の選択」と「EKS × ECSのハイブリッド設計」を体系化する。

Vol2予定テーマ:

  • App Runner vs ECS Fargate: インフラ管理をさらに抽象化したApp Runnerの選定基準。ソースコードからコンテナを自動ビルドし、スケーリング・ロードバランシングをフルマネージドで提供するApp RunnerとECS Fargateの使い分けを本番ユースケースで整理する。チーム規模10名以下の高速プロダクト開発チームにはApp Runnerが最適解となるケースが多く、ECS Fargateとの選定基準を7軸マトリクスで比較する。

  • AWS Copilot: ECS / App Runnerのデプロイを高度に抽象化するCLIツール。環境管理・パイプライン構築・サービス間通信設定をCopilotコマンドで完結させる本番導入パターンを解説する。Copilotはターゲット追跡Auto Scaling・ロードバランサー・VPCをワンコマンドで構成でき、インフラ専任者がいないチームの本番立ち上げを大幅に加速する。

  • Lambda Container Image: Lambda関数をコンテナイメージとして配布するパターン。最大10GBイメージのサポートによりServerlessとContainer運用の境界が曖昧になる中、ECS Fargateとの役割分担 (常時起動 vs イベント駆動) を整理し最適なアーキテクチャ選択を提示する。第12軸Serverlessとの統合視点での設計パターンも解説する。

  • EKS Bridge: 組織の一部チームがEKS、別チームがECSを使うハイブリッド構成の設計パターン。共通ECRリポジトリ・IAMロール設計・Observabilityの統合を第2軸EKSと第14軸Containerの双方の観点でまとめる。

Vol1 (ECS 5本柱) → Vol2 (マネージド拡張 + EKS Bridge) のロードマップで、AWS Container本番運用の全体像が完成する。Vol2は2026年後半に公開予定だ。

Container本番運用シリーズ: Vol1完成宣言

本Vol1 (ECS × Fargate × ECR × ECS Exec × Service Connect 完全ガイド) の公開をもって、AWS本番運用 第14軸 Container本番運用シリーズのVol1が完成した。

全13軸完遂という長い旅を経てContainer本番運用の起点に立ったエンジニアにとって、本記事が解決すべき最重要課題は「EKSの複雑性を排除しながらAWS Nativeで本番品質のContainer運用を確立すること」だった。ECS 5本柱はその答えだ。

  • ECS Cluster/Service/Task Definition: AWS Nativeの運用モデルで複雑性を最小化
  • Fargate + Spot + Graviton: サーバー管理なし・コスト最適化・ARM移行の三位一体
  • ECR + Enhanced Scan: セキュリティを運用フローに自然に組み込む継続的な防衛線
  • ECS Exec + Session Manager: セキュリティ強化しながら運用効率を向上させる次世代アクセス手段
  • Service Connect + Cloud Map: マイクロサービス間通信をシンプルに・確実に・観測可能に

全13軸の蓄積が第14軸 Container本番運用に収束し、「AWS本番運用 全14軸 完遂」という到達点を形成する。本シリーズVol2ではより高度なマネージドコンテナとEKS Bridgeに踏み込み、Container本番運用の全体像を完成させる。本記事が第14軸完遂への確かな一歩となることを確信する。

Vol1 達成指標:

本Vol1を読み終えた後、以下の設計判断が即座にできるようになっていることが達成基準だ。
– 新規Container化プロジェクトでECS vs EKSの選定判断を5分以内に下せる
– Fargate Task Definitionの本番品質設定 (awsvpc / circuit_breaker / Spot Strategy) を空で書ける
– ECR + Enhanced Scan + EventBridgeによるCVE自動対応フローを設計できる
– ECS Exec + S3録画 + IAM Conditionによる規制対応監査ログ体制を構築できる
– Service Connectのnamespace戦略とApp Meshからの段階移行計画を立案できる
– §7の詰まり7選を見て「自分のシステムはどれに当てはまるか」を即座に診断できる

これらすべてを達成した時、あなたはAWS Container本番運用の実践エンジニアとしての基盤を確立したと言える。

Vol1完遂で得られる Container本番運用設計力

  • ECS Cluster / Service / Task Definition の3層構造 + Launch Type選定が組織のワークロードに応じて即座に判断できる
  • Fargate Spot / Graviton / cold start特性を踏まえた本番品質のコスト・可用性・SLA設計ができる
  • ECR脆弱性スキャン (Basic vs Enhanced) + Pull-Through Cache + Lifecycle Policyで安全なイメージ管理体制を確立できる
  • ECS Exec + Session Manager録画でSSH / Bastion完全廃止と監査対応を同時実現できる
  • Service Connect + Cloud Map namespaceでマイクロサービス間通信を本番品質化できる
  • 全13軸 (IAM / EKS / 復旧 / AI / セキュリティ / コスト / マルチアカウント / Observability / Network / DevOps / Database / Serverless / IaC) の知識をContainer本番運用に統合応用できる
  • §7の詰まり7選・落とし穴10選を事前把握し、本番稼働後のインシデントを大幅に削減できる
  • 0〜180日の段階的ロードマップに従って計画的にECS本番化を推進できる

EKS Vol1 — Kubernetes本番運用との対比で選択肢を広げる
ecspresso×Terraform — ECSデプロイをコードで完全管理する