BFT名古屋 TECH BLOG

日々の業務で得た知識を所属するエンジニアたちがアウトプットしていきます。

【AWS】RDSのインスタンスタイプを上げたらRDS ProxyのENIがDBサブネットのIPを食い尽くした話

こんにちは!
BFT名古屋支店の佐野です。

今回は携わった案件にて、AWSのデータベースであるRDS、ひいてはAuroraをめぐって起きたハマり事象についてのお話です。
具体的には、RDSを配置しているサブネットのIPが足りなくなり、RDSがフェールオーバーを行なった際に“互換性のないネットワーク”というステータスとなって、接続が不可能になってしまったというケースです。
特にRDSとRDS Proxyを併用している方にとっては、油断していると発生しうるケースになりますので、参考として起きたことと解決策について紹介していきます。


はじめに:今回のケースの構成

今回お話しする事象が起きた環境では、データベースにRDS(Aurora)を採用し、インスタンスタイプ「db.r5.xlarge」のライターインスタンスとリーダーインスタンスを1台ずつ、別のAZに配置していました。
そこへレコードを自動的に書き込む仕組みをStepFunctionとLambdaを併用して実装、そしてLambdaからの多数のコネクションをプーリングするために、RDS Proxyを配置しました。
またこれらはすべてプライベートサブネット内に配置し、LambdaとStepFunctionの疎通に必要なVPCエンドポイントと、LambdaがRDSへの接続に使用する際に必要な認証情報(シークレット)をSecretsManagerから得るために必要なVPCエンドポイント、計3つのVPCエンドポイントも同じプライベートサブネット内に設置しています。
これを構成図に表すと以下の通りになります。
(AZひとつ分ですが、もうひとつのAZも同じ構成になっています)

f:id:bftnagoya:20220325170126p:plain
変更前の構成

なお、プライベートサブネットのCIDRは/28、つまりIPの数は16個です。
そしてその内、5つはAWSが確保しているため、実際に使用できるのは11個で、以上の構成を取った時に残ったIPの数は2個となっていました。
今思えばすごく余裕が無いサブネットですね…

IPの内訳としては以下となります。

  • Lambdaが使用しているエンドポイント ×1
  • VPCエンドポイント ×4
  • RDSが使用しているエンドポイント ×1
  • RDSのネットワークインターフェース ×1
  • RDS Proxyが使用しているエンドポイント ×2

この状態ではデータベースは問題なく稼働しており、またフェールオーバーも正常に行なえていました。


やったことと起きたこと

トラブル発生前、先ほど挙げた環境で性能試験を行なっていたところ、RDSの性能が足りていないということが分かり、ライター、リーダーともにインスタンスタイプを「db.r5.xlarge」から「db.r5.2xlarge」に引き上げました。
そしてインスタンスタイプ変更のため、再起動とフェールオーバーが行われましたが……
その時にフェールオーバーしたインスタンスのステータスが“互換性のないネットワーク”となってしまいました。

この“互換性のないネットワーク”ステータスは、主にRDSインスタンスを起動した際、配置しているサブネットに使用可能IPアドレスがない場合に発生するものです。
“互換性のないネットワーク”となる原因や説明については、以下の公式ドキュメントに詳しくあります。

aws.amazon.com

さて、今回の変更点はインスタンスタイプの引上げ。
公式ドキュメントにおいてもこの事象の要因となりうることが明記されているので、何がきっかけとなったかは明白です。

続けてサブネットの空きIP数を見てみると、案の定 0 になっていました。
インスタンスタイプを引き上げた時に、どこかで自動的にIPが確保されてしまったようです。
フェイルオーバーを行なう際には、RDSのネットワークインターフェースの切り替えのために必ず1つ以上のIPの空きが必要になるのですが、その空きが無くなっていた為にIPの切り替えが行えず、“互換性のないネットワーク”となってしまったのでしょう。

では何がIPを消費したのか?
ネットワークインターフェイスの一覧を見てみると、なんとRDS Proxyのエンドポイントが2つも増加していました。
逆にインスタンスタイプを変更したRDSのエンドポイントやネットワークインターフェイスは特に変化はありません。
では、変更を加えていないはずのRDS Proxyのエンドポイントは、なぜ意図せず増加してしまったのでしょうか。


どうしてこうなったのか

これは今回の問題が生じた際にAWSへサポートを投げた結果、返ってきた回答になりますが、RDS Proxyは関連付けられているRDSのインスタンスタイプや、ワークロードに基づいて自動的にスケールアウト・スケールインを行なうとのことです。
そしてその際、使用するENI、つまりエンドポイントを増減させるのです。
今回の場合、関連付けていたRDSのインスタンスタイプは「db.r5.xlarge」であり、その際はRDS Proxyは2つのIPを確保していましたが、インスタンスタイプが「db.r5.2xlarge」に変わったことにより、それに追従してRDS Proxyは新たに2つのIPを確保し、結果的にRDSを配置しているサブネットのIPが枯渇してしまったのです。

f:id:bftnagoya:20220325170151p:plain
変更後の構成

この仕様は公式ドキュメントにも詳しく記載されていない(筆者調べ)ため、意識しにくい点ではありますが、注意が必要となります。
※載っているドキュメントがあればコメントにて教えて下さると幸いです。


解決方法と対策

スケールアウトによってIPが増加すること自体はRDS Proxyの仕様となるので、これを防ぐことはできません。
なのでこれを見越して、ネットワークの構成自体を考えることが必要になるでしょう。
その例として、いくつかの方法を挙げていきます。

●サブネットのIPアドレス範囲を広くする

AWS公式からも推奨されている通り、RDSないしDBを配置するサブネットについては、使用可能なIPアドレス数についてかなり余裕を持たせる方がよいです。
今回のケースにおいても、根本ではサブネットのIPアドレス範囲を過少に設計したことが原因となっており、結果的に新なDB用サブネットに移行する方法で解決しています。
もちろん当初からDB運用に向けた、IPに余裕のあるサブネットを用意しておくことが最善となるため、RDSとRDS Proxyの併用が想定できる環境では、VPC構築の段階からDB用サブネットについて意識しておくことが重要となります。

●DB用のセカンダリVPCを追加する

もし既に運用中のVPCで今回のようなケースが発生し、かつそのVPCで新たなDB用のサブネットを用意することができない場合は、そのVPCセカンダリVPCを作成して、そこにDBを移行するという方法があります。
セカンダリVPCは既に運用中のVPC(以下、プライマリVPC)から特に追加設定なく通信できるものであり、別途ネットワークACLやセキュリティグループの設定は必要になりますが、実質的にVPCの範囲を増やせるものになります。
プライマリVPC内での解決が見込めない場合は、セカンダリVPCの利用を検討するとよいでしょう。

●RDSとRDS Proxyを別のサブネットに配置する

今回問題となったのはRDS ProxyのIP増加ですが、実はRDSとRDS Proxyを同じサブネットに配置する必要はありません。
RDSとRDS Proxyが疎通できる場所にあれば、両者の関連付けと通信は問題なく行われるため、どちらかをIPに余裕のあるサブネットに移してしまうのも手です。
ただしRDS Proxyを利用するということは、そこを経由してRDSへ通信を行なうサービスやユーザーがいるということですので、それを考慮したネットワーク構成とすることが求められます。


さいごに

今回のケースで、AWSにおけるDBサブネットの「余裕のあるIPアドレス数」という指標が中々に重要であり、きっちり無駄のない設計とすると、いざ変更という時にハマってしまうポイントが多くなるものだと感じました。
VPCの範囲はどれだけ多く取ろうと料金的には変わりないため、必要なリソースを即座に確保できるクラウド環境においては、ある程度冗長的な構成とする方がよさそうです。
クラウドと関わることが増えれば増えるほど、オンプレミス環境との差異が染みてきます。

それでは、今回はここまで。
また次回の記事でお会いしましょう。