<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>RDS - CayTech Lab</title>
	<atom:link href="https://caymezon.com/tag/rds/feed/" rel="self" type="application/rss+xml" />
	<link>https://caymezon.com</link>
	<description></description>
	<lastBuildDate>Sun, 12 Apr 2026 00:20:19 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://caymezon.com/wp-content/uploads/2026/01/cropped-CayTechLab-32x32.jpg</url>
	<title>RDS - CayTech Lab</title>
	<link>https://caymezon.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<atom:link rel='hub' href='https://caymezon.com/?pushpress=hub'/>
	<item>
		<title>AWSコンソールでRDS MySQL + EC2接続環境を構築する手順【DBサブネットグループ / Parameter Storeパスワード管理】</title>
		<link>https://caymezon.com/aws-handson-console-rds-mysql-ec2/</link>
					<comments>https://caymezon.com/aws-handson-console-rds-mysql-ec2/#respond</comments>
		
		<dc:creator><![CDATA[caymezon]]></dc:creator>
		<pubDate>Sat, 11 Apr 2026 23:47:54 +0000</pubDate>
				<category><![CDATA[AWS Basic]]></category>
		<category><![CDATA[Cloud & Infra]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWSコンソール]]></category>
		<category><![CDATA[DBサブネットグループ]]></category>
		<category><![CDATA[EC2]]></category>
		<category><![CDATA[IAM]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Parameter Store]]></category>
		<category><![CDATA[RDS]]></category>
		<category><![CDATA[SG参照]]></category>
		<category><![CDATA[SSM]]></category>
		<category><![CDATA[VPC]]></category>
		<category><![CDATA[セキュリティグループ]]></category>
		<category><![CDATA[ハンズオン]]></category>
		<category><![CDATA[マネージドサービス]]></category>
		<category><![CDATA[初心者]]></category>
		<guid isPermaLink="false">https://caymezon.com/?p=20338</guid>

					<description><![CDATA[<p>目次 はじめにキーワード解説前フェーズとの違い使用するAWSサービス構築するリソース一覧全体の作業順序【重要】⓪ 自分のIPアドレスを確認する① キーペアの作成② VPCの作成③ サブネットの作成（3つ）サブネット1:  [&#8230;]</p>
<p>The post <a href="https://caymezon.com/aws-handson-console-rds-mysql-ec2/">AWSコンソールでRDS MySQL + EC2接続環境を構築する手順【DBサブネットグループ / Parameter Storeパスワード管理】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-2" checked><label class="toc-title" for="toc-checkbox-2">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">キーワード解説</a></li><li><a href="#toc3" tabindex="0">前フェーズとの違い</a></li><li><a href="#toc4" tabindex="0">使用するAWSサービス</a></li><li><a href="#toc5" tabindex="0">構築するリソース一覧</a></li><li><a href="#toc6" tabindex="0">全体の作業順序</a></li><li><a href="#toc7" tabindex="0">【重要】⓪ 自分のIPアドレスを確認する</a></li><li><a href="#toc8" tabindex="0">① キーペアの作成</a></li><li><a href="#toc9" tabindex="0">② VPCの作成</a></li><li><a href="#toc10" tabindex="0">③ サブネットの作成（3つ）</a><ol><li><a href="#toc11" tabindex="0">サブネット1: パブリックサブネット（EC2用）</a></li><li><a href="#toc12" tabindex="0">サブネット2: プライベートサブネット1（RDS配置先）</a></li><li><a href="#toc13" tabindex="0">サブネット3: プライベートサブネット2（DBサブネットグループ用）</a></li></ol></li><li><a href="#toc14" tabindex="0">④ インターネットゲートウェイの作成・アタッチ</a><ol><li><a href="#toc15" tabindex="0">作成</a></li><li><a href="#toc16" tabindex="0">VPCへのアタッチ</a></li></ol></li><li><a href="#toc17" tabindex="0">⑤ ルートテーブルの設定</a><ol><li><a href="#toc18" tabindex="0">5-1. パブリック用ルートテーブルの作成</a></li><li><a href="#toc19" tabindex="0">5-2. プライベート用ルートテーブルの作成</a></li></ol></li><li><a href="#toc20" tabindex="0">⑥ セキュリティグループの作成</a><ol><li><a href="#toc21" tabindex="0">6-1. EC2用セキュリティグループ</a></li><li><a href="#toc22" tabindex="0">6-2. RDS用セキュリティグループ</a></li></ol></li><li><a href="#toc23" tabindex="0">⑦ IAMロールの作成</a><ol><li><a href="#toc24" tabindex="0">ステップ1</a></li><li><a href="#toc25" tabindex="0">ステップ2: ポリシーのアタッチ</a></li><li><a href="#toc26" tabindex="0">ステップ3</a></li></ol></li><li><a href="#toc27" tabindex="0">⑧ SSM Parameter Store にDBパスワードを登録する</a></li><li><a href="#toc28" tabindex="0">⑨ RDS DBサブネットグループの作成</a></li><li><a href="#toc29" tabindex="0">⑩ RDS MySQL インスタンスの作成</a><ol><li><a href="#toc30" tabindex="0">エンジンの選択</a></li><li><a href="#toc31" tabindex="0">テンプレート</a></li><li><a href="#toc32" tabindex="0">設定</a></li><li><a href="#toc33" tabindex="0">インスタンスの設定</a></li><li><a href="#toc34" tabindex="0">ストレージ</a></li><li><a href="#toc35" tabindex="0">接続</a></li><li><a href="#toc36" tabindex="0">追加設定</a></li></ol></li><li><a href="#toc37" tabindex="0">⑪ EC2インスタンスの起動</a><ol><li><a href="#toc38" tabindex="0">基本設定</a></li><li><a href="#toc39" tabindex="0">ネットワーク設定</a></li><li><a href="#toc40" tabindex="0">IAMロール</a></li><li><a href="#toc41" tabindex="0">UserData</a></li><li><a href="#toc42" tabindex="0">タグ</a></li></ol></li><li><a href="#toc43" tabindex="0">⑫ 動作確認</a><ol><li><a href="#toc44" tabindex="0">12-1. WebブラウザでEC2のWebサーバ確認</a></li><li><a href="#toc45" tabindex="0">12-2. EC2にSSH接続する</a></li><li><a href="#toc46" tabindex="0">12-3. Parameter StoreからDBパスワードを取得する</a></li><li><a href="#toc47" tabindex="0">12-4. RDSへのMySQL接続テスト</a></li><li><a href="#toc48" tabindex="0">12-5. RDS上でSQL操作を確認する</a></li><li><a href="#toc49" tabindex="0">12-6. EC2からSSH接続を切断する</a></li></ol></li><li><a href="#toc50" tabindex="0">⑬ リソースの削除</a><ol><li><a href="#toc51" tabindex="0">削除順序</a></li><li><a href="#toc52" tabindex="0">1. EC2インスタンスを終了する</a></li><li><a href="#toc53" tabindex="0">2. RDSインスタンスを削除する</a></li><li><a href="#toc54" tabindex="0">3. RDS DBサブネットグループを削除する</a></li><li><a href="#toc55" tabindex="0">4. SSM Parameter Storeのパラメータを削除する</a></li><li><a href="#toc56" tabindex="0">5. セキュリティグループを削除する</a></li><li><a href="#toc57" tabindex="0">6. ルートテーブルを削除する</a></li><li><a href="#toc58" tabindex="0">7. インターネットゲートウェイをデタッチ・削除する</a></li><li><a href="#toc59" tabindex="0">8. サブネットを削除する（3つ）</a></li><li><a href="#toc60" tabindex="0">9. VPCを削除する</a></li><li><a href="#toc61" tabindex="0">10. IAMロールを削除する</a></li><li><a href="#toc62" tabindex="0">11. キーペアを削除する（任意）</a></li></ol></li><li><a href="#toc63" tabindex="0">まとめ</a></li></ol>
    </div>
  </div>

<h2><span id="toc1">はじめに</span></h2>
<p>「EC2にMariaDBをインストールしてDBサーバを自分で管理するのは大変……」——その悩みを解決するのが <strong>Amazon RDS（マネージド型データベースサービス）</strong> です。</p>
<p>この記事では、<strong>AWSコンソール（GUI）のみ</strong>を使って、RDS MySQL 8.0インスタンスとEC2（APサーバ）をゼロから構築し、EC2からRDSへMySQL接続を確認するハンズオンを紹介します。</p>
<pre><code class="language-plaintext">インターネット
  ↓ HTTP(80) / SSH(22)  ← 自分のIPのみ
インターネットゲートウェイ（my-rds-igw）
  ↓
[VPC: 10.0.0.0/16]
  ├── パブリックサブネット（10.0.1.0/24）[AZ-a]
  │     └── EC2 APサーバ（Apache + mariadb client）
  │           └── IAMロール → SSM Parameter Store からパスワード取得
  │                     ↓ MySQL:3306（SG-to-SG制御）
  ├── DBサブネットグループ
  │     ├── プライベートサブネット1（10.0.2.0/24）[AZ-a]  ← RDS配置
  │     │     └── RDS MySQL 8.0（db.t3.micro）
  │     └── プライベートサブネット2（10.0.3.0/24）[AZ-c]  ← 2AZ要件用
  └── SSM Parameter Store: /my/rds/db-password</code></pre>
<p><strong>このハンズオンで体験できること：</strong></p>
<ul>
<li>EC2にDBをインストールする方式との違いを体感</li>
<li>RDS DBサブネットグループが「2AZ以上必須」な理由を理解</li>
<li>SSM Parameter Storeでパスワードをコードに書かずに安全に管理する方法</li>
<li>SG-to-SG制御でRDSをEC2からのみ許可する設計</li>
</ul>
<p><strong>このハンズオンのポイント：</strong></p>
<p>前フェーズ（EC2 + MariaDB）では自分でDBを管理していましたが、今回はAWSがOSのメンテナンス・パッチ・バックアップを自動管理するRDSに置き換えます。ネットワーク設計はカスタムVPC（3サブネット）で実際の本番環境に近い構成になります。</p>
<hr>
<blockquote>
<p><strong>この記事は <a href="https://caymezon.com/aws-handson-cloudformation-rds-mysql-ec2/">CloudFormation版ハンズオン</a> の比較記事です。</strong><br />コンソール操作でRDS・DBサブネットグループ・Parameter Storeを視覚的に学びたい方向けです。</p>
</blockquote>
<hr>
<p><!-- ![ハンズオン完成後のRDS接続確認画面](images/rds-mysql-ec2-top.jpg) --></p>
<p><!-- <a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"> --></p>
<p><!-- <!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51DEDQXj6oL._SL500_.jpg","\/41F589smNwL._SL500_.jpg","\/41R6f9yyCWL._SL500_.jpg","\/41HqWQ9BvmL._SL500_.jpg","\/41p8p0ZU79L._SL500_.jpg","\/41qLC-fndBL._SL500_.jpg","\/41fcLv9VT5L._SL500_.jpg","\/51lRvCsvHqL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815607850","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815607850","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"eaCUB","s":"s"});</script></p>
<div id="msmaflink-eaCUB">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --> --></p>
<h2><span id="toc2">キーワード解説</span></h2>
<table>
<thead>
<tr>
<th>用語</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Amazon RDS</strong></td>
<td>AWSが提供するマネージド型のリレーショナルDBサービス。EC2へのインストールと違い、OSのメンテナンス・パッチ・バックアップをAWSが自動管理する</td>
</tr>
<tr>
<td><strong>DBサブネットグループ</strong></td>
<td>RDSを配置できるサブネットを登録した論理グループ。2つ以上の異なるAZのサブネットが必須</td>
</tr>
<tr>
<td><strong>SSM Parameter Store</strong></td>
<td>設定値・シークレットをコードに書かずに保管・取得できるサービス。SecureString型でKMS暗号化して保管できる</td>
</tr>
<tr>
<td><strong>SG-to-SG制御</strong></td>
<td>セキュリティグループのルールで、アクセス元のIPアドレスではなく別のSGを指定する設定。EC2 SGに所属するインスタンスのみRDSへの接続を許可できる</td>
</tr>
<tr>
<td><strong>エンドポイント</strong></td>
<td>RDSに接続するためのホスト名。EC2からはこのホスト名を使ってMySQLとして接続する</td>
</tr>
<tr>
<td><strong>SecureString</strong></td>
<td>Parameter StoreでKMS暗号化して保管するタイプ。パスワードやAPIキーなどの機密情報に使用する</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc3">前フェーズとの違い</span></h2>
<table>
<thead>
<tr>
<th>比較項目</th>
<th>（EC2 + MariaDB）</th>
<th>（RDS MySQL）今回</th>
</tr>
</thead>
<tbody>
<tr>
<td>DBエンジン</td>
<td>MariaDB（EC2上で動作）</td>
<td><strong>MySQL 8.0（RDSマネージドサービス）</strong></td>
</tr>
<tr>
<td>DB管理</td>
<td>OS込みで自分で管理</td>
<td><strong>AWSがパッチ・バックアップを自動管理</strong></td>
</tr>
<tr>
<td>サブネット構成</td>
<td>デフォルトVPC（単一AZ）</td>
<td><strong>カスタムVPC（3サブネット・2AZ）</strong></td>
</tr>
<tr>
<td>パスワード管理</td>
<td>ハードコード</td>
<td><strong>SSM Parameter Store</strong></td>
</tr>
<tr>
<td>削除</td>
<td>EC2終了のみ</td>
<td><strong>RDS削除に10〜15分必要</strong></td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc4">使用するAWSサービス</span></h2>
<table>
<thead>
<tr>
<th>サービス</th>
<th>役割</th>
<th>料金</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>VPC</strong></td>
<td>カスタムネットワーク空間</td>
<td>無料</td>
</tr>
<tr>
<td><strong>EC2</strong>（t2.micro）</td>
<td>APサーバ（Apache + mariadb client）</td>
<td>月750時間まで無料枠あり</td>
</tr>
<tr>
<td><strong>RDS MySQL</strong>（db.t3.micro）</td>
<td>マネージドDBサーバ</td>
<td>月750時間まで無料枠あり</td>
</tr>
<tr>
<td><strong>SSM Parameter Store</strong></td>
<td>DBパスワードの安全な保管</td>
<td>スタンダード層は無料</td>
</tr>
<tr>
<td><strong>IAM</strong></td>
<td>EC2にSSM・Parameter Store権限を付与</td>
<td>無料</td>
</tr>
<tr>
<td><strong>S3 VPC Gateway Endpoint</strong></td>
<td>プライベートサブネットからS3へのアクセス</td>
<td><strong>無料</strong></td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>注意</strong>: RDSを稼働させたままにすると課金されます。ハンズオン後は必ず削除してください。</p>
</blockquote>
<hr>
<h2><span id="toc5">構築するリソース一覧</span></h2>
<table>
<thead>
<tr>
<th>順序</th>
<th>リソース</th>
<th>役割</th>
</tr>
</thead>
<tbody>
<tr>
<td>⓪</td>
<td>（確認）自分のIPアドレス</td>
<td>SGの設定に使用</td>
</tr>
<tr>
<td>①</td>
<td>キーペア（<code>my-rds-mysql-key</code>）</td>
<td>EC2へのSSH認証鍵</td>
</tr>
<tr>
<td>②</td>
<td>VPC（<code>my-rds-vpc</code>）</td>
<td>独立したネットワーク空間</td>
</tr>
<tr>
<td>③</td>
<td>サブネット × 3</td>
<td>パブリック1 + プライベート2</td>
</tr>
<tr>
<td>④</td>
<td>インターネットゲートウェイ（<code>my-rds-igw</code>）</td>
<td>VPCをインターネットに接続</td>
</tr>
<tr>
<td>⑤</td>
<td>ルートテーブル × 2</td>
<td>パブリック/プライベートの通信経路</td>
</tr>
<tr>
<td>⑥</td>
<td>セキュリティグループ × 2</td>
<td>EC2用SG・RDS用SG</td>
</tr>
<tr>
<td>⑦</td>
<td>IAMロール（<code>my-rds-ec2-role</code>）</td>
<td>EC2がSSM・Parameter Storeを使う権限</td>
</tr>
<tr>
<td>⑧</td>
<td>SSM Parameter Store</td>
<td>DBパスワードの保管</td>
</tr>
<tr>
<td>⑨</td>
<td>RDS DBサブネットグループ</td>
<td>RDSを配置できるサブネットを登録</td>
</tr>
<tr>
<td>⑩</td>
<td>RDS MySQL インスタンス</td>
<td>マネージドDBサーバ（作成に10〜15分）</td>
</tr>
<tr>
<td>⑪</td>
<td>EC2インスタンス（<code>my-rds-ap-instance</code>）</td>
<td>APサーバ</td>
</tr>
<tr>
<td>⑫</td>
<td>動作確認</td>
<td>EC2→RDSへのMySQL接続テスト</td>
</tr>
<tr>
<td>⑬</td>
<td>リソース削除</td>
<td>課金停止</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc6">全体の作業順序</span></h2>
<pre><code class="language-plaintext">⓪ IPアドレス確認
      ↓
① キーペア作成
      ↓
② VPC作成
      ↓
③ サブネット作成（パブリック1 + プライベート2）
      ↓
④ インターネットゲートウェイ作成・アタッチ
      ↓
⑤ ルートテーブル設定
      ↓
⑥ セキュリティグループ作成（EC2用 → RDS用）
      ↓
⑦ IAMロール作成
      ↓
⑧ SSM Parameter Store にパスワードを登録
      ↓
⑨ RDS DBサブネットグループ作成
      ↓
⑩ RDS MySQL インスタンス作成（※約10〜15分かかる）
      ↓
⑪ EC2インスタンス起動
      ↓
⑫ 動作確認（EC2 → RDS接続）
      ↓
⑬ リソース削除</code></pre>
<hr>
<h2><span id="toc7">【重要】⓪ 自分のIPアドレスを確認する</span></h2>
<pre><code class="language-cmd">curl https://checkip.amazonaws.com</code></pre>
<p>またはブラウザで <code>https://checkip.amazonaws.com</code> にアクセスして確認します。</p>
<p><strong>控えておく情報</strong>: 自分のIPアドレス（例: <code>203.0.113.1</code>）</p>
<blockquote>
<p>セキュリティグループで <code>203.0.113.1/32</code> の形式（末尾に <code>/32</code>）で使用します。</p>
</blockquote>
<hr>
<h2><span id="toc8">① キーペアの作成</span></h2>
<p><strong>AWSコンソール → EC2 → ネットワーク＆セキュリティ → キーペア → 「キーペアを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>名前</td>
<td><code>my-rds-mysql-key</code></td>
</tr>
<tr>
<td>キーペアのタイプ</td>
<td><strong>RSA</strong></td>
</tr>
<tr>
<td>プライベートキーファイル形式</td>
<td><strong>.pem</strong></td>
</tr>
</tbody>
</table>
<p>「キーペアを作成」をクリックすると <code>my-rds-mysql-key.pem</code> がダウンロードされます。</p>
<pre><code class="language-plaintext">C:\Users\ユーザー名\.ssh\my-rds-mysql-key.pem</code></pre>
<hr>
<h2><span id="toc9">② VPCの作成</span></h2>
<p><strong>AWSコンソール → VPC → お使いのVPC → 「VPCを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>作成するリソース</td>
<td><strong>VPCのみ</strong></td>
</tr>
<tr>
<td>名前タグ</td>
<td><code>my-rds-vpc</code></td>
</tr>
<tr>
<td>IPv4 CIDR</td>
<td><code>10.0.0.0/16</code></td>
</tr>
</tbody>
</table>
<p>「VPCを作成」をクリック。</p>
<blockquote>
<p><strong>VPCとは</strong>: AWS内に作る仮想的なプライベートネットワーク。<code>10.0.0.0/16</code> は「10.0.0.0〜10.0.255.255」の65,536個のIPアドレスを使える範囲です。</p>
</blockquote>
<p><!-- ![VPC作成画面](images/vpc-create.jpg) --></p>
<hr>
<h2><span id="toc10">③ サブネットの作成（3つ）</span></h2>
<p><strong>AWSコンソール → VPC → サブネット → 「サブネットを作成」</strong></p>
<p>「VPC ID」に <code>my-rds-vpc</code> を選択してから、以下の3つを作成します。</p>
<blockquote>
<p>「新しいサブネットを追加」ボタンで複数まとめて作成できます。</p>
</blockquote>
<h3><span id="toc11">サブネット1: パブリックサブネット（EC2用）</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>サブネット名</td>
<td><code>my-public-subnet</code></td>
</tr>
<tr>
<td>アベイラビリティーゾーン</td>
<td><code>ap-northeast-1a</code></td>
</tr>
<tr>
<td>IPv4 CIDR</td>
<td><code>10.0.1.0/24</code></td>
</tr>
</tbody>
</table>
<h3><span id="toc12">サブネット2: プライベートサブネット1（RDS配置先）</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>サブネット名</td>
<td><code>my-private-subnet-1</code></td>
</tr>
<tr>
<td>アベイラビリティーゾーン</td>
<td><code>ap-northeast-1a</code></td>
</tr>
<tr>
<td>IPv4 CIDR</td>
<td><code>10.0.2.0/24</code></td>
</tr>
</tbody>
</table>
<h3><span id="toc13">サブネット3: プライベートサブネット2（DBサブネットグループ用）</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>サブネット名</td>
<td><code>my-private-subnet-2</code></td>
</tr>
<tr>
<td>アベイラビリティーゾーン</td>
<td><code>ap-northeast-1c</code></td>
</tr>
<tr>
<td>IPv4 CIDR</td>
<td><code>10.0.3.0/24</code></td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>なぜプライベートサブネットが2つ必要か</strong>: RDS DBサブネットグループは「2つ以上の異なるAZ」にあるサブネットを登録する必要があります。RDSインスタンス自体はAZ-aの <code>private-subnet-1</code> に置きますが、グループ定義にはAZ-cの <code>private-subnet-2</code> も必要です。これはRDSのMulti-AZフェイルオーバーに備えた仕様です。</p>
</blockquote>
<p>「サブネットを作成」をクリック。</p>
<p><!-- ![サブネット3つの作成画面](images/subnet-create.jpg) --></p>
<hr>
<h2><span id="toc14">④ インターネットゲートウェイの作成・アタッチ</span></h2>
<h3><span id="toc15">作成</span></h3>
<p><strong>AWSコンソール → VPC → インターネットゲートウェイ → 「インターネットゲートウェイを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>名前タグ</td>
<td><code>my-rds-igw</code></td>
</tr>
</tbody>
</table>
<p>「インターネットゲートウェイを作成」をクリック。</p>
<h3><span id="toc16">VPCへのアタッチ</span></h3>
<p>作成したIGWを選択 → 「アクション」→「VPCにアタッチ」→ <code>my-rds-vpc</code> を選択 → 「インターネットゲートウェイのアタッチ」</p>
<p>ステータスが <strong>「Attached」</strong> になることを確認します。</p>
<hr>
<h2><span id="toc17">⑤ ルートテーブルの設定</span></h2>
<h3><span id="toc18">5-1. パブリック用ルートテーブルの作成</span></h3>
<p><strong>AWSコンソール → VPC → ルートテーブル → 「ルートテーブルを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>名前</td>
<td><code>my-public-rt</code></td>
</tr>
<tr>
<td>VPC</td>
<td><code>my-rds-vpc</code></td>
</tr>
</tbody>
</table>
<p>作成後、<code>my-public-rt</code> を選択 → 「ルート」タブ → 「ルートを編集」→「ルートを追加」</p>
<table>
<thead>
<tr>
<th>送信先</th>
<th>ターゲット</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>0.0.0.0/0</code></td>
<td>インターネットゲートウェイ <code>my-rds-igw</code></td>
</tr>
</tbody>
</table>
<p>「変更を保存」をクリック。</p>
<p>次に「サブネットの関連付け」タブ → 「サブネットの関連付けを編集」→ <code>my-public-subnet</code> にチェック → 「関連付けを保存」</p>
<h3><span id="toc19">5-2. プライベート用ルートテーブルの作成</span></h3>
<p>同様に「ルートテーブルを作成」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>名前</td>
<td><code>my-private-rt</code></td>
</tr>
<tr>
<td>VPC</td>
<td><code>my-rds-vpc</code></td>
</tr>
</tbody>
</table>
<p>「サブネットの関連付けを編集」→ <code>my-private-subnet-1</code> と <code>my-private-subnet-2</code> の両方にチェック → 「関連付けを保存」</p>
<blockquote>
<p>プライベートルートテーブルにはインターネットへのルートを追加しません。RDSはインターネットに出る必要がないため、VPC内のローカル通信のみで十分です。</p>
</blockquote>
<hr>
<h2><span id="toc20">⑥ セキュリティグループの作成</span></h2>
<h3><span id="toc21">6-1. EC2用セキュリティグループ</span></h3>
<p><strong>AWSコンソール → EC2 → セキュリティグループ → 「セキュリティグループを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>セキュリティグループ名</td>
<td><code>my-rds-ec2-sg</code></td>
</tr>
<tr>
<td>説明</td>
<td><code>EC2 AP server SG for RDS hands-on</code></td>
</tr>
<tr>
<td>VPC</td>
<td><code>my-rds-vpc</code></td>
</tr>
</tbody>
</table>
<p><strong>インバウンドルール:</strong></p>
<table>
<thead>
<tr>
<th>タイプ</th>
<th>プロトコル</th>
<th>ポート</th>
<th>ソース</th>
</tr>
</thead>
<tbody>
<tr>
<td>SSH</td>
<td>TCP</td>
<td>22</td>
<td><code>自分のIP/32</code></td>
</tr>
<tr>
<td>HTTP</td>
<td>TCP</td>
<td>80</td>
<td><code>自分のIP/32</code></td>
</tr>
</tbody>
</table>
<p><strong>アウトバウンドルール:</strong></p>
<table>
<thead>
<tr>
<th>タイプ</th>
<th>送信先</th>
</tr>
</thead>
<tbody>
<tr>
<td>すべてのトラフィック</td>
<td><code>0.0.0.0/0</code></td>
</tr>
</tbody>
</table>
<p>「セキュリティグループを作成」をクリック。</p>
<h3><span id="toc22">6-2. RDS用セキュリティグループ</span></h3>
<p>同様に「セキュリティグループを作成」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>セキュリティグループ名</td>
<td><code>my-rds-sg</code></td>
</tr>
<tr>
<td>説明</td>
<td><code>RDS MySQL SG - EC2 only</code></td>
</tr>
<tr>
<td>VPC</td>
<td><code>my-rds-vpc</code></td>
</tr>
</tbody>
</table>
<p><strong>インバウンドルール:</strong></p>
<table>
<thead>
<tr>
<th>タイプ</th>
<th>プロトコル</th>
<th>ポート</th>
<th>ソース</th>
</tr>
</thead>
<tbody>
<tr>
<td>MYSQL/Aurora</td>
<td>TCP</td>
<td>3306</td>
<td><strong><code>my-rds-ec2-sg</code> のSG-ID</strong>（SGを選択）</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>ポイント（SG-to-SG制御）</strong>: ソースにIPアドレスではなく<strong>セキュリティグループ</strong>を指定します。<code>my-rds-ec2-sg</code> に所属するEC2インスタンスからの通信のみ許可でき、インターネットからのアクセスを完全に遮断できます。</p>
</blockquote>
<p>「セキュリティグループを作成」をクリック。</p>
<p><!-- ![RDS用SGのインバウンドルール設定画面（SG-to-SG）](images/rds-sg-create.jpg) --></p>
<hr>
<h2><span id="toc23">⑦ IAMロールの作成</span></h2>
<p><strong>AWSコンソール → IAM → ロール → 「ロールを作成」</strong></p>
<h3><span id="toc24">ステップ1</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>信頼されたエンティティタイプ</td>
<td><strong>AWSのサービス</strong></td>
</tr>
<tr>
<td>ユースケース</td>
<td><strong>EC2</strong></td>
</tr>
</tbody>
</table>
<h3><span id="toc25">ステップ2: ポリシーのアタッチ</span></h3>
<p>以下の2つを検索してチェックを入れます。</p>
<table>
<thead>
<tr>
<th>ポリシー名</th>
<th>用途</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>AmazonSSMManagedInstanceCore</code></td>
<td>Session Manager接続用</td>
</tr>
<tr>
<td><code>AmazonSSMReadOnlyAccess</code></td>
<td>Parameter Storeからパスワードを読み取る</td>
</tr>
</tbody>
</table>
<h3><span id="toc26">ステップ3</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ロール名</td>
<td><code>my-rds-ec2-role</code></td>
</tr>
</tbody>
</table>
<p>タグを追加: <code>Cost</code> = <code>123456</code></p>
<p>「ロールを作成」をクリック。</p>
<hr>
<h2><span id="toc27">⑧ SSM Parameter Store にDBパスワードを登録する</span></h2>
<p>Parameter Storeは、DBパスワードなどの設定値をコードに書かずに安全に管理するサービスです。EC2上のアプリケーションは実行時にParameter Storeから値を取得して使用します。</p>
<p><strong>AWSコンソール → Systems Manager → パラメータストア → 「パラメータの作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>名前</td>
<td><code>/my/rds/db-password</code></td>
</tr>
<tr>
<td>説明</td>
<td><code>RDS MySQL master password for my hands-on</code></td>
</tr>
<tr>
<td>層</td>
<td><strong>スタンダード</strong></td>
</tr>
<tr>
<td>タイプ</td>
<td><strong>SecureString</strong></td>
</tr>
<tr>
<td>KMS キーID</td>
<td><code>alias/aws/ssm</code>（デフォルト）</td>
</tr>
<tr>
<td>値</td>
<td><code>Handson1234!</code></td>
</tr>
</tbody>
</table>
<p>「パラメータの作成」をクリック。</p>
<blockquote>
<p><strong>SecureStringとは</strong>: KMSで暗号化して保管するタイプです。通常の String と違い、値を取得する際に適切なIAM権限が必要です。パスワードやAPIキーなどの機密情報はSecureStringを使いましょう。</p>
</blockquote>
<p><!-- ![Parameter Store SecureString設定画面](images/parameter-store-create.jpg) --></p>
<hr>
<h2><span id="toc28">⑨ RDS DBサブネットグループの作成</span></h2>
<p><strong>AWSコンソール → Aurora and RDS → サブネットグループ → 「DBサブネットグループを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>名前</td>
<td><code>my-rds-subnet-group</code></td>
</tr>
<tr>
<td>説明</td>
<td><code>my RDS subnet group (private subnets in 2 AZs)</code></td>
</tr>
<tr>
<td>VPC</td>
<td><code>my-rds-vpc</code></td>
</tr>
</tbody>
</table>
<p><strong>サブネットの追加:</strong></p>
<table>
<thead>
<tr>
<th>アベイラビリティーゾーン</th>
<th>サブネット</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>ap-northeast-1a</code></td>
<td><code>my-private-subnet-1</code></td>
</tr>
<tr>
<td><code>ap-northeast-1c</code></td>
<td><code>my-private-subnet-2</code></td>
</tr>
</tbody>
</table>
<p>「作成」をクリック。</p>
<blockquote>
<p><strong>DBサブネットグループとは</strong>: RDSインスタンスを配置できるサブネットを登録した論理グループです。RDSはこのグループ内のサブネットにインスタンスを配置します。最低2つの異なるAZのサブネットが必要な理由は、RDSがMulti-AZフェイルオーバーに対応するための仕様です。</p>
</blockquote>
<hr>
<h2><span id="toc29">⑩ RDS MySQL インスタンスの作成</span></h2>
<p><strong>AWSコンソール → Aurora and RDS → データベース → 「データベースの作成 ▲」→「フル設定」</strong></p>
<blockquote>
<p><strong>UIの変更について（2025年以降）</strong>: サービス名が <strong>「RDS」→「Aurora and RDS」</strong> に変更されました。「データベースの作成」ボタンはドロップダウン式になっており、以下の3つが表示されます。</p>
<table>
<thead>
<tr>
<th>選択肢</th>
<th>用途</th>
</tr>
</thead>
<tbody>
<tr>
<td>エクスプレス設定</td>
<td>簡易設定（詳細設定不可）</td>
</tr>
<tr>
<td><strong>フル設定</strong></td>
<td><strong>← これを選ぶ</strong>（VPC・SGなどを細かく指定できる）</td>
</tr>
<tr>
<td>S3から復元</td>
<td>バックアップからの復元</td>
</tr>
</tbody>
</table>
<p>VPC・サブネットグループ・SGなどを細かく指定するため、<strong>必ず「フル設定」を選択します。</strong></p>
</blockquote>
<blockquote>
<p><strong>注意</strong>: RDSの作成は<strong>約10〜15分</strong>かかります。</p>
</blockquote>
<p><!-- ![「データベースの作成 ▲」→「フル設定」の選択画面](images/rds-create-fullsetting.jpg) --></p>
<h3><span id="toc30">エンジンの選択</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>エンジンのタイプ</td>
<td><strong>MySQL</strong></td>
</tr>
<tr>
<td>エンジンバージョン</td>
<td><strong>MySQL 8.0.x</strong>（最新）</td>
</tr>
</tbody>
</table>
<h3><span id="toc31">テンプレート</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>テンプレート</td>
<td><strong>無料利用枠</strong></td>
</tr>
</tbody>
</table>
<blockquote>
<p>「無料利用枠」を選択すると、スペックが自動的に無料枠対象の設定に制限されます。</p>
</blockquote>
<h3><span id="toc32">設定</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>DBインスタンス識別子</td>
<td><code>my-rds-mysql</code></td>
</tr>
<tr>
<td>マスターユーザー名</td>
<td><code>admin</code></td>
</tr>
<tr>
<td>マスターパスワード</td>
<td><code>Handson1234!</code></td>
</tr>
<tr>
<td>パスワードの確認</td>
<td><code>Handson1234!</code></td>
</tr>
</tbody>
</table>
<h3><span id="toc33">インスタンスの設定</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>DBインスタンスクラス</td>
<td><strong>db.t3.micro</strong>（無料枠）</td>
</tr>
</tbody>
</table>
<h3><span id="toc34">ストレージ</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>ストレージタイプ</td>
<td><strong>汎用SSD (gp2)</strong></td>
</tr>
<tr>
<td>割り当てられたストレージ</td>
<td><code>20</code> GiB</td>
</tr>
<tr>
<td>ストレージの自動スケーリング</td>
<td>チェックを<strong>外す</strong></td>
</tr>
</tbody>
</table>
<h3><span id="toc35">接続</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>コンピューティングリソース</td>
<td><strong>EC2コンピューティングリソースに接続しない</strong></td>
</tr>
<tr>
<td>VPC</td>
<td><code>my-rds-vpc</code></td>
</tr>
<tr>
<td>DBサブネットグループ</td>
<td><code>my-rds-subnet-group</code></td>
</tr>
<tr>
<td>パブリックアクセス</td>
<td><strong>なし</strong></td>
</tr>
<tr>
<td>VPCセキュリティグループ</td>
<td><strong>既存の選択</strong> → <code>my-rds-sg</code> を選択（<code>default</code> は削除）</td>
</tr>
<tr>
<td>アベイラビリティーゾーン</td>
<td><code>ap-northeast-1a</code></td>
</tr>
</tbody>
</table>
<h3><span id="toc36">追加設定</span></h3>
<p>「追加設定」を開きます。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>最初のデータベース名</td>
<td><code>sampledb</code></td>
</tr>
<tr>
<td>自動バックアップを有効にする</td>
<td>チェックを<strong>外す</strong></td>
</tr>
</tbody>
</table>
<blockquote>
<p>自動バックアップを無効にすることで、ハンズオン後の削除がよりスムーズになります。</p>
</blockquote>
<p>「データベースの作成」をクリック。</p>
<p><strong>控えておく情報</strong>: 作成完了後に表示される「エンドポイント」のホスト名</p>
<pre><code class="language-plaintext">my-rds-mysql.xxxxxxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com</code></pre>
<blockquote>
<p><strong>エンドポイントとは</strong>: RDSに接続するためのホスト名です。IPアドレスが変わっても同じホスト名で接続できます。</p>
</blockquote>
<p><!-- ![RDSインスタンス詳細画面のエンドポイント確認](images/rds-endpoint.jpg) --></p>
<hr>
<h2><span id="toc37">⑪ EC2インスタンスの起動</span></h2>
<blockquote>
<p><strong>注意</strong>: EC2を起動する前に⑤のルートテーブル設定（IGWルートの追加とサブネット関連付け）が完了していることを確認してください。UserDataはEC2起動時に一度だけ実行されるため、IGWルートがない状態で起動すると <code>dnf install</code> がインターネットに到達できずApacheのインストールが失敗します。</p>
</blockquote>
<p><strong>AWSコンソール → EC2 → インスタンス → 「インスタンスを起動」</strong></p>
<h3><span id="toc38">基本設定</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>名前</td>
<td><code>my-rds-ap-instance</code></td>
</tr>
<tr>
<td>AMI</td>
<td><strong>Amazon Linux 2023 AMI</strong></td>
</tr>
<tr>
<td>インスタンスタイプ</td>
<td><strong>t2.micro</strong></td>
</tr>
<tr>
<td>キーペア</td>
<td><code>my-rds-mysql-key</code></td>
</tr>
</tbody>
</table>
<h3><span id="toc39">ネットワーク設定</span></h3>
<p>「編集」をクリックして以下を設定します。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>VPC</td>
<td><code>my-rds-vpc</code></td>
</tr>
<tr>
<td>サブネット</td>
<td><code>my-public-subnet</code></td>
</tr>
<tr>
<td>パブリックIPの自動割り当て</td>
<td><strong>有効化</strong></td>
</tr>
<tr>
<td>ファイアウォール（セキュリティグループ）</td>
<td><strong>既存のセキュリティグループを選択</strong></td>
</tr>
<tr>
<td>セキュリティグループ</td>
<td><code>my-rds-ec2-sg</code></td>
</tr>
</tbody>
</table>
<h3><span id="toc40">IAMロール</span></h3>
<p>「高度な詳細」→「IAMインスタンスプロファイル」→ <code>my-rds-ec2-role</code> を選択</p>
<h3><span id="toc41">UserData</span></h3>
<p>「高度な詳細」→「ユーザーデータ」に以下を貼り付けます。</p>
<pre><code class="language-bash">#!/bin/bash
dnf update -y
dnf install -y httpd mariadb105
systemctl start httpd
systemctl enable httpd
echo "&lt;h1&gt;AP Server - RDS MySQL Hands-on&lt;/h1&gt;" &gt; /var/www/html/index.html
echo "&lt;p&gt;This server connects to RDS MySQL in the private subnet.&lt;/p&gt;" &gt;&gt; /var/www/html/index.html</code></pre>
<h3><span id="toc42">タグ</span></h3>
<table>
<thead>
<tr>
<th>キー</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Cost</code></td>
<td><code>123456</code></td>
</tr>
</tbody>
</table>
<p>「インスタンスを起動」をクリック。起動完了まで約2〜3分待ちます。</p>
<p><strong>控えておく情報</strong>: インスタンスのパブリックIPアドレス</p>
<hr>
<h2><span id="toc43">⑫ 動作確認</span></h2>
<h3><span id="toc44">12-1. WebブラウザでEC2のWebサーバ確認</span></h3>
<p>ブラウザで以下のURLにアクセスします。</p>
<pre><code class="language-plaintext">http://（EC2のパブリックIPアドレス）</code></pre>
<p>「AP Server - RDS MySQL Hands-on」と表示されればEC2は正常に動作しています。</p>
<blockquote>
<p><strong>接続できない場合のチェックポイント:</strong></p>
<ol>
<li>EC2起動後2〜3分以上待ってから再試行（UserDataの実行に時間がかかります）</li>
<li><code>https://checkip.amazonaws.com</code> で現在のIPを確認し、EC2のSGのHTTP許可IPと一致しているか確認</li>
<li>SSHでEC2に入り <code>sudo systemctl status httpd</code> でApacheの状態を確認</li>
</ol>
</blockquote>
<h3><span id="toc45">12-2. EC2にSSH接続する</span></h3>
<pre><code class="language-cmd">ssh -i C:\Users\ユーザー名\.ssh\my-rds-mysql-key.pem ec2-user@（EC2のパブリックIPアドレス）</code></pre>
<h3><span id="toc46">12-3. Parameter StoreからDBパスワードを取得する</span></h3>
<p>EC2にSSH接続した状態で以下を実行します。</p>
<pre><code class="language-bash">aws ssm get-parameter \
  --name "/my/rds/db-password" \
  --query "Parameter.Value" \
  --output text \
  --region ap-northeast-1 \
  --with-decryption</code></pre>
<p><code>Handson1234!</code> と表示されればParameter Storeからの取得成功です。</p>
<blockquote>
<p><strong><code>--with-decryption</code> について</strong>: SecureString型のパラメータを取得するときに必要なフラグです。このフラグがないと暗号化されたまま（base64のような長い文字列）返ってきます。</p>
</blockquote>
<blockquote>
<p>これがParameter Storeの活用方法：パスワードをコードに書かず、実行時にIAMロール経由で取得します。</p>
</blockquote>
<h3><span id="toc47">12-4. RDSへのMySQL接続テスト</span></h3>
<p>⑩で控えておいたRDSエンドポイントを使って接続します。</p>
<pre><code class="language-bash">RDS_ENDPOINT="my-rds-mysql.xxxxxxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com"

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

# RDSに接続
mysql -h $RDS_ENDPOINT -u admin -p"$DB_PASSWORD" sampledb</code></pre>
<p>接続に成功するとMySQLのプロンプトが表示されます。</p>
<pre><code class="language-plaintext">Welcome to the MariaDB monitor.  Commands end with ; or \g.
...
MySQL [sampledb]&gt;</code></pre>
<p><!-- ![EC2からRDS MySQLへの接続成功画面](images/rds-mysql-connect.jpg) --></p>
<h3><span id="toc48">12-5. RDS上でSQL操作を確認する</span></h3>
<pre><code class="language-sql">-- テーブル作成
CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- データ挿入
INSERT INTO users (name) VALUES ('Alice'), ('Bob');

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

-- 後片付け
DROP TABLE users;

EXIT;</code></pre>
<h3><span id="toc49">12-6. EC2からSSH接続を切断する</span></h3>
<pre><code class="language-bash">exit</code></pre>
<hr>
<h2><span id="toc50">⑬ リソースの削除</span></h2>
<p><strong>課金を止めるために、ハンズオン完了後は必ず削除します。</strong></p>
<blockquote>
<p><strong>RDSの課金について</strong>: RDSはインスタンスが稼働している間は課金されます（db.t3.micro は無料枠外の場合 約$0.017/時間）。不要になったら必ず削除してください。</p>
</blockquote>
<h3><span id="toc51">削除順序</span></h3>
<p>依存関係があるため、<strong>必ずこの順番</strong>で削除します。</p>
<pre><code class="language-plaintext">1. EC2インスタンスを終了（→ 終了済みになるまで待機）
2. RDSインスタンスを削除（→ 削除完了まで約10〜15分待機）
3. RDS DBサブネットグループを削除
4. SSM Parameter Storeのパラメータを削除
5. セキュリティグループを削除（RDS用 → EC2用の順）
6. ルートテーブルの関連付け解除・削除
7. インターネットゲートウェイをデタッチ・削除
8. サブネットを削除（3つ）
9. VPCを削除
10. IAMロールを削除
11. キーペアを削除（任意）</code></pre>
<h3><span id="toc52">1. EC2インスタンスを終了する</span></h3>
<p><strong>EC2 → インスタンス → <code>my-rds-ap-instance</code> を選択 → 「インスタンスの状態」→「インスタンスを終了」</strong></p>
<p>確認ダイアログで「終了」をクリック。「終了済み」になるまで待ちます（2〜5分）。</p>
<h3><span id="toc53">2. RDSインスタンスを削除する</span></h3>
<p><strong>Aurora and RDS → データベース → <code>my-rds-mysql</code> を選択 → 「アクション」→「削除」</strong></p>
<table>
<thead>
<tr>
<th>項目</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>最終スナップショットを作成</td>
<td><strong>チェックを外したまま</strong>（ハンズオンなので不要）</td>
</tr>
<tr>
<td>「私は〜了承します。」</td>
<td><strong>チェックを入れる</strong>（これを入れないと削除ボタンが押せない）</td>
</tr>
<tr>
<td>確認フィールド</td>
<td><code>delete me</code> と入力</td>
</tr>
</tbody>
</table>
<p>「削除」をクリック。削除完了まで<strong>約10〜15分</strong>かかります。ステータスが「削除中」から消えるまで待ちます。</p>
<blockquote>
<p><strong>注意</strong>: 「最終スナップショットを作成」にチェックを入れると、削除後もスナップショットが残り<strong>別途保存料金が発生します</strong>。必ず外してください。</p>
</blockquote>
<h3><span id="toc54">3. RDS DBサブネットグループを削除する</span></h3>
<p><strong>Aurora and RDS → サブネットグループ → <code>my-rds-subnet-group</code> を選択 → 「削除」</strong></p>
<blockquote>
<p>RDSインスタンスが完全に削除されている必要があります。「使用中」エラーが出る場合はRDS削除完了を待ちます。</p>
</blockquote>
<h3><span id="toc55">4. SSM Parameter Storeのパラメータを削除する</span></h3>
<p><strong>Systems Manager → パラメータストア → <code>/my/rds/db-password</code> を選択 → 「削除」</strong></p>
<h3><span id="toc56">5. セキュリティグループを削除する</span></h3>
<p><strong>EC2 → セキュリティグループ</strong></p>
<blockquote>
<p>EC2のSGはRDS SGのソースとして参照されているため、RDS SGから先に削除します。</p>
</blockquote>
<ol>
<li><code>my-rds-sg</code> を選択 → 「アクション」→「セキュリティグループを削除」</li>
<li><code>my-rds-ec2-sg</code> を選択 → 「アクション」→「セキュリティグループを削除」</li>
</ol>
<h3><span id="toc57">6. ルートテーブルを削除する</span></h3>
<p><strong>VPC → ルートテーブル</strong></p>
<p>まず各ルートテーブルのサブネット関連付けを解除してから削除します。</p>
<ol>
<li><code>my-public-rt</code> を選択 → 「サブネットの関連付け」タブ → 「サブネットの関連付けを編集」→ チェックをすべて外す → 「保存」</li>
<li><code>my-private-rt</code> を選択 → 同様に関連付けを解除</li>
<li>各ルートテーブルを選択 → 「アクション」→「ルートテーブルの削除」</li>
</ol>
<h3><span id="toc58">7. インターネットゲートウェイをデタッチ・削除する</span></h3>
<p><strong>VPC → インターネットゲートウェイ → <code>my-rds-igw</code> を選択</strong></p>
<ol>
<li>「アクション」→「VPCからデタッチ」→「デタッチ」</li>
<li>「アクション」→「インターネットゲートウェイの削除」→「削除」</li>
</ol>
<h3><span id="toc59">8. サブネットを削除する（3つ）</span></h3>
<p><strong>VPC → サブネット</strong></p>
<p><code>my-public-subnet</code>・<code>my-private-subnet-1</code>・<code>my-private-subnet-2</code> を選択 → 「アクション」→「サブネットの削除」</p>
<h3><span id="toc60">9. VPCを削除する</span></h3>
<p><strong>VPC → お使いのVPC → <code>my-rds-vpc</code> を選択 → 「アクション」→「VPCの削除」</strong></p>
<h3><span id="toc61">10. IAMロールを削除する</span></h3>
<p><strong>IAM → ロール → <code>my-rds-ec2-role</code> を選択 → 「削除」</strong></p>
<h3><span id="toc62">11. キーペアを削除する（任意）</span></h3>
<p><strong>EC2 → キーペア → <code>my-rds-mysql-key</code> を選択 → 「アクション」→「削除」</strong></p>
<hr>
<h2><span id="toc63">まとめ</span></h2>
<table>
<thead>
<tr>
<th>ステップ</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>①</td>
<td>キーペア作成</td>
</tr>
<tr>
<td>②③④⑤</td>
<td>VPC / サブネット3つ / IGW / ルートテーブルの設定</td>
</tr>
<tr>
<td>⑥</td>
<td>EC2用SG（HTTP:80・SSH:22）+ RDS用SG（MySQL:3306、<strong>SG-to-SG制御</strong>）</td>
</tr>
<tr>
<td>⑦⑧</td>
<td>IAMロール + Parameter Store（SecureString）でパスワードを安全に管理</td>
</tr>
<tr>
<td>⑨</td>
<td>DBサブネットグループ（2AZ必須）の作成</td>
</tr>
<tr>
<td>⑩</td>
<td>RDS MySQL 8.0 インスタンス作成（約10〜15分）</td>
</tr>
<tr>
<td>⑪</td>
<td>EC2起動（UserDataでApache自動セットアップ）</td>
</tr>
<tr>
<td>⑫</td>
<td>EC2 → Parameter Store → RDS MySQL への接続テスト</td>
</tr>
</tbody>
</table>
<p><strong>EC2にDBをインストールする方式との最大の違い</strong>は、AWSがOSのメンテナンス・パッチ・バックアップを自動管理してくれる点です。パスワードをParameter Storeで管理し、SG-to-SGでRDSへのアクセスを制御するパターンは、実際のAWS本番環境でも標準的な設計です。</p>
<p>CloudFormationで同じ構成を自動化したい場合は、<a href="https://caymezon.com/aws-handson-cloudformation-rds-mysql-ec2/">CloudFormation版ハンズオン</a>を参照してください。コマンド1本で22リソースを一括デプロイできます。</p><p>The post <a href="https://caymezon.com/aws-handson-console-rds-mysql-ec2/">AWSコンソールでRDS MySQL + EC2接続環境を構築する手順【DBサブネットグループ / Parameter Storeパスワード管理】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://caymezon.com/aws-handson-console-rds-mysql-ec2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>CloudFormationでRDS MySQL + EC2接続環境を自動構築する手順【22リソース一括デプロイ / コンソール版との比較付き】</title>
		<link>https://caymezon.com/aws-handson-cloudformation-rds-mysql-ec2/</link>
					<comments>https://caymezon.com/aws-handson-cloudformation-rds-mysql-ec2/#respond</comments>
		
		<dc:creator><![CDATA[caymezon]]></dc:creator>
		<pubDate>Sat, 11 Apr 2026 23:47:49 +0000</pubDate>
				<category><![CDATA[AWS Basic]]></category>
		<category><![CDATA[Cloud & Infra]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWSCLI]]></category>
		<category><![CDATA[CloudFormation]]></category>
		<category><![CDATA[DBサブネットグループ]]></category>
		<category><![CDATA[EC2]]></category>
		<category><![CDATA[IaC]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Parameter Store]]></category>
		<category><![CDATA[RDS]]></category>
		<category><![CDATA[SG参照]]></category>
		<category><![CDATA[SSM]]></category>
		<category><![CDATA[VPC]]></category>
		<category><![CDATA[セキュリティグループ]]></category>
		<category><![CDATA[ハンズオン]]></category>
		<category><![CDATA[マネージドサービス]]></category>
		<category><![CDATA[初心者]]></category>
		<guid isPermaLink="false">https://caymezon.com/?p=20336</guid>

					<description><![CDATA[<p>目次 はじめにCloudFormation vs コンソール：どれだけ違うかキーワード解説前提条件構築されるリソース（22個）template.yaml（完全版）作業順序【重要】⓪ 自分のIPアドレスを確認する① キーペ [&#8230;]</p>
<p>The post <a href="https://caymezon.com/aws-handson-cloudformation-rds-mysql-ec2/">CloudFormationでRDS MySQL + EC2接続環境を自動構築する手順【22リソース一括デプロイ / コンソール版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-4" checked><label class="toc-title" for="toc-checkbox-4">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">CloudFormation vs コンソール：どれだけ違うか</a></li><li><a href="#toc3" tabindex="0">キーワード解説</a></li><li><a href="#toc4" tabindex="0">前提条件</a></li><li><a href="#toc5" tabindex="0">構築されるリソース（22個）</a></li><li><a href="#toc6" tabindex="0">template.yaml（完全版）</a></li><li><a href="#toc7" tabindex="0">作業順序</a></li><li><a href="#toc8" tabindex="0">【重要】⓪ 自分のIPアドレスを確認する</a></li><li><a href="#toc9" tabindex="0">① キーペアの作成（コンソールで実施）</a></li><li><a href="#toc10" tabindex="0">② プロジェクトフォルダに移動する</a></li><li><a href="#toc11" tabindex="0">③ スタックの作成</a></li><li><a href="#toc12" tabindex="0">④ 作成完了・Outputsの確認</a><ol><li><a href="#toc13" tabindex="0">作成状況の確認</a></li><li><a href="#toc14" tabindex="0">Outputs（接続情報）の確認</a></li></ol></li><li><a href="#toc15" tabindex="0">⑤ 動作確認</a><ol><li><a href="#toc16" tabindex="0">Webブラウザで確認</a></li><li><a href="#toc17" tabindex="0">EC2にSSH接続する</a></li><li><a href="#toc18" tabindex="0">Parameter StoreからDBパスワードを取得する</a></li><li><a href="#toc19" tabindex="0">RDSへのMySQL接続テスト</a></li></ol></li><li><a href="#toc20" tabindex="0">⑥ スタックの削除</a><ol><li><a href="#toc21" tabindex="0">削除状況の確認</a></li><li><a href="#toc22" tabindex="0">キーペアの手動削除</a></li></ol></li><li><a href="#toc23" tabindex="0">コンソール版との比較</a></li><li><a href="#toc24" tabindex="0">トラブルシューティング</a><ol><li><a href="#toc25" tabindex="0">失敗時の詳細確認コマンド</a></li></ol></li><li><a href="#toc26" tabindex="0">まとめ</a></li></ol>
    </div>
  </div>

<h2><span id="toc1">はじめに</span></h2>
<p>「コンソールで40〜50分かかったRDS + EC2環境をコードで再現したい」——それを実現するのが <strong>AWS CloudFormation</strong> です。</p>
<p>この記事では、<code>template.yaml</code> 1ファイルにVPC・サブネット・セキュリティグループ・IAMロール・SSM Parameter Store・RDS MySQL・EC2（22リソース）を定義し、<strong>コマンド1本でRDS + EC2接続環境を一括構築するハンズオン</strong>を紹介します。コンソール版（<a href="https://caymezon.com/aws-handson-console-rds-mysql-ec2/">AWSコンソール版ハンズオン</a>）と全く同じ構成を、CloudFormationで自動化します。</p>
<pre><code class="language-plaintext">ローカル環境（VSCode）
  ├── template.yaml（22リソースを定義）
  └── AWS CLI コマンド
        ↓ スタック作成（コマンド1本）
AWS環境
  └── VPC（10.0.0.0/16）
        ├── パブリックサブネット（10.0.1.0/24 / AZ-a）
        │     └── EC2（Apache + mariadb client / パブリックIP あり）
        │           └── IAMロール → SSM Parameter Store
        │
        ├── DBサブネットグループ
        │     ├── プライベートサブネット1（10.0.2.0/24 / AZ-a）← RDS配置
        │     └── プライベートサブネット2（10.0.3.0/24 / AZ-c）← 2AZ要件
        │
        └── SSM Parameter Store: /my/rds/db-password</code></pre>
<p><strong>このハンズオンで体験できること：</strong></p>
<ul>
<li>VPC・サブネット3つ・IGW・ルートテーブル・SG・IAM・SSM・RDS・EC2を <code>template.yaml</code> 1ファイルで定義する方法</li>
<li><code>DBPassword</code> パラメータを <code>NoEcho: true</code> でマスクしてセキュアに渡す方法</li>
<li><code>DeletionPolicy: Delete</code> + <code>BackupRetentionPeriod: 0</code> でスタック削除時にRDSを確実に削除する設定</li>
<li><code>CloudFormation</code> が <code>SecureString</code> を作れない理由と代替手段</li>
</ul>
<p><strong>このハンズオンの特徴：</strong></p>
<ul>
<li>コンソール版では40〜50分かかった作業が、コマンド1本（RDS待ち15〜20分含む）で完了</li>
<li><code>delete-stack</code> 1本でRDS・VPC・IAMなど22リソースの依存関係を自動解決して削除</li>
</ul>
<hr>
<blockquote>
<p><strong>この記事は <a href="https://caymezon.com/aws-handson-console-rds-mysql-ec2/">AWSコンソール版ハンズオン</a> の比較記事です。</strong><br />コンソール版でRDS・DBサブネットグループ・Parameter Storeを視覚的に学んだ後に読むと理解が深まります。</p>
</blockquote>
<hr>
<p><!-- ![CloudFormationスタック作成完了・Outputs確認画面](images/cfn-create-complete.jpg) --></p>
<p><!-- <a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"> --></p>
<p><!-- <!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51DEDQXj6oL._SL500_.jpg","\/41F589smNwL._SL500_.jpg","\/41R6f9yyCWL._SL500_.jpg","\/41HqWQ9BvmL._SL500_.jpg","\/41p8p0ZU79L._SL500_.jpg","\/41qLC-fndBL._SL500_.jpg","\/41fcLv9VT5L._SL500_.jpg","\/51lRvCsvHqL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815607850","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815607850","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"eaCUB","s":"s"});</script></p>
<div id="msmaflink-eaCUB">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --> --></p>
<h2><span id="toc2">CloudFormation vs コンソール：どれだけ違うか</span></h2>
<table>
<thead>
<tr>
<th>比較項目</th>
<th>CloudFormation</th>
<th>コンソール（手動）</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>VPC + サブネット3つ + IGW + ルートテーブル</strong></td>
<td>template.yaml に定義済み</td>
<td>約15〜20分・複数画面</td>
</tr>
<tr>
<td><strong>IAMロール作成</strong></td>
<td>template.yaml に定義済み</td>
<td>別画面で作成</td>
</tr>
<tr>
<td><strong>SSM Parameter Store作成</strong></td>
<td>template.yaml に定義済み</td>
<td>別画面で作成</td>
</tr>
<tr>
<td><strong>RDS DBサブネットグループ</strong></td>
<td>template.yaml に定義済み</td>
<td>別画面で作成</td>
</tr>
<tr>
<td><strong>RDS作成（設定項目20以上）</strong></td>
<td><code>--parameters DBPassword=...</code> を渡すだけ</td>
<td>画面でポチポチ</td>
</tr>
<tr>
<td><strong>全体のデプロイ</strong></td>
<td>コマンド1本（RDS待ち15〜20分）</td>
<td><strong>40〜50分</strong></td>
</tr>
<tr>
<td><strong>削除（依存関係あり）</strong></td>
<td><code>delete-stack</code> 1本（自動解決）</td>
<td>11ステップ・手動管理</td>
</tr>
<tr>
<td><strong>再現性</strong></td>
<td>高い（同じ構成を何度でも再現可能）</td>
<td>低い（手順漏れのリスク大）</td>
</tr>
<tr>
<td><strong>バージョン管理</strong></td>
<td>Gitで管理可能</td>
<td>不可</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc3">キーワード解説</span></h2>
<table>
<thead>
<tr>
<th>用語</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>CloudFormation</strong></td>
<td>AWSが提供するIaC（Infrastructure as Code）サービス。YAMLやJSONでリソースを定義し、一括作成・削除できる</td>
</tr>
<tr>
<td><strong>スタック</strong></td>
<td>CloudFormationが管理するリソースのまとまり。今回は22リソースを1スタックで管理</td>
</tr>
<tr>
<td><strong>DeletionPolicy</strong></td>
<td>スタック削除時のリソースの扱いを指定するプロパティ。<code>Delete</code>/<code>Retain</code>/<code>Snapshot</code>（RDSのみ）の3種類</td>
</tr>
<tr>
<td><strong>NoEcho</strong></td>
<td>CloudFormationパラメータの設定。<code>true</code> にするとコンソール上でパスワードが <code>****</code> にマスクされる</td>
</tr>
<tr>
<td><strong>SecureString</strong></td>
<td>Parameter StoreでKMS暗号化して保管するタイプ。<strong>CloudFormationでは作成不可</strong></td>
</tr>
<tr>
<td><strong>CAPABILITY_NAMED_IAM</strong></td>
<td>IAMリソースを含むスタックの作成・更新時に必要なフラグ</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc4">前提条件</span></h2>
<table>
<thead>
<tr>
<th>ツール</th>
<th>確認コマンド</th>
</tr>
</thead>
<tbody>
<tr>
<td>AWS CLI v2</td>
<td><code>aws --version</code></td>
</tr>
</tbody>
</table>
<p>AWS認証確認:</p>
<pre><code class="language-cmd">aws sts get-caller-identity</code></pre>
<hr>
<h2><span id="toc5">構築されるリソース（22個）</span></h2>
<table>
<thead>
<tr>
<th>カテゴリ</th>
<th>リソース</th>
<th>論理ID</th>
</tr>
</thead>
<tbody>
<tr>
<td>ネットワーク</td>
<td>VPC</td>
<td><code>VPC</code></td>
</tr>
<tr>
<td>ネットワーク</td>
<td>インターネットゲートウェイ</td>
<td><code>InternetGateway</code> + <code>IGWAttachment</code></td>
</tr>
<tr>
<td>ネットワーク</td>
<td>パブリックサブネット</td>
<td><code>PublicSubnet</code></td>
</tr>
<tr>
<td>ネットワーク</td>
<td>プライベートサブネット1（RDS配置）</td>
<td><code>PrivateSubnet1</code></td>
</tr>
<tr>
<td>ネットワーク</td>
<td>プライベートサブネット2（2AZ要件）</td>
<td><code>PrivateSubnet2</code></td>
</tr>
<tr>
<td>ネットワーク</td>
<td>パブリックルートテーブル</td>
<td><code>PublicRouteTable</code> + <code>PublicRoute</code> + <code>PublicSubnetRTA</code></td>
</tr>
<tr>
<td>ネットワーク</td>
<td>プライベートルートテーブル</td>
<td><code>PrivateRouteTable</code> + <code>PrivateSubnet1RTA</code> + <code>PrivateSubnet2RTA</code></td>
</tr>
<tr>
<td>ネットワーク</td>
<td>S3 VPC Gateway Endpoint</td>
<td><code>S3VPCEndpoint</code></td>
</tr>
<tr>
<td>セキュリティ</td>
<td>EC2セキュリティグループ</td>
<td><code>EC2SecurityGroup</code></td>
</tr>
<tr>
<td>セキュリティ</td>
<td>RDSセキュリティグループ</td>
<td><code>RDSSecurityGroup</code></td>
</tr>
<tr>
<td>IAM</td>
<td>EC2ロール + インスタンスプロファイル</td>
<td><code>EC2Role</code> + <code>EC2InstanceProfile</code></td>
</tr>
<tr>
<td>パラメータ</td>
<td>SSM Parameter Store</td>
<td><code>DBPasswordParam</code></td>
</tr>
<tr>
<td>データベース</td>
<td>RDS DBサブネットグループ</td>
<td><code>DBSubnetGroup</code></td>
</tr>
<tr>
<td>データベース</td>
<td>RDS MySQLインスタンス</td>
<td><code>RDSInstance</code></td>
</tr>
<tr>
<td>コンピュート</td>
<td>EC2インスタンス</td>
<td><code>EC2Instance</code></td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc6">template.yaml（完全版）</span></h2>
<p>このファイルをそのまま使ってハンズオンを実施できます。<code>C:\my-aws\aws-learning-projects\rds-mysql-ec2\template.yaml</code> として保存してください。</p>
<pre><code class="language-yaml">AWSTemplateFormatVersion: '2010-09-09'
Description: 'RDS MySQL + EC2 connection hands-on with SSM Parameter Store password management'

Parameters:
  EmployeeId:
    Type: String
    Default: '123456'
    Description: Employee ID used as a prefix for resource names

  KeyName:
    Type: String
    Default: 'my-rds-mysql-key'
    Description: Name of an existing EC2 KeyPair

  MyIP:
    Type: String
    Default: '123.456.78.901/32'    # [IMPORTANT] Replace with your own IP (check: curl https://checkip.amazonaws.com)
    Description: Your IP address to allow SSH and HTTP access (CIDR format e.g. 123.456.78.901/32)

  DBPassword:
    Type: String
    Default: 'Handson1234!'
    NoEcho: true
    Description: Master password for RDS MySQL (also stored in SSM Parameter Store)

Resources:

  # VPC and Network
  # ============================================================

  # VPC: isolated network for this hands-on
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub 'n${EmployeeId}-rds-vpc'
        - Key: Cost
          Value: !Ref EmployeeId

  # Internet Gateway: connects public subnet to the internet
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub 'n${EmployeeId}-rds-igw'
        - Key: Cost
          Value: !Ref EmployeeId

  # Attach Internet Gateway to VPC
  IGWAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  # Public Subnet (AZ-a): EC2 AP server is placed here
  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      AvailabilityZone: !Select [0, !GetAZs '']
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub 'n${EmployeeId}-public-subnet'
        - Key: Cost
          Value: !Ref EmployeeId

  # Private Subnet 1 (AZ-a): RDS instance is placed here
  PrivateSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24
      AvailabilityZone: !Select [0, !GetAZs '']
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub 'n${EmployeeId}-private-subnet-1'
        - Key: Cost
          Value: !Ref EmployeeId

  # Private Subnet 2 (AZ-b): required for RDS Subnet Group (minimum 2 AZs)
  # RDS Subnet Group must span at least 2 AZs even for single-AZ deployments
  PrivateSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.3.0/24
      AvailabilityZone: !Select [1, !GetAZs '']
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub 'n${EmployeeId}-private-subnet-2'
        - Key: Cost
          Value: !Ref EmployeeId

  # Public Route Table: routes internet traffic via Internet Gateway
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub 'n${EmployeeId}-public-rt'
        - Key: Cost
          Value: !Ref EmployeeId

  # Default route for public subnet: 0.0.0.0/0 -&gt; Internet Gateway
  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: IGWAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

  # Private Route Table: no internet route (intra-VPC traffic only)
  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub 'n${EmployeeId}-private-rt'
        - Key: Cost
          Value: !Ref EmployeeId

  PrivateSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet1
      RouteTableId: !Ref PrivateRouteTable

  PrivateSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet2
      RouteTableId: !Ref PrivateRouteTable

  # S3 VPC Gateway Endpoint: free, allows EC2 in public subnet to reach S3 for dnf package downloads
  S3VPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref VPC
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3'
      VpcEndpointType: Gateway
      RouteTableIds:
        - !Ref PublicRouteTable
        - !Ref PrivateRouteTable

  # ============================================================
  # IAM
  # ============================================================

  # IAM Role: EC2 can use Session Manager and read SSM Parameter Store
  EC2Role:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub 'n${EmployeeId}-rds-ec2-role'
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
        - arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess
      Tags:
        - Key: Name
          Value: !Sub 'n${EmployeeId}-rds-ec2-role'
        - Key: Cost
          Value: !Ref EmployeeId

  EC2InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      InstanceProfileName: !Sub 'n${EmployeeId}-rds-ec2-profile'
      Roles:
        - !Ref EC2Role

  # ============================================================
  # Security Groups
  # ============================================================

  # EC2 Security Group: SSH and HTTP access from MyIP
  EC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: !Sub 'n${EmployeeId} EC2 AP server SG'
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref MyIP
          Description: SSH from my IP
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: !Ref MyIP
          Description: HTTP from my IP
      Tags:
        - Key: Name
          Value: !Sub 'n${EmployeeId}-rds-ec2-sg'
        - Key: Cost
          Value: !Ref EmployeeId

  # RDS Security Group: MySQL(3306) from EC2 SG only - not open to the internet
  RDSSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: !Sub 'n${EmployeeId} RDS MySQL SG (EC2-to-RDS only)'
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 3306
          ToPort: 3306
          SourceSecurityGroupId: !GetAtt EC2SecurityGroup.GroupId
          Description: MySQL from EC2 SG only (SG-to-SG control)
      Tags:
        - Key: Name
          Value: !Sub 'n${EmployeeId}-rds-sg'
        - Key: Cost
          Value: !Ref EmployeeId

  # ============================================================
  # SSM Parameter Store (password management)
  # NOTE: CloudFormation can only create String type, not SecureString.
  # In production, create a SecureString manually and reference it with
  # {{resolve:ssm-secure:/path/to/param}}
  # ============================================================
  DBPasswordParam:
    Type: AWS::SSM::Parameter
    Properties:
      Name: !Sub '/n${EmployeeId}/rds/db-password'
      Type: String
      Value: !Ref DBPassword
      Description: !Sub 'RDS MySQL master password for n${EmployeeId} hands-on'
      Tags:
        Cost: !Ref EmployeeId

  # ============================================================
  # RDS
  # ============================================================

  # DB Subnet Group: registers which subnets RDS can use
  # Requires subnets in at least 2 different Availability Zones
  DBSubnetGroup:
    Type: AWS::RDS::DBSubnetGroup
    Properties:
      DBSubnetGroupDescription: !Sub 'n${EmployeeId} RDS subnet group (private subnets in 2 AZs)'
      SubnetIds:
        - !Ref PrivateSubnet1
        - !Ref PrivateSubnet2
      Tags:
        - Key: Name
          Value: !Sub 'n${EmployeeId}-rds-subnet-group'
        - Key: Cost
          Value: !Ref EmployeeId

  # RDS MySQL Instance (single-AZ, db.t3.micro - free tier eligible)
  RDSInstance:
    Type: AWS::RDS::DBInstance
    DeletionPolicy: Delete
    Properties:
      DBInstanceIdentifier: !Sub 'n${EmployeeId}-rds-mysql'
      DBInstanceClass: db.t3.micro
      Engine: mysql
      EngineVersion: '8.0'
      MasterUsername: admin
      MasterUserPassword: !Ref DBPassword
      AllocatedStorage: '20'
      StorageType: gp2
      DBName: sampledb
      DBSubnetGroupName: !Ref DBSubnetGroup
      VPCSecurityGroups:
        - !GetAtt RDSSecurityGroup.GroupId
      MultiAZ: false
      PubliclyAccessible: false
      BackupRetentionPeriod: 0
      DeleteAutomatedBackups: true
      Tags:
        - Key: Name
          Value: !Sub 'n${EmployeeId}-rds-mysql'
        - Key: Cost
          Value: !Ref EmployeeId

  # ============================================================
  # EC2 (AP Server)
  # ============================================================

  # AP Server: Apache + MySQL client in public subnet
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64}}'
      InstanceType: t2.micro
      KeyName: !Ref KeyName
      SubnetId: !Ref PublicSubnet
      SecurityGroupIds:
        - !GetAtt EC2SecurityGroup.GroupId
      IamInstanceProfile: !Ref EC2InstanceProfile
      UserData:
        Fn::Base64: |
          #!/bin/bash
          dnf update -y
          dnf install -y httpd mariadb105
          systemctl start httpd
          systemctl enable httpd
          echo "&lt;h1&gt;AP Server - RDS MySQL Hands-on&lt;/h1&gt;" &gt; /var/www/html/index.html
          echo "&lt;p&gt;This server connects to RDS MySQL in the private subnet.&lt;/p&gt;" &gt;&gt; /var/www/html/index.html
      Tags:
        - Key: Name
          Value: !Sub 'n${EmployeeId}-rds-ap-instance'
        - Key: Cost
          Value: !Ref EmployeeId

Outputs:
  EC2PublicIP:
    Description: EC2 AP server public IP
    Value: !GetAtt EC2Instance.PublicIp

  WebsiteURL:
    Description: EC2 AP server website URL
    Value: !Sub 'http://${EC2Instance.PublicIp}'

  RDSEndpoint:
    Description: RDS MySQL endpoint hostname (use this from EC2 to connect)
    Value: !GetAtt RDSInstance.Endpoint.Address

  DBPasswordParamName:
    Description: SSM Parameter Store path for RDS password
    Value: !Ref DBPasswordParam

  SSHCommand:
    Description: SSH command to EC2 AP server
    Value: !Sub 'ssh -i C:\Users\username\.ssh\${KeyName}.pem ec2-user@${EC2Instance.PublicIp}'

  MySQLConnectCommand:
    Description: MySQL connect command (run this FROM the EC2 AP server)
    Value: !Sub 'mysql -h ${RDSInstance.Endpoint.Address} -u admin -pHandson1234! sampledb'</code></pre>
<p><strong>template.yaml の設計ポイント（RDS固有）:</strong></p>
<p><strong><code>DeletionPolicy</code> の3種類:</strong></p>
<table>
<thead>
<tr>
<th>設定</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>Delete</code>（今回）</td>
<td>スタック削除時にRDSも削除する</td>
</tr>
<tr>
<td><code>Retain</code></td>
<td>スタック削除時にRDSを残す</td>
</tr>
<tr>
<td><code>Snapshot</code>（RDSのみ）</td>
<td>スタック削除時にスナップショットを作成してから削除</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>なぜ <code>DeletionPolicy: Delete</code> を明示するか</strong>: RDSはデフォルトでスナップショット作成を要求される場合があります。明示的に <code>Delete</code> を指定することで確実にスキップできます。また <code>BackupRetentionPeriod: 0</code> で自動バックアップを無効にし、削除をよりスムーズにしています。</p>
</blockquote>
<p><strong>CloudFormationが <code>SecureString</code> を作れない理由:</strong></p>
<p><code>AWS::SSM::Parameter</code> は <code>String</code> と <code>StringList</code> のみサポートしています。<code>SecureString</code> は KMS の複雑な依存関係があるためサポート外です。本番環境では事前に SecureString を作成し <code>{{resolve:ssm-secure:/path}}</code> で参照する方法が推奨されます。</p>
<hr>
<h2><span id="toc7">作業順序</span></h2>
<pre><code class="language-plaintext">⓪ 自分のIPアドレスを確認する
      ↓
① キーペアを作成する（コンソールで実施）
      ↓
② プロジェクトフォルダに移動する
      ↓
③ スタックを作成する（aws cloudformation create-stack）
      ↓
④ 作成完了・Outputsを確認する（RDSは15〜20分かかる）
      ↓
⑤ 動作確認（Web・SSH・RDS接続）
      ↓
⑥ スタックを削除する（aws cloudformation delete-stack）</code></pre>
<hr>
<h2><span id="toc8">【重要】⓪ 自分のIPアドレスを確認する</span></h2>
<pre><code class="language-cmd">curl https://checkip.amazonaws.com</code></pre>
<p><strong>控えておく情報</strong>: 自分のIPアドレス（例: <code>203.0.113.1</code>）</p>
<hr>
<h2><span id="toc9">① キーペアの作成（コンソールで実施）</span></h2>
<p>CloudFormationではキーペアのダウンロードができないため、コンソールで先に作成します。</p>
<p><strong>AWSコンソール → EC2 → キーペア → 「キーペアを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>名前</td>
<td><code>my-rds-mysql-key</code></td>
</tr>
<tr>
<td>キーペアのタイプ</td>
<td><strong>RSA</strong></td>
</tr>
<tr>
<td>プライベートキーファイル形式</td>
<td><strong>.pem</strong></td>
</tr>
</tbody>
</table>
<p>ダウンロードされた <code>my-rds-mysql-key.pem</code> を保存します。</p>
<pre><code class="language-plaintext">C:\Users\ユーザー名\.ssh\my-rds-mysql-key.pem</code></pre>
<hr>
<h2><span id="toc10">② プロジェクトフォルダに移動する</span></h2>
<p>VSCodeのターミナル（CMD）を開き、プロジェクトフォルダに移動します。</p>
<pre><code class="language-cmd">cd C:\my-aws\aws-learning-projects\rds-mysql-ec2</code></pre>
<p><code>template.yaml</code> があることを確認します。</p>
<pre><code class="language-cmd">dir template.yaml</code></pre>
<hr>
<h2><span id="toc11">③ スタックの作成</span></h2>
<p>以下のコマンドを実行します。<code>203.0.113.1</code> は⓪で確認した自分のIPアドレスに置き換えます。</p>
<pre><code class="language-cmd">aws cloudformation create-stack ^
  --stack-name my-rds-mysql-stack ^
  --template-body file://template.yaml ^
  --region ap-northeast-1 ^
  --capabilities CAPABILITY_NAMED_IAM ^
  --parameters ^
    ParameterKey=EmployeeId,ParameterValue=123456 ^
    ParameterKey=KeyName,ParameterValue=my-rds-mysql-key ^
    ParameterKey=MyIP,ParameterValue=203.0.113.1/32 ^
    ParameterKey=DBPassword,ParameterValue=Handson1234!</code></pre>
<blockquote>
<p><strong><code>DBPassword</code> パラメータについて</strong>: <code>NoEcho: true</code> が設定されているため、コンソール上では <code>****</code> とマスクされます。</p>
</blockquote>
<blockquote>
<p><strong><code>CAPABILITY_NAMED_IAM</code> について</strong>: <code>EC2Role</code> のように名前を指定したIAMリソースを作成する場合に必要なフラグです。</p>
</blockquote>
<p>成功すると以下のような StackId が表示されます。</p>
<pre><code class="language-json">{
    "StackId": "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/my-rds-mysql-stack/xxxxx"
}</code></pre>
<hr>
<h2><span id="toc12">④ 作成完了・Outputsの確認</span></h2>
<blockquote>
<p><strong>注意</strong>: RDSの作成には<strong>約15〜20分</strong>かかります。<code>CREATE_IN_PROGRESS</code> が続く間は正常です。</p>
</blockquote>
<h3><span id="toc13">作成状況の確認</span></h3>
<pre><code class="language-cmd">aws cloudformation describe-stacks ^
  --stack-name my-rds-mysql-stack ^
  --query "Stacks[0].StackStatus" ^
  --output text</code></pre>
<table>
<thead>
<tr>
<th>ステータス</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>CREATE_IN_PROGRESS</code></td>
<td>作成中（待つ）</td>
</tr>
<tr>
<td><code>CREATE_COMPLETE</code></td>
<td>作成完了</td>
</tr>
<tr>
<td><code>CREATE_FAILED</code></td>
<td>作成失敗（後述のトラブルシューティングを参照）</td>
</tr>
<tr>
<td><code>ROLLBACK_COMPLETE</code></td>
<td>失敗してロールバック完了</td>
</tr>
</tbody>
</table>
<h3><span id="toc14">Outputs（接続情報）の確認</span></h3>
<p><code>CREATE_COMPLETE</code> になったら以下を実行します。</p>
<pre><code class="language-cmd">aws cloudformation describe-stacks ^
  --stack-name my-rds-mysql-stack ^
  --query "Stacks[0].Outputs" ^
  --output table</code></pre>
<pre><code class="language-plaintext">+---------------------+--------------------------------------------------------------------+
|  OutputKey          |  OutputValue                                                       |
+---------------------+--------------------------------------------------------------------+
|  EC2PublicIP        |  x.x.x.x                                                          |
|  WebsiteURL         |  http://x.x.x.x                                                   |
|  RDSEndpoint        |  my-rds-mysql.xxxxx.ap-northeast-1.rds.amazonaws.com         |
|  DBPasswordParamName|  /my/rds/db-password                                         |
|  SSHCommand         |  ssh -i C:\Users\...\.ssh\...pem ec2-user@x.x.x.x                 |
|  MySQLConnectCommand|  mysql -h my-rds-mysql.xxxxx...rds.amazonaws.com -u admin ... |
+---------------------+--------------------------------------------------------------------+</code></pre>
<p><strong>控えておく情報</strong>: <code>EC2PublicIP</code>、<code>RDSEndpoint</code></p>
<p><!-- ![CloudFormation Outputs確認コマンドの実行結果](images/cfn-outputs.jpg) --></p>
<hr>
<h2><span id="toc15">⑤ 動作確認</span></h2>
<h3><span id="toc16">Webブラウザで確認</span></h3>
<p>Outputsに表示された <code>WebsiteURL</code> をブラウザで開きます。</p>
<p>「AP Server - RDS MySQL Hands-on」と表示されればEC2は正常です。</p>
<h3><span id="toc17">EC2にSSH接続する</span></h3>
<p>Outputsの <code>SSHCommand</code> を実行します（パスは実際のパスに修正します）。</p>
<pre><code class="language-cmd">ssh -i C:\Users\ユーザー名\.ssh\my-rds-mysql-key.pem ec2-user@（EC2PublicIP）</code></pre>
<h3><span id="toc18">Parameter StoreからDBパスワードを取得する</span></h3>
<p>EC2に接続した状態で実行します。</p>
<pre><code class="language-bash">aws ssm get-parameter \
  --name "/my/rds/db-password" \
  --query "Parameter.Value" \
  --output text \
  --region ap-northeast-1</code></pre>
<p><code>Handson1234!</code> が表示されれば成功です。</p>
<blockquote>
<p><strong><code>--with-decryption</code> が不要な理由</strong>: CloudFormationで作成したパラメータは <code>Type: String</code>（平文）のため、フラグなしでそのまま値が返ります。コンソールで <strong>SecureString</strong> として作成した場合は <code>--with-decryption</code> が必要です（コンソール版参照）。</p>
</blockquote>
<h3><span id="toc19">RDSへのMySQL接続テスト</span></h3>
<pre><code class="language-bash"># RDSエンドポイントをOutputsの値に置き換える
RDS_ENDPOINT="my-rds-mysql.xxxxxxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com"

# Parameter StoreからDBパスワードを取得して接続（String型のため--with-decryption不要）
DB_PASSWORD=$(aws ssm get-parameter \
  --name "/my/rds/db-password" \
  --query "Parameter.Value" \
  --output text \
  --region ap-northeast-1)

mysql -h $RDS_ENDPOINT -u admin -p"$DB_PASSWORD" sampledb</code></pre>
<p>または Outputsに表示された <code>MySQLConnectCommand</code> を直接実行してもかまいません。</p>
<p>接続成功後、SQL操作を確認します。</p>
<pre><code class="language-sql">-- テーブル作成
CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- データ挿入
INSERT INTO users (name) VALUES ('Alice'), ('Bob');

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

-- 後片付け
DROP TABLE users;

EXIT;</code></pre>
<p><!-- ![EC2からRDS MySQLへの接続成功画面](images/rds-mysql-connect.jpg) --></p>
<p>EC2からSSH接続を切断します。</p>
<pre><code class="language-bash">exit</code></pre>
<hr>
<h2><span id="toc20">⑥ スタックの削除</span></h2>
<p><strong>課金を止めるために、ハンズオン完了後は必ず削除します。</strong></p>
<pre><code class="language-cmd">aws cloudformation delete-stack ^
  --stack-name my-rds-mysql-stack ^
  --region ap-northeast-1</code></pre>
<blockquote>
<p><strong>注意</strong>: RDS削除には<strong>約10〜15分</strong>かかります。コマンド実行後もしばらく待つ必要があります。</p>
</blockquote>
<h3><span id="toc21">削除状況の確認</span></h3>
<pre><code class="language-cmd">aws cloudformation describe-stacks ^
  --stack-name my-rds-mysql-stack ^
  --query "Stacks[0].StackStatus" ^
  --output text</code></pre>
<table>
<thead>
<tr>
<th>ステータス</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>DELETE_IN_PROGRESS</code></td>
<td>削除中（待つ）</td>
</tr>
<tr>
<td><code>DELETE_FAILED</code></td>
<td>削除失敗（トラブルシューティングを参照）</td>
</tr>
</tbody>
</table>
<p>削除完了の確認（以下のエラーが表示されれば削除完了）:</p>
<pre><code class="language-cmd">aws cloudformation describe-stacks ^
  --stack-name my-rds-mysql-stack ^
  --region ap-northeast-1</code></pre>
<pre><code class="language-plaintext">An error occurred (ValidationError) when calling the DescribeStacks operation:
Stack with id my-rds-mysql-stack does not exist</code></pre>
<p>このメッセージが表示されれば削除完了です。</p>
<h3><span id="toc22">キーペアの手動削除</span></h3>
<p>キーペアはCloudFormationで管理していないため手動で削除します。</p>
<p><strong>EC2 → キーペア → <code>my-rds-mysql-key</code> を選択 → 「アクション」→「削除」</strong></p>
<hr>
<h2><span id="toc23">コンソール版との比較</span></h2>
<table>
<thead>
<tr>
<th>作業</th>
<th>コンソール（手動）</th>
<th>CloudFormation</th>
</tr>
</thead>
<tbody>
<tr>
<td>VPC + サブネット3つ + IGW + ルートテーブル</td>
<td>約15〜20分</td>
<td>template.yaml に定義済み</td>
</tr>
<tr>
<td>IAMロール作成</td>
<td>別画面で作成</td>
<td>template.yaml に定義済み</td>
</tr>
<tr>
<td>RDS DBサブネットグループ作成</td>
<td>別画面で作成</td>
<td>template.yaml に定義済み</td>
</tr>
<tr>
<td>RDS作成（設定項目20以上）</td>
<td>画面でポチポチ</td>
<td><code>--parameters DBPassword=...</code> を渡すだけ</td>
</tr>
<tr>
<td>全体のデプロイ</td>
<td><strong>約40〜50分</strong></td>
<td>コマンド1本（RDS待ち15〜20分）</td>
</tr>
<tr>
<td>削除</td>
<td><strong>11ステップ（RDS削除待ちあり）</strong></td>
<td><code>delete-stack</code> 1本</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc24">トラブルシューティング</span></h2>
<table>
<thead>
<tr>
<th>症状</th>
<th>原因</th>
<th>対処</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>CREATE_FAILED</code> → DBInstance失敗</td>
<td>指定AZに db.t3.micro が作成できない</td>
<td>コンソールで利用可能なAZを確認する</td>
</tr>
<tr>
<td><code>stackName failed to satisfy regular expression pattern</code></td>
<td>スタック名が数字始まり</td>
<td><code>my-rds-mysql-stack</code> のように英字で始める</td>
</tr>
<tr>
<td><code>Unable to load paramfile, text contents could not be decoded</code></td>
<td>template.yaml に日本語が含まれている</td>
<td>template.yaml のコメントは<strong>英語のみ</strong>で記述する（Windows環境の既知の問題）</td>
</tr>
<tr>
<td><code>ERROR 2003: Can&#39;t connect to MySQL server</code></td>
<td>RDSがまだ起動中またはSGの設定ミス</td>
<td>RDSのステータスが「利用可能」になっているか確認。RDS SGのソースがEC2 SGのIDになっているか確認</td>
</tr>
<tr>
<td><code>ERROR 1045: Access denied for user</code></td>
<td>パスワードが誤り</td>
<td><code>--parameters DBPassword=...</code> の値を確認</td>
</tr>
<tr>
<td><code>AccessDeniedException</code> on <code>ssm get-parameter</code></td>
<td>IAMロールに <code>AmazonSSMReadOnlyAccess</code> がない</td>
<td><code>EC2Role</code> に <code>AmazonSSMReadOnlyAccess</code> がアタッチされているか確認</td>
</tr>
<tr>
<td><code>DELETE_FAILED</code></td>
<td>スナップショット作成が失敗した</td>
<td>コンソールからRDSを手動削除（スナップショットなしで）してから <code>delete-stack</code> を再実行</td>
</tr>
<tr>
<td>スタック作成後しばらく <code>CREATE_IN_PROGRESS</code> が続く</td>
<td>RDSの作成に時間がかかっている</td>
<td>正常。約15〜20分待つ</td>
</tr>
</tbody>
</table>
<h3><span id="toc25">失敗時の詳細確認コマンド</span></h3>
<pre><code class="language-cmd">aws cloudformation describe-stack-events ^
  --stack-name my-rds-mysql-stack ^
  --query "StackEvents[?ResourceStatus=='CREATE_FAILED'].[ResourceType,ResourceStatusReason]" ^
  --output table</code></pre>
<hr>
<h2><span id="toc26">まとめ</span></h2>
<table>
<thead>
<tr>
<th>ステップ</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>①</td>
<td>キーペアをコンソールで作成</td>
</tr>
<tr>
<td>②③</td>
<td><code>rds-mysql-ec2/</code> フォルダに移動し <code>create-stack</code> を実行</td>
</tr>
<tr>
<td>④</td>
<td><code>CREATE_COMPLETE</code> になったらOutputsでEC2IP・RDSエンドポイントを確認</td>
</tr>
<tr>
<td>⑤</td>
<td>EC2 → Parameter Store → RDS MySQL への接続テスト</td>
</tr>
<tr>
<td>⑥</td>
<td><code>delete-stack</code> 1本で22リソースを一括削除</td>
</tr>
</tbody>
</table>
<p>CloudFormation版の最大のメリットは<strong>再現性</strong>と<strong>削除の簡単さ</strong>です。コンソールでは40〜50分・11ステップかかった作業が、コマンド1本（待ち時間込みで約20分）で完了します。</p>
<p>コンソール操作でRDS・DBサブネットグループ・Parameter Storeを視覚的に確認したい場合は、<a href="https://caymezon.com/aws-handson-console-rds-mysql-ec2/">AWSコンソール版ハンズオン</a>を参照してください。</p><p>The post <a href="https://caymezon.com/aws-handson-cloudformation-rds-mysql-ec2/">CloudFormationでRDS MySQL + EC2接続環境を自動構築する手順【22リソース一括デプロイ / コンソール版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://caymezon.com/aws-handson-cloudformation-rds-mysql-ec2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
