algonote

There's More Than One Way To Do It

ゆっくりAWS CDK (TypeScript)

ChatGPTを活用して作ったAWS CDKのハンズオンです。誤りを含む可能性があります。

第1章 はじめに

1.1 本書の読み方・環境設定

――博麗神社。こたつの上にMacBook。

魔理沙 「なあ霊夢、AWS触りたいんだけど、コンソールぽちぽちは正直ダルいんだよな。なんか一瞬でインフラ生やす呪文ないのか?」

霊夢 「あるわよ。AWS CDK。コード書いて cdk deploy ってやると、VPCだろうがLambdaだろうがS3バケットだろうが、まとめてAWS上にできるの。」

魔理沙 「つ、ついにインフラも npm install みたいなノリで…!?」

霊夢 「そのノリでいい。で、本書は“CDKをTypeScriptで実際に書きながら”進めるハンズオン形式よ。理論よりまず手を動かす。」


この本の進め方

霊夢 「基本パターンはいつも同じよ。」

  1. 何を作るかゴールを決める
  2. CDKのコード(TypeScript)を書く
  3. cdk diff / cdk deploy でAWSに反映する
  4. 動いたことを確認する
  5. 片付けたい時は cdk destroy

魔理沙 「つまり“インフラ設計図=コード”を書いて、deployで実体化、destroyで撤収。プラモデルの設計図がそのまま3Dプリンタに入る感じだな。」

霊夢 「そういうイメージでOK。」


まずはローカル環境を整える

ここでは TypeScript で CDK v2 を使う前提の環境をつくります。 (Windows / macOS / Linux どれでも基本一緒。)

必要なもの:

  • Node.js (LTS推奨。例: 18 か 20 系)
  • npm または yarn / pnpm(本書はnpmで書く)
  • AWSアカウント
  • AWS CLI
  • AWS CDK CLI (v2)

順番にやる。


1. Node.js の確認

node -v
npm -v

魔理沙node -v が 18とか20ならOKだな?」

霊夢 「そう。あまりに古いと型サポートや依存解決でハマるから、LTS世代にしておきなさい。」


2. AWS CLI のインストールと認証

インストール後、認証情報をセットアップする。

aws configure

対話でこう聞かれる:

AWS Access Key ID [None]: AKIA...
AWS Secret Access Key [None]: xxxxx...
Default region name [None]: ap-northeast-1
Default output format [None]: json

魔理沙ap-northeast-1 は東京リージョンだな。」

霊夢 「そう。自分が使いたいリージョン入れればいいけど、以降のサンプルは ap-northeast-1 基準で書くわ。」


3. CDK CLI のインストール

グローバルにCDK v2 CLIを入れる。

npm install -g aws-cdk

確認:

cdk --version

魔理沙 「CDKのバージョンが 2.x.x みたいに出ればいいんだよな?」

霊夢 「そう。v1 はもう対象外。本書はぜんぶ v2 前提だから“v2であること”はちゃんと見て。」


4. サンプル用の最初のプロジェクトを作る

まずは作業用ディレクトリへ。

mkdir cdk-hands-on
cd cdk-hands-on
cdk init app --language typescript

これで以下みたいなファイルができる:

  • bin/cdk-hands-on.ts → エントリーポイント。スタックをアプリに登録してる。
  • lib/cdk-hands-on-stack.ts → 実際にAWSリソースを書く場所(最初はここをいじる)
  • package.json / tsconfig.json / cdk.json → 普通のNode+TSプロジェクトとしての設定

魔理沙cdk init だけで雛形くれるの助かるな…!」

霊夢 「そう。CDKは“コードでCloudFormationを組み立てるツール”だから、まずはこの雛形のStackに、S3バケットとかを追加していく。」


5. Bootstrap(初期準備)

CDKは、デプロイのためにアカウント側に“作業用の資材置き場(CDK bootstrap stack)”が必要になる。

cdk bootstrap aws://YOUR_ACCOUNT_ID/ap-northeast-1

魔理沙 「これ何?」

霊夢 「CDKが内部で使うS3バケットやロールを1回だけ作っておくコマンド。最初の1回だけやればOK。」


6. デプロイまでの流れを一回やってみる

  1. ソースを編集してリソース定義
  2. npm run buildtscで型チェック&トランスパイル)
  3. 差分確認
   cdk diff
  1. 本番投入(AWS上にリソースを実際に作る)
   cdk deploy

魔理沙cdk diff は“まだAWSにはないけど、これからこういうスタック作るよ”って教えてくれるんだな。」

霊夢 「そう。Terraformでいう plan に近いわね。怖いことはしない、という安心確認になる。」


7. 片付けるとき

「作ったけどお金かかるのは嫌だから消したい」という時。

cdk destroy

魔理沙 「文明的すぎる… もうマネコン開いて1個ずつ削除して回らなくていいのか…」

霊夢 「そのためのIaCよ。」


1.2 CDKとは何か? インフラをコードで扱う意義(IaC)

魔理沙 「で、霊夢。CDKってそもそも何者?TerraformとかCloudFormationと何がちがうんだ?」

霊夢 「AWS CDKは“プログラミング言語でAWSインフラを定義するフレームワーク”。 中身としては最終的にCloudFormationを出すのよ。」

魔理沙 「つまり、CDKでTypeScript書く → CDKがCloudFormationテンプレートを生成 → それがAWSにデプロイ、って流れか。」

霊夢 「そう。それがまず1つめのポイント。」

[あなたの TypeScript コード]
        ↓ synth
[CloudFormation テンプレート(JSON/YAML)]
        ↓ deploy
[AWS上にVPCとかS3バケットが本当に作られる]

IaC(Infra as Code)のメリットをゆっくり確認

霊夢 「IaC、つまり“インフラをコードとして管理する”ことで、こういう良いことがある。」

  1. 再現性

    • コードがあれば、同じインフラをもう1個別リージョン・別アカウントに再現できる。
  2. バージョン管理

    • Gitで差分が追える。誰が何を変えたかレビューできる。
  3. 自動化との相性

    • CI/CDパイプラインで、自動的に本番/ステージングへインフラを展開できる。
  4. ドキュメント代わり

    • 「このサービスどういう構成?」→ リポジトリ読めばすべて載ってる。

魔理沙 「“インフラ担当のベテランの頭の中だけにある謎の手順メモ.txt”が消えるってことだな。」

霊夢 「それ。人間の手クリックを減らすことで、“うっかり本番だけポート開いてた問題”みたいな再現性のない事故も防げる。」


CDKならではの嬉しさ

TerraformとかPulumiとか他のIaCツールもあるけど、CDKにはCDKならではのよさがある。

霊夢 「CDKは“普通のプログラミング言語”でインフラを書くのが特徴よ。if書けるし、forループ書けるし、クラスで共通化もできる。」

魔理沙 「YAML地獄からの解放ってことか。」

霊夢 「そう。例えば“S3バケットを環境ごとに名前変えたい”とか、“同じLambdaとAPI Gatewayの組み合わせを3回使いたい”ってとき、クラス化・関数化すればいいだけ。」

シンプルな例として、S3バケットを1つ作るStackをイメージしてみる。

import * as cdk from 'aws-cdk-lib';
import { Stack, StackProps, RemovalPolicy } from 'aws-cdk-lib';
import { Bucket, BlockPublicAccess } from 'aws-cdk-lib/aws-s3';
import { Construct } from 'constructs';

export class MyBucketStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const bucket = new Bucket(this, 'MySampleBucket', {
      bucketName: `my-sample-bucket-${this.account}-${this.region}`,
      blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
      removalPolicy: RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
    });

    // ここで作った bucket がAWS上にデプロイされる
  }
}

魔理沙 「TypeScriptのクラス書いてるだけに見えるのに、これでS3バケット実体が生えるのか…」

霊夢 「そうよ。で、cdk deploy すればそのまま作られる。」


“コードで書ける”って何がそんなに嬉しいの?

霊夢 「たとえば、ステージング用・本番用でほぼ同じ構成だけど、少しだけパラメータ違うやつを2セット欲しいとするじゃない?」

魔理沙 「あるあるすぎる。」

霊夢 「CDKなら、forループで回して2スタック生やすこともできる。」

const app = new cdk.App();

const stages = ['stg', 'prod'] as const;

for (const stage of stages) {
  new MyBucketStack(app, `MyBucketStack-${stage}`, {
    env: {
      account: process.env.CDK_DEFAULT_ACCOUNT,
      region: 'ap-northeast-1',
    },
    // StackProps を使ってステージごとの設定も渡せる
  });
}

魔理沙 「YAMLコピペ文化から解放された瞬間である。」

霊夢 「そういうこと。CDKは“インフラもふつうにコードとしてリファクタできる”世界線をくれる。」


1.3 CDK v2 の特徴と改訂ポイント(旧版 v1 → v2)

魔理沙 「で、わざわざ “v2” って言うのは何が違うんだ?」

霊夢 「CDK v2 は、v1 時代と比べて主にこういう改善があるわ。」

  1. パッケージが1本化された

    • v1は @aws-cdk/aws-s3, @aws-cdk/aws-lambda, …みたいにサービスごとに依存を追加してた。
    • v2では基本 aws-cdk-lib ひとつ入れれば、S3もLambdaもまとめて使える。
    • 管理がシンプルになった。
   // v2 ではこれ1本
   import { aws_s3 as s3 } from 'aws-cdk-lib';
  1. 安定したAPIだけが入っている

    • v1では「experimental(実験的)」なL2 Constructが大量に混ざってて、import先がややこしかった。
    • v2は基本的に安定APIが中心で、experimentalは別パッケージ扱いになる流れ。
    • つまり「どれが本番で使っていいやつ?」が分かりやすい。
  2. Nodeの要件やサポートポリシーが整理された

    • v2はモダンNode.js前提。古いNodeは対象外。
    • つまり“古い開発環境で無理やり回して壊れる”率が下がった。
    • (最新のサポートバージョンは本書時点のLTSを推奨する、というスタンスで進める)
  3. ブレイキングチェンジが一掃された

    • v1→v2移行のタイミングで、非推奨APIや古い命名などを整理している。
    • これから新しく学ぶ人は、最初からv2を覚えればいい。

魔理沙 「つまり“v2はシンプル・今風・本番向け”ってことだな。」

霊夢 「そう。これからCDKを始めるなら、v2から入るのが素直。 わざわざv1やる理由は、すでにv1プロジェクトをメンテしてる場合くらい。」


v1からv2への移行で、よくある混乱ポイント

魔理沙 「あとで既存案件にCDK突っ込むことになるかもだから、そのへん教えてくれ。」

霊夢 「代表的なのはこのあたりね。」

  • importパスが変わった

    • v1: import * as s3 from '@aws-cdk/aws-s3';
    • v2: import { aws_s3 as s3 } from 'aws-cdk-lib';
  • constructs のバージョン互換

    • v2では constructs v10系など、特定バージョンに揃える必要がある。
    • つまり package.json の依存を一緒に更新することになる。
  • 一部の機能名やプロパティが非推奨→削除されている

    • v1時代に “Deprecated: use X instead” と書いてあったやつは、v2ではもう消えてることがある。
    • 古いサンプルをコピペしたらTSで怒られる。怒られたら公式リファレンスを確認して書き直す。

魔理沙 「逆に言うと、これから学ぶ人は“v2の書き方だけ”覚えておけばいいからラクってことだよな。」

霊夢 「そう。だから本書は最初から全部v2記法だけでいく。安心してコピペしなさい。」


いまのうちに1回まとめ

魔理沙 「ここまでを私なりにまとめるぞ?」

  1. CDKは“TypeScriptでAWSインフラを宣言する”ツール
  2. cdk deploy でCloudFormationを経由してAWSにリソースが本当に生える
  3. IaCだから再現性・レビュー・自動化がしやすい
  4. CDK v2は依存管理がシンプルで、これから学ぶならv2一択
  5. この本はTypeScriptで進める。Pythonは付録でいい

霊夢 「完璧。あとは手を動かすだけよ。 次の章からは実際にスタックをいじって“S3バケットを1分で建てる”ところからやるわよ。」

魔理沙 「おー!インフラ職人の夜明けぜよ!!」

――こたつの上で cdk deploy が押される音がした。

第2章 開発環境の構築

2.1 プログラミング言語とツール選定(TypeScript/Python/他)

――再び博麗神社。魔理沙がコーヒー片手にMacBookを開いている。

魔理沙 「霊夢~、CDKっていろんな言語で書けるんだよな? TypeScriptとかPythonとかJavaとか…どれにすりゃいいんだ?」

霊夢 「そうね。AWS CDK v2はTypeScript・Python・Java・C#・Goの5言語に対応してるわ。」

魔理沙 「ふむふむ。で、この本はTypeScript推しなんだよな?」

霊夢 「その通り。理由はいくつかあるわ。」


🔸 TypeScriptを選ぶ理由

  1. CDKの本家言語  → CDK自体がTypeScriptで書かれているから、ドキュメントやサンプルが圧倒的に多い。

  2. 型安全と補完が強力  → IDEで補完が効く。プロパティ名のtypoで泣かない。

  3. CloudFormation構造に近い構文  → AWS公式の例やチュートリアルもほぼTS前提。

  4. Node.js環境ならすぐ始められる  → npmだけで全部そろう。


魔理沙 「つまり“公式と同じ道を歩け”ってことか。」

霊夢 「そう。Pythonも悪くないけど、CDKの進化スピードについていくならTypeScriptが最も情報量多いのよ。」


🔧 使う主要ツール一覧

ツール 用途 備考
Node.js / npm TypeScript実行環境 v18以上推奨
AWS CLI AWS操作・認証 aws configure で設定
AWS CDK CLI CDKコマンド実行 npm install -g aws-cdk
VS Code 編集用IDE 拡張機能AWS Toolkitが便利
Git バージョン管理 GitHub連携も想定

魔理沙 「まあこのへんはWeb開発でも使うから、怖くないな。」

霊夢 「そう。CDKは“インフラをプログラムとして書く”ツールだから、Webエンジニアにとっての学習コストは低めなの。」


2.2 AWS アカウント・CLI・CDK CLI のセットアップ

魔理沙 「よーし、準備だ。AWSアカウントって無料で作れるんだよな?」

霊夢 「うん、無料枠もあるわ。ただしクレカ登録は必要だから、気をつけなさい。」


🧾 AWSアカウントを作成する

  1. AWS公式サイト でサインアップ
  2. クレジットカード登録
  3. 電話/SMSによる本人確認
  4. IAMユーザー作成(ルートアカウント直使用はNG)

魔理沙 「IAMユーザー作るの面倒くさいけど、本番でミスると怖いもんな…。」

霊夢 「そう。最初にAdministratorAccessポリシー付きの管理用ユーザーを作っておくといいわ。」


🧰 AWS CLI のセットアップ

霊夢 「次にAWS CLI。これがないとcdk deployできないの。」

魔理沙 「インストールはどうすんだ?」

霊夢 「OS別にこう。」

macOS (Homebrew)

brew install awscli

Windows (PowerShell)

choco install awscli

Linux

sudo apt install awscli -y

インストールできたら確認:

aws --version

🌏 認証情報の設定

aws configure

入力例:

AWS Access Key ID [None]: AKIA***********
AWS Secret Access Key [None]: abc123*********
Default region name [None]: ap-northeast-1
Default output format [None]: json

魔理沙 「これでCLIからAWSにログイン完了ってわけだな。」

霊夢 「そう。以降、CDKもこの設定を使う。」


🧩 CDK CLI のインストール

npm install -g aws-cdk

バージョン確認:

cdk --version

霊夢2.x.x と出ればOK。1系はもう古いから注意よ。」

魔理沙 「v2が現役ってことだな。」


🧺 一度だけ必要なブートストラップ

CDKが内部で使うS3バケット等をデプロイ先に作る。

cdk bootstrap aws://YOUR_ACCOUNT_ID/ap-northeast-1

霊夢 「これを最初に1回やっておけば、CDKが自動的にスタックの資材をアップロードできるようになるわ。」


2.3 プロジェクトの初期化 — cdk init の実践

魔理沙 「よし、CLIも入った。ここからが本番だな!」

霊夢 「では最初のCDKアプリを作ってみましょう。」


🧱 新しいCDKプロジェクトを作る

作業用ディレクトリに移動:

mkdir cdk-hands-on
cd cdk-hands-on

初期化コマンド:

cdk init app --language typescript

実行すると、こんな感じのフォルダ構成ができる:

.
├── bin/
│   └── cdk-hands-on.ts
├── lib/
│   └── cdk-hands-on-stack.ts
├── package.json
├── cdk.json
└── tsconfig.json

霊夢bin/ はエントリーポイント、lib/ はAWSリソースを定義する場所よ。」

魔理沙 「ふむ、まるでReactアプリの雛形みたいだな。」

霊夢 「実際CDKもNode.jsプロジェクトだから似てるのよ。」


🧩 依存モジュールのインストール

npm install

必要に応じてS3やLambdaを使うときは個別で追加:

npm install aws-cdk-lib constructs

🧰 最初のビルドと差分確認

npm run build
cdk synth

出力例:

Resources:
  MyBucket12345678:
    Type: AWS::S3::Bucket

魔理沙 「おおっ、CloudFormationテンプレートが自動生成された!」

霊夢 「そう。cdk synth は“生成されるテンプレートを確認するコマンド”。 実際にAWSにデプロイする前に中身を見たいときに使うのよ。」


🚀 デプロイしてみる

cdk deploy

魔理沙 「デプロイ時に“続行しますか?”って聞かれた!」

霊夢y を押すとCloudFormationが実行されて、スタックがAWS上にできるの。」


🧹 後片付け

cdk destroy

霊夢 「これでAWS上のリソースを全部削除できる。無料枠内に収めるためにも、終わったら必ずdestroyする癖をつけなさい。」

魔理沙 「うっかり課金防止大事だな……。」


🌟 まとめ:第2章の学び

霊夢 「ここまでで、CDKを動かすための開発環境が整ったわ。」

魔理沙 「TypeScriptでコード書ける、CLIでデプロイできる、雛形も作れる!インフラ職人の扉が開いたぜ!」

霊夢 「次は第3章――CDKの中核概念“App / Stack / Construct”を学んで、どうやってAWSリソースが構成されているか見ていくわよ。」

魔理沙 「コードの中身をいじるターンだな。楽しみだぜ!」


第3章 CDKの核心概念

――神社の縁側。霊夢はお茶をすすりながら、魔理沙のノートPCを覗き込んでいる。

魔理沙 「CDKのプロジェクトできたけど、AppとかStackとかConstructとか、いろんな言葉が出てきてわけわからん!」

霊夢 「今日はそこを整理するわ。ここを押さえれば“CDKがどうAWSを動かしてるのか”が全部わかるの。」


3.1 App/Stack/Construct の構造

霊夢 「CDKの世界は、三段構造でできてるわ。」

App → Stack → Construct

魔理沙 「ほう、三権分立的なやつか?」

霊夢 「だいたいそんな感じ。詳しく説明するわ。」


🧩 App:アプリ全体のエントリーポイント

  • bin/ディレクトリにある。
  • CDKアプリケーション全体を表す“最上位の入れ物”。
  • ここでスタックを定義してcdk deployすると、AWSに反映される。

例:bin/cdk-hands-on.ts

#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { MyStack } from '../lib/my-stack';

const app = new cdk.App();

// スタックをアプリに登録
new MyStack(app, 'MyFirstStack', {
  env: { region: 'ap-northeast-1' },
});

魔理沙Appが全体の司令塔って感じだな。」

霊夢 「そう。複数のスタック(たとえばVPC用、アプリ用)をまとめて管理できる。」


🏗️ Stack:AWSリソースのまとまり

  • lib/ディレクトリにある。
  • 実際にAWS上に作られる“単位”。
  • CloudFormationのスタックと1対1対応。

例:lib/my-stack.ts

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';

export class MyStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    new s3.Bucket(this, 'MyBucket', {
      versioned: true,
    });
  }
}

魔理沙 「つまりStackの中にAWSリソース(S3とかLambdaとか)を並べて書くのか。」

霊夢 「そう。CDKは最終的にこのStack単位でCloudFormationを生成・デプロイするの。」


⚙️ Construct:CDKの最小単位(部品)

  • CDKの世界の“積み木”。
  • AWSの1リソース(S3バケット、Lambda関数)もConstruct。
  • 自作して共通化もできる。

霊夢 「CDKは“Constructを組み合わせてStackを作り、StackをAppでまとめる”の。」

魔理沙 「プログラム的にはクラスが組み木、Stackが建物、Appが街全体って感じだな。」


🧱 例:App → Stack → Construct の関係図

App
 ├── StackA
 │    ├── S3Bucket (Construct)
 │    ├── Lambda (Construct)
 │    └── DynamoDB (Construct)
 └── StackB
      └── CloudFront (Construct)

霊夢 「この構造さえ覚えれば、CDKが何をしてるか迷わないわ。」


3.2 ライブラリ構成とモジュール(aws-cdk-lib など)

魔理沙import { aws_s3 as s3 } from 'aws-cdk-lib'; とか書いてあるけど、なんか長くない?」

霊夢 「それがv2の統一仕様。v1ではサービスごとに個別パッケージだったのが、v2ではaws-cdk-lib一つに統合されたの。」


🔹 v2のインポート構文

import { aws_s3 as s3 } from 'aws-cdk-lib';
import { aws_lambda as lambda } from 'aws-cdk-lib';

霊夢 「これでS3もLambdaも同じaws-cdk-libから取れるのよ。」


🔹 Constructの階層(L1 / L2 / L3)

CDKのConstructには“抽象度”の段階がある。

レベル 名称 内容
L1 CloudFormationリソース直対応 すべてのパラメータを自分で書く必要あり
L2 AWSが提供する便利クラス よく使う構成を簡略化(例:s3.Bucket
L3 高レベルConstruct 複数サービスをまとめた構成(例:aws_cdk.aws_apigateway.LambdaRestApi

魔理沙 「L3は“便利セット”って感じか。」

霊夢 「そう。たとえば“Lambda + API Gateway をつなぐ”みたいな構成を1行で書けたりする。」


📦 ライブラリ例

サービス インポート名 主な用途
S3 aws_s3 ストレージ
Lambda aws_lambda サーバーレス実行環境
DynamoDB aws_dynamodb NoSQLデータベース
API Gateway aws_apigateway APIエンドポイント公開
EC2 aws_ec2 仮想マシン、VPC設定
IAM aws_iam 権限管理

🧩 例:複数ライブラリを組み合わせる

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { aws_s3 as s3, aws_lambda as lambda } from 'aws-cdk-lib';

export class MyAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const bucket = new s3.Bucket(this, 'MyBucket');

    const fn = new lambda.Function(this, 'MyLambda', {
      runtime: lambda.Runtime.NODEJS_18_X,
      handler: 'index.handler',
      code: lambda.Code.fromInline('exports.handler = async ()=> "Hello";'),
    });

    bucket.grantReadWrite(fn);
  }
}

魔理沙 「LambdaがS3にアクセスできる構成をコードで書けるのか!わかりやすいな。」

霊夢 「そう。aws-cdk-libを中心に、Constructを組み合わせてAWS上の世界を表現するの。」


3.3 Bootstrapping とデプロイの流れ

魔理沙 「前にcdk bootstrapってやったけど、あれ何してるんだ?」

霊夢 「AWSアカウントに“CDK用の準備リソース”を作ってるの。 たとえばS3バケットやIAMロールを、CDKが使うために事前に置いておく。」


🧰 デプロイの裏側

  1. cdk synth  → TypeScriptコードをCloudFormationテンプレート(JSON)に変換。
  2. cdk bootstrap  → デプロイに必要なリソース(S3, IAMなど)をAWS上に作成。
  3. cdk deploy  → テンプレートをCloudFormation経由でAWSへデプロイ。
  4. cdk destroy  → 作成したリソースを削除。

⚙️ 実行の流れ図

[Your CDK Code (TS)]
       ↓ synth
[CloudFormation Template]
       ↓ deploy
[AWS Resources Created]

魔理沙 「つまりCDKはCloudFormationの自動生成器ってことか。」

霊夢 「そう。CloudFormationを直接書かなくてもいいようにしたレイヤーなの。」


3.4 テスト/デバッグ/スタック構成のベストプラクティス

🧪 テストの種類

霊夢 「CDKのテストは、主に3段階あるわ。」

種類 コマンド例 内容
単体テスト npm test JestなどでConstructの出力を検証
スナップショットテスト assertions.Template.fromStack(stack) 生成されるCFNテンプレートが期待通りか
デプロイテスト cdk diffcdk deploy 実際にAWS上で動作を確認

🔍 スナップショットテスト例

import * as cdk from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import { MyAppStack } from '../lib/my-app-stack';

test('S3 Bucket Created', () => {
  const app = new cdk.App();
  const stack = new MyAppStack(app, 'TestStack');
  const template = Template.fromStack(stack);

  template.hasResourceProperties('AWS::S3::Bucket', {
    VersioningConfiguration: { Status: 'Enabled' },
  });
});

魔理沙 「CloudFormationを本当に出さなくても、コードの段階で構成をチェックできるのか!」

霊夢 「そう。CIで自動テストする時にも便利よ。」


🧩 スタック構成のベストプラクティス

  1. 1つのStackは論理的に独立させる  → 例えば「ネットワーク」「アプリ」「監視」など分ける。

  2. Constructで共通部品を再利用  → Lambda + API Gateway の組み合わせなど、独自Constructにする。

  3. 環境(dev/stg/prod)を明示的に分ける  → envプロパティをStackPropsで指定。

new MyAppStack(app, 'ProdStack', {
  env: { account: '123456789012', region: 'ap-northeast-1' },
});
  1. cdk diffで差分を常に確認  → 本番で意図しない変更を防ぐ。

  2. cdk destroyを習慣に  → テストリソースは忘れず削除。


💡 デバッグのコツ

ツール 用途
cdk synth 生成されるテンプレートを確認
cdk diff デプロイ前に差分を確認
cdk doctor バージョン不整合や環境問題を診断
console.log() 普通にTSの出力として利用可

魔理沙 「よし、だんだんCDKの“中の仕組み”が見えてきたぞ。」

霊夢 「ここを理解しておけば、もうただのコピペじゃなく“意図して設計できるCDK使い”になれるわ。」


🧭 まとめ

魔理沙 「今日のまとめいくぜ!」

  1. CDKは App → Stack → Construct の三層構造
  2. すべてのAWSリソースはConstructで表現される
  3. v2ではaws-cdk-lib1本で完結
  4. cdk synthbootstrapdeploydestroy の流れを理解
  5. テスト・差分確認・分割構成が大事!

霊夢 「完璧ね。次の章では、実際にS3 + CloudFrontを組み合わせて“静的サイトをCDKで構築”してみましょう。」

魔理沙 「いよいよインフラが形になるってことだな。ワクワクするぜ!」


第4章 シンプルな Web 静的サイトを構築してみる

――博麗神社の境内。魔理沙がノートPCを開き、静的サイトを公開しようとしている。

魔理沙 「霊夢、インフラもわかってきたし、自分のサイトをAWSでホスティングしてみたいんだぜ。」

霊夢 「いいわね。今回は“S3 + CloudFront”を使って、静的WebサイトをCDKで構築していくわ。」


4.1 S3 + CloudFront の設計/CDK で定義

🧭 構成図

霊夢 「今回の構成はこんな感じよ。」

[User] → [CloudFront (CDN)] → [S3 (静的Webホスティング)]
  • S3:HTML/CSS/JSなどの静的ファイルを格納
  • CloudFront:S3の内容をキャッシュして高速配信
  • Route53(今回は省略可):ドメインをつなぐ場合に使用

🧱 CDKでの実装手順

  1. S3バケットを作る(ウェブホスティング用)
  2. CloudFrontディストリビューションを設定
  3. CloudFrontがS3をオリジンとして使うように設定
  4. デプロイしてサイトを公開

💻 実際のCDKコード

ファイル:lib/static-site-stack.ts

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { aws_s3 as s3, aws_cloudfront as cloudfront, aws_cloudfront_origins as origins } from 'aws-cdk-lib';

export class StaticSiteStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // S3バケット:静的サイト用
    const siteBucket = new s3.Bucket(this, 'SiteBucket', {
      websiteIndexDocument: 'index.html',
      publicReadAccess: false,
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
    });

    // CloudFrontディストリビューション
    const distribution = new cloudfront.Distribution(this, 'SiteDistribution', {
      defaultBehavior: {
        origin: new origins.S3Origin(siteBucket),
        viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
      },
      defaultRootObject: 'index.html',
    });

    // 出力:CloudFront URL
    new cdk.CfnOutput(this, 'DistributionDomainName', {
      value: distribution.distributionDomainName,
    });
  }
}

魔理沙 「おお!これだけでS3とCloudFront両方作れるのか!」

霊夢 「そうよ。ポイントはaws_cloudfront_originsでS3をオリジンに指定しているところ。 このまま cdk deploy すれば、AWS上に公開用バケットとCDNができるわ。」


🔎 動作確認

  1. npm run build
  2. cdk deploy
  3. 出力されたCloudFrontのURLにアクセス

霊夢 「まだS3にファイルをアップしてないから、404が出るはず。 次に自動的にファイルをデプロイする仕組みを作るわ。」


4.2 自動化されたデプロイパイプラインの構築

魔理沙 「アップロードを手動でやるのは嫌だぜ。」

霊夢 「なら、CDKで自動アップロード+キャッシュ無効化までやりましょう。」


🧰 ライブラリ追加

npm install aws-cdk-lib constructs aws-cdk-lib/aws-s3-deployment

🧱 デプロイメントの追加コード

更新:lib/static-site-stack.ts

import { aws_s3_deployment as s3deploy } from 'aws-cdk-lib';

// ...既存のS3とCloudFront定義の後に追記
new s3deploy.BucketDeployment(this, 'DeployWebsite', {
  sources: [s3deploy.Source.asset('./site-contents')],
  destinationBucket: siteBucket,
  distribution, // CloudFrontキャッシュを自動で無効化
  distributionPaths: ['/*'],
});

📁 ディレクトリ構成

.
├── lib/
│   └── static-site-stack.ts
├── bin/
│   └── static-site.ts
└── site-contents/
    ├── index.html
    └── style.css

🧾 サンプルHTML

site-contents/index.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <title>Hello CDK!</title>
</head>
<body>
  <h1>初めてのCDK静的サイト</h1>
  <p>このページは S3 + CloudFront でホスティングされています。</p>
</body>
</html>

🚀 デプロイ

cdk deploy

出力:

Outputs:
  StaticSiteStack.DistributionDomainName = dxxxxxxxxxxxx.cloudfront.net

ブラウザでアクセスすれば…

魔理沙 「おおー! ほんとに公開された!!」

霊夢 「これであなたもCDNオーナーね。 アップロードも自動だから、index.htmlを更新してcdk deployすれば即反映される。」


4.3 演習:静的サイトのバージョニングとキャッシュ戦略

魔理沙 「でもCloudFrontのキャッシュって結構強力だろ?更新が反映されないこともあるんじゃ…」

霊夢 「いいところに気づいたわ。 CDNを使うとキャッシュ更新が課題になる。ここでは“バージョニング戦略”を試してみましょう。」


🎯 演習1:オブジェクトのバージョニング

霊夢 「S3のバケットにバージョニング機能をつけてみるわ。」

const siteBucket = new s3.Bucket(this, 'SiteBucket', {
  versioned: true,
  websiteIndexDocument: 'index.html',
  blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
  removalPolicy: cdk.RemovalPolicy.DESTROY,
  autoDeleteObjects: true,
});

魔理沙 「これで過去バージョンも残るんだな。」

霊夢 「そう。誤って上書きしてもロールバックできるようになる。」


🎯 演習2:キャッシュ無効化の制御

CDKのs3deploy.BucketDeploymentにはdistributionPathsがある。 デプロイ時に指定したパスを自動でキャッシュ無効化(invalidate)できる。

new s3deploy.BucketDeployment(this, 'DeployWebsite', {
  sources: [s3deploy.Source.asset('./site-contents')],
  destinationBucket: siteBucket,
  distribution,
  distributionPaths: ['/index.html'],
});

魔理沙 「つまりindex.htmlだけ無効化して、画像とかはキャッシュのまま残せるのか。」

霊夢 「そう。キャッシュ全削除はコストも時間もかかるから、必要な範囲だけ無効化するのがベストプラクティスよ。」


🎯 演習3:キャッシュ期間の設定

CloudFrontのキャッシュTTL(有効期間)も設定できる。

const distribution = new cloudfront.Distribution(this, 'SiteDistribution', {
  defaultBehavior: {
    origin: new origins.S3Origin(siteBucket),
    viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
    cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
  },
});

または独自のキャッシュポリシー:

const customCachePolicy = new cloudfront.CachePolicy(this, 'CustomCachePolicy', {
  defaultTtl: cdk.Duration.hours(1),
  maxTtl: cdk.Duration.days(7),
  minTtl: cdk.Duration.minutes(1),
});

const distribution = new cloudfront.Distribution(this, 'SiteDistribution', {
  defaultBehavior: {
    origin: new origins.S3Origin(siteBucket),
    cachePolicy: customCachePolicy,
  },
});

魔理沙 「へぇ〜、これでキャッシュの寿命も自由自在か。 配信スピードと更新頻度のバランスを取れるわけだな。」

霊夢 「そう。キャッシュを制御するのもCDKのコードで完結できるのが強みよ。」


🌟 まとめ:第4章のポイント

魔理沙 「よし、今日の内容を整理するぜ!」

  1. S3とCloudFrontをCDKで定義して、静的サイトを公開できる
  2. aws_s3_deploymentで自動アップロードとキャッシュ無効化ができる
  3. バージョニングとキャッシュ戦略を組み合わせて安全に更新できる

霊夢 「CDKの面白さは、“コードでインフラのふるまいまで定義できる”こと。 ここまでできれば、もうWebサイト運用の自動化は一歩手前ね。」

魔理沙 「つぎは何をやるんだ?」

霊夢 「次章では、Lambda + API Gateway でサーバーレスAPIを構築するわ。 “フロントはS3、バックエンドはLambda”で、フルサーバーレス構成を作るの。」

魔理沙 「おおっ!本格的なアプリの匂いがしてきたぜ!」

――神社の夜空に、CloudFrontのログが流れた。


第5章 サーバーレス API を構築する

――夜の博麗神社。魔理沙が「CDNの次はAPIだ!」と張り切っている。

魔理沙 「霊夢!静的サイトにフォームとか動的機能を足したいんだぜ! サーバー建てなくてもできる方法あるか?」

霊夢 「あるわよ。AWSのLambda + API Gatewayで“サーバーレスAPI”を作るの。 今回はこれをCDKで定義して、さらにDynamoDB認証までやってみましょう。」


5.1 Lambda 関数+API Gateway の CDK 定義

霊夢 「まずは基本構成。API GatewayがHTTPリクエストを受け取り、Lambdaで処理、結果を返す。」

[Client] → [API Gateway] → [Lambda Function] → (Optional) [DynamoDB]

🧱 Lambda + API Gateway をCDKで作る

ファイル:lib/serverless-api-stack.ts

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { aws_lambda as lambda, aws_apigateway as apigw } from 'aws-cdk-lib';

export class ServerlessApiStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Lambda関数
    const helloFn = new lambda.Function(this, 'HelloFunction', {
      runtime: lambda.Runtime.NODEJS_18_X,
      handler: 'index.handler',
      code: lambda.Code.fromInline(`
        exports.handler = async (event) => {
          return {
            statusCode: 200,
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ message: "Hello from Lambda!", input: event })
          };
        };
      `),
    });

    // API Gateway
    const api = new apigw.LambdaRestApi(this, 'HelloApi', {
      handler: helloFn,
      proxy: false, // 明示的にルート定義する
    });

    // GET /hello
    const hello = api.root.addResource('hello');
    hello.addMethod('GET');

    new cdk.CfnOutput(this, 'ApiUrl', { value: api.url ?? '' });
  }
}

魔理沙cdk deploy すれば、LambdaもAPI Gatewayも勝手に作ってくれるのか!?」

霊夢 「そう。しかもCDKがIAM権限を自動で付けてくれる。 あとはcurlで叩くだけよ。」


🚀 実行

cdk deploy
curl https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/hello

結果:

{
  "message": "Hello from Lambda!",
  "input": {...}
}

魔理沙 「すげぇ…サーバー立ててないのにAPIできた…。」

霊夢 「それが“サーバーレス”の威力よ。」


5.2 DynamoDB 連携/アクセス権限設計

魔理沙 「次はデータを保存したい。ファイルに書くのはだるいし。」

霊夢 「ならDynamoDBを使いましょう。完全マネージドなNoSQLデータベースよ。」


🧩 DynamoDBテーブルの作成

import { aws_dynamodb as dynamodb } from 'aws-cdk-lib';

// DynamoDBテーブル
const table = new dynamodb.Table(this, 'MessagesTable', {
  partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
  removalPolicy: cdk.RemovalPolicy.DESTROY,
});

🧩 Lambdaにテーブルを渡してアクセス許可を付与

helloFn.addEnvironment('TABLE_NAME', table.tableName);
table.grantReadWriteData(helloFn);

🧱 LambdaコードをDynamoDB対応に変更

code: lambda.Code.fromInline(`
  const { DynamoDBClient, PutItemCommand, ScanCommand } = require("@aws-sdk/client-dynamodb");
  const client = new DynamoDBClient({});

  exports.handler = async (event) => {
    const tableName = process.env.TABLE_NAME;
    const body = JSON.parse(event.body || "{}");

    if (event.httpMethod === "POST") {
      await client.send(new PutItemCommand({
        TableName: tableName,
        Item: { id: { S: Date.now().toString() }, message: { S: body.message || "empty" } }
      }));
      return { statusCode: 201, body: JSON.stringify({ result: "saved" }) };
    }

    if (event.httpMethod === "GET") {
      const res = await client.send(new ScanCommand({ TableName: tableName }));
      return { statusCode: 200, body: JSON.stringify(res.Items) };
    }

    return { statusCode: 405, body: "Method not allowed" };
  };
`),

🌐 APIルートを拡張

const messages = api.root.addResource('messages');
messages.addMethod('GET');  // 取得
messages.addMethod('POST'); // 登録

魔理沙POSTで保存、GETで一覧取得か。まるで簡易掲示板だな。」

霊夢 「まさにそう。DynamoDBを使えば、スケールも自動でやってくれるわ。」


5.3 演習:CORS + 認証付き API の実装

魔理沙 「フロント(S3サイト)から呼び出すなら、CORS必要だよな?」

霊夢 「その通り。addMethodにCORSオプションを追加するの。」


🧩 CORS設定

messages.addMethod('GET', undefined, {
  authorizationType: apigw.AuthorizationType.NONE,
  methodResponses: [{ statusCode: '200' }],
});

messages.addCorsPreflight({
  allowOrigins: ['*'],
  allowMethods: ['GET', 'POST', 'OPTIONS'],
});

魔理沙allowOrigins*にすればどこからでも叩けるけど、本番では限定しとけってことだな。」

霊夢 「そう。CORSは便利だけどセキュリティも意識してね。」


🔐 Cognitoによる認証追加(応用)

霊夢 「ここではCDKでCognito認証付きAPIを構築してみるわ。」

import { aws_cognito as cognito } from 'aws-cdk-lib';

// ユーザープール
const userPool = new cognito.UserPool(this, 'UserPool', {
  selfSignUpEnabled: true,
  signInAliases: { email: true },
});

const authorizer = new apigw.CognitoUserPoolsAuthorizer(this, 'APIAuthorizer', {
  cognitoUserPools: [userPool],
});

// 認証付きメソッド
messages.addMethod('POST', undefined, {
  authorizer,
  authorizationType: apigw.AuthorizationType.COGNITO,
});

魔理沙 「つまり、ログイン済みユーザーだけが投稿できるAPIになるのか!」

霊夢 「そう。サーバーレスでも認証は全部AWSで完結できる。 Cognito → API Gateway → Lambda → DynamoDB。もう完全にフルマネージドアプリよ。」


🌐 完成構成図

[S3 Frontend] 
     │
     ▼
[API Gateway] → [Lambda Function] → [DynamoDB]
     │
 [Cognito UserPool]

魔理沙 「これはもう立派なWebアプリだな…。サーバーどこにもないのに!」

霊夢 「管理もスケールもAWS任せ。運用コストが最小で済むのがサーバーレスの魅力よ。」


🌟 まとめ:第5章の学び

項目 内容
Lambda ビジネスロジックを実行する関数
API Gateway HTTPエンドポイントの管理
DynamoDB サーバーレスNoSQLデータベース
CORS フロントから安全にAPIを呼び出す仕組み
Cognito 認証・認可を提供するサービス

魔理沙 「ここまでできたら、静的フロントと組み合わせてアプリ完成じゃね?」

霊夢 「そうね。S3 + CloudFront がフロント、Lambda + API Gateway + DynamoDB がバックエンド。 フルサーバーレス構成をCDKで一発構築、これがAWSの強みよ。」

魔理沙 「よーし、次はCI/CDで自動デプロイだな!」

霊夢 「次章では“CDK Pipelines”を使って、コード変更から自動デプロイまでの流れを作るわよ。」

――神社の夜空に、Lambdaのログが流れた。


第6章 コンテナ/ECS+Fargate を使ったマイクロサービス

――博麗神社の裏庭。焚き火のそばで、魔理沙がDockerをいじっている。

魔理沙 「霊夢、Lambdaもいいけど、やっぱDockerでアプリ動かしたいんだぜ! “自分の環境ごと持ち込み”できる感じがいい!」

霊夢 「わかるわ。でもEC2に直接コンテナ置くのはメンテが大変よ。 そこで登場するのがECS + Fargate。サーバーレスなコンテナ実行基盤ね。」


6.1 VPC/サブネット/セキュリティグループの定義

魔理沙 「いきなりECS作る前に、まずネットワークを定義するのか?」

霊夢 「そう。ECSタスクはVPC内で動くから、VPC・サブネット・セキュリティグループを先に作るの。」


💻 CDKコード例:ネットワークの定義

ファイル:lib/ecs-fargate-stack.ts

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import {
  aws_ec2 as ec2,
  aws_ecs as ecs,
  aws_ecs_patterns as ecs_patterns,
  aws_elasticloadbalancingv2 as elbv2,
} from 'aws-cdk-lib';

export class EcsFargateStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // --- VPCの作成 ---
    const vpc = new ec2.Vpc(this, 'AppVpc', {
      maxAzs: 2, // 2つのAZにサブネットを作成
    });

    // --- セキュリティグループ ---
    const sg = new ec2.SecurityGroup(this, 'AppSecurityGroup', {
      vpc,
      allowAllOutbound: true,
    });
    sg.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(80));

    new cdk.CfnOutput(this, 'VpcId', { value: vpc.vpcId });
  }
}

魔理沙 「CDKでネットワークも1行でできるのすげぇな…。 Vpcって書くだけでサブネットとかルートテーブルまで自動生成されるのか。」

霊夢 「そう。maxAzs: 2ならパブリック+プライベートサブネットをそれぞれ2つずつ作ってくれる。 CDKはネットワーク設計の初期構築を楽にしてくれるの。」


6.2 ECS サービス、タスク定義、ALB の構築

霊夢 「さて、ここからが本番。ECSクラスタを作って、Fargateでコンテナを動かしましょう。」


🧩 ECSクラスタの作成

// --- ECSクラスタ ---
const cluster = new ecs.Cluster(this, 'AppCluster', { vpc });

🧩 Fargateサービスの構築(ALB付き)

CDKのecs_patterns.ApplicationLoadBalancedFargateServiceを使えば、 ALB(Application Load Balancer)込みで一気に作成できる。

const fargateService = new ecs_patterns.ApplicationLoadBalancedFargateService(
  this,
  'WebService',
  {
    cluster,
    cpu: 256,
    desiredCount: 2,
    memoryLimitMiB: 512,
    publicLoadBalancer: true,
    taskImageOptions: {
      image: ecs.ContainerImage.fromRegistry('nginxdemos/hello'),
      containerPort: 80,
    },
  }
);

new cdk.CfnOutput(this, 'LoadBalancerURL', {
  value: `http://${fargateService.loadBalancer.loadBalancerDnsName}`,
});

魔理沙 「えっ、これだけでALB付きECS環境完成?!」

霊夢 「そう。ApplicationLoadBalancedFargateServiceは、 VPC・ALB・TargetGroup・Listener・ECSサービスを一括で作る“高レベルConstruct”よ。」


🌐 動作確認

  1. npm run build
  2. cdk deploy
  3. 出力されたURLにアクセス

魔理沙 「うおおお!“Welcome to nginx”出たーーー!!」

霊夢 「今のアプリはDocker Hubのnginxサンプルだけど、 自分のアプリイメージ(ECRにpushしたやつ)にも差し替えられるのよ。」


🐳 自前Dockerイメージに差し替える例

taskImageOptions: {
  image: ecs.ContainerImage.fromAsset('./app'), // ローカルDockerfileを使う
  containerPort: 3000,
},

魔理沙 「なるほど、fromAssetで手元のアプリをそのままFargateに送れるのか。」

霊夢 「そうよ。cdk deploy時に自動的にECRへアップロードされる。 開発・デプロイが1コマンドで終わるの。」


6.3 演習:Blue/Green デプロイを CDK で構築

魔理沙 「本番運用だと、デプロイ中に止まらないようにしたいよな。」

霊夢 「そういうときはBlue/Greenデプロイよ。 ECSではCodeDeployを使って安全にトラフィックを切り替えられる。」


💡 Blue/Greenの仕組み(図)

             ┌─────────────┐
             │  ALB Listener│
             └─────┬───────┘
                   │
          ┌────────┴────────┐
   (Blue)│ old ECS Service │ (Green)│ new ECS Service │
          └────────┬────────┘
                   ▼
           Traffic Shift

霊夢 「新バージョン(Green)を立ち上げて、テストが成功したら少しずつトラフィックを移すの。」


🧱 CDKによるBlue/Green構成例

import { aws_codedeploy as codedeploy } from 'aws-cdk-lib';

// デプロイ構成
const deploymentGroup = new codedeploy.EcsDeploymentGroup(this, 'BlueGreenGroup', {
  service: fargateService.service,
  blueGreenDeploymentConfig: {
    terminateBlueInstancesOnDeploymentSuccess: true,
  },
  deploymentConfig: codedeploy.EcsDeploymentConfig.ALL_AT_ONCE,
});

魔理沙terminateBlueInstancesOnDeploymentSuccess: true…ってことは、 新バージョンが成功したら古いやつは自動削除されるのか。」

霊夢 「そう。これでゼロダウンタイムデプロイが可能になる。 CI/CDパイプライン(CodePipeline)と組み合わせれば完全自動化できるわ。」


🧩 デプロイ流れのサマリ

ステップ 内容
1 新しいDockerイメージをビルド&ECRにpush
2 CDKで新リビジョンをcdk deploy
3 CodeDeployがALB経由でトラフィックを徐々に移行
4 Green環境が安定したらBlueを削除

魔理沙 「これなら“更新中に落ちる”こともなくなるな。 Webサービスの運用もCDKで完結するってわけか。」

霊夢 「そう。ECS + Fargate + ALB + CodeDeploy の組み合わせで、 本格的なマイクロサービス環境を自動化できるの。」


🌟 まとめ:第6章の学び

項目 内容
VPC/セキュリティグループ ECSが動くネットワークを定義
ECSクラスタ/Fargateサービス コンテナアプリをサーバーレス実行
ALB 複数タスクへのトラフィックを自動分散
Blue/Greenデプロイ 無停止リリースのための構成
CDKパターン ApplicationLoadBalancedFargateServiceなど便利Constructを活用

魔理沙 「Lambdaの次はコンテナか…。CDKって本当に“何でもコードで作れる”んだな。」

霊夢 「そうよ。しかも同じTypeScriptで全部統一できる。 これが“インフラもアプリも同じ言語で書く”時代の到来ね。」

魔理沙 「次は何をやるんだ?」

霊夢 「次章は“マルチスタック運用とCI/CDパイプライン構築”。 つまり、複数サービスを連携し、変更を自動デプロイする世界に進むわ。」

魔理沙 「うおー!DevOpsの香りがしてきたぜ!」

――夜空にALBのログが光り、神社のネットワークもVPCの中に包まれた。


第7章 ネットワーク・認証・セキュリティ設計

――博麗神社。霊夢が防犯ベルを取り付けている横で、魔理沙がAWSのセキュリティグループ設定を眺めている。

魔理沙 「なぁ霊夢。CDKでアプリ動かせるのはわかったけど…… 本番運用で“セキュリティ事故”起こしたら洒落にならんよな。」

霊夢 「その通り。AWSでは“便利さ=責任の分担”。 つまり“ユーザー側が設定すべきセキュリティ”をCDKで正しく書く必要があるのよ。」


7.1 IAMポリシー/ロール設計のベストプラクティス

魔理沙 「IAMっていろいろあるけど、正直どこから手をつけていいか分からん!」

霊夢 「まずはCDKでIAMロールやポリシーを安全に管理する方法を押さえましょう。」


💡 IAMの基本構造

ユーザー / サービス
   ↓
ロール (Role)
   ↓
ポリシー (Policy)
   ↓
アクセス権限 (Actions / Resources)

霊夢 「“誰が(Principal)”“何を(Action)”“どこに(Resource)”できるかをJSONで定義するのがポリシー。 CDKではこの構造をTypeScriptで表現できるの。」


🧱 例:S3読み取り専用ロールを定義

import { aws_iam as iam } from 'aws-cdk-lib';

// S3読み取り専用ポリシー
const s3ReadOnlyPolicy = new iam.PolicyStatement({
  effect: iam.Effect.ALLOW,
  actions: ['s3:GetObject', 's3:ListBucket'],
  resources: ['arn:aws:s3:::my-app-bucket', 'arn:aws:s3:::my-app-bucket/*'],
});

// Lambda実行ロールにアタッチ
const lambdaRole = new iam.Role(this, 'LambdaRole', {
  assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
});
lambdaRole.addToPolicy(s3ReadOnlyPolicy);

魔理沙 「おお、JSONポリシーをTypeScriptで書けるのか。 コード化すると“どんな権限があるか”が一目で分かるな。」


🧩 ベストプラクティス(霊夢メモ)

分類 推奨方針
最小権限の原則 (Least Privilege) 必要なActionsとResourcesだけ指定する
サービスロール分離 Lambda, ECS, CodeBuild などでロールを分ける
明示的拒否を活用 必要に応じてEffect: DENYを利用
インラインよりマネージドを優先 共有ポリシーは再利用可能なマネージド化が◎
条件(Condition)を活用 例: aws:SourceIpでIP制限、aws:MultiFactorAuthPresentでMFA強制

🧰 例:条件付きIAMポリシー

new iam.PolicyStatement({
  actions: ['s3:*'],
  resources: ['*'],
  effect: iam.Effect.DENY,
  conditions: {
    'BoolIfExists': { 'aws:MultiFactorAuthPresent': 'false' },
  },
});

魔理沙 「MFAなしの操作を自動拒否!……地味に助かるやつだな。」

霊夢 「そう。CDKなら“条件付きセキュリティ”もコードで管理できるのよ。」


魔理沙 「ECSもLambdaも動いてるけど、VPCが分かれてたら通信できなくないか?」

霊夢 「いい質問ね。AWSでは複数のネットワークを安全につなぐ方法が3つあるわ。」


🧭 ① VPC Peering(1対1接続)

  • 2つのVPCを直接つなぐ最もシンプルな方法。
  • 同じリージョンでも、アカウントをまたいでも接続可能。
import { aws_ec2 as ec2 } from 'aws-cdk-lib';

// VPC A と VPC B
const vpcA = new ec2.Vpc(this, 'VpcA');
const vpcB = new ec2.Vpc(this, 'VpcB');

// ピアリング接続
new ec2.CfnVPCPeeringConnection(this, 'VpcPeering', {
  vpcId: vpcA.vpcId,
  peerVpcId: vpcB.vpcId,
});

魔理沙 「“トンネル”を作るイメージだな。」

霊夢 「そう。小規模・固定ペアの接続ならPeeringで十分。」


🕸️ ② Transit Gateway(複数VPCの集約接続)

  • 多数のVPC・オンプレを相互接続する“ハブ”。
  • 大規模システムやマルチアカウントで使う。
import { aws_ec2 as ec2 } from 'aws-cdk-lib';

const transitGateway = new ec2.CfnTransitGateway(this, 'TransitGateway', {
  description: 'Shared Transit Gateway',
});

new ec2.CfnTransitGatewayAttachment(this, 'VpcAttachment', {
  transitGatewayId: transitGateway.ref,
  vpcId: vpcA.vpcId,
  subnetIds: vpcA.privateSubnets.map(s => s.subnetId),
});

魔理沙 「なるほど。これで複数VPCが“中央の道路”でつながるってことか。」

霊夢 「その通り。複数チームやマイクロサービスを連携する基盤に使うわ。」


🔒 ③ PrivateLink(VPC間で特定サービスだけ公開)

  • 1つのVPCのサービスを他VPCへプライベートエンドポイント経由で共有。
  • API Gatewayや自社バックエンドを安全に内部共有する時に便利。
import { aws_ec2 as ec2, aws_elasticloadbalancingv2 as elbv2 } from 'aws-cdk-lib';

// ALBのPrivateLinkエンドポイントサービス公開
const alb = new elbv2.ApplicationLoadBalancer(this, 'InternalAlb', {
  vpc: vpcA,
  internetFacing: false,
});
const service = new ec2.InterfaceVpcEndpointService('com.amazonaws.vpce.internal', {
  acceptanceRequired: false,
});

魔理沙 「なるほど、公開じゃなくて“社内VPN越しのHTTP共有”みたいな感じか。」

霊夢 「そう。PrivateLinkは“セキュアな内線電話”のようなものね。」


7.3 演習:セキュアなマルチアカウント構成を CDK で定義

魔理沙 「企業だとアカウントが複数あるよな?開発用・本番用とか。」

霊夢 「そう。AWSではOrganizationsでマルチアカウントを管理できる。 CDKでも、アカウントを跨いだ構成が書けるのよ。」


🧩 StackPropsでアカウント指定

const app = new cdk.App();

new MyVpcStack(app, 'DevVpcStack', {
  env: { account: '111111111111', region: 'ap-northeast-1' },
});

new MyVpcStack(app, 'ProdVpcStack', {
  env: { account: '222222222222', region: 'ap-northeast-1' },
});

魔理沙 「これで同じコードから、アカウントごとのVPCを自動作成できるのか。」

霊夢 「そう。しかもCDKはcross-account roleを通じて安全にデプロイできる。 つまり“中央CDKアカウント”から他のAWS環境にスタックを展開できるわ。」


🔐 Cross-AccountデプロイのIAM設定例

const deployRole = new iam.Role(this, 'CdkDeployRole', {
  assumedBy: new iam.AccountPrincipal('111111111111'), // 管理アカウントID
  roleName: 'CdkDeployRole',
  managedPolicies: [
    iam.ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess'),
  ],
});

魔理沙AccountPrincipalを使うのか。CDK CLIを実行するアカウントがこれを引き受ける感じだな。」

霊夢 「そう。マルチアカウントCI/CDやセキュリティ境界設計に使われる仕組みよ。」


🧰 マルチアカウント設計のポイント

項目 解説
単一責任アカウント設計 開発・本番・監査・共有を分離
Cross-account role管理 管理アカウントだけが他アカウントにデプロイできる
共通VPC共有 PrivateLinkやTransit Gatewayを活用して接続
セキュリティ監査統合 AWS Config, CloudTrailを全アカウント集中収集

魔理沙 「こうやって見ると、CDKで全部“構成コード化”できるのがいいな。 設定ミスも減るし、再現性も高い。」

霊夢 「そう。セキュリティ設計もIaCの範囲に含めるべきなのよ。 “人間の手でクリックするセキュリティ”は危ないからね。」


🌟 まとめ:第7章の学び

分野 ポイント
IAM 最小権限・条件付きポリシー・ロール分離を徹底
ネットワーク接続 VPC Peering(1対1)/Transit Gateway(多対多)/PrivateLink(サービス共有)
マルチアカウント StackPropsでenv指定・CrossAccountRoleで安全展開
CDKの強み セキュリティ構成も再現性・レビュー可能なコード化

魔理沙 「よし、セキュリティの基礎がコードで全部書けるってのは強いな。 運用も自動化できるし。」

霊夢 「その通り。CDKは“安全を自動化するツール”でもあるの。 これを理解しておけば、怖いクラウド設定事故も防げるわ。」

魔理沙 「次は何やるんだ?」

霊夢 「次章はCI/CDとパイプライン構築。 CDK Pipelinesで、変更をpushしたら自動でAWSにデプロイされる仕組みを作るわ。」

魔理沙 「うおー!DevOps神社の完成だな!」

――博麗神社の上空に、Transit Gatewayの雲が広がった。


第8章 多スタック構成・ライブラリ化・モジュール化

――博麗神社の縁側。霊夢がCDKプロジェクトのフォルダを眺めてため息をついている。

魔理沙 「霊夢、どうした?なんかディレクトリ多くなってないか?」

霊夢 「そうなのよ……サービス増やしてたらlib/フォルダがカオスになってきたの。 Lambda、ECS、S3、VPC、ぜんぶ1スタックに詰め込んでたらもう地獄よ。」

魔理沙 「あるある案件だな。コードもデプロイも分けたいけど、どうすりゃいいんだ?」

霊夢 「そこで使うのが“多スタック構成”と“Constructライブラリ化”。 CDKをモジュール設計で整理していくわよ。」


8.1 クロススタック参照と共有リソース設計

霊夢 「まずは基本。CDKでは、1つのアプリ(App)に複数のStackを定義できるの。」


🧩 例:複数スタックを1つのアプリで管理

bin/multi-app.ts

#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { NetworkStack } from '../lib/network-stack';
import { AppStack } from '../lib/app-stack';

const app = new cdk.App();

const network = new NetworkStack(app, 'NetworkStack');
new AppStack(app, 'AppStack', {
  vpc: network.vpc,
});

lib/network-stack.ts

import * as cdk from 'aws-cdk-lib';
import { aws_ec2 as ec2 } from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class NetworkStack extends cdk.Stack {
  public readonly vpc: ec2.Vpc;

  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    this.vpc = new ec2.Vpc(this, 'MainVpc', { maxAzs: 2 });
  }
}

lib/app-stack.ts

import * as cdk from 'aws-cdk-lib';
import { aws_ecs as ecs, aws_ecs_patterns as ecs_patterns } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { aws_ec2 as ec2 } from 'aws-cdk-lib';

interface AppStackProps extends cdk.StackProps {
  vpc: ec2.IVpc;
}

export class AppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: AppStackProps) {
    super(scope, id, props);

    new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'WebApp', {
      cluster: new ecs.Cluster(this, 'AppCluster', { vpc: props.vpc }),
      taskImageOptions: { image: ecs.ContainerImage.fromRegistry('nginxdemos/hello') },
    });
  }
}

魔理沙 「なるほど、NetworkStackで作ったVPCをAppStackで再利用してるのか!」

霊夢 「そう。これがクロススタック参照 (Cross-Stack Reference)。 Stack間でリソースを共有するときは、こうやってPropsで受け渡すの。」


💡 注意点(霊夢メモ)

項目 内容
直接参照 Props経由でオブジェクトを渡す(例:vpc: network.vpc
Output参照 別リージョン/別アカウント間ではCfnOutput + Fn.importValue()を使う
循環参照禁止 Stack間が双方向に依存するのはNG(デプロイ不可)

🧰 Output/ImportValue例(別アカウント用)

NetworkStack側:

new cdk.CfnOutput(this, 'VpcIdExport', {
  value: this.vpc.vpcId,
  exportName: 'SharedVpcId',
});

AppStack側:

const vpcId = cdk.Fn.importValue('SharedVpcId');
const vpc = ec2.Vpc.fromLookup(this, 'ImportedVpc', { vpcId });

魔理沙 「へぇ〜、まるで“環境変数の受け渡し”みたいだな。」

霊夢 「そう。アカウントやリージョンをまたぐときは、このOutput経由が王道よ。」


8.2 マルチアカウント/マルチリージョン展開戦略

魔理沙 「でもさ、開発・本番でAWSアカウントが違う場合、全部同じコードで動かせるのか?」

霊夢 「できるわ。CDKはenv指定でマルチ環境展開をサポートしてる。」


🧱 Stackごとに環境を指定

new NetworkStack(app, 'NetworkStack-Dev', {
  env: { account: '111111111111', region: 'ap-northeast-1' },
});

new NetworkStack(app, 'NetworkStack-Prod', {
  env: { account: '222222222222', region: 'us-east-1' },
});

魔理沙 「おお、同じクラス定義でリージョンやアカウントを切り替えられるのか!」

霊夢 「そうよ。CI/CDパイプラインと組み合わせれば、同じコードで複数環境を自動展開できるわ。」


🧩 ベストプラクティス:マルチ環境展開のコツ

分類 推奨方針
Stack命名規則 ServiceName-Envなど、環境名を含める
環境ごとの設定ファイル config/dev.json, config/prod.jsonを用意し、CDKで読み込む
共有Constructライブラリ 同じ構成を複数Stackで再利用するためにconstructs/フォルダを分ける
環境変数管理 .envAWS SSM Parameter Storeで安全に共有

📦 例:環境ごとに設定を読み込む

import * as fs from 'fs';

const envConfig = JSON.parse(fs.readFileSync(`config/${process.env.ENV}.json`, 'utf8'));

new AppStack(app, `AppStack-${process.env.ENV}`, {
  env: envConfig.env,
  vpcId: envConfig.vpcId,
});

魔理沙 「おー、Nodeのスクリプトっぽく設定できるのか。 これならGitOps的に管理できそうだな。」

霊夢 「そう。CDKは“設定もコード”の思想に沿ってるの。」


8.3 演習:社内ライブラリ(Constructs)を自作し、再利用可能なインフラ設計

魔理沙 「Stackが増えるとコード量も増えるよな…。共通部分を切り出したい。」

霊夢 「まさにそこ。CDKではConstructを自作して、社内ライブラリとして再利用できるのよ。」


🧱 自作Constructの作り方

ファイル:lib/constructs/web-app-construct.ts

import { Construct } from 'constructs';
import {
  aws_ecs as ecs,
  aws_ecs_patterns as ecs_patterns,
  aws_ec2 as ec2,
} from 'aws-cdk-lib';

export interface WebAppConstructProps {
  vpc: ec2.IVpc;
  image: string;
}

export class WebAppConstruct extends Construct {
  constructor(scope: Construct, id: string, props: WebAppConstructProps) {
    super(scope, id);

    const cluster = new ecs.Cluster(this, 'Cluster', { vpc: props.vpc });

    new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'Service', {
      cluster,
      desiredCount: 2,
      taskImageOptions: {
        image: ecs.ContainerImage.fromRegistry(props.image),
        containerPort: 80,
      },
      publicLoadBalancer: true,
    });
  }
}

💡 これをStackで再利用

import { WebAppConstruct } from './constructs/web-app-construct';

new WebAppConstruct(this, 'FrontendApp', {
  vpc,
  image: 'nginxdemos/hello',
});

new WebAppConstruct(this, 'BackendApp', {
  vpc,
  image: 'public.ecr.aws/lambda/nodejs:18',
});

魔理沙 「おお!まるでReactコンポーネントみたいに“再利用”できるのか!」

霊夢 「そうよ。Constructは“インフラの関数化”みたいなもの。 チーム内で共通の設計をモジュールとして配布できるわ。」


🧰 社内ライブラリ化の実例

  1. constructs/ フォルダに共通Constructをまとめる
  2. package.jsonprivate: true を追加してnpmパッケージ化
  3. 他プロジェクトから npm install ../shared-constructs で再利用

魔理沙 「つまり“社内の共通IaCライブラリ”を作れるってことか。 毎回ゼロから書かなくていいの最高じゃん。」

霊夢 「その通り。たとえば“ログ付きVPC”とか“モニタリング付きLambda”をConstruct化しておくと、 全プロジェクトで安全な設計が共通化できるの。」


🧱 演習:共通S3バックアップConstructを作ってみよう

export interface BackupBucketProps {
  lifecycleDays?: number;
}

export class BackupBucket extends Construct {
  public readonly bucket: s3.Bucket;

  constructor(scope: Construct, id: string, props?: BackupBucketProps) {
    super(scope, id);

    this.bucket = new s3.Bucket(this, 'BackupBucket', {
      versioned: true,
      lifecycleRules: [
        {
          expiration: cdk.Duration.days(props?.lifecycleDays ?? 30),
        },
      ],
    });
  }
}

使い方:

import { BackupBucket } from './constructs/backup-bucket';

const backup = new BackupBucket(this, 'SharedBackup', { lifecycleDays: 60 });

魔理沙 「これなら新しいプロジェクトでも共通のポリシーを即適用できるな!」

霊夢 「そう。“再利用できる安全な設計”こそIaCの本質よ。」


🌟 まとめ:第8章の学び

項目 ポイント
クロススタック参照 PropsやOutputでリソースを共有
マルチアカウント/リージョン env指定で展開環境を分ける
Constructの自作 再利用可能な“インフラ部品”をライブラリ化
社内共有ライブラリ npmパッケージ化してチーム間で共有
目的 スタック整理・再現性・安全な標準化

魔理沙 「なんかCDKが一気に“設計ツール”っぽくなってきたな。 コード管理から、社内共通インフラ基盤まで作れちゃう。」

霊夢 「そう。ここまで来たらもう一人前のCDK使いよ。 次章では、このモジュール化した構成をパイプライン化して自動デプロイしていくわ。」

魔理沙 「いよいよ本格的なDevOpsじゃねぇか。ワクワクしてきたぜ!」

――神社の空に、Constructたちが並ぶアーキテクチャ図が浮かび上がった。


第9章 パイプラインと継続的デリバリー(CI/CD)

――博麗神社の夜。魔理沙が「cdk deploy」を10回くらい連打している。

魔理沙 「うおお、毎回コマンド叩くのもう限界だぁぁ!」

霊夢 「……魔理沙、それCI/CDで自動化できるわよ。」

魔理沙 「まじで!?Pushしたら勝手にデプロイしてくれるやつ?」

霊夢 「そう。AWSでは CodePipelineCDK Pipelines を使えば、 Gitの変更からテスト・ビルド・デプロイまで全部自動化できるの。」


9.1 AWS CodePipeline/CodeBuild/CDK Pipelines を用いた自動デプロイ構成

霊夢 「まずは全体の仕組みをイメージしてね。」

🧭 アーキテクチャ図

[GitHub (main branch push)]
         │
         ▼
  [CodePipeline]
     ├─ Source Stage  → GitHubからソース取得
     ├─ Build Stage   → CodeBuildでCDK synth実行
     └─ Deploy Stage  → CDKがAWS上にスタックをデプロイ

魔理沙 「おお、つまりGit push → 自動でcdk deployまで流れるってことか!」

霊夢 「そう。CDK Pipelinesを使えば、パイプラインそのものも“コードで定義”できるのよ。」


💻 CDK Pipelinesの基本構成

ファイル:lib/pipeline-stack.ts

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import {
  pipelines as pipelines,
  aws_codebuild as codebuild,
  aws_codepipeline_actions as actions,
} from 'aws-cdk-lib';
import { AppStack } from './app-stack';

export class PipelineStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // 1. ソースコード(GitHub)
    const source = pipelines.CodePipelineSource.gitHub(
      'hiromichinomata/cdk-hands-on', // ← 自分のリポジトリ名に変更
      'main'
    );

    // 2. ビルドステップ(CDK synth)
    const synth = new pipelines.ShellStep('Synth', {
      input: source,
      commands: [
        'npm ci',
        'npm run build',
        'npx cdk synth',
      ],
    });

    // 3. パイプライン定義
    const pipeline = new pipelines.CodePipeline(this, 'CdkPipeline', {
      pipelineName: 'HandsOnPipeline',
      synth,
    });

    // 4. ステージ追加(本番環境)
    pipeline.addStage(new AppStage(this, 'Prod'));
  }
}

// AppStageの定義
import { Stage } from 'aws-cdk-lib';
class AppStage extends Stage {
  constructor(scope: Construct, id: string, props?: cdk.StageProps) {
    super(scope, id, props);
    new AppStack(this, 'AppStack');
  }
}

魔理沙 「うわ、たったこれだけでパイプライン作れるのか!」

霊夢 「そう。昔はCodePipelineとCodeBuildを別々に定義してたけど、 pipelines.CodePipelineを使えばワンストップで完結するのよ。」


🧰 CodePipelineを動かすための前準備

  1. GitHubのPersonal Access TokenをAWS Secrets Managerに登録(例:github-token
  2. CDKでcdk bootstrapを実行(パイプラインの資材置き場を作成)
  3. 1回目だけcdk deploy PipelineStackで初期構築

🚀 実行の流れ

git push origin main
# ↓ 自動でAWSに反映される
# Source → Build → Deploy の順に進む

霊夢 「これで“Git pushしたら自動デプロイ”の完成よ。 もしSyntaxエラーがあっても、CodeBuildログで原因が分かる。」

魔理沙 「完全自動…!これがDevOpsの味か…。」


9.2 演習:テスト → ステージング → 本番 のフローを CDK で実装

魔理沙 「でも、本番に直接デプロイしたくない時もあるよな? まずステージングで動作確認してから本番に出したい。」

霊夢 「いい心がけね。CDK Pipelinesではマルチステージデプロイができるの。 addStage()を複数回呼べばOK。」


💻 ステージング+本番を分ける例

// --- pipeline-stack.ts 内 ---

// ステージング環境
pipeline.addStage(new AppStage(this, 'Staging', {
  env: { account: '111111111111', region: 'ap-northeast-1' },
}));

// 本番環境
pipeline.addStage(new AppStage(this, 'Production', {
  env: { account: '222222222222', region: 'ap-northeast-1' },
}));

魔理沙 「なるほど、ステージごとにデプロイ先アカウントも切り替えられるんだな!」

霊夢 「そうよ。CodePipelineがStaging → Productionの順に実行するから、 “本番前にステージングを必ず通す”安全フローが自動化できるわ。」


🧩 各ステージにテストを追加する

CDK PipelinesのaddPost()テストステップを追加可能。

pipeline.addStage(new AppStage(this, 'Staging'))
  .addPost(new pipelines.ShellStep('IntegrationTest', {
    commands: [
      'npm install',
      'npm test',
      'curl -f $ENDPOINT_URL/healthcheck',
    ],
  }));

魔理沙curlで動作チェックできるのか。ステージングで落ちたら本番行かない?」

霊夢 「そう。テストが失敗するとパイプラインが止まる。 だから“動かないコードは絶対に本番に行かない”安全設計になるの。」


⚙️ CodeBuildの環境キャッシュ最適化(上級)

もしビルドが遅いなら、CodeBuildにキャッシュを設定する。

const synth = new pipelines.ShellStep('Synth', {
  input: source,
  commands: ['npm ci', 'npm run build', 'npx cdk synth'],
  primaryOutputDirectory: 'cdk.out',
  env: { NODE_OPTIONS: '--max_old_space_size=4096' },
});

魔理沙 「これ、ビルドのたびにnpm installしてるけど、キャッシュできるのか。」

霊夢 「そう。CodeBuildプロジェクト単位でキャッシュやDockerレイヤーを共有できる。 CDK Pipelinesは裏でCodeBuildを自動生成してるから、そこにパラメータ渡せばいいのよ。」


💡 演習:可視化してみよう

CodePipelineの画面を開くと──

[Source] → [Build] → [Staging Deploy] → [Integration Test] → [Production Deploy]

魔理沙 「おおっ、グラフィカルに流れが見える!進捗バーが気持ちいいな!」

霊夢 「ステージングでエラーになったら赤く止まるわ。 ログもCloudWatchに全部出るから、CI/CDの“監視”も統合されてるの。」


🌟 まとめ:第9章の学び

項目 内容
CodePipeline CI/CD全体のパイプラインを自動実行
CodeBuild ビルド・テスト・CDK synthを自動実行
CDK Pipelines パイプラインをコードで定義できるCDK専用Construct
ステージング/本番分離 addStage()で複数環境を順番に展開
自動テスト連携 addPost()で統合テストを組み込み
メリット 人為的な操作ミスがなくなり、変更が安全に自動展開される

魔理沙 「これでついに“Pushするだけで世界にデプロイ”できるようになったわけだな!」

霊夢 「そう。CDKは“インフラもパイプラインもコード化”することで、 開発〜運用の境界をなくしてくれる。まさにDevOps実践よ。」

魔理沙 「すごい…最初はS3バケット1個だったのに、気づいたらCI/CDまで来ちゃった。」

霊夢 「ここまで来たらもう“CDKマスター”ね。 次章ではこの自動化した環境をテスト・監視・運用改善の観点から磨いていくわ。」

魔理沙 「インフラが動くだけじゃ終わりじゃないってことか。…深いぜAWS。」

――神社の空に、CodePipelineの緑色チェックマークが浮かんだ。


第10章 テスト・モニタリング・運用管理

――博麗神社の夜。魔理沙がデプロイを終えて満足げに寝転がっている。 ……しかし、霊夢はモニターを見て渋い顔。

霊夢 「魔理沙……アプリ動いてるのはいいけど、壊れたときどうするの?」

魔理沙 「えっ?CloudFrontもECSも動いてるし、もう完成じゃないのか?」

霊夢 「ふふ、それは“開発完了”であって“運用完了”じゃないの。 CDKの真の力は、テスト・監視・自動復旧までコード化できるところにあるのよ。」


10.1 単体テスト/スナップショットテスト(Assertions)を CDK で書く

魔理沙 「テストってアプリコードだけじゃなくて、インフラ構成もテストできるのか?」

霊夢 「もちろん。CDKにはassertionsモジュールがあって、 CloudFormationテンプレートを直接検証できるの。」


💻 例:スタックのテストコード(Jest)

ファイル:test/app-stack.test.ts

import * as cdk from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import { AppStack } from '../lib/app-stack';

test('S3 Bucket Created with Versioning', () => {
  const app = new cdk.App();
  const stack = new AppStack(app, 'TestStack');

  const template = Template.fromStack(stack);
  template.hasResourceProperties('AWS::S3::Bucket', {
    VersioningConfiguration: { Status: 'Enabled' },
  });
});

魔理沙 「おお、インフラに対する“単体テスト”ってこう書くのか。 template.hasResourceProperties()がアサート代わりなんだな。」

霊夢 「そう。アプリが壊れる前に“構成が壊れてないか”確認できるのよ。」


🧩 スナップショットテストもできる

test('Stack Snapshot', () => {
  const app = new cdk.App();
  const stack = new AppStack(app, 'SnapshotStack');
  const template = Template.fromStack(stack);
  expect(template.toJSON()).toMatchSnapshot();
});

魔理沙 「つまり“CloudFormationテンプレートが変化してないか”自動検知できるってことか!」

霊夢 「その通り。IaCで事故が起きるのは“構成の意図しない変化”。 スナップショットテストでリグレッション(後退)を防げるの。」


🧰 ベストプラクティス(霊夢メモ)

項目 内容
テスト自動化 npm test を CI/CD パイプラインに組み込む
構成差分チェック cdk diffassertions を使う
スナップショット活用 意図しない変更を検出する
コンストラクト単体テスト 自作Constructを対象に部分的に検証

10.2 モニタリング、アラート、ログ設計(CloudWatch, X-Ray 等)

魔理沙 「デプロイしたサービスが落ちたら、どうやって気づくんだ?」

霊夢 「いい質問ね。AWSでは“CloudWatch”が監視の中心になるわ。」


🧭 モニタリングの全体像

[CloudWatch Logs] ← Lambda, ECS, API Gateway のログ
[CloudWatch Metrics] ← CPU使用率・リクエスト数など
[CloudWatch Alarms] ← 閾値超過時に通知(SNSなど)
[AWS X-Ray] ← サービス間トレーシング

💻 例:CloudWatch アラームを CDK で定義

import { aws_cloudwatch as cw, aws_sns as sns, aws_sns_subscriptions as subs } from 'aws-cdk-lib';

// SNSトピック作成
const topic = new sns.Topic(this, 'AlarmTopic');
topic.addSubscription(new subs.EmailSubscription('admin@example.com'));

// ECS CPU使用率のアラーム
const alarm = new cw.Alarm(this, 'CpuAlarm', {
  metric: new cw.Metric({
    namespace: 'AWS/ECS',
    metricName: 'CPUUtilization',
    dimensionsMap: { ServiceName: 'MyService' },
    statistic: 'Average',
  }),
  threshold: 80,
  evaluationPeriods: 2,
  comparisonOperator: cw.ComparisonOperator.GREATER_THAN_THRESHOLD,
});

alarm.addAlarmAction({
  bind: () => ({ alarmActionArn: topic.topicArn }),
});

魔理沙 「つまり“CPU80%以上が2回続いたらメール通知”ってことか。」

霊夢 「その通り。メールの代わりにSlackやWebhookに流すこともできるわ。」


🧱 Lambda関数のログモニタリング例

import { aws_logs as logs } from 'aws-cdk-lib';

const logGroup = new logs.LogGroup(this, 'LambdaLogGroup', {
  retention: logs.RetentionDays.ONE_WEEK,
  removalPolicy: cdk.RemovalPolicy.DESTROY,
});

霊夢 「これでLambdaのログもCDKで管理できる。 “ログの保存期間”をコードで定義しておけば、監査要件にも対応できるわ。」


🔍 X-Rayによる分散トレーシング設定

import { aws_lambda as lambda } from 'aws-cdk-lib';

new lambda.Function(this, 'TracedLambda', {
  runtime: lambda.Runtime.NODEJS_18_X,
  handler: 'index.handler',
  code: lambda.Code.fromAsset('lambda'),
  tracing: lambda.Tracing.ACTIVE, // X-Rayを有効化
});

魔理沙 「X-RayをONにすると、リクエストの流れが可視化されるんだな。」

霊夢 「そう。ECSやAPI Gatewayと連携すれば“どの区間で遅いか”もトレースできる。 パフォーマンス問題の特定が一気に楽になるわ。」


10.3 演習:障害対応シナリオを CDK による Infrastructure as Code で組む

魔理沙 「障害っていうと、サーバー落ちたときとかだよな? そういうのもCDKで自動対応できるのか?」

霊夢 「できるの。IaCは“構築コード”だけじゃなく、“復旧コード”でもあるのよ。」


💡 シナリオ1:ECSタスクの自動再起動(ヘルスチェック)

import { aws_ecs as ecs } from 'aws-cdk-lib';

const service = new ecs.FargateService(this, 'WebService', {
  cluster,
  taskDefinition,
  healthCheckGracePeriod: cdk.Duration.seconds(30),
});

service.configureAwsVpcNetworking({ assignPublicIp: true });

霊夢 「Fargateはヘルスチェック失敗で自動的に再起動するけど、 CDKで“猶予期間”を設定すれば誤検知も防げる。」


💡 シナリオ2:自動スケーリング設定

const scaling = service.autoScaleTaskCount({ minCapacity: 2, maxCapacity: 10 });
scaling.scaleOnCpuUtilization('CpuScaling', {
  targetUtilizationPercent: 70,
});

魔理沙 「負荷が上がったら自動でスケールアウト、下がったら縮小! クラウドの醍醐味だな。」


💡 シナリオ3:障害時に自動フェイルオーバー(Route53ヘルスチェック)

import { aws_route53 as r53, aws_route53_targets as targets } from 'aws-cdk-lib';

const zone = new r53.HostedZone(this, 'Zone', { zoneName: 'example.com' });

new r53.ARecord(this, 'AppRecord', {
  zone,
  target: r53.RecordTarget.fromAlias(new targets.LoadBalancerTarget(alb)),
  healthCheck: {
    type: 'HTTP',
    resourcePath: '/health',
    failureThreshold: 3,
  },
});

霊夢 「Route53ヘルスチェックを入れれば、ALBが落ちたときに別リージョンへ自動切り替えできる。 CDKならこの“災害対策”すらコードで再現できるの。」


🧰 まとめ:IaCで障害対応も自動化

項目 対応方法
再起動 ECS/Lambdaのヘルスチェック・リトライ設定
スケーリング CPU/メモリ/カスタムメトリクスで自動スケール
フェイルオーバー Route53ヘルスチェックとマルチリージョン構成
通知 CloudWatchアラーム + SNS/Slack連携
復旧テスト cdk destroycdk deploy で本番再構築の検証

魔理沙 「つまり“落ちても立ち上がる仕組み”までコードにしとけってことか。」

霊夢 「そう。人間の対応じゃなく“コードで治す”のがInfrastructure as Codeの究極形よ。」


🌟 第10章まとめ

分野 内容
テスト CDK Assertionsで構成の単体・スナップショットテスト
モニタリング CloudWatch, SNS, X-RayをCDKで一括管理
障害対応 ヘルスチェック・スケーリング・フェイルオーバーをIaC化
ポイント 運用・監視・復旧まですべて“再現可能なコード”で定義する

魔理沙 「これでやっと“本番運用に耐えるインフラ”になったわけか。 開発から監視まで、全部CDKで完結だな!」

霊夢 「そう。CDKは“クラウドの設計図”であり、“運用マニュアルの代わり”でもあるの。 コードを見れば、何がどう守られているか全部わかる。」

魔理沙 「……最初にバケット1個作ってた頃が懐かしいな。」

霊夢 「ふふ、でも今やあなたの神社は完全自動化クラウドよ。 お賽銭もCloudWatchメトリクスで管理できるわ。」

魔理沙 「いやそれは違う意味で怖いわ!」

――神社の夜空に、CloudWatchのダッシュボードが光り、 霊夢と魔理沙のCDKハンズオンは静かに幕を閉じた。


第11章 本番移行とコスト・セキュリティ最適化

――博麗神社の早朝。 デプロイがすべて成功し、雲ひとつない空の下で魔理沙がコーヒーを飲んでいる。

魔理沙 「いや〜、やっと全部動いたな!これで本番投入できるぜ!」

霊夢 「ちょっと待った。デプロイできたからって“本番準備完了”とは限らないのよ。」

魔理沙 「え?何が足りないんだ?」

霊夢 「“お金と安全”よ。 本番運用では、コスト最適化セキュリティ対策を怠ると、痛い目を見るの。」


11.1 コスト見積もり/インフラの見える化

魔理沙 「確かに。気づいたら請求が爆発してた…なんて話も聞くよな。」

霊夢 「AWSは使った分だけ課金されるけど、構成をCDKで書いてるなら、 “どのリソースにいくらかかるか”も把握できるのよ。」


💡 1. CDKのコスト見積もりツール活用

霊夢 「AWSには AWS Pricing Calculator が公式にあるけど、 CDKユーザーはcdk-nag + AWS Budgets + CloudFormation StackCostを組み合わせるのがオススメ。」


🧰 cdk-nagでコスト・セキュリティチェック

npm install cdk-nag

lib/app-stack.ts の末尾に追記:

import { AwsSolutionsChecks } from 'cdk-nag';
import { Aspects } from 'aws-cdk-lib';

Aspects.of(this).add(new AwsSolutionsChecks());

魔理沙cdk-nagって、Lintみたいなもんか?」

霊夢 「そう。デプロイ前に“コストやセキュリティ上の問題”を警告してくれる。 たとえば、“バケットが公開されてる”とか“CloudWatchが設定されてない”とかね。」


🧾 2. CloudFormation StackCost の利用

npx cdk synth > template.json
aws cloudformation estimate-template-cost --template-body file://template.json

魔理沙 「うお、CLIで見積もり出せるのか!しかもCDKから生成したテンプレートで!」

霊夢 「そう。これで“実際のAWS料金モデル”をもとに見積もりできるわ。」


📊 3. AWS Budgetsでコスト監視

CDKでも簡単に定義できる:

import { aws_budgets as budgets } from 'aws-cdk-lib';

new budgets.CfnBudget(this, 'MonthlyBudget', {
  budget: {
    budgetLimit: { amount: 100, unit: 'USD' },
    budgetType: 'COST',
    timeUnit: 'MONTHLY',
  },
  notificationsWithSubscribers: [
    {
      notification: {
        comparisonOperator: 'GREATER_THAN',
        threshold: 80,
        thresholdType: 'PERCENTAGE',
        notificationType: 'ACTUAL',
      },
      subscribers: [{ subscriptionType: 'EMAIL', address: 'admin@example.com' }],
    },
  ],
});

魔理沙 「80%超えたらメールが飛ぶ…!いいな、保険代わりになる。」

霊夢 「そう。CDKで“お財布の監視”まで自動化できるのよ。」


11.2 セキュリティベストプラクティス(Encryption, Least Privilege, Logging)

魔理沙 「じゃあ次はセキュリティ強化だな。」

霊夢 「AWSのセキュリティの基本はこの3つ。」

① 暗号化 (Encryption)
② 最小権限 (Least Privilege)
③ ログの完全記録 (Logging)

🧩 暗号化 (Encryption)

S3 バケットのデフォルト暗号化

const bucket = new s3.Bucket(this, 'SecureBucket', {
  encryption: s3.BucketEncryption.S3_MANAGED,
  blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
});

DynamoDB の暗号化

new dynamodb.Table(this, 'SecureTable', {
  partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
  encryption: dynamodb.TableEncryption.AWS_MANAGED,
});

霊夢 「基本は“すべて暗号化”。特に個人情報やログは要注意よ。」


🧱 最小権限 (Least Privilege)

const role = new iam.Role(this, 'AppRole', {
  assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
});

role.addToPolicy(new iam.PolicyStatement({
  actions: ['s3:GetObject'],
  resources: ['arn:aws:s3:::my-app-bucket/*'],
}));

魔理沙*:*とか安易に書かない!ってことだな。」

霊夢 「そう。1リソース1ポリシー設計を徹底するのがベストプラクティス。」


🪵 ログの完全記録 (Logging)

CloudTrail の有効化

import { aws_cloudtrail as ct } from 'aws-cdk-lib';

new ct.Trail(this, 'OrgTrail', {
  isMultiRegionTrail: true,
  includeGlobalServiceEvents: true,
  enableFileValidation: true,
});

S3アクセスログ

bucket.addLifecycleRule({ expiration: cdk.Duration.days(90) });
bucket.addEventNotification(s3.EventType.OBJECT_REMOVED, new s3n.LambdaDestination(auditLambda));

霊夢 「“誰が何をしたか”を全部残すのがAWSの基本。 事故調査もIaCで仕組み化できるわ。」


🧠 霊夢のセキュリティ三箇条

項目 内容
🔒 Encryption S3・RDS・DynamoDB・SecretsManagerはすべて暗号化ON
👁 Least Privilege IAMは最小限、AWS管理ポリシーに依存しすぎない
📜 Logging CloudTrail + CloudWatch Logs + X-Rayを常時有効化

魔理沙 「IaCでセキュリティも再現できるってのはいいな。 設定を忘れた時点で“再現性ゼロ”だもんな。」

霊夢 「そう。“安全もコードで管理する”のがプロのCDK使いよ。」


11.3 演習:既存 CloudFormation テンプレートを CDK にマイグレート

魔理沙 「ところでさ、うちの古いCloudFormationテンプレートもCDKにしたいんだが…… ゼロから書き直すしかないのか?」

霊夢 「実はそんなことないの。 AWS公式ツールでCloudFormation → CDKへの変換ができるのよ。」


💻 cdk import(旧テンプレートの移行)

cdk import --template cloudformation-template.json

霊夢 「このコマンドを使うと、既存のテンプレートを解析してCDK構成に変換してくれる。 ただし100%ではないから、出力されたコードを整えるのがポイントよ。」


🧩 例:CloudFormationテンプレート(S3)

{
  "Resources": {
    "MyBucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": { "VersioningConfiguration": { "Status": "Enabled" } }
    }
  }
}

→ 変換後のCDKコード:

import { aws_s3 as s3 } from 'aws-cdk-lib';
new s3.Bucket(this, 'MyBucket', { versioned: true });

魔理沙 「なるほど、これなら既存資産をCDKプロジェクトに統合できるな!」

霊夢 「そう。移行後は差分管理・テスト・自動化の恩恵をすべて受けられる。 CloudFormation時代より安全で可視性の高い運用にできるの。」


🧰 移行時の注意点

項目 注意内容
リソース名の整合性 CDKは論理IDを再生成するため、retain指定を忘れずに
パラメータ化 Parameterscontext.env に置き換える
Outputs CfnOutput で再現し、クロススタック参照に統合
テスト 移行後はassertions.Template.fromStack()で構成一致を確認

🌟 まとめ:第11章の学び

分野 内容
コスト管理 cdk-nag / CloudFormation見積もり / Budgetsで監視
セキュリティ Encryption・Least Privilege・Loggingの三本柱
移行 既存CFnテンプレートをCDKに統合し、IaC統一を実現
目的 安全・透明・効率的な本番環境運用への最終仕上げ

魔理沙 「これでやっと、コストも安全も見える本番環境が完成したわけか。」

霊夢 「そう。CDKは“作る”だけじゃなく、“守る”“測る”“直す”まで全部コードで扱える。 それこそ真のInfrastructure as Codeよ。」

魔理沙 「CDK、奥が深いな……まさかお賽銭の課金まで監視できるとは。」

霊夢 「だからそれはやめなさい。」

――神社の上空に、CDKの11章分のスタック図がきらめき、 霊夢と魔理沙のAWS CDK旅はここで幕を閉じた。


第12章 アーキテクチャパターン集

――博麗神社。満月の夜。 これまでのスタック図を眺めながら、霊夢が感慨深げに呟く。

霊夢 「ここまでで、インフラ構築からCI/CDまで全部CDKで作れるようになったわね。」

魔理沙 「うむ!でも世の中のアプリって、LambdaだけでもECSだけでも済まないんだろ? どう組み合わせたらいいか、いまいちピンと来ないんだ。」

霊夢 「いいわ。今日は“アーキテクチャパターン”の整理編。 CDKでどう表現するか、3つの定番を見ていきましょう。」


12.1 サーバーレスアーキテクチャ

魔理沙 「まずは王道のサーバーレス構成からだな。」

霊夢 「そう。サーバーレスは“イベント駆動型”のクラウド設計。 AWSだとAPI Gateway → Lambda → DynamoDBの組み合わせが最も代表的よ。」


🧭 構成図

[CloudFront] 
   ↓
[S3 static site] --calls--> [API Gateway]
                             ↓
                          [Lambda]
                             ↓
                        [DynamoDB]

💻 CDKによる構築例(サマリ)

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { aws_lambda as lambda, aws_apigateway as apigw, aws_dynamodb as ddb, aws_s3 as s3, aws_cloudfront as cf, aws_cloudfront_origins as origins } from 'aws-cdk-lib';

export class ServerlessArchStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const table = new ddb.Table(this, 'Items', {
      partitionKey: { name: 'id', type: ddb.AttributeType.STRING },
    });

    const handler = new lambda.Function(this, 'ApiHandler', {
      runtime: lambda.Runtime.NODEJS_18_X,
      handler: 'index.handler',
      code: lambda.Code.fromAsset('lambda'),
      environment: { TABLE_NAME: table.tableName },
    });
    table.grantReadWriteData(handler);

    const api = new apigw.LambdaRestApi(this, 'Api', { handler });

    const bucket = new s3.Bucket(this, 'WebBucket', { websiteIndexDocument: 'index.html' });
    const distribution = new cf.Distribution(this, 'CDN', {
      defaultBehavior: { origin: new origins.S3Origin(bucket) },
    });

    new cdk.CfnOutput(this, 'ApiUrl', { value: api.url ?? '' });
    new cdk.CfnOutput(this, 'WebUrl', { value: distribution.domainName });
  }
}

魔理沙 「S3で静的サイト、API GatewayでAPI、Lambdaで処理、DynamoDBでデータ保存。 完全にサーバーいらずの構成だな!」

霊夢 「そう。スケールもメンテも全部AWS任せ。 小規模Webサービスやスタートアップには最強の構成よ。」


💡 特徴まとめ

項目 内容
管理負荷 サーバーレス(運用不要)
コスト トラフィックに応じた従量課金
スケーラビリティ 自動スケーリング
適用例 Webアプリ、社内ツール、モバイルAPI

魔理沙 「でも常時高負荷のシステムだと、Fargateとかの方が安くなるパターンもあるんだよな?」

霊夢 「その通り。“Lambdaのメリット=可変負荷向け”と覚えておきなさい。」


12.2 マイクロサービスアーキテクチャ

霊夢 「次はマイクロサービスアーキテクチャ。 複数の独立したサービスを疎結合で構成するスタイルね。」


🧭 構成図(ECSベース)

[API Gateway] 
   ├─ /users → [ECS Service: UserService]
   ├─ /orders → [ECS Service: OrderService]
   └─ /products → [ECS Service: ProductService]
                     ↓
                 [RDS or DynamoDB]

💻 CDKによる構築例(概要)

import { aws_ecs as ecs, aws_ecs_patterns as ecs_patterns, aws_apigateway as apigw } from 'aws-cdk-lib';

// ECS Cluster
const cluster = new ecs.Cluster(this, 'AppCluster', { vpc });

// 各サービス
const userService = new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'UserService', {
  cluster,
  taskImageOptions: { image: ecs.ContainerImage.fromRegistry('myorg/user-service') },
});

const orderService = new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'OrderService', {
  cluster,
  taskImageOptions: { image: ecs.ContainerImage.fromRegistry('myorg/order-service') },
});

const productService = new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'ProductService', {
  cluster,
  taskImageOptions: { image: ecs.ContainerImage.fromRegistry('myorg/product-service') },
});

// API Gatewayで統合
const api = new apigw.RestApi(this, 'MicroApi');
api.root.addResource('users').addMethod('GET', new apigw.HttpIntegration(userService.loadBalancer.loadBalancerDnsName));

魔理沙 「なるほど、サービスごとにコンテナ分割して独立デプロイできるのか。」

霊夢 「そう。CDKでは複数Stackに分けると、サービス単位デプロイが自然にできる。 しかもIAMロールもサービスごとに限定できるの。」


💡 パターン比較表

項目 内容
管理単位 サービスごとに分割 (独立Stack)
通信 REST / gRPC / EventBridge
スケール サービスごとに個別設定
適用例 大規模システム、チーム分割開発、SaaS基盤

魔理沙 「マイクロサービスはチーム開発向きだな。 でも監視とかデプロイが複雑そう…。」

霊夢 「だからこそCDK Pipelines + CloudWatch + X-Rayを組み合わせるの。 全部コードで統一しておけば、構成が増えても混乱しない。」


12.3 ハイブリッドクラウド/オンプレミス統合

魔理沙 「最後は“ハイブリッドクラウド”か。 つまりオンプレとAWSをつなぐやつだな?」

霊夢 「そう。CDKでもオンプレミスとの連携は定義できる。 代表的なのはDirect Connect / VPN / PrivateLinkの活用ね。」


🧭 構成図

[On-Prem Network]
      │  (VPN/DirectConnect)
      ▼
   [VPC (AWS)]
      ├─ Private Subnet: RDS, ECS
      └─ Public Subnet: ALB

💻 CDKでのVPN Gateway構成例

import { aws_ec2 as ec2 } from 'aws-cdk-lib';

const vpc = new ec2.Vpc(this, 'HybridVpc', { maxAzs: 2 });

// VPN接続
const vpn = new ec2.CfnVPNConnection(this, 'VpnConnection', {
  type: 'ipsec.1',
  customerGatewayId: 'cgw-abc12345',
  staticRoutesOnly: true,
  vpnGatewayId: 'vgw-xyz67890',
});

🧩 PrivateLink構成(オンプレからAWSサービスへ安全接続)

import { aws_ec2 as ec2 } from 'aws-cdk-lib';

new ec2.InterfaceVpcEndpoint(this, 'S3Endpoint', {
  vpc,
  service: ec2.InterfaceVpcEndpointAwsService.S3,
  privateDnsEnabled: true,
});

霊夢 「オンプレや他クラウドからAWSに接続するときは“プライベート接続”が鉄則。 CDKならルーティングやエンドポイントもIaCで明示できるわ。」


💡 ハイブリッド運用のベストプラクティス

項目 内容
通信経路 VPN / Direct Connect / PrivateLinkで閉域接続
認証統合 AWS IAM Identity Center or AD Connector
監視連携 CloudWatch Agent + オンプレPrometheus
デプロイ CodePipeline + CodeDeploy でオンプレにもCI/CD
利点 クラウド移行の段階的導入が可能

魔理沙 「CDKでオンプレ接続まで定義できるとは…! もうクラウドと社内ネットの境界すら曖昧だな。」

霊夢 「そう。クラウドはもはや“外部”じゃなく、“拡張インフラ”。 CDKで両者を同じコードベースで扱えるのが最大の強みよ。」


🌟 第12章まとめ(アーキテクチャ比較表)

パターン 構成要素 特徴 適用例
サーバーレス API Gateway, Lambda, DynamoDB, S3 運用負荷最小、従量課金 Webアプリ・社内ツール
マイクロサービス ECS/Fargate, API Gateway, RDS チーム分割開発、スケール制御 SaaS・大規模Webサービス
ハイブリッドクラウド VPC, VPN, DirectConnect, PrivateLink オンプレ統合、セキュア接続 金融・製造・企業システム

魔理沙 「なるほど…どの構成を選ぶかで、CDKの設計も変わってくるんだな。」

霊夢 「そう。大事なのは“目的に合った構成をコードで再現できること”。 CDKはアーキテクチャ設計を実行可能なドキュメントに変えるツールなの。」

魔理沙 「構成図を描くだけじゃなく、実際に動く構成をコミットできるってことか。 ……なんかエンジニアの未来っぽいな。」

霊夢 「ふふ。これであなたも“インフラアーキテクト兼デプロイ魔法使い”ね。」

魔理沙 「……魔法陣じゃなくて、CDKスタックを描く魔法使いか。」

――満月の夜、神社の空にサーバーレス・ECS・VPNが重なる三つの光の円。 霊夢と魔理沙のCDKハンズオンはここで完結した。(もう少しだけ続きます)


第13章 CDK の拡張:カスタムConstruct・外部ライブラリ

――博麗神社の縁側。 魔理沙が肩をバキバキ鳴らしながらキーボードを叩いている。

魔理沙 「霊夢~、同じ組み合わせのインフラをプロジェクトごとにコピペしまくってるんだが、そろそろつらいんだぜ。」

霊夢 「その症状が出たらいよいよ“Construct化”のタイミングね。 今日は『インフラを部品にして、配れるようにしよう』って話をするわ。」


13.1 自作 Construct の設計と公開

まず、Constructって何だっけ?

霊夢 「CDKでいうConstructっていうのは、“ひとかたまりのインフラと設定”をひとつのオブジェクトにしたものよ。 S3 + CloudFront + ログ設定とか、ALB + ECSサービス + AutoScalingとか、よくある組み合わせをパッケージ化して、使い回せるようにするの。」

魔理沙 「つまり“よく使う最強セットを、自分専用のレゴブロックにする”ってことだな。」

霊夢 「そういうこと。で、そのブロックをチーム全員に配ったら、全員が安全で統一された構成を簡単にデプロイできるようになるのよ。」


🔧 カスタムConstructの最小サンプル

今回の例は「ALBつきのFargateサービス」を「毎回いい感じに作ってくれる部品」を作る。

lib/constructs/web-app-construct.ts

import { Construct } from 'constructs';
import {
  Duration,
  aws_ecs as ecs,
  aws_ecs_patterns as ecs_patterns,
  aws_ec2 as ec2,
  aws_iam as iam,
  aws_logs as logs,
} from 'aws-cdk-lib';

export interface WebAppConstructProps {
  vpc: ec2.IVpc;
  image: ecs.ContainerImage;
  publicLoadBalancer?: boolean;
  desiredCount?: number;
}

export class WebAppConstruct extends Construct {
  public readonly service: ecs_patterns.ApplicationLoadBalancedFargateService;

  constructor(scope: Construct, id: string, props: WebAppConstructProps) {
    super(scope, id);

    // Fargateサービス+ALBをまとめて作る
    this.service = new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'Svc', {
      cluster: new ecs.Cluster(this, 'Cluster', { vpc: props.vpc }),
      desiredCount: props.desiredCount ?? 2,
      publicLoadBalancer: props.publicLoadBalancer ?? true,
      taskImageOptions: {
        image: props.image,
        containerPort: 3000,
        // デフォルトでログをCloudWatchに飛ばす
        logDriver: ecs.LogDrivers.awsLogs({
          streamPrefix: 'app',
          logRetention: logs.RetentionDays.ONE_WEEK,
        }),
      },
      healthCheckGracePeriod: Duration.seconds(30),
      listenerPort: 80,
    });

    // セキュリティ: このサービスのタスクロールは最小権限で開始
    this.service.taskDefinition.addToTaskRolePolicy(
      new iam.PolicyStatement({
        actions: ['ssm:GetParameter'],
        resources: ['*'], // 本番では絞ること推奨
      }),
    );
  }
}

魔理沙 「すごい、これ1クラスで ALB, Fargate Service, Cluster, CW Logs, HealthCheck が一式できるのか。」

霊夢 「そう。しかも“監視つき”“最低限のIAMロールつき”みたいな社内標準をここで押し込めるわけ。」


🧪 そのConstructをStack内で使う

lib/app-stack.ts

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { aws_ec2 as ec2, aws_ecs as ecs } from 'aws-cdk-lib';
import { WebAppConstruct } from './constructs/web-app-construct';

export class AppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const vpc = new ec2.Vpc(this, 'AppVpc', { maxAzs: 2 });

    new WebAppConstruct(this, 'FrontendService', {
      vpc,
      image: ecs.ContainerImage.fromRegistry('nginxdemos/hello'),
      publicLoadBalancer: true,
      desiredCount: 2,
    });

    new WebAppConstruct(this, 'BackendService', {
      vpc,
      image: ecs.ContainerImage.fromRegistry('public.ecr.aws/lambda/nodejs:18'),
      publicLoadBalancer: false,
      desiredCount: 1,
    });
  }
}

魔理沙 「おお、new WebAppConstruct(...)を2回呼んだだけで、 フロントとバックエンドのFargateサービスが別々に並んだ! 便利すぎる!!」

霊夢 「これが“インフラを再利用可能なコンポーネント化する”ってこと。 CDKはReactに似てるって言われるの、こういうところなのよ。」


🧪 Constructをテストする

「社内で配る=壊すと全員を巻き込んで死ぬ」なので、テストは必須。

import * as cdk from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import { AppStack } from '../lib/app-stack';

test('ALB is created for WebAppConstruct', () => {
  const app = new cdk.App();
  const stack = new AppStack(app, 'TestStack');

  const template = Template.fromStack(stack);
  template.resourceCountIs('AWS::ElasticLoadBalancingV2::LoadBalancer', 2);
  template.hasResourceProperties('AWS::ECS::Service', {
    DesiredCount: 2,
  });
});

魔理沙 「これ、CIで回せば“誰かがライブラリ壊すとすぐわかる”ってことだな?」

霊夢 「そう。CDKのConstructはインフラだけど、ふつうのアプリと同じようにユニットテスト&スナップショットテストを回すべきなの。」


📦 Constructを社内配布するには?

  1. constructs/ を別リポジトリに切り出す
  2. package.json を用意してnpmパッケージ化
  3. 名前をスコープ化(例:"name": "@company/web-app-construct"
  4. 社内のプライベートnpmレジストリ(GitHub PackagesやCodeArtifactなど)にpublish
  5. 各プロジェクトで npm install @company/web-app-construct するだけで使える

魔理沙 「えっ、それってもう“社内標準インフラをnpm installするだけで再現できる”ってことか?」

霊夢 「そう。新人が“Fargateでアプリ公開したいんですが…”って聞いてきたら、 『npm install @company/web-app-construct してね』で終わる世界になるの。最高でしょ?」


🧠 自作Constructを設計する時の指針(霊夢メモ)

指針 なぜ大事?
呼び出し側は props で最低限の値だけ渡せばいい 使いやすさと安全性
セキュアなデフォルト値を持たせる “危険な設定”を素で使われないようにする
ロギング・監視を内蔵しておく 本番で後から付け忘れが起きない
IAM権限は最小権限 社内監査で怒られにくくなる
バージョンをSemVerで管理 “壊れる変更”をメジャーアップに閉じ込める

魔理沙 「これはもう完全に“社内のSREが作った黄金テンプレ”ってやつだな…」

霊夢 「そう。CDKを“ただのツール”から“社内プラットフォーム”に変えるのが、この章のテーマよ。」


13.2 OSS ライブラリ/AWS Solutions Constructs の活用

魔理沙 「で、逆パターンもあるよな? “自分で全部設計する前に、誰かがもう作ってくれてるやつを使いたい”っていう。」

霊夢 「もちろんあるわ。 CDKには公式・非公式ふくめて、いろんな再利用可能なConstructライブラリが公開されてるの。」


🏗 AWS Solutions Constructs とは?

霊夢 「AWSがベストプラクティスとしてよく使う“安全な構成”をパッケージにしたのが AWS Solutions Constructs っていうライブラリ群。 例えばこんなやつがあるわ。」

  • aws-lambda-dynamodb
  • aws-cloudfront-s3
  • aws-apigateway-lambda
  • aws-lambda-sqs
  • aws-events-rule-lambda
  • …など

だいたい「よく一緒に使う2〜3サービス」をベストプラクティスの形でまとめてある。

魔理沙 「つまり“LambdaとDynamoDBを繋いで、最低限の権限・ログ・監視を設定済み”みたいな完成品?」

霊夢 「そういうこと。CDKで一気に生やせる便利パーツよ。」


💻 例:aws-lambda-dynamodb を使うイメージ

※ 以下はイメージ的な使い方のパターン(構文は概念化)

import { LambdaToDynamoDB } from '@aws-solutions-constructs/aws-lambda-dynamodb';
import { Runtime, Code, Function as LambdaFunction } from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';
import * as cdk from 'aws-cdk-lib';

export class ServerlessWithSolutionsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    new LambdaToDynamoDB(this, 'LambdaDdbPattern', {
      lambdaFunctionProps: {
        runtime: Runtime.NODEJS_18_X,
        handler: 'index.handler',
        code: Code.fromAsset('lambda'),
      },
      dynamoTableProps: {
        partitionKey: { name: 'id', type: 'S' },
      },
    });
  }
}

魔理沙 「うわ、これだけでLambdaとDynamoDB、権限、イベント処理、全部揃うのか。 やっぱ公式の組み合わせはおいしいな。」

霊夢 「そう。AWS Solutions Constructsは“安全でだいたい正解”な構成を、 ノータイムで導入できるようにしてくれる。 スピード勝負のプロトタイピングには超向いてるのよ。」


👍 OSS / Construct Hub を使うメリット

  1. プロダクション級のパターンをすぐ呼べる

    • 例:ALB+ECS+AutoScaling+ログ設定みたいなやつ
  2. ベストプラクティスが最初から入ってる

    • 暗号化、ロギング、Least Privilegeなどを忘れにくい
  3. 学習教材として優秀

    • “AWSの人はこう組むのか”が丸見えになる
  4. 社内標準との合体も楽

    • OSSのConstructをベースに、ちょっとだけ社内ルール足したものを再エクスポートしてもいい

👀 気をつけたいポイント

注意点 なぜ?
バージョン固定しないと壊れることがある OSSなのでBreaking Changeが入ることもある
サービス制限・SLAは自分で確認する OSSは便利でも、社内コンプラがNGなときもある
全自動に甘えすぎない 何やってるか分からないまま本番投入は危険

魔理沙 「“何が勝手に作られるのか”はちゃんとcdk synthで見るべきってことだな。」

霊夢 「そう。IaCはコードだけじゃなく、生成されるCloudFormationもちゃんと見るのよ。 ブラックボックスのまま本番に入れるのはやめなさいってことね。」


📦 じゃあ、自作ConstructとOSS、どっちを使うべき?

魔理沙 「ぶっちゃけ、自作と外部ライブラリってどう使い分けるんだ?」

霊夢 「こう考えなさい。」

状況 おすすめ
早く動くプロトが欲しい まずは AWS Solutions Constructs / OSS を使う
チーム標準のガードレールを配りたい 自作Constructを社内npmとして配布
法規制・監査・監視要件が厳しい 自作Constructで“会社仕様”を強制する
似た構成を複数チームに横展開したい 自作Constructが長期的に有利

魔理沙 「プロトはOSS、社内標準は自作、ってことか。わかりやすいな。」

霊夢 「そう。CDKのゴールは“チーム全員で安全に同じやり方を共有すること”なのよ。 CDKがインフラを民主化するっていうのは、そういう意味。」


🌟 第13章まとめ

テーマ 要点
カスタムConstruct よく使うインフラ構成を1クラスにまとめて再利用する
Props設計 呼び出し元が最低限の値だけ渡せば安全に使えるようにする
テスト Constructはユニットテスト&スナップショットで壊さない
公開 社内npmやCodeArtifactにpublishして“標準インフラ”として配布
AWS Solutions Constructs AWS公式のベストプラクティスをコンポーネント化した便利セット
使い分け OSSはスピード、自作は統制と再現性。両方役割がある

魔理沙 「いや~、ここまで来るとCDKってもう“ツール”じゃなくて“組織の基盤”だな。」

霊夢 「そうね。あなたが作るConstructは、もう“1チームの便利機能”じゃない。 “会社のインフラ標準”にもなりうるのよ。」

魔理沙 「つまり私は……インフラアーキテクトであり、プラットフォームエンジニア…!」

霊夢 「そういうこと。 CDKを使える人から、CDKを設計して配れる人へ。 これが第13章の卒業試験よ。」

魔理沙 「よし、まずは@company/web-app-constructを社内に配布してドヤるところから始めるぜ!」

――神社の上に、npm publishされた社内Constructのアイコンがきらりと光った。


第14章 将来展望:インフラコードの進化と CDK 以外の選択肢

――博麗神社の夜、境内の灯りの中。 魔理沙がCDKスタック図を見ながら、しみじみと呟く。

魔理沙 「ここまでCDKで何でも作れるようになったけど、 クラウドの世界って、まだまだ進化してるんだよな。」

霊夢 「そう。CDKは現時点では最強のIaCツールのひとつだけど、 “コードでインフラを扱う”という発想そのものも、どんどん広がっているの。」


14.1 CDK for Terraform (CDKtf)/CDK8s などの動向

🌍 CDK for Terraform(CDKtf)

霊夢 「まずは CDK for Terraform(CDKtf)。 CDKの“クラスベースの記述体験”を、Terraformのプロバイダ資産で使えるようにしたツールよ。」


💡 構成イメージ

import { App, TerraformStack } from 'cdktf';
import { AwsProvider, s3 } from '@cdktf/provider-aws';

class MyStack extends TerraformStack {
  constructor(scope: App, id: string) {
    super(scope, id);

    new AwsProvider(this, 'AWS', { region: 'ap-northeast-1' });

    new s3.S3Bucket(this, 'MyBucket', {
      bucketPrefix: 'cdktf-demo-',
      versioning: { enabled: true },
    });
  }
}

const app = new App();
new MyStack(app, 'cdktf-stack');
app.synth();

魔理沙 「おお、見た目はほぼCDKだな。 でも裏で動いてるのはCloudFormationじゃなくてTerraformか。」

霊夢 「そう。cdktfはTerraformの全プロバイダを利用できるから、 AWSだけじゃなくGCP・Azure・Datadog・GitHubまで全部IaCで管理できるのよ。 つまり“マルチクラウドCDK”。」


🧠 CDKtfの特徴まとめ

項目 内容
対応基盤 Terraform (HCL互換)
対応クラウド AWS / Azure / GCP / ほか数百プロバイダ
言語 TypeScript / Python / Go / C#
メリット CDKの構文+Terraformのリソース資産を両取り
デメリット CloudFormationよりやや低速、State管理が必要

魔理沙 「CDKが“言語で書けるCloudFormation”なら、 CDKtfは“言語で書けるTerraform”って感じだな。」

霊夢 「まさにそれ。組織によってはTerraform文化が根強いから、 CDKtfを使うと既存のStateファイル運用を保ったまま、 CDKライクに移行できるのよ。」


☸ CDK8s(CDK for Kubernetes)

霊夢 「次は CDK8s。これはKubernetesマニフェストをTypeScriptやPythonで生成する仕組みね。」


💻 例:CDK8sでKubernetesデプロイ定義

import { App, Chart } from 'cdk8s';
import { KubeDeployment, KubeService } from 'cdk8s-plus-25';

const app = new App();
const chart = new Chart(app, 'NginxChart');

new KubeDeployment(chart, 'Deployment', {
  spec: {
    replicas: 2,
    selector: { matchLabels: { app: 'nginx' } },
    template: {
      metadata: { labels: { app: 'nginx' } },
      spec: {
        containers: [{ name: 'nginx', image: 'nginx:1.25' }],
      },
    },
  },
});

new KubeService(chart, 'Service', {
  spec: {
    type: 'LoadBalancer',
    selector: { app: 'nginx' },
    ports: [{ port: 80, targetPort: 80 }],
  },
});

app.synth();

魔理沙 「なるほど、これが生成されると deployment.yamlservice.yaml が出てくるのか!」

霊夢 「そう。cdk8s synth でYAMLが生成されて、 それを kubectl apply -f でデプロイできる。 Helmよりも“型安全で再利用しやすい”のがポイントよ。」


🧩 CDK / CDKtf / CDK8s の比較

ツール 対象 バックエンド 言語サポート 特徴
AWS CDK AWSリソース CloudFormation TS / Python / Java / C# AWS専用で最適化・CI/CD統合が強い
CDKtf 全クラウド/SaaS Terraform TS / Python / Go / C# マルチクラウド構築に最適
CDK8s Kubernetes YAML生成 TS / Python / Go K8s構成を型安全に管理可能

魔理沙 「CDKって、AWSだけの話じゃなかったんだな。 “CDKファミリー”って言っていいくらい広がってるじゃん。」

霊夢 「そう。CDKは“宣言的なIaCをプログラミング言語で記述する”という思想の象徴なのよ。 TerraformもKubernetesも、みんなその流れに乗ってる。」


14.2 Infrastructure as Code におけるベストプラクティスの進化

魔理沙 「でもさ、IaCってもう完成された概念じゃないの?」

霊夢 「ふふ、そう思うでしょ。でも実際はまだ進化の途中よ。 ここ数年で IaC → GitOps → Platform Engineering って流れが加速してるの。」


🧭 進化の流れ

[Infrastructure as Code]
    ↓
[GitOps]
    ↓
[Platform Engineering / Internal Dev Platforms]

💡 GitOpsとは?

霊夢 「GitOpsは、“環境の正”をGitで管理して、 変更を自動的に反映する仕組みのこと。 ArgoCDやFluxCDが有名ね。」

Git push → ArgoCDが検知 → Kubernetesリソース自動更新

魔理沙 「CDK Pipelinesが自動デプロイしてたのと似てるな。」

霊夢 「そう。でもGitOpsはKubernetesネイティブで、 人の操作を完全に排除できるのがポイント。 環境の整合性も常に“Gitと現実が一致”してる。」


🧱 Platform Engineering(プラットフォームエンジニアリング)

霊夢 「さらに最近は、“開発者が安全にセルフサービスでデプロイできる社内プラットフォーム”を CDKなどで構築する動きが増えてるわ。」

魔理沙 「つまり“インフラ専門チームが、インフラをサービス化して他の開発者に提供する”感じか。」

霊夢 「そう。CDK Constructの社内配布なんて、まさにその第一歩よ。 最終的には、PortalやCLIを通じて誰でも安全に環境を立ち上げられる世界になる。」


🧠 新時代のIaCベストプラクティス

テーマ これまで これから
定義方法 CloudFormation/Terraformで宣言的に CDKなどで動的+型安全に
実行方法 手動 or CLI GitOps / CI/CDで自動
配布単位 リポジトリ/テンプレート Constructライブラリ/モジュール
運用文化 インフラチーム主導 開発者セルフサービス(Platform Eng)

魔理沙 「CDKを学ぶって、単にAWSを触るだけじゃなくて、 “これからのインフラ運用の形”を学んでる感じがするな。」

霊夢 「まさにそう。IaCはツールじゃなくて、 “クラウドをどう設計し、どう組織で共有するか”という文化なの。」


14.3 次のステップ:クラウドネイティブ設計・GitOps/サービスメッシュ

☁️ クラウドネイティブ設計の要点

霊夢 「クラウドネイティブ設計では、スケーリング・可用性・監視・デプロイが前提で自動化されていることが重要。 CDKをその設計思想と組み合わせると、より“自己修復的なインフラ”になるの。」


🧩 GitOps + CDK のハイブリッド構成例

GitHub (CDKコード)
   ↓ Push
CodePipeline → CDK synth → Output YAML
   ↓
ArgoCD watches repo
   ↓
Kubernetes cluster updated

魔理沙 「つまり、CDKでK8sマニフェストを生成して、それをGitOpsで適用するわけか。 IaCの自動化の二段構えだな。」


🔗 サービスメッシュ(Service Mesh)

霊夢 「マイクロサービスが増えると通信や監視がカオスになる。 そこで登場するのがサービスメッシュ(Istio, Linkerd, AWS App Meshなど)よ。」

[Service A] ⇄ [Sidecar Proxy] ⇄ [Sidecar Proxy] ⇄ [Service B]

魔理沙 「ネットワークの監視やトレーシングをアプリ改修なしでできるってやつか。」

霊夢 「そう。しかも、CDKでApp MeshやIstio構成をIaC化できる。 つまりネットワーク層すらコード管理の対象になってるの。」


🧠 クラウドネイティブ時代のCDK活用指針(霊夢メモ)

項目 ポイント
自動化 GitOps+CDK Pipelinesで完全自動化
標準化 Constructで社内ベースライン化
観測性 X-Ray/OpenTelemetry統合
回復性 AutoHealing+Blue/Greenデプロイ
ポリシーコード化 AWS Config/OPA/cfn-guardで自動監査

魔理沙 「なるほど、インフラもセキュリティも、 “全部コードで管理する”時代に完全に移ってるんだな。」

霊夢 「そう。人が手で操作する時代はもう終わり。 これからはコードが組織のインフラそのものになるの。」


🌟 第14章まとめ:CDKの先へ

項目 内容
CDKtf / CDK8s CDKの思想をTerraform・Kubernetesへ拡張
GitOps / Platform Eng インフラ運用をコードとGitで自動管理
クラウドネイティブ設計 自動化・可視化・回復性を前提とする構築
将来像 “すべての運用をコードで表す” Infrastructure as Everything

魔理沙 「……つまり、CDKはゴールじゃなくて、 “コードでインフラを語る時代”への入り口なんだな。」

霊夢 「そう。CDKを使いこなせるあなたなら、 TerraformもKubernetesもGitOpsも、もう怖くないわ。」

魔理沙 「インフラをコードで描き、Gitで統制し、自動で動く世界…。 なんか未来が見えてきたな。」

霊夢 「ふふ。これが“ゆっくり霊夢と学ぶCDKの旅”の最終章よ。 でも、あなたのクラウドアーキテクトとしての旅は、これからが本番。」

――満月の夜。 神社の空に、AWS・Kubernetes・Terraform・GitHubが輝くアーキテクチャの星座が浮かんだ。 霊夢と魔理沙のCDKハンズオンは、ここで静かに幕を閉じる。


付録 ゆっくり霊夢と学ぶ CDKハンズオン道具箱

――博麗神社の静かな午後。 魔理沙がノートPCを閉じて伸びをしている。

魔理沙 「ふー、やっと14章まで読み終えたぜ!でも、 正直“もう一度整理したい言葉とか、動かなかったときの解決法”もほしいな。」

霊夢 「そう思うと思って、ちゃんと“付録”を用意しておいたわ。 この章を読めば、あなたもCDKで迷子にならなくなる。」


A. 用語集(CDK/CloudFormation/AWS主要サービス)

霊夢 「まずは用語集から。 CDK・CloudFormation・AWSサービスの違いをしっかり押さえておきましょう。」


🌱 CDK関連用語

用語 意味
App CDKアプリ全体を表すルートオブジェクト。複数のStackをまとめて管理する。
Stack CloudFormationスタック1つ分。AWS上の1つの環境単位。
Construct 再利用可能なインフラ構成単位(部品)。Stackやリソースの基本要素。
Props Constructに渡すパラメータ(プロパティ)。
Aspects 既存リソースに一括ポリシーを適用できる機構。
Synth CDKコードをCloudFormationテンプレート(YAML/JSON)に変換する処理。
Bootstrap CDKの初回準備。CDKが使うS3バケットやIAMロールを作成する。
Deploy CloudFormationを使ってAWS環境に反映するコマンド。

🏗 CloudFormation関連用語

用語 意味
Template AWSリソースを定義したJSON/YAMLファイル。CDKはこれを自動生成する。
Stack TemplateをもとにAWS上に作られるリソース群の集合体。
ChangeSet 変更内容の差分プレビュー。デプロイ前に安全確認ができる。
Parameter / Output 他スタックや環境間で値を受け渡す仕組み。

☁️ AWS主要サービス(CDKでよく使うもの)

サービス 用途
S3 静的サイトホスティング、ファイル格納、CDKアセット保存など。
Lambda サーバーレス関数実行基盤。APIやイベント駆動処理に利用。
DynamoDB 高速NoSQLデータベース。LambdaやAPI Gatewayと好相性。
ECS Fargate コンテナ実行基盤。サーバーレスコンテナを簡単に実行可能。
CloudFront CDN(コンテンツ配信)。S3やALBと組み合わせて高速配信。
IAM 権限・認証管理。最小権限設計の要。
CloudWatch ログ・メトリクス・アラーム管理。監視と運用の中心。
CodePipeline / CodeBuild CI/CD自動化ツール。CDK Pipelinesの裏側でも使用される。

魔理沙 「おー、これ1ページ貼っとくだけで“CDK会話”についていけるな!」

霊夢 「特にConstructStackの違いを混同しやすいから注意してね。」


B. トラブルシューティング Q&A(よくあるエラーと対処)

霊夢 「次は“動かないときの定番”。 焦らず一つずつ原因を潰すのがコツよ。」


💥 よくあるエラーと解決法

症状 原因 対処法
AccessDenied IAM権限不足 cdk bootstrapでロール作成/AWS CLIの認証確認
⚙️ Network Error VPC設定ミスやポート閉塞 SGのIngress/Egressルールを再確認
💡 Resource already exists 同名リソースが既に存在 Stack名やリソース名を一意に変更
🌀 Circular dependency detected スタック間で循環参照 Output/ImportValueを使って一方向依存に直す
🚫 Unable to assume role CDK実行ロール不一致 aws sts get-caller-identityで実行アカウント確認
🕒 デプロイが進まない CloudFormationスタックが保留状態 AWSコンソールのイベントで詳細確認し、失敗リソース削除
🧩 Nodeバージョン不整合 CDK CLIとプロジェクトのバージョン不一致 npm install aws-cdk-lib@<CLIと同じ> で揃える
🪣 Asset upload failed S3バケットリージョン不一致 cdk bootstrap --cloudformation-execution-policiesを再実行

魔理沙 「“デプロイ止まったけどどこが悪いか分からない”ってとき、 CloudFormationのイベントタブを見たら解決すること多いんだよな。」

霊夢 「そうそう。焦らず“どのリソースで止まったか”を見れば、ほとんどの場合すぐ原因がわかるわ。」


C. CDK プロジェクト構成例テンプレート

霊夢 「CDKプロジェクトのフォルダ構成も、整理しておくと管理が楽になるの。」


📁 標準構成テンプレート

my-cdk-project/
├─ bin/
│   └─ app.ts                 # エントリーポイント
├─ lib/
│   ├─ app-stack.ts           # メインスタック
│   ├─ constructs/
│   │   ├─ web-app.ts         # 再利用可能Construct
│   │   └─ pipeline.ts
│   ├─ stages/
│   │   ├─ staging-stage.ts
│   │   └─ prod-stage.ts
├─ test/
│   ├─ app-stack.test.ts      # Assertionsテスト
│   └─ constructs.test.ts
├─ scripts/
│   └─ setup.sh               # bootstrapやlint自動化
├─ cdk.json                   # エントリーポイント設定
├─ package.json
├─ tsconfig.json
└─ README.md

💡 プロジェクト構成の考え方

フォルダ 役割
bin/ CDKアプリのエントリーポイント。Stackを登録する。
lib/ 実際のStack・Construct定義。プロジェクトの心臓部。
constructs/ 再利用したいリソースのまとまりをクラス化して保存。
stages/ ステージング/本番など、複数環境を管理する設定。
test/ CDK Assertionsを使った構成テスト。
scripts/ 環境セットアップやビルド自動化スクリプト。

魔理沙 「こうしてフォルダを分けておけば、 将来Constructをnpm公開したり、複数チームで開発しても混乱しないな。」

霊夢 「そう。CDKは“コードで構成する”からこそ、設計の秩序が大事なのよ。」


D. サンプルコード/演習解答集(GitHub リポジトリ参照)

霊夢 「そして最後に、実際に動くコードサンプルと演習の解答例をまとめたGitHubを用意したわ。」(注: まだないです)


📦 GitHubリポジトリ構成イメージ

https://github.com/yukkuri-cdk-hands-on/
├─ chapter01-intro/
├─ chapter04-s3-cloudfront/
├─ chapter05-lambda-api/
├─ chapter06-ecs-fargate/
├─ chapter09-pipeline/
├─ chapter10-monitoring/
├─ chapter11-security/
├─ chapter13-constructs/
└─ appendix/

魔理沙 「おおっ、章ごとにフォルダ分けされてるのか! これなら途中から読み始めた人も助かるな。」

霊夢 「うん。各フォルダには README.mddeploy手順、 さらに cdk diff 結果も入れてあるから、差分学習にも使えるわ。」


💡 GitHub学習のポイント

学習目的 リポジトリ活用法
コマンド練習 cdk synth / cdk diff / cdk deploy を試す
Stack構成の理解 lib/フォルダ内を読む
テスト習慣づけ test/フォルダのJestテストを実行
セキュリティ/監視の設定 10〜11章フォルダを重点的に参照

魔理沙 「本を読みながらGitHubのコードを動かせば、 ハンズオンの“手触り”が倍になるな。」

霊夢 「そう。IaCは“読むより触る”が一番の学習法よ。」


🌟 付録まとめ

セクション 内容
A. 用語集 CDK・CloudFormation・AWSの主要概念を整理
B. トラブルQ&A よくあるエラーと対処法一覧
C. プロジェクト構成テンプレート ベストプラクティスなフォルダ構成例
D. GitHubリポジトリ 全章のサンプルコードと演習解答集

魔理沙 「これでもう“CDK迷子”にならなくて済むな。 トラブルのときも付録見れば何とかなる!」

霊夢 「その通り。 CDKは一度環境さえ整えば、あとは“考え方”と“型”を守るだけ。 付録はそのナビゲーションマップなの。」

魔理沙 「ありがとう霊夢。これでCDKだけじゃなく、クラウドも怖くないぜ。」

霊夢 「ふふ。じゃあ最後にひとこと―― “コードで描いた設計図こそ、未来のインフラ”よ。」

――神社の空に、無数のAWSリソースが星座のように輝いた。 霊夢と魔理沙のCDKハンズオンシリーズ、ここに完全完結


🎓 『AWS CDKハンズオン完全版(TypeScript編)』 🌟 完全版 全14章+付録:終了!


所感

以前ChatGPTで本を書き、それをベースに再現実装したものもあります。

ja.algonote.com

Zennの規約が少しAI生成に対して厳しめになったので今後はブログに書いていこうかどうしようかといったところです。本形式はブログだと見づらいのでGitBookとかもよさそうですね。