はじめに
前回のAWSコンソール版ハンズオン(Spring Boot Webアプリ)では、コンソールでインフラを手動構築してSCPでWARをデプロイしました。
この記事では、同じ構成を CloudFormation で自動化します。template.yaml 1ファイルにVPC・SG・IAM・SSM・RDS・ALB・EC2(約30リソース)を定義し、さらに EC2のUserDataがS3からWARを自動取得してTomcatにデプロイするため、コマンド数本でWebアプリが動く状態まで一気に構築できます。
ローカル環境(VSCode)
├── app/target/webapp.war(mvn packageでビルド済み)
├── template.yaml(約30リソースを定義)
└── AWS CLI コマンド
↓ スタック作成(コマンド1本)
AWS環境
├── S3バケット(webapp.war置き場)
└── VPC(10.0.0.0/16)
├── パブリックサブネット1・2(ALB + EC2)
├── プライベートサブネット1・2(RDS)
├── IGW + ルートテーブル
├── IAMロール(SSM + S3読み取り権限)
├── ALB SG → EC2 SG → RDS SG(SG-to-SG制御)
├── SSM Parameter Store(/my/webapp/db-password)
├── RDS MySQL 8.0(db.t3.micro / sampledb)
├── ALB(HTTP:80)→ TG(HTTP:8080)
└── EC2(t2.micro)
UserDataが自動実行:
1. Java + Tomcat インストール
2. SSMからDBパスワード取得 → setenv.sh作成
3. S3からwebapp.warをダウンロード → ROOT.warとして配置
4. Tomcat起動(Spring Bootアプリが自動展開)このハンズオンで体験できること:
- WARのデプロイをS3 + UserDataで完全自動化する設計
- SSMからDB接続情報を取得してsetenv.shを自動作成する仕組み
delete-stack1本でALB・RDS・IAMなど全リソースを自動削除
テンプレートとアプリのソースコードはGitHubで公開しています:
aws-handson/alb-ec2-rds-webapp at main · caymezon/aws-handsonAWS HANDSON. Contribute to caymezon/aws-handson development by creating an account on GitHub.
この記事は AWSコンソール版ハンズオン の比較記事です。
コンソール版でSCPデプロイの仕組みを理解した後に読むと理解が深まります。
-->
CloudFormation vs コンソール:どれだけ違うか
| 比較項目 | CloudFormation | コンソール(手動) |
|---|---|---|
| VPC + サブネット4つ + IGW + ルートテーブル | template.yaml に定義済み | 約20〜30分・複数画面 |
| SG 3つ(ALB/EC2/RDS)の作成 | template.yaml に定義済み | 3画面で個別設定 |
| ALB + TG + Listener の作成 | template.yaml に定義済み | 3つの画面で設定 |
| WARのデプロイ | S3 + UserDataで自動 | SCPで転送 + SSH操作 |
| DB接続設定(setenv.sh) | UserDataがSSMから自動取得・作成 | SSH接続して手動作成 |
| 全体のデプロイ | コマンド数本(RDS待ち15〜20分) | 約60〜90分 |
| 削除 | delete-stack 1本 | 16ステップ手動 |
キーワード解説
| 用語 | 意味 |
|---|---|
| CloudFormation | AWSが提供するIaC(Infrastructure as Code)サービス |
| スタック | CloudFormationが管理するリソースのまとまり。今回は約30リソースを1スタックで管理 |
| S3 VPC Gateway Endpoint | EC2からS3にインターネットを経由せずアクセスするための無料エンドポイント |
| UserData | EC2初回起動時に自動実行されるシェルスクリプト |
| CAPABILITY_NAMED_IAM | 名前付きIAMリソースを含むスタック作成に必要なフラグ |
| DeletionPolicy: Delete | スタック削除時にRDSも確実に削除する設定 |
前提条件
aws sts get-caller-identity
aws --version
java -version
mvn -version構築されるリソース(約30個)
template.yaml の詳細はGitHubを参照してください:
aws-handson/alb-ec2-rds-webapp/template.yaml at main ?? caymezon/aws-handsonAWS HANDSON. Contribute to caymezon/aws-handson development by creating an account on GitHub.
| カテゴリ | リソース |
|---|---|
| ネットワーク | VPC / IGW / パブリックサブネット×2 / プライベートサブネット×2 / ルートテーブル×2 / S3 VPC Endpoint |
| セキュリティ | ALB SG / EC2 SG / RDS SG |
| IAM | EC2ロール(SSM + S3読み取り権限)+ インスタンスプロファイル |
| パラメータ | SSM Parameter Store(/my/webapp/db-password) |
| データベース | RDS DBサブネットグループ / RDS MySQL 8.0 |
| ロードバランサー | ターゲットグループ / ALB本体 / リスナー |
| コンピュート | EC2インスタンス(Tomcat + WAR自動デプロイ) |
作業順序
⓪ Webアプリをビルドする(mvn package)
↓
⓪-2 自分のIPアドレスを確認する
↓
① キーペアを作成する(コンソールで実施)
↓
② S3バケットを作成してWARをアップロードする
↓
③ スタックを作成する(aws cloudformation create-stack)
↓
④ 作成完了・Outputsを確認する(RDS待ち15〜20分)
↓
⑤ 動作確認(ALBアクセス・アイテム追加削除)
↓
⑥ スタックを削除する(S3バケットも忘れず削除)⓪ Webアプリのビルド
アプリのソースコードはGitHubで公開しています:
aws-handson/alb-ec2-rds-webapp/app at main ?? caymezon/aws-handsonAWS HANDSON. Contribute to caymezon/aws-handson development by creating an account on GitHub.
cd C:\(プロジェクトフォルダ)\alb-ec2-rds-webapp\app
mvn package -DskipTests
dir target\webapp.warwebapp.war(約20〜30MB)が生成されていれば成功です。
⓪-2 自分のIPアドレスを確認する
curl https://checkip.amazonaws.com控えておく情報: 自分のIPアドレス(例: 203.0.113.1)
① キーペアの作成(コンソールで実施)
CloudFormationではキーペアのダウンロードができないため、コンソールで先に作成します。
AWSコンソール → EC2 → キーペア → 「キーペアを作成」
| 設定項目 | 値 |
|---|---|
| 名前 | my-webapp-key |
| キーペアのタイプ | RSA |
| プライベートキーファイル形式 | .pem |
ダウンロードされた my-webapp-key.pem を保存します。
C:\Users\ユーザー名\.ssh\my-webapp-key.pem② S3バケットの作成とWARのアップロード
EC2のUserDataがS3から webapp.war をダウンロードするため、スタック作成より前にアップロードしておく必要があります。
プロジェクトフォルダに移動する
cd C:\(プロジェクトフォルダ)\alb-ec2-rds-webappS3バケットを作成する
バケット名はグローバルで一意である必要があります。末尾に任意の識別子を加えてユニークにしてください。
aws s3 mb s3://my-webapp-bucket-(任意の識別子) --region ap-northeast-1WARをS3にアップロードする
aws s3 cp app\target\webapp.war s3://my-webapp-bucket-(任意の識別子)/webapp.warアップロードを確認します。
aws s3 ls s3://my-webapp-bucket-(任意の識別子)/2026-04-18 10:00:00 26214400 webapp.war③ スタックの作成
以下のコマンドを実行します。各パラメータを自分の値に置き換えます。
aws cloudformation create-stack ^
--stack-name my-webapp-stack ^
--template-body file://template.yaml ^
--region ap-northeast-1 ^
--capabilities CAPABILITY_NAMED_IAM ^
--parameters ^
ParameterKey=KeyName,ParameterValue=my-webapp-key ^
ParameterKey=MyIP,ParameterValue=(⓪-2で確認したIP)/32 ^
ParameterKey=DBPassword,ParameterValue=(任意のパスワード) ^
ParameterKey=WARBucketName,ParameterValue=my-webapp-bucket-(任意の識別子)
CAPABILITY_NAMED_IAMについて: 名前を指定したIAMリソース(EC2ロールなど)を作成する場合に必要なフラグです。
TomcatVersionパラメータについて: デフォルト値は10.1.28。変更する場合はParameterKey=TomcatVersion,ParameterValue=10.1.xxを追加します。利用可能なバージョンは https://archive.apache.org/dist/tomcat/tomcat-10/ で確認します。
成功すると以下のような StackId が表示されます。
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/my-webapp-stack/xxxxx"
}④ 作成完了・Outputsの確認
注意: RDSの作成には約15〜20分かかります。EC2のUserDataでWARのデプロイも行うため、さらに数分かかります。
作成状況の確認
aws cloudformation describe-stacks ^
--stack-name my-webapp-stack ^
--query "Stacks[0].StackStatus" ^
--output text| ステータス | 意味 |
|---|---|
CREATE_IN_PROGRESS | 作成中(待つ) |
CREATE_COMPLETE | 作成完了 |
ROLLBACK_COMPLETE | 失敗してロールバック完了(トラブルシューティングを参照) |
Outputs(接続情報)の確認
CREATE_COMPLETE になったら以下を実行します。
aws cloudformation describe-stacks ^
--stack-name my-webapp-stack ^
--query "Stacks[0].Outputs" ^
--output table+--------------------+-------------------------------------------------------------------+
| OutputKey | OutputValue |
+--------------------+-------------------------------------------------------------------+
| ALBEndpoint | http://my-webapp-alb-1234567890.ap-northeast-1.elb.amazonaws.com |
| EC2PublicIP | x.x.x.x |
| RDSEndpoint | my-webapp-rds-mysql.xxxxx.ap-northeast-1.rds.amazonaws.com |
| DBPasswordParamName | /my/webapp/db-password |
| SSHCommand | ssh -i ~/.ssh/my-webapp-key.pem ec2-user@x.x.x.x |
+--------------------+-------------------------------------------------------------------+控えておく情報: ALBEndpoint、EC2PublicIP、RDSEndpoint
⑤ 動作確認
ALBのヘルスチェック確認
EC2 → ターゲットグループ → my-webapp-tg → 「ターゲット」タブ
EC2のステータスが 「healthy」 になるまで待ちます(EC2起動後5〜10分)。
Tomcatの起動 + WARのデプロイはEC2「実行中」からさらに数分かかります。
initialやunhealthyが続く場合はしばらく待ちます。
ALB経由でWebアプリにアクセスする
Outputsに表示された ALBEndpoint をブラウザで開きます。
http://(ALBEndpointのDNS名)Spring Boot + RDS Item Manager
ALB → EC2(Tomcat) → RDS MySQL の3層構成で動作しています。が表示されれば成功です。
アイテムの追加・削除を試す
- テキストボックスにアイテム名を入力して「追加」をクリック
- アイテムが一覧に表示されることを確認
- 「削除」ボタンでアイテムが削除されることを確認
ブラウザをリロードしてもデータが保持されていれば、RDSへの永続化が成功しています。
(任意)ログでデプロイ過程を確認する
OutputsのSSHCommandでEC2に接続して確認します。
sudo cat /var/log/user-data.log
# Tomcatのログ(Spring Bootのスタートアップログ)
sudo tail -50 /opt/tomcat/logs/catalina.out
# setenv.shの内容確認(DB接続情報が正しく設定されているか)
sudo cat /opt/tomcat/bin/setenv.sh
exit⑥ スタックの削除
課金を止めるために、ハンズオン完了後は必ず削除します。
スタックを削除する
aws cloudformation delete-stack ^
--stack-name my-webapp-stack ^
--region ap-northeast-1注意: RDS削除には約10〜15分かかります。
削除状況の確認
aws cloudformation describe-stacks ^
--stack-name my-webapp-stack ^
--query "Stacks[0].StackStatus" ^
--output text削除完了の確認(以下のエラーが表示されれば削除完了):
An error occurred (ValidationError) when calling the DescribeStacks operation:
Stack with id my-webapp-stack does not existS3バケットを削除する
S3バケットはCloudFormationで管理していないため手動で削除します。
aws s3 rm s3://my-webapp-bucket-(任意の識別子) --recursive
aws s3 rb s3://my-webapp-bucket-(任意の識別子)キーペアを削除する(任意)
EC2 → キーペア → my-webapp-key を選択 → 「アクション」→「削除」
コンソール版との比較
| 作業 | コンソール版 | CloudFormation版 |
|---|---|---|
| VPC + サブネット + IGW + RT | 約20〜30分 | template.yaml に定義済み |
| SG 3つの作成 | 3画面で個別設定 | template.yaml に定義済み |
| ALB + TG + Listener | 3つの画面で設定 | template.yaml に定義済み |
| WARのデプロイ | SCP + SSH操作 | S3 + UserDataで自動 |
| DB接続設定(setenv.sh) | SSH接続して手動作成 | UserDataがSSMから自動取得・作成 |
| 全体のデプロイ | 約60〜90分 | コマンド数本(RDS待ち15〜20分) |
| 削除 | 16ステップ手動 | delete-stack 1本(+S3手動削除) |
トラブルシューティング
| 症状 | 原因 | 対処 |
|---|---|---|
CREATE_FAILED → ROLLBACKになる | パラメータ不正・リソース上限など | コンソールのCloudFormationイベントタブでエラー詳細を確認 |
| ALBに繋がらない | WARデプロイがまだ完了していない | TGのヘルスチェックがHealthyになるまで待つ(5〜10分) |
| ヘルスチェックがUnhealthy | WAR取得失敗 or Spring Boot起動失敗 | SSH接続して sudo cat /var/log/user-data.log を確認 |
NoSuchKey エラー | S3にwebapp.warがない | aws s3 ls s3://バケット名/ で存在確認 |
| DB接続エラー(500エラー) | setenv.shのDB_HOSTが空 | sudo cat /opt/tomcat/bin/setenv.sh で確認 |
| Tomcatバージョンエラー | 指定バージョンがアーカイブに存在しない | https://archive.apache.org/dist/tomcat/tomcat-10/ で確認して TomcatVersion パラメータを更新 |
DELETE_FAILED | リソースの依存関係が残っている | コンソールからALBを手動削除してから delete-stack を再実行 |
失敗時の詳細確認コマンド
aws cloudformation describe-stack-events ^
--stack-name my-webapp-stack ^
--query "StackEvents[?ResourceStatus=='CREATE_FAILED'].[ResourceType,ResourceStatusReason]" ^
--output tableまとめ
| ステップ | 内容 |
|---|---|
| ⓪ | Mavenで webapp.war をビルド |
| ① | キーペアをコンソールで作成 |
| ② | S3バケット作成 + WARをアップロード |
| ③ | create-stack 1本(RDS待ち15〜20分) |
| ④ | CREATE_COMPLETE になったらOutputsでALBエンドポイント・EC2IP・RDSエンドポイントを確認 |
| ⑤ | ヘルスチェックがHealthyになったらブラウザでCRUD動作確認 |
| ⑥ | delete-stack 1本 + S3バケット手動削除 |
CloudFormation版の最大のポイントはWARデプロイの自動化です。コンソール版ではSCPでWARを転送してSSHでsetenv.shを作成する必要がありましたが、今回はS3にWARをアップロードするだけでUserDataが全て自動で行います。
コンソール操作でSCPデプロイの仕組みを手を動かして確認したい場合は、AWSコンソール版ハンズオンを参照してください。
コメント