対象読者: AWSをこれから触る人。 AWS勉強シリーズの8本目です。全体の地図は索引記事にあります。
この記事を読むと、次の2つの症状が自分で切り分けられるようになります。
- 「EC2にPostgreSQLを入れるのと何が違うの?」に答えられない
- DBを作ったはいいが、止め方が分からなくて課金だけ続いている
RDSとは何か
Amazon Relational Database Service(RDS)は、PostgreSQLやMySQLなどのデータベースを、AWSが面倒を見てくれる形で借りるサービスです。上の絵のとおり、一軒家(自分でDBサーバーを建てる)だと修理も掃除も全部自分ですが、RDSは管理人付き賃貸。バックアップ・ソフトの更新(パッチ当て)・壊れた部品の交換を管理人(AWS)がやってくれるので、住人は「住むこと」=テーブルを作ってデータを入れることに集中できます。
中で動いているのは普通のPostgreSQLやMySQLです。RDSという名前の新しいデータベースがあるわけではありません。だから接続の仕方もSQLも、ローカルで使っていたものがそのまま通ります。
何に使うか
- Webアプリのデータ置き場: ユーザー情報・注文・在庫など、「表で管理して、条件で検索する」データ全般
- EC2に自分で入れたDBの引っ越し先: バックアップ忘れ・パッチ忘れから解放される
- 複数サーバーからの共有: EC2やLambdaの複数台から同じデータベースに接続する
今AWSの地図のどこにいるか
IAM(権限)→S3(ファイル)→EC2(サーバー)→VPC(ネットワーク)→Lambda(関数)と来て、今回はデータの本丸です。RDSはVPCの中に建てるので、前回までのSecurity Groupの話がそのまま効いてきます。
今はこれだけ分かればOK
必須の3語だけ覚えます。
| 語 | 意味 |
|---|---|
| DBインスタンス | 借りる1台分。この単位で作り、この単位で課金される |
| エンジン | 中で動くDBの種類。postgres / mysql など。作った後から変更できない
|
| エンドポイント | 接続先のアドレス。psqlやpsycopg2にこれを渡す |
マルチAZ、リードレプリカ、パラメータグループ、Auroraといった用語は今は後回しで大丈夫です。1台建てて繋げるようになってからで間に合います。
使い方
やることは4つです。上の図がそのままコードの順番になります。
import boto3
rds = boto3.client("rds", region_name="ap-northeast-1")
# ① データベースサーバーを1台建てる
rds.create_db_instance(
DBInstanceIdentifier="my-first-db", # 自分で決める名前
Engine="postgres", # エンジン。後から変更不可
DBInstanceClass="db.t4g.micro", # マシンの大きさ
MasterUsername="admin_user",
MasterUserPassword="dummy-password-123",
AllocatedStorage=20, # ディスク容量(GB)
)
# ② 状態と接続先(エンドポイント)を見る
db = rds.describe_db_instances(DBInstanceIdentifier="my-first-db")["DBInstances"][0]
print("status:", db["DBInstanceStatus"])
print("endpoint:", db["Endpoint"]["Address"], ":", db["Endpoint"]["Port"])
motoで実行した出力です(motoの使い方はシリーズSQS回参照)。
status: available
endpoint: my-first-db.aaaaaaaaaa.ap-northeast-1.rds.amazonaws.com : 5432
このエンドポイントに、あとは普通のPostgreSQLクライアントで繋ぐだけです。psql -h my-first-db.xxxx.ap-northeast-1.rds.amazonaws.com -U admin_user のように使います。RDS専用の接続方法は無い、というのが大事なところです。
注意が1つ。motoでは①が一瞬で available になりますが、本物のAWSでは10分前後 creating のままです。エンドポイントも available になるまで生えてきません。「describe_db_instancesにEndpointが無い」と焦ったら、まだ建設中です。
# ③ 止める(課金を止める)・再開する
rds.stop_db_instance(DBInstanceIdentifier="my-first-db")
rds.start_db_instance(DBInstanceIdentifier="my-first-db")
# ④ スナップショット(その瞬間の完全な複製)を取ってから消す
rds.create_db_snapshot(DBInstanceIdentifier="my-first-db",
DBSnapshotIdentifier="my-first-snap")
rds.delete_db_instance(DBInstanceIdentifier="my-first-db", SkipFinalSnapshot=True)
今あなたが作ったもの
①で建ったのは「PostgreSQLがインストールされ、起動済みで、バックアップ設定までされた仮想サーバー1台」です。自分のPCにPostgreSQLを入れたときと違うのは、OSに入れない(SSHできない)こと。中のOSは管理人の領域で、住人が触れるのはDBのポート(5432)だけです。
1か所だけ変えてみる
Engine="postgres" を Engine="mysql" に変えて②まで実行してみてください。エンドポイントのポートが 5432 から 3306 に変わります。エンジンを選ぶと接続ポートも決まる、という関係が1行の変更で見えます。
実際に叩くと止まるところ
作り方を間違えたときに何が返るか、5パターンmotoで実際に叩きました(エラーの種類名は本物のAWSと同じです。メッセージの文言は多少違います)。
describe_db_instances(DBInstanceIdentifier="nope") # 無い名前を見る
→ DBInstanceNotFound - DBInstance nope not found.
create_db_instance(同じ名前でもう一度)
→ DBInstanceAlreadyExists - DB instance already exists
create_db_instance(Engine="postgresql") # 正しくは postgres
→ InvalidParameterValue - engine postgresql not supported
stop_db_instance(止まっているDBをもう一度止める)
→ InvalidDBInstanceState - Instance is not in available state
delete_db_instance(SkipFinalSnapshotを付けずに消す)
→ 最終スナップショットの指定が要る(付けるか、FinalDBSnapshotIdentifierを渡す)
3つ目は自分も引っかかりました。世間では「PostgreSQL」と書くのに、RDSのエンジン名は postgres です。mysql はそのまま mysql なのに、です。エラーメッセージに正しい候補が出ないので、初見だと数分止まります。
5つ目は逆に安全装置です。S3の「無いキーを消しても成功扱い」と正反対で、RDSは消すときに「本当にスナップショット無しでいいのか」を明示させます。スナップショットが無いままこの確認をすり抜けて消したDBは戻せません。
似たサービスとの使い分け
| 迷うところ | 答え |
|---|---|
| EC2に自分でDBを入れるか、RDSか | 特殊な拡張やOSレベルのチューニングが要るならEC2。それ以外はRDS。バックアップとパッチの当番を自分で持つ価値はまず無い |
| RDSかDynamoDBか | 表と表を結合して検索する(SQL)ならRDS。キー1発で読み書きする単純で巨大なデータならDynamoDB |
| RDSかS3か | 検索・更新するデータはRDS。ファイルのまま置いて読むだけならS3 |
| RDSかAuroraか | AuroraはAWS製の互換エンジンで速くて高い。入門の段階ではRDSの postgres で十分 |
料金の考え方
課金は主に2つです。
-
インスタンス料: 建てている時間×マシンの大きさ。
db.t4g.micro(東京)で1時間約0.026 USD、つけっぱなしで月19 USD前後 - ストレージ料: 確保した容量。gp2の20GBで月2.7 USD前後
Lambdaと違って、呼ばれていなくても建っている限り課金です。EC2と同じ感覚で扱ってください。学習用なら使わない時間は stop_db_instance で止めます。ただし止めても7日後に自動で再起動する仕様と、ストレージ料は止まっている間も掛かる点は覚えておいてください。「消したつもりが止めただけ」「止めたつもりが再起動していた」が、初心者の請求事故の定番です。
よくある注意点
- 繋がらない原因の9割はSecurity Group。 RDSはVPCの中に建つので、VPC回で書いた「入れてもらう側の設定」がここでも要ります。接続元(EC2やあなたのPC)からポート5432の受信を許可していないと、エンドポイントが正しくてもタイムアウトします
- パスワードをコードに書かない。 上の例はmoto用のダミーです。本物ではSecrets Managerか環境変数に置きます
- エンジンとバージョンは最初に決め切る。 エンジンの変更は作り直し。メジャーバージョンの上げ方はあるが停止を伴う
-
公開設定(PubliclyAccessible)は自分でFalseを明示する。 コンソールの新規作成画面では既定で非公開ですが、boto3でサブネットの指定なしに建てると、デフォルトVPCではパブリックになり得ます。上のコードを本物のAWSで使うなら
PubliclyAccessible=Falseを足してください。DBをインターネットに晒すのは、S3のバケット公開よりさらに事故の影響が大きい設定です
まとめ
冒頭の2つの症状に答えます。EC2に自分で入れるのとの違いは「管理人が付くかどうか」で、バックアップ・パッチ・故障対応を持たなくていい代わりに、OSには入れません。課金は「建っている時間」に対して発生するので、止め方は stop_db_instance(ただし7日で再起動)、完全に終わらせるならスナップショットを取って delete_db_instance です。
次に手を動かすなら、motoで①〜④を通したあと、Engine を変えてポートの変化を見るところまでやってみてください。そこまでできれば、RDSの入門は卒業です。
次回はDynamoDB(NoSQL)を予定しています。
参考
- Amazon RDS 公式ドキュメント
- Amazon RDS の料金
- シリーズ索引: AWSとは何か





