AWS CDK(Python)でALB + EC2(Tomcat) + RDS 3層構成を構築する手順【CloudFormation 460行 → CDK 200行】

AWS Basic
スポンサーリンク
スポンサーリンク

はじめに

「CloudFormation の YAML 460行をもっとシンプルに書けないか」——それを実現するのが AWS CDK(Cloud Development Kit) です。

この記事では、CloudFormation版ハンズオンで構築した ALB + EC2(Tomcat) + RDS の3層構成を、AWS CDK(Python) で再現します。YAML を Python コードで書き直すことで、460行 → 約200行に削減できることを体験します。

インターネット
  ↓ HTTP(80)
[ALB: my-cdk-alb-alb]  ← インターネット向け / パブリックサブネット 2AZ
  ↓ HTTP(8080)  ← ALB SG → EC2 SG(SG-to-SG 制御)
[EC2: my-cdk-alb-ap-instance]  ← Tomcat / パブリックサブネット AZ-a
  ↓ MySQL(3306)  ← EC2 SG → RDS SG(SG-to-SG 制御)
[RDS: my-cdk-alb-rds-mysql]  ← MySQL 8.0 / プライベートサブネット AZ-a

[VPC: my-cdk-alb-vpc (10.0.0.0/16)]
  ├── パブリックサブネット (10.0.0.0/24) [AZ-a]  ← ALB + EC2
  ├── パブリックサブネット (10.0.1.0/24) [AZ-b]  ← ALB(2AZ 必須)
  ├── プライベートサブネット (10.0.2.0/24) [AZ-a]  ← RDS 配置
  └── プライベートサブネット (10.0.3.0/24) [AZ-b]  ← DBサブネットグループ用

このハンズオンで体験できること:

  • Python コードで AWS インフラを定義する CDK の世界観を理解
  • ec2.Vpc 1つでVPC・IGW・ルートテーブルを自動生成する L2 Construct の威力を体験
  • cdk synth で CloudFormation テンプレートを生成・確認
  • cdk diff でデプロイ前の差分確認(CloudFormation の変更セット相当)
  • cdk deploy / cdk destroy でワンコマンドデプロイ・削除

このハンズオンの特徴:

  • CloudFormation 版で460行必要だった YAML が Python コード約200行で記述できる
  • cdk destroy 1本でALB・RDS・IAMなど全リソースを自動削除
  • コードの変更差分を cdk diff で即確認できる(CloudFormation の変更セットより簡単)

この記事は CloudFormation版ハンズオン の発展記事です。
同じ構成を CDK で再現し、IaC の進化を体験したい方向けです。CDK のコード詳細は GitHub を参照してください。


-->

スポンサーリンク

キーワード解説

用語意味
AWS CDKPython・TypeScript などのプログラミング言語で AWS インフラを定義する IaC フレームワーク
CDK Appapp.py がエントリポイント。cdk synth でここから CloudFormation テンプレートを生成
CDK Stack1つの CloudFormation スタックに対応する単位。今回は CdkAlbEc2RdsStack
L2 ConstructAWS がベストプラクティスを組み込んだ高レベルな抽象クラス(ec2.Vpc 等)。内部で複数の AWS リソースを自動生成
CDK Contextcdk.json に書くデプロイ設定。-c key=value で上書き可能
CDK BootstrapCDK が AWS にデプロイするために必要な事前準備(S3 バケット等を作成)。同じアカウント・リージョンで初回のみ
cdk synthPython コードから CloudFormation テンプレートを生成(デプロイなし)
cdk diff現在のデプロイ状態と新しいコードの差分を表示
cdk deployCloudFormation スタックをデプロイ
cdk destroyCloudFormation スタックとその全リソースを削除

スポンサーリンク

CloudFormation vs CDK:どれだけ違うか

比較項目CloudFormation(alb-ec2-rds)CDK(このハンズオン)
記述言語YAML(宣言型)Python(プログラミング言語)
コード量約460行約200行
VPC 定義15+ リソースを手動定義ec2.Vpc 1つで IGW・ルートテーブル等を自動生成
SG-to-SG 制御SourceSecurityGroupId: !GetAtt で参照add_ingress_rule(alb_sg, ...) で直感的に記述
ALB + TG + リスナー3リソースを別々に定義add_listener → add_targets でメソッドチェーン
変数・ループ!Sub / !If でのみ表現Python の変数・f-string・for文が使える
デプロイコマンドaws cloudformation deploy ...cdk deploy
削除コマンドaws cloudformation delete-stack ...cdk destroy
差分確認変更セット(手動作成)cdk diff(自動)

使用するAWSサービス

サービス役割料金
VPCカスタムネットワーク空間無料
EC2(t2.micro)APサーバ(Tomcat)月750時間まで無料枠あり
RDS MySQL(db.t3.micro)マネージドDBサーバ月750時間まで無料枠あり
ALBロードバランサー約$0.008/時間 + LCU料金(無料枠なし
SSM Parameter StoreDBパスワードの安全な保管スタンダード層は無料
IAMEC2にSSM・Parameter Store権限を付与無料

注意: ALBは無料枠がありません。ハンズオン後は必ず cdk destroy で削除してください。


前提条件

ツール確認コマンド
AWS CLI v2aws --version
Python 3.9 以上python --version
Node.js 18 以上node --version
CDK CLIcdk --version

AWS 認証確認:

aws sts get-caller-identity

Node.js と CDK CLI のインストール手順は docs/setup/09_nodejs-cdk.md を参照してください。


構築されるリソース

CDK が cdk deploy 時に自動生成するリソース一覧です。

カテゴリリソース
ネットワークVPC / IGW / パブリックサブネット×2 / プライベートサブネット×2 / ルートテーブル×2
セキュリティALB SG / EC2 SG / RDS SG
IAMEC2ロール / インスタンスプロファイル
パラメータSSM Parameter Store(DBパスワード)
データベースRDS DBサブネットグループ / RDS MySQL 8.0
ロードバランサーターゲットグループ / ALB / リスナー
コンピュートEC2インスタンス(Tomcat)

CloudFormation 版では約27リソースを YAML に個別定義しましたが、CDK では ec2.Vpc 1つがVPC・IGW・ルートテーブル等を自動生成するため、Python コードとして書くのは主要リソースのみです。


作業順序

⓪ 自分のIPアドレスを確認する
      ↓
① キーペアを作成する(AWS CLI で実施)
      ↓
② プロジェクトのセットアップ(Python 仮想環境)
      ↓
③ cdk.json を設定する
      ↓
④ CDK Bootstrap(初回のみ)
      ↓
⑤ CDK Synth(テンプレート確認)
      ↓
⑥ デプロイ(cdk deploy)
      ↓
⑦ 動作確認(ALBアクセス・SSH・RDS接続)
      ↓
⑧ CDK diff(参考)
      ↓
⑨ リソース削除(cdk destroy)

【重要】⓪ 自分のIPアドレスを確認する

curl https://checkip.amazonaws.com

控えておく情報: 自分のIPアドレス(例: 203.0.113.1

セキュリティグループで 203.0.113.1/32 の形式(末尾に /32)で使用します。


① キーペアの作成

CDK では cdk deploy 時にキーペアのダウンロードができないため、事前に AWS CLI で作成します。

%USERPROFILE%\.ssh\ が存在しない場合は先に mkdir %USERPROFILE%\.ssh を実行してください。

aws ec2 create-key-pair ^
  --key-name my-cdk-alb-key ^
  --query KeyMaterial ^
  --output text ^
  --region ap-northeast-1 > %USERPROFILE%\.ssh\my-cdk-alb-key.pem

控えておく情報: キーペア名 my-cdk-alb-key


② プロジェクトのセットアップ

CDK の Python プロジェクトを実行するために、Python 仮想環境(venv)を作成してパッケージをインストールします。

cd C:\my-aws\aws-learning-projects\cdk-alb-ec2-rds

python -m venv .venv

.venv\Scripts\activate

pip install -r requirements.txt

仮想環境が有効になると、プロンプトの先頭に (.venv) が表示されます。

重要: CDK のコマンド(synth / deploy / diff / destroy)はすべてこの仮想環境が有効な状態で実行する必要があります。
ターミナルを閉じると仮想環境の有効化が解除されるため、ターミナルを開き直した際は必ず最初に以下を実行してください

cd C:\my-aws\aws-learning-projects\cdk-alb-ec2-rds
.venv\Scripts\activate

プロンプトに (.venv) が付いていることを確認してから CDK コマンドを実行してください。


③ cdk.json の設定

cdk.jsoncontext セクションを自分の環境に合わせて編集します。

{
  "context": {
    "employee_id": "my",
    "my_ip": "203.0.113.1/32",
    "db_password": "Handson1234!",
    "key_name": "my-cdk-alb-key",
    "tomcat_version": "10.1.28"
  }
}
設定項目説明
employee_idmyリソース名のプレフィックス(my-cdk-alb-xxx という名前になる)
my_ip⓪で確認したIP /32EC2へのSSHを許可するIP
db_passwordHandson1234!RDS MySQL のパスワード
key_namemy-cdk-alb-key①で作成したキーペア名
tomcat_version10.1.28Tomcat バージョン

cdk.json はバージョン管理に含めますcdk.context.json.gitignore 対象)。

CDK の詳細なコード(stacks/alb_ec2_rds_stack.py など)は GitHub を参照してください。


④ CDK Bootstrap(初回のみ)

CDK が AWS 環境にデプロイするために必要なリソース(S3 バケット等)を事前にセットアップします。
同じアカウント・リージョンで一度だけ実行すれば以降は不要です。

cdk bootstrapapp.py を実行しないため、仮想環境の有効・無効に関わらず実行できます。② で有効にした仮想環境はそのままで進めてください。

rem アカウントIDを確認
aws sts get-caller-identity --query Account --output text

rem Bootstrap を実行(アカウントIDを置き換えて実行)
cdk bootstrap aws://123456789012/ap-northeast-1

正常完了すると「CDKToolkit」という CloudFormation スタックが作成されます。

ステータス意味
CREATE_COMPLETEBootstrap 完了
ALREADY_EXISTS既に Bootstrap 済み(スキップ可)

⑤ CDK Synth(テンプレート確認)

デプロイ前に CDK が生成する CloudFormation テンプレートを確認します。この段階では AWS へのデプロイは行われません。

cdk synth

cdk.out/ ディレクトリに CloudFormation テンプレート(JSON)が生成されます。

CloudFormation 版との比較ポイント:

  • CDK が自動生成したVPC・ルートテーブル等のリソースが含まれていることを確認
  • Python コード(約200行)から生成されたテンプレートの行数を確認(はるかに多い)

なぜテンプレートは増えるのか: CDK の Python コードは「人間が書く量」を減らすための抽象化です。実際に AWS に渡される CloudFormation テンプレートは CDK が自動生成するため、行数は多くなります。

rem 生成されたテンプレートをテキストエディタで確認
notepad cdk.out\CdkAlbEc2RdsStack.template.json

⑥ デプロイ

cdk deploy

実行中に「Do you wish to deploy these changes?」と表示されたら y を入力します。

所要時間: RDS の作成に 15〜20 分かかります。

デプロイ完了後、Outputs が表示されます:

Outputs:
CdkAlbEc2RdsStack.ALBEndpoint = http://my-cdk-alb-alb-xxxx.ap-northeast-1.elb.amazonaws.com
CdkAlbEc2RdsStack.EC2PublicIP = x.x.x.x
CdkAlbEc2RdsStack.RDSEndpoint = my-cdk-alb-rds-mysql.xxxx.ap-northeast-1.rds.amazonaws.com
CdkAlbEc2RdsStack.SSHCommand = ssh -i %USERPROFILE%\.ssh\my-cdk-alb-key.pem ec2-user@x.x.x.x
CdkAlbEc2RdsStack.MySQLConnectCommand = mysql -h my-cdk-alb-rds-mysql.xxxx... -u admin -pHandson1234! sampledb

控えておく情報: ALBEndpointEC2PublicIPRDSEndpoint


⑦ 動作確認

7-1. ALB のヘルスチェック確認

EC2 → ターゲットグループ → my-cdk-alb-tg → 「ターゲット」タブ

EC2 のステータスが 「healthy」 になるまで待ちます(EC2 起動後 5〜10 分)。

ステータス意味
initial初期ヘルスチェック中(待つ)
healthy正常(トラフィック転送される)
unhealthy異常(Tomcat が起動していない可能性)

Tomcat の起動はEC2が「実行中」になってからさらに 3〜5 分かかります。

ターゲットグループの ARN を CLI で確認する場合:

aws elbv2 describe-target-groups ^
  --names my-cdk-alb-tg ^
  --query TargetGroups[0].TargetGroupArn ^
  --output text ^
  --region ap-northeast-1

7-2. ALB 経由でWebアクセス確認

Outputs の ALBEndpoint の URL をブラウザで開きます。

http://(ALBEndpoint の DNS 名)

以下が表示されれば正常です:

AP Server - my-cdk ALB + EC2 + RDS
Deployed via AWS CDK (Python). Connects to RDS MySQL in the private subnet.

EC2 のパブリック IP に直接アクセスしても表示されません(ポート 8080 は ALB SG からのみ許可しているため)。

7-3. EC2 に SSH 接続する

Outputs の SSHCommand を実行します(パスは実際のパスに修正します)。

ssh -i %USERPROFILE%\.ssh\my-cdk-alb-key.pem ec2-user@(EC2PublicIP)

7-4. EC2 から RDS への接続確認

EC2 に SSH 接続後(以下は EC2 上での操作):

sudo dnf install -y mariadb105

# SSM Parameter Store からパスワードを取得
DB_PASSWORD=$(aws ssm get-parameter \
  --name /my/cdk-alb/db-password \
  --query Parameter.Value \
  --output text \
  --region ap-northeast-1)

# RDS に接続(Outputs の RDSEndpoint を使用)
mysql -h <RDSEndpoint> -u admin -p${DB_PASSWORD} sampledb
-- テーブル作成
CREATE TABLE items (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- データ挿入
INSERT INTO items (name) VALUES ('Apple'), ('Banana');

-- データ確認
SELECT * FROM items;

-- 後片付け
DROP TABLE items;

EXIT;

7-5. SSH 接続を切断する

exit

7-6. UserData の実行ログ確認

EC2 に SSH 接続後(以下は EC2 上での操作):

sudo cat /var/log/user-data.log

エラーなく最後まで実行されていれば正常です。


⑧ CDK の差分確認(参考)

コードを変更した後、デプロイ前に差分を確認できます。これが CDK の強力な機能の1つです。

cdk diff

CloudFormation の変更セット相当の情報が自動で表示されます。

Stack CdkAlbEc2RdsStack
Resources
[~] AWS::EC2::Instance EC2Instance
 └─ [~] UserData
     └─ [~] .Fn::Base64
         └─ ...

⑨ リソース削除

課金を止めるために、ハンズオン完了後は必ず削除します。

cdk destroy

「Are you sure you want to delete?」に y を入力します。

所要時間: RDS の削除に 10〜15 分かかります。

削除されるリソース一覧

リソース削除タイミング
ALB・リスナー・ターゲットグループcdk destroy 実行直後
EC2 インスタンスcdk destroy 実行直後
RDS インスタンス10〜15 分(削除ポリシー: DESTROY)
VPC・サブネット・SGRDS 削除後
SSM Parameter Storeスタック削除と同時
IAM ロール・インスタンスプロファイルスタック削除と同時

キーペアの削除(手動)

CDK が管理していないリソースは手動で削除します:

aws ec2 delete-key-pair ^
  --key-name my-cdk-alb-key ^
  --region ap-northeast-1

del %USERPROFILE%\.ssh\my-cdk-alb-key.pem

仮想環境の終了

ハンズオンが終わったらプロンプトの (.venv) を外します。

deactivate

(.venv) が消えて通常のプロンプトに戻れば完了です。

(.venv) が付いている状態とは: このプロジェクト専用の Python 環境(venv)が有効な状態です。deactivate しなくてもターミナルを閉じれば自動的に解除されます。次回 CDK コマンドを使う際は再度 .venv\Scripts\activate が必要です。

削除完了の確認

aws cloudformation describe-stacks ^
  --stack-name CdkAlbEc2RdsStack ^
  --region ap-northeast-1

「Stack with id CdkAlbEc2RdsStack does not exist」エラーが出れば削除完了です。

CDK Bootstrap リソースの削除(任意)

CDK を今後も使う場合は残したままでよいです。
削除する場合は AWS コンソールで CDKToolkit スタックを手動削除します。


CDK のポイント解説

L1 / L2 / L3 Construct の違い

レベル名前説明
L1Cfn ConstructCloudFormation リソースと 1:1 対応。Cfn プレフィックスec2.CfnVPC
L2Default ConstructAWS のベストプラクティスを組み込んだ高レベル抽象ec2.Vpc
L3Pattern複数サービスを組み合わせた再利用可能なパターンecs_patterns.ApplicationLoadBalancedFargateService

このハンズオンでは主に L2 Construct を使用しています。ec2.Vpc 1つを書くだけで、CloudFormation では15+ リソースが必要だったVPC・IGW・ルートテーブル・サブネット設定を自動生成します。

CDK Context 変数

cdk.jsoncontext に設定した値は self.node.try_get_context("key") で取得できます。
デプロイ時に -c key=value で上書きも可能です:

cdk deploy -c my_ip=1.2.3.4/32 -c db_password=MyPass123!

cdk synth で CloudFormation テンプレートを確認

rem cdk.out/ に生成されたテンプレートをテキストエディタで確認
notepad cdk.out\CdkAlbEc2RdsStack.template.json

CDK コードの詳細(stacks/alb_ec2_rds_stack.py 全文)は GitHub を参照してください。


トラブルシューティング

症状原因対処
cdk deploy で認証エラーAWS 認証情報が未設定aws sts get-caller-identity で確認
cdk bootstrap が必要と言われるBootstrap 未実施④の手順を実施
ModuleNotFoundError: aws_cdk仮想環境が無効.venv\Scripts\activate を実行してから再度 CDK コマンドを実行
ALB にアクセスすると 502Tomcat 起動前3〜5 分待ってリトライ
SSH できないmy_ip が違う、またはキー名が違うcdk.jsonmy_ipkey_name を確認
RDS に接続できないSG 設定の問題EC2 SG から RDS SG への 3306 ルールを確認
cdk destroy が途中で止まるRDS の削除待ち10〜15 分待つ(自動的に続行される)
No match for argument: mysqlAL2023 では mysql パッケージが存在しないsudo dnf install -y mariadb105 を使う

デプロイ失敗時のログ確認:

aws cloudformation describe-stack-events ^
  --stack-name CdkAlbEc2RdsStack ^
  --region ap-northeast-1 ^
  --query "StackEvents[?ResourceStatus=='CREATE_FAILED'].[ResourceType,ResourceStatusReason]" ^
  --output table

コンソール版・CloudFormation版との比較

作業コンソール(手動)CloudFormationCDK(今回)
VPC + サブネット4つ + IGW + RT約20〜30分template.yaml に定義済みec2.Vpc 1行で自動生成
SG 3つ(ALB/EC2/RDS)の作成3画面で個別設定template.yaml に定義済みPython コードで直感的に記述
ALB + TG + Listener の作成3つの画面で設定template.yaml に定義済みメソッドチェーンで接続
コード量約460行(YAML)約200行(Python)
全体のデプロイ約40〜50分コマンド1本(RDS待ち15〜20分)cdk deploy 1本(同等)
削除13ステップ手動delete-stack 1本cdk destroy 1本
差分確認変更セット(手動作成)cdk diff(自動・即時)
バージョン管理不可Gitで管理可能Gitで管理可能

まとめ

ステップ内容
①②キーペア作成 + Python 仮想環境のセットアップ
cdk.json に自分の環境(IP・パスワード・キー名)を設定
cdk bootstrap(初回のみ。以降は不要)
cdk synth で CloudFormation テンプレートを確認(デプロイなし)
cdk deploy でデプロイ(RDS 待ち 15〜20 分)
ALB DNS 名でアクセス → EC2 → Parameter Store → RDS への接続テスト
cdk destroy で全リソースを一括削除

CDK の最大の魅力は プログラミング言語でインフラを書ける点です。CloudFormation の460行の YAML が Python 約200行に削減されただけでなく、cdk diff による差分確認や L2 Construct による抽象化など、開発者体験が大きく向上します。

コンソールで3層構成の概念を視覚的に学びたい場合は AWSコンソール版ハンズオン、まずCloudFormationで同じ構成を試したい場合は CloudFormation版ハンズオン を参照してください。

コメント