好きなAWSサービスはCloudFrontのコマコウです。
(本記事は、2017年12月20日時点のCloudFrontの仕様です。)
要点
- CloudFrontはオリジンからのHTTP 5xxステータスコードを処理する際に、エッジロケーションのオブジェクト有無で挙動が異なる
- キャッシュの有効期限が切れても、エッジロケーションはオブジェクトを保持し続けることはある
- エッジロケーションにオブジェクトが無い場合:CloudFrontのカスタムエラーページ設定に従う
- エッジロケーションにオブジェクトが有る場合:エッジロケーションのオブジェクトをレスポンスし続ける
背景
CloudFrontがオリジンからのHTTP 5xxステータスコード処理する際に、エッジロケーションに保持していたオブジェクトをビューワーにHTTP 200ステータスコードで応答し続けると問題があるシステムはあります。例えば、動的サイト・APIサービスでCloudFrontを利用している構成は注意が必要です。
環境
今回は、LAMP環境で、RDS/EC2(WEBサーバ)/ELB/CloudFrontを利用した環境を例とします。
CloudFrontの挙動
##エッジロケーションにオブジェクトが無い場合
- ビューワーがリクエストする。
- エッジロケーションがオリジンにリクエストをする。
- オリジンが5xxエラーをエッジロケーションにレスポンスする。
- CloudFrontのカスタムエラーページの設定に従い、ビューワーにレスポンスする。
カスタムエラーページが未設定(デフォルト)の場合、5xxステータスコードをビューワーにレスポンスする。5分間に渡り、エッジロケーションは 5xxステータスコードをキャッシュする。
##エッジロケーションにオブジェクトが有る場合
- ビューワーがリクエストする
- オブジェクトの有効期限が切れてない場合は、エッジロケーションがオブジェクトをビューワーにレスポンスする。キャッシュの有効期限が切れている場合は、オリジン(ELB・WEBサーバ)にリクエストする
- オリジンが5xxエラーをエッジロケーションにレスポンスする
- カスタムエラーページのエラーキャッシュ最小 TTL の期間(デフォルトで5分)、エッジロケーションはビューワーに対して、オブジェクトの有効期限が切れていても、エッジロケーションに保持しているオブジェクトをレスポンスし続ける。エラーキャッシュ最小TTLを経過後のリクエストは、再度オリジンにリクエストを行う。
- 再度オリジンにリクエストされたオブジェクトが、5xxステータスコードをレスポンスすると、エッジロケーションに保持しているオブジェクトをレスポンスする。
- 1~5を繰り返えします。ビューワーにはエッジロケーションからオブジェクトが200ステータスコードでレスポンスされますので、表面上は正常に動作しているようにみえます。
#対策案
CloudFrontが、オリジンからの5xxステータスコードのレスポンスを、ビューワに 200ステータスコードでレスポンスさせない対策について検討しました。各環境によって、最善な方法は異なると思われます。(無作為にインバリデーションを行うと、エッジロケーションから、よしなに200ステータスコードでレスポンスされていたオブジェクトが、5xxステータスコードでレスポンスされますので、サービスダウンする可能性があります。)
-
デプロイ時にCloudFrontのインバリデーション
基本的な処理ですが、デプロイ後にインバリデーションを行い、エッジロケーションに保持しているオブジェクトをクリアにする。 -
オリジン(ELB/WEBサーバ)の5xxエラーを監視モニタリング
オリジンでHTTP 5xxステータスコードを検知したら、CloudFrontから応答しているレスポンスの確認を行う。5xxステータスコード対策後に、インバリデーションを行う。5xxステータスコードが頻繁に出ないようにエラーハンドリングしておこうね...
3. Lambda@Edgeを利用して、オリジンからHTTP 5xxステータスコードを応答したレスポンスに対して処理を加える。
こちらの対策は、発想段階なので、2017年度の冬休みの宿題とします。
※追記
(2017年12月21日時点)
Lambdaのドキュメントによると、 CloudFront オリジンレスポンスはオリジンが 400 以上の HTTP ステータスコードを返した場合に発火しない とのことです。
Lambda 関数をトリガーできる CloudFront イベント
http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-cloudfront-trigger-events.html
#参考
上記の挙動は、公式ドキュメントに詳細に記載されております。
CloudFront がオリジンからの HTTP 4xx および 5xx ステータスコードを処理してキャッシュに保持する方法
http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/HTTPStatusCodes.html