AWS CI/CD実践Vol2|Container CD×CodeArtifact×SAM×Amplify

目次

DevOps/CI/CD実践 Vol2 — Container CD × CodeArtifact × SAM Pipeline × Amplify Hosting

fig01: DevOps Vol2 全体図 (Container CD / CodeArtifact / SAM Pipeline / Amplify Hosting)

AWS本番運用 第10軸 DevOps/CI/CD実践 シリーズ Vol2
本記事は Vol1 (CodePipeline/CodeBuild/CodeDeploy/GitHub Actions OIDC) を読了した中堅エンジニアに向けた、Container CD・パッケージ管理・Serverless CD・静的サイトCI/CD の深化編です。Vol1の4本柱の上に、現代的なデプロイ対象別 (Container / Lambda / Static) の本番運用パターンを統合します。

前巻 (必読)

関連シリーズ (個別 deep-dive)

  • ECS Fargate CI/CD Vol1-2 (Container CD の Fargate 限定 deep-dive)
  • EKS+ArgoCD Production (Kubernetes GitOps の deep-dive)
  • CodeArtifact + CodeGuru Production (CodeArtifact + 静的解析の deep-dive)

1. なぜVol2か — Vol1からの架橋 + デプロイ対象別 CD の必要性

1-1. Vol1の振り返り — 4本柱が解いた問題

Vol1 では CI/CD の基礎として以下の4本柱を習得しました。

本柱サービス解いた問題
パイプライン オーケストレーションCodePipelineSource → Build → Test → Deploy の自動化フロー定義
ビルド・テスト自動化CodeBuildbuildspec.yml による宣言型ビルド・コンテナ内隔離実行
デプロイ自動化CodeDeployBlue/Green・In-Place・Canary の3戦略 + 自動ロールバック
GitHub Actions OIDCGitHub Actions長命トークン排除・OIDC フェデレーションによる最小権限CD

Vol1を読了したエンジニアは「汎用的な CI/CD ループ」を手に入れています。しかし現場では デプロイ対象が何か (Container イメージ / Lambda 関数 / 静的サイト) によって必要な追加インフラと運用パターンが大きく異なります。Vol1 の汎用 CD だけでは解決できない3種類のペインが存在します。

1-2. なぜ Vol1 の汎用 CD では不十分か — 3つのペイン

ペイン 1: Container CD のペイン

CodeDeploy は EC2/Lambda/ECS に対応していますが、Container 特有のイメージライフサイクル管理は別の仕組みが必要です。ECR (Elastic Container Registry) で image_tag_mutability = "IMMUTABLE" を設定しなければ latest タグの上書きによる本番事故が起き、ライフサイクルポリシーがなければ古いイメージが蓄積してストレージコストが膨張します。さらに EKS クラスタでは Argo CD / Flux による GitOps (宣言的同期) が事実上の標準ですが、CodeDeploy は EKS には対応していないため、全く別のデプロイ戦略が必要です。

ペイン 2: Serverless CD のペイン

Lambda 関数のデプロイでは SAM (Serverless Application Model) が最適解です。sam pipeline init で CI/CD 雛形を対話的に生成し、sam pipeline bootstrap でマルチアカウント対応 IAM Role + S3 バケットを自動プロビジョニングできます。Lambda Alias + Traffic Shifting (Canary 10% / Linear 10%毎10分 / All-at-once) による段階的ロールアウトは SAM テンプレートでのみ宣言的に管理でき、CodeDeploy の汎用 Deployment Group では Lambda Alias のライフサイクルが追いきれません。

ペイン 3: Package管理 と Static Hosting のペイン

チーム開発では社内パッケージの安全な配布が問題になります。npm / Maven / PyPI のパブリックレジストリに直接依存したままでは Dependency Confusion 攻撃リスクがあります。CodeArtifact でプライベートリポジトリを構築し、buildspec.yml の phases.pre_buildaws codeartifact login を実行して短命トークン (12時間有効) を取得する構成が必要です。フロントエンドの静的サイトは Amplify Hosting を使えば Branch deploy と PR ごとの Preview deploy が自動化されますが、CloudFront + S3 自前構築とのトレードオフを正しく理解しなければ誤選定が起きます。

1-3. Vol2 で得られる4つの成果

#成果習得後に解決できること
1Container CDECR イメージ管理 + ECS Blue/Green + EKS GitOps の本番パターン実装
2Package管理CodeArtifact プライベートリポジトリ + buildspec.yml 統合による安全な依存解決
3Serverless CDSAM Pipeline によるマルチアカウント Lambda デプロイ完全自動化
4Static HostingAmplify Hosting による SPA/SSG の Branch/Preview deploy + Custom Domain 設定

1-4. 既存シリーズとの住み分け

本 Vol2 は 概念整理 + 選定軸 + 最小 IaC 例 の提供に絞ります。詳細な deep-dive は以下の専門シリーズを参照してください。

既存シリーズ対象読者本 Vol2 との関係
ECS Fargate CI/CD Vol1-2Fargate 本番運用の詳細設定が必要な方§3 の ECS Blue/Green を補完 (ALB ターゲットグループ詳細・健全性チェック設定等)
EKS+ArgoCD ProductionKubernetes GitOps を完全実装したい方§3 の EKS GitOps を補完 (App-of-Apps / Sync wave / IRSA 統合の完全実装)
CodeArtifact + CodeGuruパッケージ管理 + 静的解析を一体化したい方§4 の CodeArtifact を補完 (CodeGuru 統合・詳細ポリシー設定等)

1-5. 本記事の構成 (第10軸シリーズ Vol2)

§テーマ行数目標
§1 (本節)Vol1架橋 + デプロイ対象別ペイン + 成果150-180行
§2DevOps深化マップ (4本柱位置付け + 選定軸)200-240行
§3 ★山場1Container CD実践 (ECS Blue/Green × EKS GitOps × ECR)250-290行
§4CodeArtifact実践 (パッケージリポジトリ / 認証 / Cross-Account)220-260行
§5 ★山場2SAM Pipeline実践 (Serverless CD / Bootstrap / マルチアカウント)250-290行
§6Amplify Hosting実践 (Branch/Preview deploy / Custom Domain)220-260行
§7アンチパターン→正解パターン演習5件200-250行
§8まとめ + 落とし穴10選 + 全10軸クロスリンク100-140行

1-6. Terraform 例 — ECR リポジトリ (Container CD の起点)

Vol2 の Container CD を始める第一歩は ECR リポジトリの適切な設定です。以下は本番運用で必須となる設定を含む最小構成です。

resource "aws_ecr_repository" "app" {
  name  = "myapp"
  image_tag_mutability = "IMMUTABLE"

  image_scanning_configuration {
 scan_on_push = true
  }

  encryption_configuration {
 encryption_type = "KMS"
  }

  tags = {
 Environment = "production"
 ManagedBy= "terraform"
  }
}

resource "aws_ecr_lifecycle_policy" "app" {
  repository = aws_ecr_repository.app.name

  policy = jsonencode({
 rules = [
{
  rulePriority = 1
  description  = "untagged images を 7日後に削除"
  selection = {
 tagStatus= "untagged"
 countType= "sinceImagePushed"
 countUnit= "days"
 countNumber = 7
  }
  action = { type = "expire" }
}
 ]
  })
}

image_tag_mutability = "IMMUTABLE" が Container CD の必須設定です。latest タグの上書きを防ぎ、ロールバック時に旧バージョンイメージが消失する事故を根本から防止します。scan_on_push = true で ECR 拡張スキャンが有効になり、OS レベルとアプリケーション依存の両方の脆弱性を検出します。encryption_type = "KMS" はコンプライアンス要件対応としてカスタマーマネージドキーを指定する際のベースラインです。

1-7. 本 Vol2 の対象読者と前提知識

前提知識推奨記事重要度
IAM ロールと OIDC フェデレーションIAM Vol1 / Vol4★★★ (GitHub Actions OIDC で必須)
CodePipeline / CodeBuild / CodeDeploy の基本DevOps Vol1★★★ (必読)
ECS Fargate の基本的な運用ECS Fargate CI/CD Vol1★★☆ (§3 で参照)
EKS クラスタ構成と IRSAEKS Vol1 / EKS Vol3★★☆ (§3 GitOps で参照)
Terraform の基礎文法 (HCL)★★☆ (IaC 例を読む場合)

Vol1 未読の方: 先に DevOps Vol1 を読んでください。Vol2 の各節は Vol1 の CodePipeline / CodeBuild / CodeDeploy / GitHub Actions OIDC の知識を前提として書かれています。Vol1 未読のまま Vol2 を読むと、ビルドステージや承認ゲートの設定箇所が文脈なしに現れるため理解が困難になります。

§3・§5 だけ読みたい方: 各節の冒頭にある「このセクションで使う前提リソース」リストを確認し、必要な IaC を先に apply してから本文を読むと効率的です。

1-8. 全10軸 + DevOps Vol2 ナビ (22記事)


2. DevOps 深化マップ — Container CD / Package管理 / Serverless CD / Static Hosting

2-1. DevOps 深化マップ — 4本柱の位置付け

上図 (fig01: DevOps Vol2 全体図) が示すように、Vol2 では Vol1 の4本柱 (CodePipeline/CodeBuild/CodeDeploy/GitHub Actions) を基盤として、デプロイ対象別に特化した4つの深化柱を追加します。

深化柱主サービス群対象デプロイ物Vol1との関係
Container CDECR + ECS CodeDeploy + EKS + Argo CD / FluxコンテナイメージCodeDeploy ECS Platform を拡張
Package管理CodeArtifact + buildspec.yml 統合npm / Maven / PyPI パッケージCodeBuild ビルドステップに統合
Serverless CDSAM Pipeline + SAM Bootstrap + Lambda AliasLambda 関数 + API GatewayCodePipeline の Serverless 専用ステージ
Static HostingAmplify Hosting + CloudFront + S3 + OACReact / Vue / Next.js / AstroGitHub Actions の Static デプロイフロー

Vol1 の4本柱が「CI/CD の骨格」なら、Vol2 の4深化柱は「デプロイ対象別の筋肉」です。骨格なしに筋肉はつかず、筋肉なしに実際の仕事はできません。両方を理解して初めて本番運用の全像が見えます。

2-2. Container CD の選定軸

ECS と EKS では CD 戦略が根本的に異なります。どちらを選ぶかは「コンテナオーケストレーターが ECS か Kubernetes か」で決まります。

選定軸ECS Fargate (CodeDeploy)EKS (Argo CD / Flux)
デプロイ指定方法CodeDeploy Deployment Group (Console / Terraform)GitOps Repo への Manifest Push
Blue/Green切替ALB Target Group 2セット切替Argo CD Rollout または Flagger
ロールバックCloudWatch Alarm → CodeDeploy 自動 RollbackGit Revert → Argo CD 自動同期
カナリアTest traffic % 設定 (ALB Listener Rule)Argo Rollouts Canary Step
採用基準ECS Fargate 中心・既存 CodeDeploy 資産がある場合Kubernetes 標準・マルチクラスタ・GitOps 中心

ECS Blue/Green の核心は Test Listener Rule の設定 です。ALB に2つのリスナー (本番ポート 443 / テストポート 8443) を設定し、CodeDeploy がデプロイ時に自動切替します。Test Listener Rule の設定漏れが最も多い失敗パターンです (§7 演習1)。

EKS GitOps の核心は Argo CD の Sync Wave です。Sync Wave を設定することで、データベースマイグレーション → アプリケーションデプロイ → 後処理ジョブ の順序保証が実現します。Sync Wave 設定漏れによる依存リソース順序事故が最多トラブルです (§8 落とし穴2)。

2-3. Package管理の選定軸

選定軸CodeArtifactGitHub Packagesセルフホスト Nexus
AWS 統合ネイティブ (IAM / KMS / VPC Endpoint)GitHub Actions 統合手動 IAM 設定
対応フォーマットnpm / Maven / PyPI / NuGet / Swift / genericnpm / Maven / NuGet / Docker / RubyGems全フォーマット対応
認証方式aws codeartifact get-authorization-token (12h TTL)GitHub PAT / OIDCAPI Key / LDAP
Cross-AccountResource Policy / Domain Policy でネイティブ対応Organization Packageネットワーク設定依存
コスト$0.05/GB ストレージ + $0.09/GB 転送GitHub Enterprise で利用可サーバー運用コスト

CodeArtifact の認証トークン有効期限は 12時間 です。長時間 CI (夜間バッチ等) では phases.pre_build でのトークン再取得ステップが必須です (§7 演習2)。

2-4. Serverless CD の選定軸

選定軸SAM PipelineCDK PipelinesServerless Framework
標準化度AWS 公式 (CloudFormation ネイティブ)AWS 公式 (L3 Construct)サードパーティ
Bootstrapsam pipeline bootstrap (IAM Role + S3 自動作成)cdk bootstrap手動 IAM 設定
Traffic ShiftingLambda Alias + DeploymentPreference (Canary / Linear)CodeDeploy 統合Plugin 依存
マルチアカウント対応Pipeline Bootstrap で各アカウントの Role 作成CDK Bootstrap + Trusted Accounts手動設定
採用基準Lambda 中心・CloudFormation 標準に従いたい場合CDK 全面採用している場合既存 FW 資産がある場合

SAM Bootstrap の 役割 は、Staging / Prod 各アカウントに samCLIRole / cfnExecutionRole / pipelineArtifactsBucket を作成し、パイプラインアカウントからのクロスアカウントデプロイを可能にすることです。SAM Bootstrap を重複実行すると既存 IAM Role との命名衝突エラーが発生します (§8 落とし穴5)。

2-5. Static Hosting の選定軸

選定軸Amplify HostingCloudFront + S3 自前構築
セットアップConsole / CLI で数分Terraform ~150行
Branch deployビルトイン (自動)手動または Lambda@Edge が必要
Preview deployPR ごとに自動 URL 発行手動 CI/CD 実装が必要
Custom DomainConsole または Terraform (自動 ACM 発行)手動 ACM + Route 53 + CloudFront Origins
Cache制御Amplify が自動管理 (細粒度制御は制限あり)CloudFront Behavior/TTL を完全制御可能
採用基準開発速度重視・フロントエンド単体でデプロイCDN 細粒度制御・複雑な Routing ルール必要

Amplify Hosting の SPA routing で最も多いトラブルが Rewrites/Redirects の設定漏れ です。/*/index.html への Rewrite が未設定だと、Direct URL アクセス (/about 等) で 403/404 が発生します (§7 演習4)。

2-6. 4柱統合パイプラインの全体像

Vol2 の最終形は、Container / Lambda / Static の3デプロイ対象を1つのリポジトリから管理するモノレポ + マルチパイプライン構成です。

[GitHub Repo: monorepo]
├── services/
│├── api/→ CodePipeline (Container CD: ECS Blue/Green)
│├── functions/→ CodePipeline (Serverless CD: SAM Pipeline)
│└── frontend/ → Amplify Hosting (Static CD: Branch deploy)
└── packages/
 └── shared-lib/  → CodeArtifact (Package管理: npm publish)

各パイプラインの連携ポイント:

  1. shared-lib の変更 → CodeArtifact に publish → api / functions の buildspec.yml が codeartifact login で最新版取得
  2. api の変更 → CodePipeline 起動 → CodeBuild (ビルド + ECR push) → CodeDeploy (ECS Blue/Green)
  3. functions の変更 → CodePipeline 起動 → SAM build → SAM deploy (Lambda Alias Traffic Shifting)
  4. frontend の変更 → Amplify Hosting が自動検知 → Branch build → Preview deploy (PR) / Production deploy (main)

2-7. ep-box: 4本柱比較まとめ

Vol2 4深化柱 早見表

| 柱 | 対象 | キーサービス | Vol1との差分 |
|—|——|————|————|
| Container CD | コンテナイメージ | ECR / ECS CodeDeploy / EKS+Argo CD | ECR ライフサイクル管理 + GitOps が追加 |
| Package管理 | ライブラリ/成果物 | CodeArtifact | buildspec.yml への codeartifact login 統合 |
| Serverless CD | Lambda / API GW | SAM Pipeline / SAM Bootstrap | Alias Traffic Shifting が追加 |
| Static Hosting | SPA / SSG | Amplify Hosting / CloudFront+S3 | Branch / Preview deploy が追加 |

選定早見き: Container → ECR+ECS (Fargate) または EKS (Kubernetes) / Serverless → SAM (AWS標準) または CDK Pipelines (CDK採用時) / Static → Amplify (速度重視) または CloudFront+S3 (細粒度制御)

2-8. Terraform 例 — SAM Pipeline クロスアカウント IAM Role

SAM Pipeline のマルチアカウント構成で sam pipeline bootstrap が作成する IAM Role を Terraform で定義する例です。

resource "aws_iam_role" "sam_pipeline_execution" {
  name = "samCLIRole"

  assume_role_policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Effect = "Allow"
  Principal = {
 AWS = "arn:aws:iam::${var.pipeline_account_id}:root"
  }
  Action = "sts:AssumeRole"
  Condition = {
 StringEquals = {
"sts:ExternalId" = var.pipeline_external_id
 }
  }
}
 ]
  })

  tags = {
 ManagedBy= "terraform"
 Environment = var.environment
  }
}

resource "aws_iam_role_policy" "sam_pipeline_execution" {
  name = "samCLIPipelinePolicy"
  role = aws_iam_role.sam_pipeline_execution.id

  policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Effect = "Allow"
  Action = [
 "cloudformation:CreateStack",
 "cloudformation:UpdateStack",
 "cloudformation:DeleteStack",
 "cloudformation:DescribeStacks",
 "lambda:CreateFunction",
 "lambda:UpdateFunctionCode",
 "lambda:CreateAlias",
 "lambda:UpdateAlias",
 "s3:GetObject",
 "s3:PutObject"
  ]
  Resource = "*"
}
 ]
  })
}

sts:ExternalId 条件はクロスアカウント AssumeRole の混乱代理問題 (Confused Deputy) 対策として必須です。パイプラインアカウント ID と組み合わせることで、意図しない第三者からの AssumeRole を防止します。

2-9. buildspec.yml 統合例 — CodeArtifact + Container CD の組み合わせ

以下は CodeArtifact (npm) + ECR push を組み合わせた buildspec.yml の例です。Vol2 の Package管理 と Container CD を1つの CodeBuild ジョブで実現します。

version: 0.2

phases:
  install:
 runtime-versions:
nodejs: 20
 commands:
- CODEARTIFACT_TOKEN=$(aws codeartifact get-authorization-token \
 --domain mycompany --domain-owner $AWS_ACCOUNT_ID \
 --query authorizationToken --output text)
- npm config set registry https://mycompany-${AWS_ACCOUNT_ID}.d.codeartifact.${AWS_REGION}.amazonaws.com/npm/myrepo/
- npm config set //mycompany-${AWS_ACCOUNT_ID}.d.codeartifact.${AWS_REGION}.amazonaws.com/npm/myrepo/:_authToken $CODEARTIFACT_TOKEN
- npm install

  pre_build:
 commands:
- aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $ECR_REGISTRY
- npm run lint
- npm run test

  build:
 commands:
- docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$CODEBUILD_BUILD_NUMBER .
- docker push $ECR_REGISTRY/$ECR_REPOSITORY:$CODEBUILD_BUILD_NUMBER

  post_build:
 commands:
- printf '[{"name":"app","imageUri":"%s:%s"}]' $ECR_REGISTRY/$ECR_REPOSITORY $CODEBUILD_BUILD_NUMBER > imagedefinitions.json

artifacts:
  files:
 - imagedefinitions.json

phases.install で CodeArtifact トークンを取得し npm config に設定する点が鍵です。phases.pre_build 以降はすでに認証済みのレジストリを使うため、依存解決が失敗しません。imagedefinitions.json は CodeDeploy が ECS Blue/Green のデプロイ対象イメージを特定するために使うアーティファクトです。


3. Container CD 実践 ★山場1 — ECS Blue/Green × EKS GitOps × ECR

3-1. Container CD の全体像 — ECS vs EKS 選定軸

Container ワークロードの CD 戦略は、オーケストレーション層 (ECS か EKS か) によって大きく2方向に分かれる。ECS では AWS マネージドの CodeDeploy ECS Blue/Green が中心となり、EKS では Git リポジトリを唯一の信頼源とする GitOps (Argo CD / Flux) が標準パターンとなる。いずれも「ゼロダウンタイムでのコンテナ入れ替え」を実現するが、制御層の設計思想が根本的に異なる。

比較軸ECS Blue/Green (CodeDeploy)EKS GitOps (Argo CD / Flux)
CD エンジンAWS CodeDeploy (ECS Compute Platform)Argo CD / Flux (クラスタ内エージェント)
デプロイ方式Push 型 (CodePipeline からトリガー)Pull 型 (Git 変更を Argo CD が検知)
切り戻しCloudWatch Alarm 自動切り戻しGit Revert / Argo CD Sync undo
状態管理CodeDeploy コンソール / CloudWatchArgo CD UI / kubectl
Terraform 統合aws_codedeploy_* リソースargocd_application または kubectl manifest
向いている構成ECS Fargate 単一サービス / 少数マイクロサービスKubernetes Multi-Service / マルチクラスタ

ECS を使う場合は §3-2 の Blue/Green を、Kubernetes を使う場合は §3-3 の GitOps を参照されたい。ECR は ECS/EKS 双方で使うコンテナレジストリとして §3-4 で扱う。

fig02: ECS Blue/Green vs EKS GitOps 比較フロー

3-2. ECS Blue/Green Deploy (CodeDeploy ECS Compute Platform)

ECS Blue/Green デプロイは、ALB の Target Group を 2 セット (Blue: 既存本番タスク / Green: 新版タスク) 用意し、トラフィックを段階的に切り替えることでゼロダウンタイムを実現する。AWS CodeDeploy の ECS Compute Platform がこの切替プロセスをオーケストレーションする。

Blue/Green 切替の仕組み

ALB Listener (Port 443)
  ├── Production Listener Rule → Blue Target Group (既存タスク: 本番トラフィック受信)
  └── Test Listener Rule → Green Target Group (新タスク: 検証トラフィック受信)
  1. CodeDeploy が新しいタスク定義で Green Target Group にタスクを起動
  2. Test Listener (Port 8080) に一部トラフィックを流し、アプリケーションの動作確認
  3. 確認 OK → Production Listener を Green に切替 (Blue の重みを 0 に)
  4. Blue タスクは指定した Termination wait time 後に削除

ALB Listener Rule の重み付け (Canary デプロイ)

段階的切替では ALB Weighted Target Group を使って本番トラフィックを徐々に移行できる。Blue:90 / Green:10Blue:50 / Green:50Blue:0 / Green:100 のように重みを段階的に変化させる Canary デプロイにより、新版の品質を本番で確認しながらリスクを最小化できる。

Auto 切り戻し (CloudWatch Alarm 閾値)

CodeDeploy のデプロイグループに CloudWatch Alarm を設定すると、デプロイ中にアラームが発火した時点で自動的に Blue へ切り戻す。aws_cloudwatch_metric_alarm で HTTP 5xx エラー率が閾値 (例: 5%) を超えたら自動切り戻しする設定が典型パターンだ。

Terraform 例: ECS Blue/Green

resource "aws_codedeploy_app" "ecs_app" {
  name = "my-ecs-app"
  compute_platform = "ECS"
}

resource "aws_codedeploy_deployment_group" "ecs_dg" {
  app_name= aws_codedeploy_app.ecs_app.name
  deployment_group_name  = "my-ecs-deployment-group"
  service_role_arn = aws_iam_role.codedeploy.arn
  deployment_config_name = "CodeDeployDefault.ECSCanary10Percent5Minutes"

  auto_rollback_configuration {
 enabled = true
 events  = ["DEPLOYMENT_FAILURE", "DEPLOYMENT_STOP_ON_ALARM"]
  }

  alarm_configuration {
 alarms  = [aws_cloudwatch_metric_alarm.http5xx.name]
 enabled = true
  }

  blue_green_deployment_config {
 deployment_ready_option {
action_on_timeout = "CONTINUE_DEPLOYMENT"
wait_time_in_minutes = 5
 }
 terminate_blue_instances_on_deployment_success {
action= "TERMINATE"
termination_wait_time_in_minutes = 10
 }
  }

  deployment_style {
 deployment_option = "WITH_TRAFFIC_CONTROL"
 deployment_type= "BLUE_GREEN"
  }

  ecs_service {
 cluster_name = aws_ecs_cluster.main.name
 service_name = aws_ecs_service.main.name
  }

  load_balancer_info {
 target_group_pair_info {
prod_traffic_route { listener_arns = [aws_lb_listener.prod.arn] }
test_traffic_route { listener_arns = [aws_lb_listener.test.arn] }
target_group { name = aws_lb_target_group.blue.name }
target_group { name = aws_lb_target_group.green.name }
 }
  }
}

3-3. EKS GitOps (Argo CD / Flux)

EKS 環境では GitOps が実質的な標準デプロイパターンとなっている。Git リポジトリが唯一の信頼源 (Source of Truth) となり、クラスタ内の Argo CD / Flux エージェントが継続的に Git と同期する Pull 型アーキテクチャだ。

Container CD パイプライン実行フロー

sequenceDiagram
 participant Dev as 開発者
 participant GH as GitHub
 participant CB as CodeBuild
 participant ECR as ECR
 participant ArgoCD as Argo CD
 participant EKS as EKS Cluster

 Dev->>GH: git push (アプリコード)
 GH->>CB: Webhook → Build trigger
 CB->>ECR: docker build → docker push (タグ: sha-abc1234)
 CB->>GH: GitOps repo の image tag を更新 (PR merge)
 GH-->>ArgoCD: (Pull) image tag 変更を検知
 ArgoCD->>EKS: kubectl apply (新イメージ Deployment)
 EKS-->>ArgoCD: Sync OK / Health OK
 ArgoCD-->>Dev: デプロイ完了通知

Cluster Bootstrap (Argo CD)

Argo CD を EKS クラスタへ導入する標準手順は Helm Chart 経由だ。argocd 名前空間に Argo CD コンポーネントをデプロイし、最初の Application (App-of-Apps) を手動登録することでブートストラップが完了する。

GitOps リポジトリ構造

GitOps ではアプリケーションコードと Kubernetes manifest を分離するリポジトリ設計が鉄則だ。

gitops-repo/
  apps/
 my-app/
base/ # 共通 manifest (Deployment / Service)
overlays/
  dev/# dev 差分 (replica: 1 / namespace: dev)
  staging/  # staging 差分
  prod/  # prod 差分 (replica: 3 / PodDisruptionBudget)
  clusters/
 dev/ # App-of-Apps (dev クラスタ向け)
 prod/# App-of-Apps (prod クラスタ向け)

Sync Wave / Pre-sync / Post-sync Hook

依存関係のあるリソース (CRD → CR / ConfigMap → Deployment) は Sync wave で順序制御する。argocd.argoproj.io/sync-wave: "0" で早期適用、"5" で後から適用というアノテーションで制御する。Pre-sync hook は DB マイグレーション、Post-sync hook は Smoke test の実行に活用されるパターンが多い。

App-of-Apps パターン

Argo CD の Application リソース自体を Argo CD で管理する再帰パターンだ。clusters/prod/ に置いた App-of-Apps Application が apps/ 以下の全アプリを一括管理し、新サービス追加が Git コミット1件で完結する。

Terraform 例: argocd_application (HCL)

resource "argocd_application" "my_app" {
  metadata {
 name= "my-app"
 namespace = "argocd"
  }

  spec {
 project = "default"

 source {
repo_url  = "https://github.com/my-org/gitops-repo.git"
path= "apps/my-app/overlays/prod"
target_revision = "main"
 }

 destination {
server = "https://kubernetes.default.svc"
namespace = "my-app"
 }

 sync_policy {
automated {
  prune  = true
  self_heal = true
}
sync_options = ["CreateNamespace=true"]
 }
  }
}

3-4. ECR (Elastic Container Registry) 実践

ECR はコンテナイメージの保管・脆弱性スキャン・レプリケーションを担う AWS マネージドレジストリだ。ECS/EKS を問わず使われる共通インフラとなるため、正しい設定が Container CD 全体の安全性に直結する。

Image Tag Immutability

imageTagMutability: IMMUTABLE を設定すると、同一タグへの上書き push が禁止される。latest タグを使い回して「どのイメージがデプロイ中か分からない」状態を防ぐためにも、本番環境では必須の設定だ。Git commit SHA をタグとして使う運用 (sha-a1b2c3d) と組み合わせると、デプロイ履歴の追跡と確実な切り戻しが可能になる。

Vulnerability Scanning (Enhanced Scanning / Amazon Inspector V2)

ECR Enhanced Scanning は Amazon Inspector V2 と統合し、OS パッケージとアプリケーション依存ライブラリの CVE をスキャンする。基本スキャン (SCAN_ON_PUSH のみ) と異なり、新しい CVE が公開された際に既存イメージを自動的に再スキャンする継続評価機能を持つ。

Lifecycle Policy (untagged image 削除)

ECR ライフサイクルポリシーで古いイメージを自動削除する。CI が失敗した際の中間成果物 (untagged image) はそのまま蓄積するとストレージコストが増大するため、7日以上経過した untagged image を削除するルールが基本設定となる。

Cross-Region Replication

Multi-Region デプロイ環境では ECR Replication Rule を設定し、Primary Region のイメージを Secondary Region に自動コピーする。各リージョンの ECS/EKS がローカル ECR からイメージを pull することで、クロスリージョン転送コストと pull レイテンシーを削減できる。

Terraform 例: ECR

resource "aws_ecr_repository" "app" {
  name  = "my-app"
  image_tag_mutability = "IMMUTABLE"

  image_scanning_configuration {
 scan_on_push = true
  }
}

resource "aws_ecr_lifecycle_policy" "app" {
  repository = aws_ecr_repository.app.name

  policy = jsonencode({
 rules = [
{
  rulePriority = 1
  description  = "Expire untagged images older than 7 days"
  selection = {
 tagStatus= "untagged"
 countType= "sinceImagePushed"
 countUnit= "days"
 countNumber = 7
  }
  action = { type = "expire" }
},
{
  rulePriority = 2
  description  = "Keep only the last 30 SHA-tagged images"
  selection = {
 tagStatus  = "tagged"
 tagPrefixList = ["sha-"]
 countType  = "imageCountMoreThan"
 countNumber= 30
  }
  action = { type = "expire" }
}
 ]
  })
}

resource "aws_ecr_replication_configuration" "main" {
  replication_configuration {
 rule {
destination {
  region= "ap-southeast-1"
  registry_id = data.aws_caller_identity.current.account_id
}
 }
  }
}
【Container CD 失敗事例】Image Tag Mutable のまま切り戻しで旧版が消える事故

ECR の imageTagMutabilityMUTABLE (デフォルト) のまま運用し、latest タグで push → 切り戻し時に古いイメージが存在しないという事故が多発する。latest は常に最新イメージを指すため、新版を push した時点で旧版 latest は上書きされ、切り戻し先が消える。

  • 発生条件: imageTagMutability: MUTABLE + latest タグ運用 + 切り戻し操作
  • 対策: imageTagMutability: IMMUTABLE に変更し、Git commit SHA をタグとして使う (sha-a1b2c3d)
  • GitOps での切り戻し: GitOps リポジトリで image tag を旧 SHA に戻す変更をコミットし、Argo CD が自動 Sync することで旧版へ確実に戻せる
関連記事 Deep-dive

本 §3 は Container CD の概念整理・選定軸・実装例に絞った解説です。EKS GitOps の完全実装 (ApplicationSet・マルチクラスタ・Sync wave 詳細) は上記 EKS deep-dive 記事を参照してください。


4. CodeArtifact 実践 — パッケージリポジトリ / 認証 / Dependency / Cross-Account

4-1. CodeArtifact の位置付け — Maven Central / npm / PyPI のプロキシ + 私設リポジトリ

CodeArtifact はフルマネージドのパッケージリポジトリサービス。パブリックレジストリ (Maven Central / npm / PyPI / NuGet) へのプロキシと、社内限定の私設リポジトリの両方を提供する。

用途従来の課題CodeArtifact の解決策
外部パッケージのキャッシュ毎回 Maven Central 等から取得 → CI が遅い・ネット障害で失敗upstream キャッシュで高速取得・オフラインビルド可
社内ライブラリ共有S3 や Nexus 等を自前管理フルマネージドで運用コスト削減
サプライチェーン攻撃対策直接パブリックレジストリを参照承認済みパッケージのみ upstream に設定

パブリックレジストリとの住み分け:

開発者/CodeBuild
 ↓ npm install / mvn package
CodeArtifact Repository (Internal)
 ↓ upstream chain
Maven Central / npm Registry / PyPI

4-2. Domain / Repository 階層構造

CodeArtifact は Domain → Repository の 2 層構造で管理する。

Domain: mycompany (AWS Account: 123456789012)
├── Repository: internal-maven  (社内 Java ライブラリ)
│└── upstream: maven-central(パブリックプロキシ)
├── Repository: internal-npm (社内 Node.js ライブラリ)
│└── upstream: npmjs(npm registry プロキシ)
└── Repository: shared-pypi  (Python ライブラリ)
 └── upstream: pypi (PyPI プロキシ)

Domain の役割: 複数 Repository をグループ化し、Cross-Account 共有の単位となる。KMS 暗号化は Domain 単位で設定。

resource "aws_codeartifact_domain" "main" {
  domain= "mycompany"
  encryption_key = aws_kms_key.codeartifact.arn

  tags = {
 Name = "mycompany-artifact-domain"
  }
}

resource "aws_codeartifact_repository" "internal_npm" {
  repository = "internal-npm"
  domain  = aws_codeartifact_domain.main.domain

  upstream {
 repository_name = aws_codeartifact_repository.npmjs_proxy.repository
  }

  tags = {
 Name = "internal-npm"
  }
}

resource "aws_codeartifact_repository" "npmjs_proxy" {
  repository = "npmjs"
  domain  = aws_codeartifact_domain.main.domain

  external_connections {
 external_connection_name = "public:npmjs"
  }
}

4-3. 認証フロー — 短命トークンと IAM 統合

CodeArtifact へのアクセスには短命の認証トークン (有効期限: デフォルト 12 時間、最大 12 時間) が必要。aws codeartifact get-authorization-token で取得し、npm / mvn / pip の設定ファイルに注入する。

npm 認証例:

# CodeBuild / CI での認証
CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token \
  --domain mycompany \
  --domain-owner 123456789012 \
  --query authorizationToken \
  --output text)

npm config set registry https://mycompany-123456789012.d.codeartifact.ap-northeast-1.amazonaws.com/npm/internal-npm/
npm config set //mycompany-123456789012.d.codeartifact.ap-northeast-1.amazonaws.com/npm/internal-npm/:_authToken $CODEARTIFACT_AUTH_TOKEN

buildspec.yml 統合例:

version: 0.2
phases:
  pre_build:
 commands:
- CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token
 --domain mycompany --domain-owner $AWS_ACCOUNT_ID
 --query authorizationToken --output text)
- aws codeartifact login --tool npm --domain mycompany
 --domain-owner $AWS_ACCOUNT_ID --repository internal-npm
  build:
 commands:
- npm ci
- npm run build
- npm publish --registry https://mycompany-$AWS_ACCOUNT_ID.d.codeartifact.ap-northeast-1.amazonaws.com/npm/internal-npm/

IAM Role 設計:

resource "aws_iam_role_policy" "codebuild_codeartifact" {
  name = "codeartifact-access"
  role = aws_iam_role.codebuild.id

  policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Effect = "Allow"
  Action = [
 "codeartifact:GetAuthorizationToken",
 "codeartifact:ReadFromRepository",
 "codeartifact:PublishPackageVersion",
 "sts:GetServiceBearerToken"
  ]
  Resource = "*"
}
 ]
  })
}

4-4. Cross-Account 共有 — Resource Policy / Domain Policy

複数 AWS Account で同一 CodeArtifact Domain / Repository を共有する場合は Resource Policy を設定する。

resource "aws_codeartifact_domain_permissions_policy" "cross_account" {
  domain = aws_codeartifact_domain.main.domain
  domain_owner = data.aws_caller_identity.current.account_id
  policy_document = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Effect = "Allow"
  Principal = { AWS = "arn:aws:iam::987654321098:root" }
  Action = [
 "codeartifact:GetAuthorizationToken",
 "codeartifact:DescribeDomain",
 "sts:GetServiceBearerToken"
  ]
  Resource = "*"
}
 ]
  })
}

resource "aws_codeartifact_repository_permissions_policy" "cross_account" {
  repository= aws_codeartifact_repository.internal_npm.repository
  domain = aws_codeartifact_domain.main.domain
  domain_owner = data.aws_caller_identity.current.account_id
  policy_document = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Effect = "Allow"
  Principal = { AWS = "arn:aws:iam::987654321098:root" }
  Action = ["codeartifact:ReadFromRepository", "codeartifact:DescribeRepository"]
  Resource  = "*"
}
 ]
  })
}

4-5. Dependency 解決 — upstream repository chain

CodeArtifact の upstream chain により、パッケージ検索順序を制御できる。

クライアント → internal-npm (CodeArtifact)
 ├── 内部パッケージ → ヒット → 返す
 └── 内部になし → npmjs (upstream = npm registry プロキシ)
└── ヒット → internal-npm にキャッシュ → 返す

重要ポイント:
– upstream でキャッシュされたパッケージはその後の取得が高速化される
allow / block 設定で外部パッケージの流入を制限できる (サプライチェーン管理)
– 複数 upstream を指定した場合は登録順に検索される

Maven (mvn) 認証と publish 例:

# .m2/settings.xml の自動更新
aws codeartifact login --tool mvn \
  --domain mycompany \
  --domain-owner $AWS_ACCOUNT_ID \
  --repository internal-maven

# パッケージのデプロイ
mvn deploy -DaltDeploymentRepository=internal-maven::default::https://mycompany-$AWS_ACCOUNT_ID.d.codeartifact.ap-northeast-1.amazonaws.com/maven/internal-maven/

pip (Python) 認証例:

# pip の設定
aws codeartifact login --tool pip \
  --domain mycompany \
  --domain-owner $AWS_ACCOUNT_ID \
  --repository shared-pypi

# インストール確認
pip install boto3  # shared-pypi 経由で取得・キャッシュ
認証トークンの 12 時間有効期限 — 長時間ビルドでの自動更新パターン

CodeArtifact の認証トークンはデフォルト 12 時間で失効します。通常の CI ビルドでは問題ありませんが、長時間のインテグレーションテストやバッチビルドでは途中で失効してパッケージ取得が失敗します。

対策:

  • 短縮トークン + 再取得: buildspec の各 phase 開始時に get-authorization-token を再実行し、新しいトークンを取得する
  • CodeBuild Service Role 活用: aws codeartifact login コマンドはデフォルトで実行ロールの認証情報を使用するため、Service Role に適切な権限を付与すれば再ログイン不要
  • npm credential helper: @aws-sdk/codeartifact-npm-login を使うと npm install 時に自動的にトークンを更新できる

5. SAM Pipeline 実践 ★山場2 — Serverless CD / Bootstrap / Multi-Account Deploy

5-1. SAM の位置付け — CloudFormation 上の Serverless 抽象化

AWS SAM (Serverless Application Model) は CloudFormation を基盤とした Serverless 専用 IaC ツール。AWS::Serverless::Function 等の簡略化されたリソース型で Lambda + API Gateway + DynamoDB 等を数十行で定義できる。

比較軸SAMTerraform
対象Serverless (Lambda/API GW/DynamoDB)汎用 (あらゆる AWS リソース)
デプロイ方式sam deploy (CloudFormation Stack)terraform apply (State 管理)
ローカル実行sam local invoke でローカルテスト可なし (LocalStack 等が必要)
CI/CD 雛形sam pipeline init で自動生成手動構築
選定目安Lambda 中心のサービス / 迅速な Serverless 開発複数リソース統合 / 既存 Terraform 資産活用

SAM template.yaml 例 (Node.js):

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
 Runtime: nodejs20.x
 Timeout: 30
 Environment:
Variables:
  TABLE_NAME: !Ref ItemsTable

Resources:
  GetItemFunction:
 Type: AWS::Serverless::Function
 Properties:
Handler: src/handlers/get-item.handler
Policies:
  - DynamoDBReadPolicy:
TableName: !Ref ItemsTable
Events:
  GetItem:
 Type: Api
 Properties:
Path: /items/{id}
Method: get

  ItemsTable:
 Type: AWS::Serverless::SimpleTable
 Properties:
PrimaryKey:
  Name: id
  Type: String

Outputs:
  ApiEndpoint:
 Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod"

5-2. sam pipeline init — CI/CD 雛形の自動生成

sam pipeline init は対話形式で CI/CD パイプラインの設定ファイルを生成するコマンド。

sam pipeline init

# 対話的な設定
# CI/CD プロバイダー選択:
#1. AWS CodePipeline
#2. GitHub Actions
#3. Jenkins
#4. GitLab CI/CD

# 生成されるファイル:
# .aws-sam/pipeline/pipelineconfig.toml
# codepipeline.yaml (または .github/workflows/pipeline.yaml)
# assume-role.sh

GitHub Actions 生成例 (pipeline.yaml 抜粋):

name: SAM Pipeline

on:
  push:
 branches: [main, develop]

jobs:
  build-and-package:
 runs-on: ubuntu-latest
 steps:
- uses: actions/checkout@v4
- uses: aws-actions/setup-sam@v2
- uses: aws-actions/configure-aws-credentials@v4
  with:
 role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-sam-deploy
 aws-region: ap-northeast-1
- run: sam build
- run: sam package --s3-bucket ${{ secrets.PIPELINE_ARTIFACTS_BUCKET }} --output-template-file packaged.yaml
- uses: actions/upload-artifact@v4
  with:
 name: packaged-template
 path: packaged.yaml

  deploy-dev:
 needs: build-and-package
 runs-on: ubuntu-latest
 environment: dev
 steps:
- uses: actions/download-artifact@v4
  with:
 name: packaged-template
- uses: aws-actions/configure-aws-credentials@v4
  with:
 role-to-assume: ${{ secrets.DEV_PIPELINE_EXECUTION_ROLE }}
 aws-region: ap-northeast-1
- run: |
 sam deploy --template-file packaged.yaml \
--stack-name my-app-dev \
--capabilities CAPABILITY_IAM \
--no-confirm-changeset \
--no-fail-on-empty-changeset

5-3. sam pipeline bootstrap — Multi-Account 環境準備

sam pipeline bootstrap は各環境 (dev / test / prod) に必要な AWS リソースを自動作成する。

# dev 環境のブートストラップ
sam pipeline bootstrap \
  --stage dev \
  --region ap-northeast-1 \
  --pipeline-user arn:aws:iam::111111111111:user/github-actions-user \
  --pipeline-execution-role arn:aws:iam::222222222222:role/dev-pipeline-execution-role \
  --cloudformation-execution-role arn:aws:iam::222222222222:role/dev-cfn-execution-role \
  --artifacts-bucket my-pipeline-artifacts-dev \
  --image-repository 222222222222.dkr.ecr.ap-northeast-1.amazonaws.com/my-app-dev

# prod 環境のブートストラップ
sam pipeline bootstrap \
  --stage prod \
  --region ap-northeast-1 \
  --pipeline-user arn:aws:iam::111111111111:user/github-actions-user \
  --pipeline-execution-role arn:aws:iam::333333333333:role/prod-pipeline-execution-role \
  --cloudformation-execution-role arn:aws:iam::333333333333:role/prod-cfn-execution-role \
  --artifacts-bucket my-pipeline-artifacts-prod \
  --image-repository 333333333333.dkr.ecr.ap-northeast-1.amazonaws.com/my-app-prod

bootstrap が作成するリソース:
IAM Role (PipelineExecutionRole): GitHub Actions / CodeBuild から AssumeRole されるロール
IAM Role (CloudFormationExecutionRole): SAM が CloudFormation Stack を操作するロール
S3 Bucket: ビルドアーティファクト保存
ECR Repository: コンテナイメージ (Container-based Lambda 使用時)

5-4. Deploy Stages — 3 段階承認ゲート

dev → test → prod の 3 段階デプロイで品質ゲートを設ける。

fig03: SAM Pipeline Bootstrap → Deploy stages フロー

sequenceDiagram
  participant GH as GitHub Actions
  participant DevAcc as Dev Account (222...)
  participant TestAcc as Test Account (444...)
  participant ProdAcc as Prod Account (333...)

  GH->>GH: sam build + sam package
  GH->>DevAcc: AssumeRole (PipelineExecutionRole-dev)
  DevAcc->>DevAcc: sam deploy → Stack: my-app-dev
  DevAcc-->>GH: Deploy complete (dev)

  GH->>TestAcc: AssumeRole (PipelineExecutionRole-test)
  TestAcc->>TestAcc: sam deploy → Stack: my-app-test
  TestAcc-->>GH: Deploy complete (test)

  Note over GH: Manual Approval Gate (GitHub Environment protection)
  GH->>ProdAcc: AssumeRole (PipelineExecutionRole-prod)
  ProdAcc->>ProdAcc: sam deploy --deployment-method trafficshifting
  ProdAcc-->>GH: Deploy complete (prod / Canary 10%)

5-5. Lambda Alias Traffic Shifting — Canary / Linear / All-at-once

SAM は DeploymentPreference で Lambda Alias のトラフィック移行戦略を指定できる。

Resources:
  ApiFunction:
 Type: AWS::Serverless::Function
 Properties:
Handler: src/index.handler
Runtime: nodejs20.x
AutoPublishAlias: live
DeploymentPreference:
  Type: Canary10Percent5Minutes  # 10% → 5分後 → 100%
  Alarms:
 - !Ref ApiErrorAlarm
  Hooks:
 PreTraffic: !Ref PreTrafficHook
 PostTraffic: !Ref PostTrafficHook

  PreTrafficHook:
 Type: AWS::Serverless::Function
 Properties:
Handler: src/hooks/pre-traffic.handler
Runtime: nodejs20.x
Policies:
  - Version: "2012-10-17"
 Statement:
- Effect: Allow
  Action: codedeploy:PutLifecycleEventHookExecutionStatus
  Resource: "*"

  ApiErrorAlarm:
 Type: AWS::CloudWatch::Alarm
 Properties:
AlarmName: api-function-errors
MetricName: Errors
Namespace: AWS/Lambda
Statistic: Sum
Period: 60
Threshold: 5
ComparisonOperator: GreaterThanThreshold
EvaluationPeriods: 1
Dimensions:
  - Name: FunctionName
 Value: !Ref ApiFunction

Traffic Shifting 戦略一覧:

設定値移行パターン推奨ユースケース
Canary10Percent5Minutes10% → 5分後 → 100%一般的な本番 Lambda
Canary10Percent15Minutes10% → 15分後 → 100%長時間テストが必要な場合
Linear10PercentEvery1Minute1分ごとに 10% 増 (10分で完了)緩やかな移行が必要な場合
AllAtOnce即時 100%テスト環境 / 低リスク関数

5-6. samconfig.toml — 環境別パラメータ管理

version = 0.1

[default.global.parameters]
stack_name = "my-app"
region = "ap-northeast-1"
confirm_changeset = false

[dev.deploy.parameters]
stack_name = "my-app-dev"
s3_bucket = "my-pipeline-artifacts-dev"
image_repository = "222222222222.dkr.ecr.ap-northeast-1.amazonaws.com/my-app-dev"
role_arn = "arn:aws:iam::222222222222:role/dev-cfn-execution-role"
parameter_overrides = "Environment=dev LogLevel=DEBUG"

[prod.deploy.parameters]
stack_name = "my-app-prod"
s3_bucket = "my-pipeline-artifacts-prod"
image_repository = "333333333333.dkr.ecr.ap-northeast-1.amazonaws.com/my-app-prod"
role_arn = "arn:aws:iam::333333333333:role/prod-cfn-execution-role"
parameter_overrides = "Environment=prod LogLevel=INFO"

デプロイ実行:

sam deploy --config-env dev# dev 環境
sam deploy --config-env prod  # prod 環境
SAM Bootstrap で IAM Role 重複作成事故 — 既存環境への再 bootstrap

既存の dev/prod 環境に対して誤って sam pipeline bootstrap を再実行すると、既存の IAM Role や S3 Bucket が上書き・再作成されて権限設定が失われる事故が発生します。

よくある発生シナリオ:

  • 新しい CI/CD プロバイダーへの移行時: GitHub Actions → CodePipeline に変更する際に既存環境に再 bootstrap → 既存 Role の Trust Policy が上書きされて旧 CI が認証不可になる
  • チームメンバーが誤ってコマンド実行: ドキュメント通りにコマンドを実行したつもりが既存 prod 環境を指定してしまう

対策:

  • bootstrap 前に既存リソースを確認: aws cloudformation describe-stacks --stack-name aws-sam-cli-managed-dev-pipeline-resources で既存 Stack を確認
  • 環境変数で誤操作防止: samconfig.tomlrole_arn に既存ロール ARN を明示し、bootstrap コマンドの実行を制限する
  • 本番環境の bootstrap は手順書化: prod bootstrap は Pull Request + レビューを経てから実行するワークフローを整備する

6. Amplify Hosting 実践 — Static/SPA CI/CD / Branch deploy / Preview deploy

6-1. Amplify Hosting の位置付け

AWS Amplify Hosting は Vercel / Netlify に相当する AWS ネイティブのフルマネージド静的サイト・SPA ホスティングサービス。フロントエンドのビルド・デプロイ・CDN 配信・カスタムドメイン管理を単一サービスで完結させる。GitHub / GitLab / Bitbucket リポジトリと直接連携し、push をトリガーに自動ビルド・デプロイが走る。

対応フレームワークと SSR サポート:

フレームワークビルドプリセットSSR 対応
React (CRA / Vite)自動検出× (CSR のみ)
Vue 3 / Vite自動検出×
Next.js 12–14自動検出○ (Compute platform)
Nuxt 3自動検出○ (Compute platform)
Angular自動検出×
Astro自動検出○ (SSR モード)

SSR 対応フレームワーク (Next.js / Nuxt) は Amplify の Compute platform を選択することで Lambda + CloudFront 構成でサーバーサイドレンダリングが有効になる。静的サイトと SSR を同一サービスで管理できる点が強みである。

6-2. Branch deploy — ブランチごとに環境を自動分離

Amplify Hosting ではリポジトリのブランチと 1:1 でデプロイ環境を自動構築する。ブランチを push するだけで独立した URL 付きの環境がプロビジョニングされるため、feature ブランチごとの動作確認が容易になる。

ブランチパターン用途自動生成 URL 例
main本番https://main.d1abc.amplifyapp.com
developステージングhttps://develop.d1abc.amplifyapp.com
feature/*機能開発https://feature-login.d1abc.amplifyapp.com

enable_auto_build = true を設定すると新規ブランチの push 時点で環境が自動プロビジョニングされる。feature/* の glob パターンを指定することで命名規則に沿ったブランチを一括でデプロイ対象にできる。ブランチごとに異なる環境変数を設定できるため、本番・ステージング・開発環境の設定分離が Terraform だけで完結する。

fig04: Amplify Branch deploy + Preview deploy フロー

6-3. Preview deploy — Pull Request ごとの確認 URL

Previews 機能を有効にすると、Pull Request を作成するたびに独立したプレビュー URL が自動発行される。フロントエンドレビューを PR 上で完結させられるため、ステージング環境への手動デプロイ作業が不要になる。

PR #42 open  → https://pr-42.d1abc.amplifyapp.com が自動生成
PR #42 merge → preview 環境を自動削除 (設定要)
PR #42 close → preview 環境を自動削除 (設定要)

PR クローズ後のリソース残存を防ぐには、Amplify コンソール → App settings → Previews → 「Automatically delete Preview environments when a PR is closed」 を有効化する。Terraform では enable_pull_request_preview = truepull_request_environment_name を合わせて指定し、PR クローズ時の自動削除が機能していることを確認する。

6-4. Custom Domain + Route 53 統合

カスタムドメインの紐付けは aws_amplify_domain_association で管理する。Amplify は ACM 証明書を自動発行・自動更新するため、手動で ACM を操作する必要はない。Route 53 ホストゾーンに Amplify が自動作成する CNAME レコードまたは Alias A レコードを登録することでサブドメインが有効化される。

domain_name に頂点ドメインを指定し、sub_domain ブロックで prefix = "" を設定することで Apex ドメイン直接割り当てが可能。

resource "aws_amplify_domain_association" "example" {
  app_id= aws_amplify_app.frontend.id
  domain_name = "example.com"

  sub_domain {
 branch_name = aws_amplify_branch.main.branch_name
 prefix= ""  # apex domain (example.com)
  }

  sub_domain {
 branch_name = aws_amplify_branch.main.branch_name
 prefix= "www"  # www.example.com
  }

  sub_domain {
 branch_name = aws_amplify_branch.develop.branch_name
 prefix= "staging" # staging.example.com
  }
}

6-5. amplify.yml — ビルドスペック詳細

Amplify のビルド設定はリポジトリルートの amplify.yml で管理する。CodeBuild の buildspec.yml に相当するが、フロントエンド特化の 4 フェーズ構成 (preBuild / build / postBuild / cache) を持つ。

version: 1
frontend:
  phases:
 preBuild:
commands:
  - node --version
  - npm ci --prefer-offline # node_modules キャッシュを活用
 build:
commands:
  - npm run build  # Vite / CRA: dist/ へ出力
 postBuild:
commands:
  - echo "Build ID $AWS_JOB_ID complete"
  artifacts:
 baseDirectory: dist # Next.js の場合は .next
 files:
- '**/*'
  cache:
 paths:
- node_modules/**/*  # npm キャッシュ (ビルド高速化)
- .next/cache/**/*# Next.js ISR キャッシュ

Environment Variables / Secrets Manager 統合:

設定方法用途推奨
Amplify Console → Environment variablesAPI エンドポイント URL 等の非機密値
aws_amplify_app.environment_variablesTerraform 管理の非機密環境変数
Secrets Manager 参照 (Amplify Backend)API Key / DB パスワード等の機密情報○ (機密必須)
amplify.yml へのハードコード✗ 禁止

ビルド時に $VITE_API_ENDPOINT 等の環境変数を参照する場合は Amplify コンソールまたは aws_amplify_app.environment_variables で一元管理する。機密情報は Secrets Manager に格納し、Amplify IAM ロール経由で参照する。

6-6. Terraform 完全例

# ── Amplify App 本体 ──────────────────────────────────────────
resource "aws_amplify_app" "frontend" {
  name = "my-spa-app"
  repository = "https://github.com/my-org/my-spa"

  access_token = var.github_access_token

  build_spec = <<-EOT
 version: 1
 frontend:
phases:
  preBuild:
 commands:
- npm ci
  build:
 commands:
- npm run build
artifacts:
  baseDirectory: dist
  files:
 - '**/*'
cache:
  paths:
 - node_modules/**/*
  EOT

  environment_variables = {
 VITE_API_ENDPOINT = "https://api.example.com"
 NODE_ENV = "production"
  }

  custom_rule {
 source = "/<*>"
 status = "404"
 target = "/index.html"
  }
}

# ── main ブランチ (本番環境) ──────────────────────────────────
resource "aws_amplify_branch" "main" {
  app_id= aws_amplify_app.frontend.id
  branch_name = "main"
  framework= "React"
  stage = "PRODUCTION"

  enable_auto_build  = true
  enable_pull_request_preview = false

  environment_variables = {
 VITE_ENV = "production"
  }
}

# ── develop ブランチ (ステージング) ──────────────────────────
resource "aws_amplify_branch" "develop" {
  app_id= aws_amplify_app.frontend.id
  branch_name = "develop"
  framework= "React"
  stage = "DEVELOPMENT"

  enable_auto_build = true
  enable_pull_request_preview= true
  pull_request_environment_name = "pr"

  environment_variables = {
 VITE_ENV = "staging"
  }
}

# ── カスタムドメイン (Route 53 + ACM 自動統合) ───────────────
resource "aws_amplify_domain_association" "main" {
  app_id= aws_amplify_app.frontend.id
  domain_name = "example.com"

  sub_domain {
 branch_name = aws_amplify_branch.main.branch_name
 prefix= ""
  }

  sub_domain {
 branch_name = aws_amplify_branch.main.branch_name
 prefix= "www"
  }

  sub_domain {
 branch_name = aws_amplify_branch.develop.branch_name
 prefix= "staging"
  }
}
詰まり: SPA Routing で Direct URL アクセスが 404 になる

React Router / Vue Router を使った SPA で /dashboard など直接 URL にアクセスすると 404 が返る。CloudFront + S3 では ErrorDocument で対処するが、Amplify では Rewrites/Redirects (custom_rule) で解決する。

Terraform 設定: custom_rule { source = "/<*>" / status = "404" / target = "/index.html" }

Amplify コンソールでは「App settings → Rewrites and redirects」→ Source: /<*> / Target: /index.html / Type: 404 (Rewrite) を追加する。この設定を忘れると本番公開後にブックマーク・直リンクが全て 404 になる。デプロイ直後に必ず直接 URL アクセスの動作確認を実施すること。

6-7. Amplify Hosting vs CloudFront + S3 自前構築

観点Amplify HostingCloudFront + S3 自前構築
セットアップ工数GitHub 連携のみ / 5 分Terraform 100 行以上 / OAC 設定必要
ビルドパイプライン内蔵 (amplify.yml)CodePipeline + CodeBuild を別途構築
Branch / PR Preview標準機能独自実装 (スタック / Lambda) が必要
カスタムキャッシュ制御制限あり (ヘッダー単位)CloudFront Cache Policy で細粒度制御
Edge Function×CloudFront Functions / Lambda@Edge
コスト (小〜中規模)低 (ビルド分数課金)S3 + CloudFront 転送量課金
採用場面SPA / 静的サイト / SSR フロントエンドEdge Logic / 独自 CDN ルール / 大規模

小〜中規模の SPA・静的サイトは Amplify Hosting が開発速度と運用コストの両面で有利。独自の Edge Logic や細粒度キャッシュ制御が必要な場合は CloudFront + S3 構成を選択する。


7. アンチパターン→正解パターン変換演習 (5件)

本節では、Container CD / CodeArtifact / SAM / Amplify の実際の設定でよく発生するアンチパターンを 5問提示します。
各演習は ■ Before (アンチパターン)■ After (正解パターン)解説 の 3部構成です。


演習1: ECS Blue/Green — Test traffic Listener Rule 設定漏れ (Terraform)

ECS Blue/Green デプロイでは、Production traffic を Green に切り替える前に Test traffic (ポート 8080) で
動作確認を行う Listener Rule が必要です。設定漏れがあると Green 環境の検証をスキップして
Production traffic が直接 Green に流れ込みます。

■ Before (アンチパターン)

resource "aws_codedeploy_deployment_group" "ecs_bg" {
  app_name= aws_codedeploy_app.ecs.name
  deployment_group_name  = "ecs-production"
  service_role_arn = aws_iam_role.codedeploy.arn
  deployment_config_name = "CodeDeployDefault.ECSAllAtOnce"

  ecs_service {
 cluster_name = aws_ecs_cluster.main.name
 service_name = aws_ecs_service.app.name
  }

  load_balancer_info {
 target_group_pair_info {
prod_traffic_route {
  listener_arns = [aws_lb_listener.https.arn]
}
# test_traffic_route が存在しない → Green 検証スキップ
target_group {
  name = aws_lb_target_group.blue.name
}
target_group {
  name = aws_lb_target_group.green.name
}
 }
  }

  auto_rollback_configuration {
 enabled = true
 events  = ["DEPLOYMENT_FAILURE"]
  }
}

■ After (正解パターン)

resource "aws_lb_listener" "test" {
  load_balancer_arn = aws_lb.main.arn
  port  = 8080
  protocol = "HTTP"

  default_action {
 type = "forward"
 target_group_arn = aws_lb_target_group.blue.arn
  }
}

resource "aws_codedeploy_deployment_group" "ecs_bg" {
  app_name= aws_codedeploy_app.ecs.name
  deployment_group_name  = "ecs-production"
  service_role_arn = aws_iam_role.codedeploy.arn
  deployment_config_name = "CodeDeployDefault.ECSAllAtOnce"

  ecs_service {
 cluster_name = aws_ecs_cluster.main.name
 service_name = aws_ecs_service.app.name
  }

  load_balancer_info {
 target_group_pair_info {
prod_traffic_route {
  listener_arns = [aws_lb_listener.https.arn]
}
test_traffic_route {
  listener_arns = [aws_lb_listener.test.arn]# ポート 8080 でテスト
}
target_group {
  name = aws_lb_target_group.blue.name
}
target_group {
  name = aws_lb_target_group.green.name
}
 }
  }

  auto_rollback_configuration {
 enabled = true
 events  = ["DEPLOYMENT_FAILURE", "DEPLOYMENT_STOP_ON_ALARM"]
  }
}

解説:
test_traffic_route を省略すると CodeDeploy は Green 検証フェーズをスキップして
Production traffic を直接 Green Target Group に切り替えます。
ポート 8080 の Test Listener を追加することで、デプロイ担当者が Green 環境をエンドツーエンドで
検証してから ContinueDeployment を実行できます。
Security Group に 8080 のインバウンドを許可することも忘れずに設定してください。


演習2: buildspec.yml — CodeArtifact login フェーズミス (YAML)

CodeArtifact の認証トークンは aws codeartifact get-authorization-token で取得しますが、
build フェーズで実行すると pre_buildnpm install 時点で認証がなく Dependency 解決が失敗します。

■ Before (アンチパターン)

version: 0.2

phases:
  pre_build:
 commands:
- npm ci # この時点で CodeArtifact 認証なし → 失敗
  build:
 commands:
- CODEARTIFACT_TOKEN=$(aws codeartifact get-authorization-token \
 --domain my-domain \
 --domain-owner 123456789012 \
 --query authorizationToken \
 --output text)# install の後に認証実行 → 意味なし
- npm run build
- npm test
  post_build:
 commands:
- npm run package

artifacts:
  files:
 - "dist/**/*"

■ After (正解パターン)

version: 0.2

phases:
  install:
 commands:
- CODEARTIFACT_TOKEN=$(aws codeartifact get-authorization-token \
 --domain my-domain \
 --domain-owner 123456789012 \
 --query authorizationToken \
 --output text)
- npm config set //my-domain-123456789012.d.codeartifact.ap-northeast-1.amazonaws.com/npm/my-repo/:_authToken $CODEARTIFACT_TOKEN
 runtime-versions:
nodejs: 20
  pre_build:
 commands:
- npm ci # install フェーズで認証済みのため解決可能
  build:
 commands:
- npm run build
- npm test
  post_build:
 commands:
- npm run package

artifacts:
  files:
 - "dist/**/*"

解説:
CodeArtifact の認証トークンは有効期限が最大 12時間です。
install フェーズで認証を完了させ、npm config に authToken を設定しておくことで
pre_buildnpm ci が CodeArtifact リポジトリから依存パッケージを解決できます。
CODEARTIFACT_TOKEN 変数は環境変数として後続フェーズに引き継がれません。
npm config set で永続化するか、各フェーズで再取得する必要があります。


演習3: SAM template.yaml — Lambda Alias DeploymentPreference Hooks 順序ミス (YAML)

SAM の DeploymentPreference では PreTrafficHookPostTrafficHook の順序が重要です。
逆順にすると新バージョンの事前検証なしにトラフィックが切り替わります。

■ Before (アンチパターン)

Resources:
  MyFunction:
 Type: AWS::Serverless::Function
 Properties:
Handler: index.handler
Runtime: nodejs20.x
AutoPublishAlias: live
DeploymentPreference:
  Type: Canary10Percent5Minutes
  Hooks:
 PostTrafficHook: !Ref ValidateAfterTraffic  # 後検証を先に定義 (順序ミス)
 PreTrafficHook: !Ref ValidateBeforeTraffic  # 前検証が後に定義

  ValidateBeforeTraffic:
 Type: AWS::Serverless::Function
 Properties:
Handler: validate_before.handler
Runtime: nodejs20.x

  ValidateAfterTraffic:
 Type: AWS::Serverless::Function
 Properties:
Handler: validate_after.handler
Runtime: nodejs20.x

■ After (正解パターン)

Resources:
  MyFunction:
 Type: AWS::Serverless::Function
 Properties:
Handler: index.handler
Runtime: nodejs20.x
AutoPublishAlias: live
DeploymentPreference:
  Type: Canary10Percent5Minutes
  Hooks:
 PreTrafficHook: !Ref ValidateBeforeTraffic  # 前検証: 新バージョン起動確認
 PostTrafficHook: !Ref ValidateAfterTraffic  # 後検証: トラフィック切替後の動作確認
  Alarms:
 - !Ref FunctionErrorAlarm# エラー率アラームで自動ロールバック

  ValidateBeforeTraffic:
 Type: AWS::Serverless::Function
 Properties:
Handler: validate_before.handler
Runtime: nodejs20.x

  ValidateAfterTraffic:
 Type: AWS::Serverless::Function
 Properties:
Handler: validate_after.handler
Runtime: nodejs20.x

解説:
PreTrafficHook は新バージョンの Lambda にトラフィックを流すに実行されます。
ここでは新バージョンを直接呼び出してレスポンスを検証します。
PostTrafficHook はトラフィック切替の健全性確認です。
YAML の記述順序に関わらず CodeDeploy は Pre → Post の順で実行しますが、
意図を明確にするために Pre を先に記述する習慣を持つことで誤解を防げます。
Alarms を追加することで CloudWatch Alarm 発火時に自動ロールバックが発動します。


演習4: amplify.yml — SPA Rewrites 設定漏れで Direct URL 404 (YAML)

React / Vue / Next.js などの SPA はクライアントサイドルーティングを使います。
Amplify Hosting でリライトルールを設定しないと、ブラウザから直接 /dashboard
アクセスしたときにサーバーが index.html を返さず 404 になります。

■ Before (アンチパターン)

# amplify.yml — リライト設定なし
version: 1
frontend:
  phases:
 preBuild:
commands:
  - npm ci
 build:
commands:
  - npm run build
  artifacts:
 baseDirectory: dist
 files:
- '**/*'
  cache:
 paths:
- node_modules/**/*
# カスタムリライトルールが存在しない
# → /dashboard に直接アクセスすると S3 の dist/dashboard が存在せず 404

■ After (正解パターン)

# amplify.yml — SPA リライトルール追加
version: 1
frontend:
  phases:
 preBuild:
commands:
  - npm ci
 build:
commands:
  - npm run build
  artifacts:
 baseDirectory: dist
 files:
- '**/*'
  cache:
 paths:
- node_modules/**/*

上記の amplify.yml とあわせて、Amplify Console または Terraform で Rewrites ルールを設定します。

# Terraform: aws_amplify_app の custom_rule ブロック
resource "aws_amplify_app" "spa" {
  name = "my-spa"
  repository = "https://github.com/myorg/my-spa"

  custom_rule {
 source = "</^[^.]+$|\\.((?!css|gif|ico|jpg|js|png|txt|svg|woff|woff2|ttf|map|json)[^.]+)$/>"
 target = "/index.html"
 status = "200"# Rewrite (200 = URL維持してindex.htmlを返す)
  }
}

解説:
SPA のクライアントサイドルーティングはブラウザの History API を使います。
/dashboard のような URL は index.html を起点に React Router 等が処理しますが、
Amplify がそのパスを S3 オブジェクトとして探すと存在しないため 404 を返します。
リライトルール (status = "200") で全ての非アセットパスを index.html に転送することで、
クライアントサイドルーティングが正常に機能します。
status = "301" はリダイレクトなので URL が変わってしまいます。必ず 200 (Rewrite) を使用してください。


演習5: ECR Lifecycle Policy — untagged/tagged 誤削除 (JSON)

ECR Lifecycle Policy で tagStatus: "any" を使うと、タグ付きイメージ (リリースバージョン) も
削除対象になります。untagged のみ削除したい場合は tagStatus: "untagged" に限定してください。

■ Before (アンチパターン)

{
  "rules": [
 {
"rulePriority": 1,
"description": "古いイメージを削除",
"selection": {
  "tagStatus": "any",
  "countType": "imageCountMoreThan",
  "countNumber": 10
},
"action": {
  "type": "expire"
}
 }
  ]
}

■ After (正解パターン)

{
  "rules": [
 {
"rulePriority": 1,
"description": "untagged イメージを1件以上になったら削除",
"selection": {
  "tagStatus": "untagged",
  "countType": "imageCountMoreThan",
  "countNumber": 1
},
"action": {
  "type": "expire"
}
 },
 {
"rulePriority": 2,
"description": "タグ付きイメージは最新30件を保持",
"selection": {
  "tagStatus": "tagged",
  "tagPrefixList": ["v", "release-"],
  "countType": "imageCountMoreThan",
  "countNumber": 30
},
"action": {
  "type": "expire"
}
 }
  ]
}

解説:
tagStatus: "any" は untagged / tagged を問わず全イメージを対象にするため、
countNumber: 10 を超えるとタグ付きリリースイメージも削除されます。
tagStatus: "untagged" でビルド中間イメージのみを削除し、
tagStatus: "tagged" + tagPrefixList で本番リリースイメージを最新 30件保持する
2ルール構成が推奨パターンです。ルールの優先度 (rulePriority) は数値が小さいほど先に評価されます。

§7 で扱う内容:
– 演習1: 壊れた ECS Blue/Green (Test traffic Listener Rule 設定漏れ → Production traffic に全量流入) を直す (Terraform)
– 演習2: 壊れた buildspec.yml (CodeArtifact login が phases.install で実行されず Dependency解決失敗) を直す (YAML)
– 演習3: 壊れた SAM template.yaml (Lambda Alias DeploymentPreference の Hooks 順序ミス) を直す (YAML)
– 演習4: 壊れた amplify.yml (SPA で Rewrites設定漏れ → Direct URL アクセスで 404) を直す (YAML + Console設定)
– 演習5: 壊れた ECR Lifecycle Policy (untagged image 削除が tagged image にも誤適用) を直す (JSON Policy)
– 各演習: アンチパターン Before / 正解 After / 解説の3部構成
– ep-btn: 演習解答アンカーリンク
– code×5 (HCL / YAML / YAML / YAML+console / JSON)


8. まとめ + Vol3予告 + 落とし穴10選 + 全10軸クロスリンク + Vol2完結宣言

本節では Vol2 の学習内容を整理し、よくある落とし穴と次のステップを示します。

Vol2 の振り返り

Vol1 (Pipeline/Build/Deploy/GHA) の基礎の上に、Vol2 では 4本柱を追加習得しました。

本柱技術Vol2 のポイント
Container CDECS Blue/Green × EKS GitOps (ArgoCD/Flux)Blue/Green Listener Rule / Sync wave / Canary
Package管理CodeArtifact × npm/Maven/pip統合ドメイン設計・認証トークン管理・upstream proxy
Serverless CDSAM × Lambda Canary × DeploymentPreferenceHooks順序・Alarm自動ロールバック・Bootstrap設計
Static CDAmplify Hosting × Branch/Preview deploySPA Rewrites・環境変数管理・OAC設計

Vol2 の 4本柱は全て Vol1 の CodePipeline / CodeBuild / GitHub Actions OIDC を基盤として動作します。
Container → Package → Serverless → Static の4層が揃うことで、あらゆるアプリ形態の CI/CD を AWS でカバーできます。


落とし穴10選

Vol2 で頻出する落とし穴をまとめます。

  1. ECS Blue/Green Test traffic Listener Rule 漏れ — Production traffic が Green 検証スキップで直接流入
  2. EKS GitOps Sync wave 設定漏れ — 依存リソース (Namespace/CRD) がアプリより後にデプロイされる順序事故
  3. ECR Image Tag mutable のまま rollbacklatest タグが上書きされ旧バージョン Image が消失
  4. CodeArtifact 認証トークン期限切れ — 12時間後に CI が失敗。定期更新または都度取得の設計が必要
  5. SAM Bootstrap 重複実行で IAM Role 命名衝突 — 同一リージョン・同一アカウントで sam deploy --guided を複数回実行
  6. SAM Lambda Alias DeploymentPreference Hooks 順序ミス — PreTrafficHook なしにトラフィックが新バージョンへ切替
  7. Amplify Branch deploy で環境変数の上書き事故 — ブランチ固有の環境変数がアプリ全体に誤適用
  8. Amplify Preview deploy でリソース残存 — Pull Request クローズ後に Preview 環境が削除されず課金継続
  9. Amplify SPA Rewrites 設定漏れで Direct URL 404 — クライアントサイドルーティングで index.html が返らない
  10. CloudFront + S3 自前構築で OAC 設定漏れ — S3 バケットポリシーが Public になり直 S3 URL が露出

Vol3 予告 — Observability for CI/CD

Vol3 では CI/CD パイプライン自体の可観測性を扱います。

  • Trace: X-Ray × OpenTelemetry で CodeBuild ビルドとデプロイの分散トレーシング
  • Metrics: CloudWatch × Embedded Metrics Format で Pipeline 成功率・ビルド時間を可視化
  • Cost最適化: CodeBuild スポットインスタンス活用・ARM ビルドへの移行・キャッシュ戦略最適化
  • アラート: Pipeline 失敗を EventBridge → SNS → PagerDuty/Slack に自動通知する設計

Vol1/Vol2 で構築した CI/CD 基盤の品質を Observability で継続的に改善するサイクルを確立します。


AWS本番運用 全10軸シリーズ (21記事) + 第10軸 DevOps/CI/CD実践 Vol2
本記事は全10軸シリーズのハブ記事として、各軸の本番運用知識を CI/CD 自動化基盤に接続します。

第1軸: IAM (4記事)
IAM ポリシー設計入門 Vol1 / IAM マルチアカウント設計 Vol2 / IAM 権限棚卸し自動化 Vol3 / IAM STS クロスアカウント Vol4

第2軸: EKS (3記事)
EKS 本番基盤構築 Vol1 / EKS 本番 Observability Vol2 / EKS GitOps×ArgoCD Vol3

第3軸: 復旧 (4記事)
DR 基礎設計 Vol1 / カオスエンジニアリング Vol2 / 障害対応自動化 Vol3 / マルチリージョン Active-Active Vol4

第4軸: AI (2記事)
Bedrock Agent 本番運用 Vol1 / Bedrock Knowledge Bases RAG Vol2

第5軸: セキュリティ (2記事)
AWS セキュリティ SOC 基盤 Vol1 / AWS セキュリティ運用 Vol2

第6軸: コスト (1記事)
AWS コスト最適化入門 Vol1

第7軸: マルチアカウント (1記事)
AWS マルチアカウント運用基礎 Vol1

第8軸: Observability (1記事)
AWS Observability 基礎 Vol1

第9軸: Network (2記事)
VPC ネットワーク設計入門 Vol1 / AWS ハイブリッドネットワーク Vol2

第10軸: DevOps/CI/CD実践 (本シリーズ)
Vol1: CodePipeline × CodeBuild × CodeDeploy × GitHub Actions OIDC
Vol2 (本記事): Container CD × CodeArtifact × SAM × Amplify
Vol3 (次回): Observability for CI/CD — Trace × Metrics × Cost最適化

第11軸: Database本番運用 (1記事)
Database本番運用入門 Vol1 — RDS × Aurora × DynamoDB


第10軸 DevOps/CI/CD実践シリーズ — Vol2 完結

本記事では、Vol1 で確立した CI/CD 基盤の上に Container CD / Package管理 / Serverless CD / Static CD の
4本柱を積み上げ、AWS でのあらゆるアプリ形態に対応できる本番品質の CI/CD を習得しました。

ECS Blue/Green の Test traffic 設計から EKS GitOps、CodeArtifact のパッケージ管理、
SAM の Canary デプロイ、Amplify の SPA ホスティングまで、5問の演習と落とし穴10選で実践力を養いました。

Vol3 では CI/CD パイプライン自体を観測・改善する Observability 基盤を構築します。

§8 で扱う内容:
– まとめ: 4本柱 (Container CD / Package管理 / Serverless CD / Static CD) 統合理解 + Vol1の上に乗る位置付け
– 落とし穴10選:
1. ECS Blue/Green の Test traffic Listener Rule 漏れ
2. EKS GitOps Sync wave 設定漏れ (依存リソース順序事故)
3. ECR Image Tag mutable のまま rollback で旧版消失
4. CodeArtifact 認証トークン期限切れ (12時間後の CI 失敗)
5. SAM Bootstrap 重複実行で IAM Role 命名衝突
6. SAM Lambda Alias DeploymentPreference Hooks 順序ミス
7. Amplify Branch deploy で環境変数の上書き事故
8. Amplify Preview deploy で Pull Request クローズ後の リソース残存
9. Amplify SPA Rewrites設定漏れで Direct URL 404
10. CloudFront + S3 自前構築での OAC 設定漏れ → 直 S3 URL 露出
– Vol3 予告: Observability for CI/CD — Trace × Metrics × Cost optimization
– 全10軸 (IAM4+EKS3+復旧4+AI2+セキュリティ2+コスト1+マルチアカウント1+Observability1+Network2+DevOps Vol1=21記事) + 本Vol2 = 22記事 クロスリンク ep-box (brc-blue)
– 第10軸 シリーズ Vol2 完結宣言