ちょっと話題の記事

[速報]RDS ProxyがGAされました!!

RDS ProxyついにGAです!!
2020.07.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

CX事業本部@大阪の岩田です。 re:invent2019で発表されたRDS ProxyがついにGAされました!!

RDS Proxyって何?

RDS向けのフルマネージドなDBプロキシです。よくLambdaとの組み合わせについて取り上げられますが、Lambda専用のサービスというわけではなく、EC2やFargate上で動作するアプリから利用することも可能です。 つい数日前にこんなブログを公開しているので、よければ参考にして下さい。

何が嬉しいの?

これまでも自前でEC2を構築してPgpool-IIやPgBouncerを導入すれば、RDSでもプロキシ型のコネクションプーリング機構を利用することができましたが、EC2やミドルウェアの管理負荷を考えるとあまり良い選択肢とは言えませんでした。今回RDS ProxyがGAされたことによりプーリングレイヤーを簡単に構築&運用することが可能になり、アプリケーションの可用性やスパイク耐性の向上といった効果が期待できます。

対応しているDBエンジン

2020/7/1現在で以下のDBエンジンに対応しています。

  • RDS for MySQL 5.6 and 5.7(Aurora含む)
  • RDS for PostgreSQL 10.11 and 11.5(Aurora含む)

MariaDB、Oracle、SQL Serverは未対応ですが、re:invent2019での発表当初からPostgreSQLファミリーの対応が増えています。

料金

プロキシ先のデータベースインスタンスのvCPU数に応じた課金体系で、東京リージョンではvCPU1つ、1時間あたりにつき0.018USDの課金となります。ただし、最低でも2vCPU分の課金が発生することに注意が必要です。

つまり、t2.smallのDBインスタンスに対してRDS Proxyを構築した場合、DBインスタンス自体のvCPU数は1ですが、RDS Proxyの課金としては1時間あたり0.036USD(0.018USD x 2 vCPU) の課金です。

m5.largeのDBインスタンスに対してRDS Proxyを構築した場合はDBインスタンスのvCPU数と同じ2vCPUが課金対象となり、1時間あたり0.036USD(0.018USD x 2 vCPU) の課金です。

詳細は以下のリンクを参照して下さい。

https://aws.amazon.com/jp/rds/proxy/pricing/

注意点!!

ピン留めに注意!!

RDS ProxyにプールされたDB接続が特定のクライアントに固定され、複数のクライアント間で共有できなくなる「ピン留め」に注意しましょう。最悪の場合RDS Proxyを導入したものの

  • レイテンシーが増えた
  • 運用コストが増えた
  • アプリケーションの可用性は特に改善されない

といった具合にRDS Proxyを導入することで環境が改悪されることも考えられます。

ピン留めは

  • 一時テーブルの利用
  • Prepared Statemetの利用

等の条件によって引き起こされます。この辺りは公式ドキュメントに詳しく記載されているので、RDS Proxy利用前には是非ご一読下さい。

https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/rds-proxy.html#rds-proxy-pinning

Auroraクラスターのプロキシ先はライターインスタンスになる

RDS Proxyのプロキシ先がAuroraクラスターの場合、RDS ProxyがプールするDB接続は全てライターインスタンスとの接続です。読み取り処理の負荷分散を行う場合、アプリケーションはRDS Proxyに対して接続するのではなく、リーダーエンドポイントに対して直接接続する必要があります。

その他にも諸々の制約事項があるので、詳細は公式ドキュメントをご参照下さい。

https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/rds-proxy.html#rds-proxy.limitations

やってみる

実際にRDS Proxyの環境を構築してみます。自分の手元の環境にRDS for PostgreSQL 11.5のDBインスタンスがいたので、このDBインスタンスに対してRDS Proxyの環境を構築します。

postgres=> select version();
                                                 version
---------------------------------------------------------------------------------------------------------
 PostgreSQL 11.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11), 64-bit

まずはマネコンのProxiesから「プロキシを作成」をクリックします。

続いて「プロキシ識別子」に適当な名前を、エンジンの互換性に適切なDBエンジンを選択しましょう。今回はPostgreSQLです。

続いてプロキシ先となるデータベースを指定します。今回は元々作成済みだったPostgreSQLのインスタンスを指定しています。

続いてSecrete Managerのシークレットを指定する必要があります。Secrete Managerのマネコンに移動してシークレットを作成してしまいます。

シークレットの種類に「RDSデータベースの認証情報」を選択し、RDSに接続するためのユーザー名とパスワードを入力、「このシークレットがアクセスする...」にはプロキシ先となるデータベースを指定します。

続いてシークレットに適当な名前を付けます。

今回は自動ローテーション無しで作ります。そのままシークレットの作成を完了させましょう。

シークレットが作成できたら、RDS Proxyの接続設定が作成したシークレットを参照するように構成します。その他接続要件を満たすように適切なサブネットやセキュリティグループを設定しておきましょう。

全て設定できたら「プロキシを作成」をクリックします。作成完了までしばらく時間がかかるので待ちましょう。

作成できたら適当な環境から接続テストを行います。まずは通常のエンドポイントに対して...

[ec2-user@ip-172-31-41-239 ~]$  psql -h postgres11.xxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -U postgres
Password for user postgres:
psql (10.4, server 11.6)
WARNING: psql major version 10, server major version 11.
         Some psql features might not work.
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=>

今度はRDS Proxy経由で接続してみましょう。

[ec2-user@ip-172-31-41-239 ~]$  psql -h my-proxy.proxy-xxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -U postgres
Password for user postgres:
psql (10.4, server 11.6)
WARNING: psql major version 10, server major version 11.
         Some psql features might not work.
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=>

接続できました!!

せっかくなので、pg_stat_activityでも見てみましょう

postgres=> select distinct usename from pg_stat_activity ;
    usename
---------------

 rdsproxyadmin
 postgres
 rdsadmin
(4 rows)

rdsproxyadminなるユーザーが接続していますね。このユーザーが何をしてるのか、少し覗いてみます。

postgres=> select * from pg_stat_activity  where usename = 'rdsproxyadmin';
-[ RECORD 1 ]----+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
datid            | 14008
datname          | postgres
pid              | 25154
usesysid         | 16401
usename          | rdsproxyadmin
application_name |
client_addr      | 172.31.32.254
client_hostname  |
client_port      | 22309
backend_start    | 2020-07-01 01:11:19.640069+00
xact_start       |
query_start      | 2020-07-01 01:19:17.215596+00
state_change     | 2020-07-01 01:19:17.215766+00
wait_event_type  | Client
wait_event       | ClientRead
state            | idle
backend_xid      |
backend_xmin     |
query            | SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime;
backend_type     | client backend
-[ RECORD 2 ]----+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
datid            | 14008
datname          | postgres
pid              | 25150
usesysid         | 16401
usename          | rdsproxyadmin
application_name |
client_addr      | 172.31.30.4
client_hostname  |
client_port      | 64211
backend_start    | 2020-07-01 01:11:18.940568+00
xact_start       |
query_start      | 2020-07-01 01:19:17.383175+00
state_change     | 2020-07-01 01:19:17.383347+00
wait_event_type  | Client
wait_event       | ClientRead
state            | idle
backend_xid      |
backend_xmin     |
query            | SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime;
backend_type     | client backend

max_connections等の設定値を読み取っていることが分かります。このあたりの情報をもとに実際にプールするコネクション数を計算していると思われます。

まとめ

「ピン留め」に代表されるように、RDS Proxyの向き、不向きは考慮が必要ですが、これでまた1つアーキテクチャの選択肢が広がりました。細かな注意点については今後実際に検証しながら改めて記事にしていきたいと思います。

参考