背景
RDS MySQL + EC2の接続環境をAWSコンソールで手動構築するハンズオンをやりました。RDSインスタンス自体は1つのAZにしか配置しないのに、なぜDBサブネットグループには2つ以上のAZのサブネットが必要なのか、という一見不思議な仕様を実際に体験した内容です。
1. DBサブネットグループは「配置候補」であって「配置先」そのものではない
DBサブネットグループに登録:
ap-northeast-1a → my-private-subnet-1
ap-northeast-1c → my-private-subnet-2
実際にRDSが配置されるAZ:
ap-northeast-1a のみ(今回はシングルAZ構成)
RDS DBサブネットグループは、RDSインスタンスが「配置され得る」サブネットの集合を登録するグループです。今回のようにシングルAZで構築する場合でも、グループの定義自体には最低2つの異なるAZのサブネットが必要という制約があります。これはRDSがMulti-AZフェイルオーバー(障害時の自動切り替え)に対応するための仕様で、将来Multi-AZ構成に切り替える際にサブネットの追加作業が発生しないようにするための設計です。
2. 使わないAZのサブネットも実際に作成する必要がある
今回のハンズオンでは、パブリックサブネット1つ・プライベートサブネット2つの計3サブネットを作成しています。実際にRDSが使うのはap-northeast-1aのプライベートサブネットだけですが、DBサブネットグループの要件を満たすためにap-northeast-1cのプライベートサブネットもあらかじめ用意しておく必要があります。
3. RDSのパスワードはSSM Parameter Store(SecureString)で管理する
aws ssm get-parameter \
--name "/my/rds/db-password" \
--query "Parameter.Value" \
--output text \
--region ap-northeast-1 \
--with-decryption
コンソールでパラメータを作成する際に「SecureString」タイプを選ぶとKMSで暗号化されて保存されます。取得時は--with-decryptionフラグが必須で、これを付け忘れると暗号化されたままの値が返ってきます。EC2側はIAMロールにAmazonSSMReadOnlyAccessを付与しておくだけで、パスワードをコードに一切書かずに実行時取得できます。
4. RDS用SGはEC2用SGへの参照だけで守る
RDS用SG インバウンド:
MySQL(3306) ソース: my-rds-ec2-sg(SG-ID・SGを選択)
RDS用SGのソースには、IPアドレスの代わりにEC2用SGを直接指定します。これにより「EC2用SGに所属するインスタンスからの通信のみ」を許可でき、インターネットからの直接アクセスを完全に遮断できます。EC2のIPアドレスが変わってもSG参照なので設定変更が不要という利点もあります。
5. RDSの削除は10〜15分かかり、依存関係の順序を守る必要がある
1. EC2インスタンスを終了
2. RDSインスタンスを削除(10〜15分)
3. DBサブネットグループを削除
4. Parameter Storeのパラメータを削除
5. セキュリティグループを削除(RDS用 → EC2用の順)
RDS SGはEC2 SGを参照しているため、削除は必ずRDS用SGを先に行います。逆順で削除しようとすると「使用中」エラーになります。RDSインスタンス自体の削除にも10〜15分かかるため、削除作業全体で余裕を持ったスケジュールが必要です。
まとめ
DBサブネットグループが「実際に使わないAZのサブネットも要求する」仕様と、SSM Parameter StoreのSecureStringによるパスワード管理が、このハンズオンで最も実務的な学びでした。EC2にDBを直接インストールする方式と比べ、RDSはOSのメンテナンス・パッチ・バックアップをAWSが自動管理してくれる点が最大のメリットです。