CloudFormation CI/CD(CodePipeline)ハンズオン

IaC テンプレートを検証 → 変更セット → 手動承認 → 自動デプロイするパイプラインを構築する

CodePipeline CodeBuild CloudFormation 変更セット / 手動承認 マネコン操作 所要時間 75〜90 分 v1.0

📋 概要

このハンズオンでは、CloudFormation テンプレート(IaC)そのものを CI/CD で自動デプロイするパイプラインを構築します。GitHub への push をトリガーに、CodeBuild でテンプレートを検証(cfn-lint)し、CodePipeline の CloudFormation デプロイアクション変更セット(Change Set)を作成、手動承認を経て実行します。コンテナをデプロイする既存の CI/CD ハンズオンとは異なり、インフラ定義の安全な継続的デリバリーを学びます。

項目内容
対象サービスCodePipeline、CodeBuild、CloudFormation、CodeConnections(GitHub 連携)、IAM、S3
主な学習内容テンプレート検証・変更セット・手動承認ゲート・CloudFormation デプロイアクション
所要時間75〜90 分
難易度★★★☆☆(中〜上級者向け)
前提知識CloudFormation・IAM の基礎知識、GitHub アカウント
費用目安約 0〜1 USD(CodeBuild の実行時間と S3 が中心。デプロイ対象は無料枠内)
ℹ️ なぜ「変更セット + 手動承認」なのか
  • 変更セット(Change Set):実際にスタックを変更する前に、「何が追加・変更・削除されるか」を差分プレビューできる。意図しない置換・削除を事前に発見できる
  • 手動承認:差分を人がレビューしてから実行。本番インフラへの誤適用を防ぐゲート
  • cfn-lint 検証:構文・ベストプラクティス違反をデプロイ前に検出

🏗️ アーキテクチャ

🐙 GitHub リポジトリ
template.yaml + buildspec.yml(main への push がトリガー)
↓ CodeConnections
AWS CodePipeline — Source ステージ
変更を検知してパイプライン起動
AWS CodeBuild — Validate ステージ
aws cloudformation validate-template + cfn-lint
AWS CloudFormation — 変更セット作成(CHANGE_SET_REPLACE)
デプロイ前に差分を生成
↓ 手動承認(差分レビュー)
AWS CloudFormation — 変更セット実行(CHANGE_SET_EXECUTE)
スタックを更新 → S3 バケット・DynamoDB テーブルを作成/変更

作成するリソース

リソース名前 / 値備考
GitHub リポジトリhandson-iacIaC テンプレート置き場
CodeConnections 接続handson-iac-connectionGitHub 認証
CodeBuild プロジェクトhandson-iac-validateテンプレート検証
CodePipelinehandson-iac-pipelineSource → Build → Deploy
CloudFormation デプロイロールhandson-iac-cfn-roleCFN が引き受けるロール
デプロイ対象スタックhandson-iac-stackS3 + DynamoDB

✅ 前提条件

🔧 ツールの事前セットアップ

AWS CLI・Git・Docker などのインストールと初期設定は 環境セットアップガイド にまとめています。初めての方は先にご確認ください。

ℹ️ CodeCommit は新規利用停止

AWS は CodeCommit の新規利用を 2024 年 7 月に停止しました。本ハンズオンでは GitHub を Source として CodeConnections(旧 CodeStar Connections)で連携します。

📁 ステップ 1 ― リポジトリとテンプレートの準備

GitHub に新規リポジトリ handson-iac を作成し、以下の 2 ファイルを置きます。

1-1. template.yaml(デプロイ対象の IaC)

S3 バケットと DynamoDB テーブルを定義した、無料枠内の安全なテンプレートです。

AWSTemplateFormatVersion: '2010-09-09'
Description: Handson IaC CI/CD sample stack (S3 + DynamoDB)

Resources:
  SampleBucket:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: Enabled
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

  SampleTable:
    Type: AWS::DynamoDB::Table
    Properties:
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH

Outputs:
  BucketName:
    Value: !Ref SampleBucket
  TableName:
    Value: !Ref SampleTable
1-2. buildspec.yml(CodeBuild の検証手順)

テンプレートを validate-templatecfn-lint で検証し、成果物として次ステージへ渡します。

version: 0.2

phases:
  install:
    runtime-versions:
      python: 3.12
    commands:
      - pip install cfn-lint
  build:
    commands:
      - echo "Validating template..."
      - aws cloudformation validate-template --template-body file://template.yaml
      - cfn-lint template.yaml

artifacts:
  files:
    - template.yaml

2 ファイルを main ブランチに push しておきます。

🔗 ステップ 2 ― GitHub 接続(CodeConnections)

2-1. 接続を作成

CodePipeline コンソール → 左メニュー 「設定」→「接続」 →「接続を作成」。

プロバイダーGitHub
接続名handson-iac-connection
2-2. GitHub を認可

「GitHub に接続」→ 「AWS Connector for GitHub」アプリのインストールを許可し、対象リポジトリを選択します。接続のステータスが 利用可能(Available) になれば完了です。

🔐 ステップ 3 ― CloudFormation デプロイロールの作成

CodePipeline の CloudFormation アクションは、CFN がリソースを作成する際に引き受けるロール(デプロイロール)を必要とします。

3-1. ロールを作成(信頼されたエンティティ)

IAM → ロール → ロールを作成 → カスタム信頼ポリシー。CloudFormation サービスが引き受けられるようにします。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "Service": "cloudformation.amazonaws.com" },
      "Action": "sts:AssumeRole"
    }
  ]
}
3-2. 権限を付与してロール名を設定

テンプレートが作る S3 と DynamoDB を操作できる権限を付与します(ハンズオンでは管理ポリシー、本番では最小権限を推奨)。

  • AmazonS3FullAccess
  • AmazonDynamoDBFullAccess
ロール名handson-iac-cfn-role

作成後、ロール ARN(arn:aws:iam::<account-id>:role/handson-iac-cfn-role)を控えます。

ℹ️ パイプラインのサービスロールは自動作成でOK

CodePipeline / CodeBuild のサービスロールは、後続ステップのウィザードで自動作成されます。パイプラインのロールには CloudFormation アクションで上記デプロイロールを渡すための iam:PassRole が必要ですが、ウィザード作成のロールには通常含まれます。

🛠️ ステップ 4 ― CodeBuild プロジェクト(検証)

4-1. ビルドプロジェクトを作成

CodeBuild → ビルドプロジェクトを作成。

プロジェクト名handson-iac-validate
環境イメージマネージド型 / Amazon Linux / 標準ランタイム
Buildspecbuildspec.yml を使用(リポジトリ同梱)

ソースは後で CodePipeline から渡されるため、ここでは「ソースなし/後で設定」でも構いません(パイプライン作成時に CodeBuild ステージとして組み込みます)。

ℹ️ CodeBuild ロールに検証権限

aws cloudformation validate-template を実行するため、CodeBuild サービスロールに cloudformation:ValidateTemplate を許可します(自動作成ロールに追加)。cfn-lint は API を使わないローカル検証です。

🚦 ステップ 5 ― CodePipeline の構築

Source → Build →(変更セット作成 → 手動承認 → 変更セット実行)の Deploy ステージを組みます。

5-1. パイプラインと Source ステージ
パイプライン名handson-iac-pipeline
サービスロール新しいサービスロール(自動作成)

Source プロバイダー:接続 handson-iac-connection → リポジトリ handson-iac → ブランチ main。出力アーティファクト名は SourceArtifact とします。

5-2. Build ステージ

プロバイダー AWS CodeBuild → プロジェクト handson-iac-validate。入力 SourceArtifact、出力 BuildArtifact

5-3. Deploy ステージ①:変更セットの作成

アクションプロバイダー AWS CloudFormation を追加し、次のように設定します。

アクション名CreateChangeSet
アクションモード変更セットの置換(CHANGE_SET_REPLACE)
スタック名(StackName)handson-iac-stack
変更セット名(ChangeSetName)handson-iac-changeset
テンプレート(TemplatePath)BuildArtifact::template.yaml
デプロイロール(RoleArn)handson-iac-cfn-role
ℹ️ IAM リソースを含む場合は Capabilities

テンプレートが IAM リソースを作る場合は CapabilitiesCAPABILITY_NAMED_IAM を指定します。本サンプル(S3 + DynamoDB)は IAM を含まないため不要です。

5-4. Deploy ステージ②:手動承認

同じ Deploy ステージに、変更セット作成アクションの後段として手動承認アクションを追加します。

アクションプロバイダーManual approval
アクション名ReviewChangeSet

(任意)SNS トピックを指定すると承認依頼を通知できます。

5-5. Deploy ステージ③:変更セットの実行

承認の後段に、もう 1 つ CloudFormation アクションを追加します。

アクション名ExecuteChangeSet
アクションモード変更セットの実行(CHANGE_SET_EXECUTE)
スタック名handson-iac-stack
変更セット名handson-iac-changeset
ℹ️ アクションの実行順

1 つの Deploy ステージ内で「CreateChangeSet(実行順 1)→ ReviewChangeSet(実行順 2)→ ExecuteChangeSet(実行順 3)」と直列になるよう実行順序を設定します。

✅ ステップ 6 ― 動作確認

6-1. 初回デプロイ

パイプライン作成後、自動的に 1 回目が走ります。Source → Build と進み、CreateChangeSet で変更セットが作られると ReviewChangeSet で停止します。

6-2. 変更セットをレビューして承認

CloudFormation コンソール → スタック handson-iac-stack →「変更セット」タブで handson-iac-changeset を開き、追加されるリソース(S3・DynamoDB)を確認します。問題なければ CodePipeline に戻り、「レビュー」→「承認」します。

6-3. 変更を加えて再実行(差分プレビューの体験)

リポジトリの template.yaml を編集して push し、変更セットに差分が出ることを確認します。例:DynamoDB にタグを追加。

  SampleTable:
    Type: AWS::DynamoDB::Table
    Properties:
      BillingMode: PAY_PER_REQUEST
      Tags:
        - Key: Project
          Value: handson-iac
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH

push 後、パイプラインが再実行され、変更セットに [~] Modify として差分が表示されます。承認すると適用されます。

✅ 確認ポイント
  • cfn-lint 検証に失敗するとパイプラインが Build で止まる(不正なテンプレートを弾ける)
  • 変更セットでデプロイ前に差分を確認できた
  • 手動承認を挟まないと本番スタックが変更されない(誤適用防止)
  • CloudFormation スタックに S3 バケットと DynamoDB テーブルが作成された

🧹 クリーンアップ

⚠️ 課金停止のため必ず実施してください

以下を順番に削除します。CloudFormation スタックを削除すると、作成した S3・DynamoDB もまとめて消えます。

  1. デプロイ対象スタックを削除:CloudFormation → handson-iac-stack を削除(S3 バケットにオブジェクトがある場合は先に空にする)
  2. CodePipeline を削除handson-iac-pipeline
  3. CodeBuild プロジェクトを削除handson-iac-validate
  4. CodeConnections の接続を削除handson-iac-connection
  5. IAM ロールを削除handson-iac-cfn-role とウィザードが作成したパイプライン/ビルド用ロール
  6. アーティファクト用 S3 バケットを削除codepipeline-ap-northeast-1-xxxxx(中身を空にしてから削除)
✅ クリーンアップ完了の確認
  • CloudFormation に handson-iac-stack が残っていない
  • CodePipeline / CodeBuild に該当リソースが残っていない
  • 不要な S3 バケット(アーティファクト・サンプル)が残っていない

学習のまとめ

習得したスキル実践内容
IaC の継続的デリバリーGitHub push → 検証 → 変更セット → 承認 → デプロイの自動化
テンプレート検証CodeBuild で validate-template + cfn-lint
変更セットデプロイ前に差分をプレビューし誤適用を防止
手動承認ゲート人のレビューを挟んだ安全なデプロイ
ℹ️ 別実装もあります

同じことを GitHub だけで完結させたい場合は CloudFormation CI/CD(GitHub Actions)ハンズオン を参照してください。OIDC でアクセスキー無しに認証します。