はじめに
こんにちは!インフラエンジニアのなみきです。
Webサーバーなどユーザーにサービスを提供するサーバーと、バッチサーバーなど裏方の処理を行うサーバーがある時、バッチ処理によるDB負荷がユーザー側へ影響しないよう、接続するDBインスタンスを分けたいシーンがあると思います。
ここで役立つのがAmazon Auroraのカスタムエンドポイントです。 以下のようにエンドポイントを使い分けるのがよくあるユースケースかと思います。
ここで、フェイルオーバーしたときの挙動はどうなるのだろうと疑問に思いました。
リーダーだけを含むカスタムエンドポイントを作ったつもりでも、フェイルオーバーで昇格してしまったら、リーダーとライターが混ざったカスタムエンドポイントになってしまうのでは? そして、ライターからリーダーになったインスタンスには接続がなくなるのでは?
理想としては、もしフェイルオーバーが起きてライターとリーダーが入れ替わったとしても、「カスタムエンドポイントはリーダーインスタンスに接続する」という点は変わらないようにしたいです。
そこで、理想を満たす方法はないか、RDSのカスタムエンドポイントについて調べて検証してみました。
結論
このように設定すると、理想を満たす挙動にできます。
詳しくは以下より解説します。
CLIでのみ確認できる「エンドポイントタイプ」
まずはカスタムエンドポイントで何ができるのか公式ドキュメントを読んでみると、エンドポイントタイプという設定を見つけました。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/Aurora.Overview.Endpoints.html
AWS CLI および Amazon RDS API では: エンドポイントタイプを指定できます。そのため、エンドポイントタイプを READER または WRITER に設定すると、フェイルオーバーやプロモーション時にエンドポイントのメンバーシップが自動的に調整されます。 例えば、タイプ READER のカスタムエンドポイントに Aurora レプリカが含まれ、その後、ライターインスタンスに昇格されたとします。新しいライターインスタンスは、カスタムエンドポイントの一部ではなくなります。
コンソールでは表示されませんが、CLIでdescribeしてみると確かに CustomEndpointType
という設定が存在していました。
$ aws rds describe-db-cluster-endpoints --db-cluster-endpoint-identifier myendpoint { "DBClusterEndpoints": [ { "DBClusterEndpointIdentifier": "myendpoint", "DBClusterIdentifier": "mycluster", "DBClusterEndpointResourceIdentifier": "cluster-endpoint-XXXXXXXXXXXX", "Endpoint": "myendpoint.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com", "Status": "available", "EndpointType": "CUSTOM", "CustomEndpointType": "ANY", "StaticMembers": [ "instance1", "instance2" ], "ExcludedMembers": [], "DBClusterEndpointArn": "arn:aws:rds:ap-northeast-1:000000000000:cluster-endpoint:myendpoint" } ] }
コンソールではエンドポイントタイプを指定できません。コンソールを使用して作成されたカスタムエンドポイントは、すべて ANY タイプです。 そのため、フェイルオーバーやプロモーションにより DB インスタンスのロールがライターとリーダーの間で変更されても、Aurora はカスタムエンドポイントのメンバーシップを変更しません。
つまり、コンソール上から「リーダーのみで構成されたカスタムエンドポイント」を作っても、そのメンバーがフェイルオーバーで昇格してしまうと「リーダーとライターが混在するエンドポイント」になってしまうということです。
確実にリーダーのみのエンドポイントとするためには、CLIでエンドポイントタイプを READER
に指定すると良いと分かりました。
しかし、「フェイルオーバー時にメンバーシップが自動的に調整される」のであれば、エンドポイントタイプが READER
のカスタムエンドポイントにリーダーインスタンスだけを含めておくと、フェイルオーバーしたときにアクセスできるインスタンスが1台減ってしまいます。これは理想の挙動ではありません。
そこで、あらかじめカスタムエンドポイントにライターインスタンスも含めておくことができれば、その時々のリーダーインスタンスだけが有効になるという挙動をしてくれるのでは?と考えました。
とはいえ、エンドポイントタイプがREADERなのにライターインスタンスを追加するなんてできるのでしょうか。 期待通りの挙動をしてくれるのか、実際に検証してみました。
検証
1. クラスターを作成
2. カスタムエンドポイントをCLIで作成
メンバーの指定方法には2通りあります。ここではCLIのオプションに従って以下のように呼びます。
- Static members: 固定のインスタンスからなるリスト。今後追加されるインスタンスは追加されない。
- Excluded members: 特定のインスタンスを除外したリスト。今後追加されるインスタンスは自動で追加される。
挙動の違いを確認するため、両方のリストを作ってみます。
Static members
--db-cluster-endpoint-identifier
: 作成したいエンドポイント名--db-cluster-identifier
: クラスター名--endpoint-type
: エンドポイントタイプREADER
を指定
--static-members
: 含めたいインスタンス- readerとwriterを指定
エンドポイントタイプを READER
としておきながらメンバーにライターインスタンスを含めたので、この時点でエラーにならないか不安でしたが、無事に作成されました。
作成完了までには3〜4分ほどかかりました。
$ aws rds create-db-cluster-endpoint \ --db-cluster-endpoint-identifier reader-static \ --db-cluster-identifier mycluster \ --endpoint-type READER \ --static-members reader writer { "DBClusterEndpointIdentifier": "reader-static", "DBClusterIdentifier": "mycluster", "DBClusterEndpointResourceIdentifier": "cluster-endpoint-XXXXXXXXXXXX", "Endpoint": "reader-static.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com", "Status": "creating", "EndpointType": "CUSTOM", "CustomEndpointType": "READER", "StaticMembers": [ "reader", "writer" ], "ExcludedMembers": [], "DBClusterEndpointArn": "arn:aws:rds:ap-northeast-1:000000000000:cluster-endpoint:reader-static" }
コンソールから確認すると、エンドポイントメンバーとしてはreaderしか見えていません。
VPC内から名前解決すると、何回やってもreaderしか返りません。
$ dig +noall +ans reader-static.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com reader-static.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 1 IN CNAME reader.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. reader.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 5 IN A 10.xx.xx.xx
以上のことから、エンドポイントタイプに合わないインスタンスもメンバーとしては追加できるが、エンドポイントタイプと一致するメンバーにしかルーティングされないということが分かりました。 また、コンソールに表示されているのがルーティング対象のメンバーであることが分かりました。
Excluded members
さきほどのコマンドのオプションを変えます。
--db-cluster-endpoint-identifier
: 作成したいエンドポイント名--db-cluster-identifier
: クラスター名--endpoint-type
: エンドポイントタイプREADER
を指定
--excluded-members
: 除外するインスタンス
こちらもStatic同様ライターインスタンスを含む形になりますが、エラーにならず無事に作成されました。
$ aws rds create-db-cluster-endpoint --profile goc-stg-admin \ --db-cluster-endpoint-identifier reader-excluded \ --db-cluster-identifier mycluster \ --endpoint-type READER \ --excluded-members reader-for-batch { "DBClusterEndpointIdentifier": "reader-excluded", "DBClusterIdentifier": "mycluster", "DBClusterEndpointResourceIdentifier": "cluster-endpoint-XXXXXXXXXXXX", "Endpoint": "reader-excluded.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com", "Status": "creating", "EndpointType": "CUSTOM", "CustomEndpointType": "READER", "StaticMembers": [], "ExcludedMembers": [ "reader-for-batch" ], "DBClusterEndpointArn": "arn:aws:rds:ap-northeast-1:000000000000:cluster-endpoint:reader-excluded" }
コンソールから確認すると、エンドポイントメンバーとしてはreaderしか見えていません。
VPC内から名前解決すると、何回やってもreaderしか返りません。
$ dig +noall +ans reader-static.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com reader-static.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 1 IN CNAME reader.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. reader.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 5 IN A 10.xx.xx.xx
こちらもStatic同様、エンドポイントタイプに合わないメンバーも含むこともできるが、エンドポイントタイプと一致するメンバーにしかルーティングされないということが分かりました。
カスタムエンドポイント作成のまとめ
- エンドポイントタイプに合わないインスタンスを含めることもできるが、ルーティングはされない
- コンソールに表示されているのがルーティング対象のメンバー
- 作成時点でStaticとExcludedの挙動の違いはなかった
理想を満たすためにはエンドポイントタイプに合わないインスタンスを含む形でカスタムエンドポイントを作成できる必要がありました。 作成の時点で弾かれる可能性もあると思っていたので、特に弾かれず作成できてホッとしました。
3. リーダーを追加
ここでStaticとExcludedの挙動の違いを確認するため、クラスターに「reader2」というリーダーインスタンスを1台追加してみました。
Static members
コンソールから確認すると、メンバーは変化なくreaderのみのままです。
CLIで見ても変化なし。
$ aws rds describe-db-cluster-endpoints --db-cluster-endpoint-identifier reader-static { "DBClusterEndpoints": [ { "DBClusterEndpointIdentifier": "reader-static", "DBClusterIdentifier": "mycluster", "DBClusterEndpointResourceIdentifier": "cluster-endpoint-XXXXXXXXXXXX", "Endpoint": "reader-static.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com", "Status": "available", "EndpointType": "CUSTOM", "CustomEndpointType": "READER", "StaticMembers": [ "reader", "writer" ], "ExcludedMembers": [], "DBClusterEndpointArn": "arn:aws:rds:ap-northeast-1:000000000000:cluster-endpoint:reader-static" } ] }
VPC内から名前解決してみると、追加前と同じくreaderしか返りません。
$ dig +noall +ans reader-static.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com reader-static.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 1 IN CNAME reader.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. reader.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 1 IN A 10.xx.xx.xx
Excluded members
コンソールから確認すると、メンバーにreader2が追加されています。
CLI上は変化なし。ExcludedMembersにreader-for-batchがいるのみです。
$ aws rds describe-db-cluster-endpoints --db-cluster-endpoint-identifier reader-excluded { "DBClusterEndpoints": [ { "DBClusterEndpointIdentifier": "reader-excluded", "DBClusterIdentifier": "mycluster", "DBClusterEndpointResourceIdentifier": "cluster-endpoint-XXXXXXXXXXXX", "Endpoint": "reader-excluded.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com", "Status": "available", "EndpointType": "CUSTOM", "CustomEndpointType": "READER", "StaticMembers": [], "ExcludedMembers": [ "reader-for-batch" ], "DBClusterEndpointArn": "arn:aws:rds:ap-northeast-1:000000000000:cluster-endpoint:reader-excluded" } ] }
VPC内から名前解決すると、readerとreader2の両方が返ってきます。
$ dig +noall +ans reader-excluded.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com reader-excluded.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 1 IN CNAME reader2.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. reader2.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 5 IN A 10.xx.xx.xx $ dig +noall +ans reader-excluded.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com reader-excluded.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 0 IN CNAME reader.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. reader.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 4 IN A 10.xx.xx.xx
リーダー追加のまとめ
- Static memberで指定すると新しいリーダーは自動では追加されない
- Excluded memberで指定すると新しいリーダーが自動で追加される
これはCLIのドキュメントに書いてあるとおりなので、想定内です。
4. フェイルオーバーしてみる
いよいよ本題です。
readerのフェイルオーバー優先度を最も高くした上でフェイルオーバーを実行します。 writerがリーダーインスタンスになり、readerがライターインスタンスとなりました。
このとき、カスタムエンドポイントの挙動はどうなっているのでしょうか。
Static members
コンソールで確認すると、ライターインスタンスに昇格したreaderがなくなり、かわりにリーダーインスタンスとなったwriterが追加されています。
CLIで見ると、 StaticMembers
はフェイルオーバー前と変わりません。
$ aws rds describe-db-cluster-endpoints --db-cluster-endpoint-identifier reader-static { "DBClusterEndpoints": [ { "DBClusterEndpointIdentifier": "reader-static", "DBClusterIdentifier": "mycluster", "DBClusterEndpointResourceIdentifier": "cluster-endpoint-XXXXXXXXXXXX", "Endpoint": "reader-static.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com", "Status": "available", "EndpointType": "CUSTOM", "CustomEndpointType": "READER", "StaticMembers": [ "reader", "writer" ], "ExcludedMembers": [], "DBClusterEndpointArn": "arn:aws:rds:ap-northeast-1:000000000000:cluster-endpoint:reader-static" } ] }
VPC内から名前解決すると、writer(現リーダーインスタンス)だけが返るようになっています。
$ dig +noall +ans reader-static.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com reader-static.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 1 IN CNAME writer.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. writer.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 1 IN A 10.xx.xx.xx
Excluded members
コンソールで確認すると、ライターインスタンスに昇格したreaderがなくなり、かわりにリーダーインスタンスとなったwriterが追加されています。Staticと同じ挙動ですね。
こちらもCLI上は変化なしです。
$ aws rds describe-db-cluster-endpoints --db-cluster-endpoint-identifier reader-excluded { "DBClusterEndpoints": [ { "DBClusterEndpointIdentifier": "reader-excluded", "DBClusterIdentifier": "mycluster", "DBClusterEndpointResourceIdentifier": "cluster-endpoint-XXXXXXXXXXXX", "Endpoint": "reader-excluded.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com", "Status": "available", "EndpointType": "CUSTOM", "CustomEndpointType": "READER", "StaticMembers": [], "ExcludedMembers": [ "reader-for-batch" ], "DBClusterEndpointArn": "arn:aws:rds:ap-northeast-1:000000000000:cluster-endpoint:reader-excluded" } ] }
VPC内から名前解決すると、writer(現リーダーインスタンス)とreader2が返ります。
$ dig +noall +ans reader-excluded.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com reader-excluded.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 1 IN CNAME writer.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. writer.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 1 IN A 10.xx.xx.xx $ dig +noall +ans reader-excluded.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com reader-excluded.cluster-custom-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 1 IN CNAME reader2.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. reader2.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com. 5 IN A 10.xx.xx.xx
フェイルオーバーまとめ
登録されたメンバーの中から、エンドポイントタイプに合うインスタンスにルーティングします。 そのため、ライターインスタンスをメンバーとして登録しておくと、フェイルオーバーでライターインスタンスがリーダーインスタンスになったとき、入れ替わりで有効なメンバーとなります。
期待通りの挙動をしてくれることが確認できました!
まとめ
- エンドポイントタイプに一致しないインスタンスもメンバーとして登録できるが、ルーティングはされない
- コンソールに表示されているのがルーティング対象のメンバー
- エンドポイントタイプに一致しないインスタンスが、フェイルオーバーによってエンドポイントタイプに一致するようになると、ルーティングされるようになる(逆も然り)
- StaticかExcludedかでフェイルオーバー時の挙動に違いはないため、「リーダーインスタンスを追加した際に自動でカスタムエンドポイントに追加されてほしいかどうか」で決めれば良い
エンドポイントタイプを指定することで動的にメンバーを調整してくれることはドキュメントに書いているので想定通りといえばそうなのですが、「カスタムエンドポイント作成のまとめ」でも述べた通り、そもそもエンドポイントタイプに合わないインスタンスを追加できるかが最も不安な点でした。 そのため、エンドポイントタイプに合わないインスタンスを追加できた時点でほぼ勝ちを確信していました。 実際にフェイルオーバー時に意図通りに動いてくれるのを確認できて良かったです。
とっても賢いカスタムエンドポイント、ぜひみなさんも使ってみてください。