AWS CDKでサーバーレスなフェイルオーバールーティングを実装してみた
大阪リージョンもついにローカルリージョンから正式なリージョンへと昇格したので、冗長化した構成を試してみたいと思い実装しました。
やったこととしては
- 東京リージョンと大阪リージョンにapi-gateway × lambda で簡単なAPIを用意
- Route53で東京リージョン側をPRIMARY、大阪リージョン側をSECONDARYとしてfailoverした際に切り替えれるようにした
フェイルオーバーの試し方
- CDKのスタックを流し、環境をつくる
packages/cdk/lib/config.ts
で設定したドメインを叩き、 東京リージョン側のレスポンスが返ってくることを確認する- 東京リージョン側のlambdaのレスポンスを意図的に失敗するようにする
- -> 30~60秒後に大阪リージョンからレスポンスがくるようになる
ハマったこと & 注意点
Route53の設定が Cfn
のメソッドで実装する必要があった(2021/04/02時点)
High Level Construct
がまだ提供されていないようだったので、 Low Level Construct
で実装する必要がありました。
そのため、Route53のCloudFormationの理解を求められました。
AWS::Route53::RecordSet
AWS::Route53::HealthCheck
- CfnRecordSet.failover の型は
string
だが許容される文字はPRIMARY
かSECONDARY
のどちらかのみ - CfnRecordSet. AliasTarget に設定する
dnsName
やhostedZoneId
はapi-gateway
のAliasDomainName
やAliasHostedZoneId
を使用する - api-gatewayで生成されるendpoint(今回healthcheckに利用するendpoint)は
https
でしか叩けないため、CfnHealthCheck. healthCheckConfig のtype
とport
にはそれぞれHTTPS
と443
を指定する必要がある - CfnHealthCheck. healthCheckConfig. fullyQualifiedDomainName はいわゆる
URI
の部分を差し込む必要がある- CDK上の
apigw.LambdaRestApi
からは urlForPath でapi-gatewayのendpointを取得することはできるがhttps://xxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/
として返ってきてしまい、https://
や/prod
の箇所が不要である - そのため
this.healthCheckDomainName = `${this.api.restApiId}.execute-api.${props.env?.region}.amazonaws.com`;
といったように自前で URI 部分だけstringに格納して、CfnHealthCheck. healthCheckConfig. fullyQualifiedDomainName
にわたす必要がある
- CDK上の
CfnHealthCheck. healthCheckConfig のデフォルトの設定値だと、failoverで切り替えするまでに時間がかかる
HealthCheck
を行ってターゲットを切り替えようとする際に、Route53では以下のように評価を行っているとのこと。
Route 53 はヘルスチェッカーからデータを集計し、エンドポイントが正常であるかどうかを判断します。
・18% を超えるヘルスチェッカーがエンドポイントを正常であるとレポートした場合、Route 53 はそのエンドポイントを正常と見なします。
・ ヘルスチェッカーが正常であるエンドポイントが 18% 以下であるとレポートした場合、Route 53 はそのエンドポイントを異常と見なします。
※Amazon Route 53 がヘルスチェックの正常性を判断する方法
そのため、エラーがおきたらすぐ切り替わるかというとそうではありません。
また、 HealthCheckConfig のデフォルト値は以下のような設定になります
- FailureThreshold : 3
- RequestInterval : 30
- Regions : [us-east-1, us-west-1, us-west-2, eu-west-1, ap-southeast-1, ap-southeast-2, ap-northeast-1, sa-east-1] (現在ヘルスチェッカーとして指定できるリージョンすべてから叩かれる)
18% を超えるヘルスチェッカー
がとあるため、Regionsの数が多くてFailureThresholdの条件も回数が多いと18%
に至るまでに時間がかかります。
※厳密に計測はできていないですが、上記のデフォルト値でfailoverさせると切り替えまでに1分以上かかっていました
そのためエラーが発生したらすぐに切り替えたい、ということであれば上記の値を低め、少なめに設定する必要があります。
今回試した値は以下のような設定値にしており、これだと30秒から長くても1分以内には切り替わるようになりました。
- FailureThreshold : 1
- RequestInterval : 10
- Regions : [ap-southeast-1, ap-southeast-2, ap-northeast-1]
このようにいろいろ考慮する必要はありましたが、ひとまずfailover routingはできたかなと思います。
Low Level Construct はしんどいな〜と思いましたが、本来 High Level Construct で書くときも同じくらい把握して書かないとだめだなと再認識しました。