Route53のルーティング方式毎のクエリ応答切り替わりを確認する - 加重+フェイルオーバールーティング編
はじめに
前回のブログから随分と時間が経ってしまいました。
その間に、AWS Certified Developer - Associateに合格したり、転職のための準備などをやっていました。
転職のことについては、気が向いたらその内ブログにまとめようかと思います。
さて、今更ではありますが、以前Route53のシンプルルーティングの挙動を確認したので、今回はその続きとして、加重+フェイルオーバールーティングの挙動を確認したいと思います。
今回の構成
今回は、下図のように「プライマリリソース2台、セカンダリリソース2台」の構成にし、リソースのダウン状態に応じてアクセス結果がどうなるか見ていきたいと思います。
実務ではこのような構成は採用しないと思いますが、あくまで動作検証目的なのでご容赦ください。
今回はプライベートホステッドゾーンを使用し、VPC内の踏み台サーバからWEBサーバにアクセスすることにします。
NATゲートウェイは、プライベートサブネットのEC2にパッケージをインストールするために使用します。
環境構築の方法
今回は、VPC内の環境はCloudFormationで構築し、Route53の設定は手動で行います。
CloudFormationのテンプレートは以下のものを使用します。
Route53_Failover_Routing.yml
環境構築
VPC内構築(CloudFormation)
まずは上述のテンプレートを使ってVPC内の環境を構築します。
[cloudshell-user@ip-10-0-175-26 ~]$ ls -l total 3000 -rw------- 1 cloudshell-user cloudshell-user 3489792 Sep 25 08:20 core.3704 -rw-rw-r-- 1 cloudshell-user cloudshell-user 18077 Nov 6 16:31 Route53_Failover_Routing.yml [cloudshell-user@ip-10-0-175-26 ~]$ [cloudshell-user@ip-10-0-175-26 ~]$ [cloudshell-user@ip-10-0-175-26 ~]$ [cloudshell-user@ip-10-0-175-26 ~]$ aws cloudformation validate-template --template-body file:///home/cloudshell-user/Route53_Failover_Routing.yml { "Parameters": [ { "ParameterKey": "KeyName", "NoEcho": false, "Description": "Name of an existing EC2 KeyPair to enable SSH access to the instances" }, { "ParameterKey": "EnvironmentType", "DefaultValue": "test", "NoEcho": false, "Description": "The environment type" }, { "ParameterKey": "ClientIP", "DefaultValue": "0.0.0.0/0", "NoEcho": false, "Description": "Client IP Address" } ], "Description": "EC2 WEB Server Deploy for Route53 Failover Routing" } [cloudshell-user@ip-10-0-175-26 ~]$ [cloudshell-user@ip-10-0-175-26 ~]$ [cloudshell-user@ip-10-0-175-26 ~]$ [cloudshell-user@ip-10-0-175-26 ~]$ aws cloudformation create-stack \ > --stack-name EC2deploy-for-Route53Failover \ > --template-body file:///home/cloudshell-user/Route53_Failover_Routing.yml \ > --parameters \ > ParameterKey=KeyName,ParameterValue="xxx" \ > ParameterKey=ClientIP,ParameterValue="114.xxx.xxx.xxx/32" \ > ParameterKey=EnvironmentType,ParameterValue="test" { "StackId": "arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/EC2deploy-for-Route53Failover/888ef8d0-3f1f-11ec-8a07-069142138e3f" } [cloudshell-user@ip-10-0-175-26 ~]$ [cloudshell-user@ip-10-0-175-26 ~]$ [cloudshell-user@ip-10-0-175-26 ~]$ aws cloudformation describe-stacks --stack-name EC2deploy-for-Route53Failover { "Stacks": [ { "StackId": "arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/EC2deploy-for-Route53Failover/888ef8d0-3f1f-11ec-8a07-069142138e3f", "StackName": "EC2deploy-for-Route53Failover", "Description": "EC2 WEB Server Deploy for Route53 Failover Routing", "Parameters": [ { "ParameterKey": "KeyName", "ParameterValue": "xxx" }, { "ParameterKey": "EnvironmentType", "ParameterValue": "test" }, { "ParameterKey": "ClientIP", "ParameterValue": "114.xxx.xxx.xxx/32" } ], "CreationTime": "2021-11-06T16:35:21.031000+00:00", "RollbackConfiguration": {}, "StackStatus": "CREATE_COMPLETE", "DisableRollback": false, "NotificationARNs": [], "Outputs": [ { "OutputKey": "PublicIPaddress", "OutputValue": "18.xxx.xxx.xxx", "Description": "PublicIpaddress for Bastion" }, { "OutputKey": "InstanceSecurityGroup1", "OutputValue": "sg-xxxxxxxxxxxxxxxxx", "Description": "InstanceSecurityGroup1", "ExportName": "EC2deploy-for-Route53Failover-InstanceSecurityGroup1" }, { "OutputKey": "PublicSubnet1", "OutputValue": "subnet-xxxxxxxxxxxxxxxxx", "Description": "PublicSubnet1", "ExportName": "EC2deploy-for-Route53Failover-PublicSubnet1" } ], "Tags": [], "EnableTerminationProtection": false, "DriftInformation": { "StackDriftStatus": "NOT_CHECKED" } } ] } [cloudshell-user@ip-10-0-175-26 ~]$ [cloudshell-user@ip-10-0-175-26 ~]$
Route53設定
次はRoute53の設定です。加重+フェイルオーバールーティングの場合、先にヘルスチェックの作成をする必要があります。
ただし、今回WEBサーバにはパブリックIPを割り当てていないので、IPアドレスによるヘルスチェックは出来ません。詳細は以下のリンクを参照してください。
そのため、今回はCloudWatchアラームを使用してヘルスチェックを行います。
CloudWatchアラームの作成
というわけで、まずCloudWatchアラームを作成します。
EC2インスタンスの「StatusCheckFailed_Instance」メトリクスを使用します。
各インスタンス毎にアラームを作成します。
Route53ヘルスチェックの作成
続いて、Route53ヘルスチェックを作成します。
まずはヘルスチェック作成ボタンを押します。
続いて、諸々の情報を入力します。なお、今回はアラームが不足状態の時は異常扱いとしました。理由は、疑似障害として対象インスタンスを手動で停止した所、CloudWatchアラームが「NG」ではなく「データ不足」になってしまったためです。
Route53ヘルスチェックも、インスタンス毎に作成します。
DNSレコードの追加
続いて、DNSレコードを追加していきます。フェイルオーバーのプライマリリソース、セカンダリリソースが複数ある場合、エイリアスレコードを併用する必要があります。詳細は以下のリンクを参照してください。
まずはインスタンスのAレコードを加重ルーティングで登録します。最初はEC2Aです。
レコード名は「failover-primary」としています。先ほど作成したヘルスチェックと紐づけます。TTLは図では300秒になっていますが、後で10秒に変更しました。(TTLが長いと、短時間のアクセスでは想定通り加重されない場合がありました。)EC2Bも同様に設定します。
EC2C、EC2Dはレコード名を「failover-secondary」としました。
続いて、名前解決したいホスト名「www.example.com」のエイリアスレコードを、フェイルオーバールーティングで作成します。
「failover-primary」と紐づけ、プライマリリソースとします。
もう一つ「www.example.com」のレコードを作成します。こちらは「failover-secondary」と紐づけ、セカンダリリソースとします。
最終的にレコードは上図のようになりました。
アクセス確認
今回のアクセス確認方法
前述通り、今回は踏み台EC2からアクセス確認します。簡便なスクリプトを使い、10秒おきに「www.example.com/index.html」宛てに100回curlして、応答したインスタンスの数をカウントします。(※各WEBサーバにはCloudFormaitonでindex.htmlを配置しています。index.htmlのBodyに自身の名前が記述されているので、それを抜き出します。)
踏み台EC2で使用するスクリプトの中身は以下です。これもCloudFormationで事前に配置しています。
#!/bin/bash for ((i=1; i<=100; i++)) do curl -s http://www.example.com/index.html | grep -o "EC2." >> ./curlresult sleep 10 done cat ./curlresult | sort | uniq -c echo "curl done!!"
アクセス確認結果
全インスタンスの正常時
全インスタンスの正常時は、プライマリリソースの2台で加重ルーティングされました。
[ec2-user@ip-10-100-0-78 ~]$ [ec2-user@ip-10-100-0-78 ~]$ ./curlrepeat.sh 70 EC2A 30 EC2B curl done!! [ec2-user@ip-10-100-0-78 ~]$ [ec2-user@ip-10-100-0-78 ~]$
EC2Aの異常時
EC2Aに異常がある場合、もう1台のプライマリリソースであるEC2Bに全アクセスが集中しました。
[ec2-user@ip-10-100-0-78 ~]$ ./curlrepeat.sh 100 EC2B curl done!! [ec2-user@ip-10-100-0-78 ~]$
EC2A、EC2Bの異常時
プライマリリソースの全台に異常がある場合、セカンダリリソースの2台で加重ルーティングされました。
[ec2-user@ip-10-100-0-78 ~]$ ./curlrepeat.sh 17 EC2C 83 EC2D curl done!! [ec2-user@ip-10-100-0-78 ~]$
EC2A、EC2B、EC2Cの異常時
プライマリリソースの全台+セカンダリリソースの1台に異常がある場合、セカンダリリソースの残り1台に全アクセスが集中しました。
[ec2-user@ip-10-100-0-78 ~]$ ./curlrepeat.sh 100 EC2D curl done!! [ec2-user@ip-10-100-0-78 ~]$
結論
というわけで、以下のような結果となりました。
- プライマリリソースが全異常にならない限り、プライマリリソースの正常なレコードで加重ルーティングされる。
- プライマリリソースが全異常になっている間は、セカンダリリソースの正常なレコードで加重ルーティングされる。
ログの記載は省略しますが、EC2Bのみ異常の場合や、EC2A、EC2B、EC2Dに異常がある場合も、上記ルールに則った結果となりました。
なお、今回はプライマリ、セカンダリ両方にヘルスチェックを設定していましたが、ヘルスチェックを設定していない場合は挙動が変わるようです。詳細は以下リンクを参照ください。
Route53ヘルスチェックについての補足
もしヘルスチェックをIPで行う場合、Route53ヘルスチェッカーからのアクセスをセキュリティグループ等で許可する必要があります。Route53ヘルスチェッカーはVPC外に存在しているためです。詳細は以下のリンクを参照してください。
また、Route53ヘルスチェッカーのIPアドレスはリージョン毎に異なります。アドレス範囲については以下のリンクを参照してください。
おわりに
というわけで、前回のシンプルルーティングから2ヶ月も経ってしまいましたが、ようやく加重+フェイルオーバールーティングの設定と動作確認が出来ました。
今回もCloudFormationの設定で色々躓いたうえ、複数リソースでのフェイルオーバールーティング設定でも苦戦したため、予想以上に時間を使ってしまいました。
ただ、おかげでCloudFormationやRoute53に少しずつ慣れてきたので、今後も試行錯誤しながら色々試していきたいと思います。