[アップデート]CloudFrontオリジンフェイルオーバー時のタイムアウト判定条件をカスタマイズできるようになりました!
CloudFrontでは、オリジンをプライバリ・セカンダリのグループで定義し、障害時にセカンダリへフェイルオーバーする機能が備わっています。
今回のアップデートにより、フェイルオーバー判定に利用するタイムアウト条件を細かく設定できるようになりました。
Amazon CloudFront enables configurable origin connection attempts and origin connection timeouts
実際に、この動作を確認してみます。
CloudFront オリジンフェイルオーバー機能について
CloudFrontのオリジンフェイルオーバー機能は、プライマリ・セカンダリをグループ指定すると
- エラー系HTTPステータスコード
- 接続障害
発生時にプライマリからセカンダリにフェイルオーバーするというものです。
発生条件
タイプ | オリジン制限 | 条件 |
---|---|---|
エラー系HTTPステータスコード | - | 指定したHTTPステータスコードを受け取る |
オリジンへの接続がタイムアウト | - | 指定したタイムアウト(1s〜10s)が指定した回数(1〜3)発生 |
オリジンからのレスポンスがタイムアウト | カスタムオリジンのみ | 指定したタイムアウト(1s〜60s)が指定した回数(1〜3)発生 |
Keep-alive接続がタイムアウト | カスタムオリジンのみ | 指定したタイムアウトが発生 |
フェイルオーバーのフロー
アップデート内容
今回のアップデートでは、
- オリジン接続時のタイムアウト時間
- 試行回数
をカスタマイズできるようになりました。
結果、上記表の
- オリジンへの接続がタイムアウト
- オリジンからのレスポンスがタイムアウト
をより細かく指定できるようになりました。
やってみた
- プライマリにはEC2(Flask)のカスタムオリジン
- セカンダリにはS3
を利用し、フェイルオーバーを確認します。
オリジンの作成
プライマリ・セカンダリのオリジンを作成します。
カスタムオリジンの場合、と非カスタムオリジンで設定可能な項目箱となります。
カスタムオリジン
非カスタムオリジン
オリジングループの作成
Origin Groupの作成画面に移動し、追加したオリジンをプライマリ・セカンダリに登録します。
また、「Failover criteria」にはフェイルオーバー判定に利用したい HTTP ステータスコードを指定します。
Behaviorとオリジングループの紐付け
Behaviorの「Origin or Origin Group」の設定項目に、先程作成したオリジングループを指定します。
サーバープログラム
今回は、サーバー側で特定のHTTPステータスコードを返したり、ブロッキングしたかったので、Flaskで簡単なアプリを書きました。
/数字
にアクセスすると、そのHTTPステータスコードを返すメソッドを用意し、/block
にアクセスすると、300秒後にHTTP 200ステータスを返します。
import time from flask import Flask, abort app = Flask(__name__) @app.route('/200') def s200(): return 'ok' @app.route('/403') def s403(): abort(403) @app.route('/404') def s404(): abort(404) @app.route('/500') def s500(): abort(500) @app.route('/502') def s502(): abort(502) @app.route('/503') def s503(): abort(503) @app.route('/504') def s504(): abort(504) @app.route('/block') def block(): time.sleep(300) return 'block' if __name__ == '__main__': app.run(host='0.0.0.0', port=80)
動作確認
- HTTP ステータスコードのフェイルオーバー
- オリジンへの接続がタイムアウト
- レスポンスタイムアウトのフェイルオーバー
をそれぞれ確認します。
フェイルオーバー判定方法
レスポンスヘッダーの Server
から
- プライマリ(
Server: Werkzeug/1.0.1 Python/3.7.6
) - セカンダリ(
Server: AmazonS3
)
を判定します。
1. HTTP ステータスコードのフェイルオーバー
プライマリからのレスポンスのHTTPステータスコードがフェイルオーバー対象の場合、直ちにセカンダリにリクエストし直します。
プライマリオリジンへ再リクエストしないため、試行回数(Origin Connection Attempts)の設定は関係ありません。
そのため、プライマリオリジンへのアクセスログは1回分です。
正常系HTTPステータスコード(200)
まずは正常系のレスポンスヘッダーです
$ curl -I dummy.cloudfront.net/200 HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 13 Connection: keep-alive Server: Werkzeug/1.0.1 Python/3.7.6 Date: Sat, 06 Jun 2020 20:22:38 GMT X-Cache: Miss from cloudfront Via: 1.1 04599a8a3c6eb66f23e5ae02d1ec4cf2.cloudfront.net (CloudFront) X-Amz-Cf-Pop: FRA6-C1 X-Amz-Cf-Id: XGtd95MGV_kreMWPTF6ldgaGmGN4hVY_t5nol1dyhhbQTneFE-d0Eg==
EC2からのレスポンスです。
対応するオリジンサーバーアクセスログ
1.2.3.4 - - [06/Jun/2020 20:22:38] "HEAD /200 HTTP/1.1" 200 -
200ステータスを返しています。
異常系HTTPステータスコード(500)
次に異常系のレスポンスヘッダーです
$ curl -I dummy.cloudfront.net/500 HTTP/1.1 403 Forbidden Content-Type: application/xml Connection: keep-alive Date: Sat, 06 Jun 2020 20:22:23 GMT Server: AmazonS3 X-Cache: Error from cloudfront Via: 1.1 2ef0748a2a8fca13fd6065b6b046c33c.cloudfront.net (CloudFront) X-Amz-Cf-Pop: FRA6-C1 X-Amz-Cf-Id: 9FC9EKNpOirgMArN-e6DHsWKfakIojA65rZUS01Fq1loWAYV7xLLIw==
EC2からS3にフェイルオーバーしています。
対応するオリジンサーバーアクセスログ
1.2.3.4 - - [06/Jun/2020 20:22:23] "HEAD /500 HTTP/1.1" 500 -
500ステータスを返しています。
2. オリジンへの接続がタイムアウト
CloudFrontからオリジンへの通信で、指定したタイムアウト(1s〜10s)が指定した回数(1〜3)発生すると、フェイルオーバーします。
デフォルトでは
- タイムアウト(Origin Connection Timeout)が10s
- 試行回数(Origin Connection Attempts)が3回
のため、フェイルオーバー発生まで 10x3=30秒かかります。
CloudFrontからのHTTPアクセスをブロックして、意図的にタイムアウトを発生させます。
$ time curl -I dummy.cloudfront.net/200 HTTP/1.1 403 Forbidden Content-Type: application/xml Connection: keep-alive Date: Sat, 06 Jun 2020 18:52:13 GMT Server: AmazonS3 X-Cache: Error from cloudfront Via: 1.1 d3039ad83798b26ecb9f9f1e666afe27.cloudfront.net (CloudFront) X-Amz-Cf-Pop: FRA6-C1 X-Amz-Cf-Id: BYylaraUA7aC3eOJBdNsy_11vqiLn3ITPXZse1if6Rq1qcIwS-GqjA== real 0m30.247s user 0m0.005s sys 0m0.005s
EC2からS3にフェイルオーバーしています。
また、リクエストの処理に30秒かかっています。
Originの設定画面で、試行回数(Origin Connection Attempts)を3回から2回に変更してみます。
$ time curl -I dummy.cloudfront.net/200 HTTP/1.1 403 Forbidden Content-Type: application/xml Connection: keep-alive Date: Sat, 06 Jun 2020 18:57:02 GMT Server: AmazonS3 X-Cache: Error from cloudfront Via: 1.1 89c822bb1ce1445a7be6d1057088cfbf.cloudfront.net (CloudFront) X-Amz-Cf-Pop: FRA6-C1 X-Amz-Cf-Id: T3VcoQEjcjgO_JCkP4K_DQRAR1IjPdOfavflFkHjlnUV3Intadt7Cg== real 0m20.238s user 0m0.003s sys 0m0.006s
リクエストは、タイムアウト10s x 2回 = 20秒に減っています。
3. レスポンスタイムアウトのフェイルオーバー
CloudFrontからオリジンへ接続確立後のレスポンス処理で、指定したタイムアウト(1s〜10s)が指定した回数(1〜3)発生すると、フェイルオーバーします。
デフォルトは
- タイムアウト(Origin Response Timeout)が30s
- 試行回数(Origin Connection Attempts)が3回
のため、フェイルオーバー発生まで 30x3=90秒かかります。
300秒ブロックするパスを用意し
@app.route('/block') def block(): time.sleep(300) return 'block'
意図的にタイムアウトを発生させます。
$ time curl -I dummy.cloudfront.net/block HTTP/1.1 403 Forbidden Content-Type: application/xml Connection: keep-alive Date: Sat, 06 Jun 2020 18:19:20 GMT Server: AmazonS3 X-Cache: Error from cloudfront Via: 1.1 5076c8187f430eebe5e26fc594d6125a.cloudfront.net (CloudFront) X-Amz-Cf-Pop: FRA2-C1 X-Amz-Cf-Id: 7zV5QYbWLteantOJTgZCMXo5avA04-wtwfLxhs8gzwXbm6Doq0EBWQ== real 1m30.317s user 0m0.003s sys 0m0.009s
レスポンスを受け取るまで90秒かかり、S3にフェイルオーバーしています。
EC2サーバーには、CloudFrontで設定したタイムアウト(30秒)間隔で、試行回数(3回)のリクエストが来ています。
1.2.3.4 - - [06/Jun/2020 18:22:49] "HEAD /block HTTP/1.1" 200 - 1.2.3.4 - - [06/Jun/2020 18:23:19] "HEAD /block HTTP/1.1" 200 - 1.2.3.4 - - [06/Jun/2020 18:23:49] "HEAD /block HTTP/1.1" 200 -
CloudFrontからのレスポンス時刻は「Date: Sat, 06 Jun 2020 18:19:20 GMT」で、プライマリオリジンのアクセスログは「06/Jun/2020 18:22:49」です。
- 18:17:49 頃にプライマリオリジンにリクエスト
- 30秒後にタイムアウト、再度リクエストを3回繰り返す
- 初回リクエストの90秒後の18:19:20にセカンダリオリジンにリクエストし、その時のレスポンスが「Date: Sat, 06 Jun 2020 18:19:20 GMT」
- 18:17:49 頃のプライマリオリジンへのリクエストの300秒後のレスポンスが「06/Jun/2020 18:22:49」
というようなことが起きていたと考えられます。
次に
- タイムアウト(Origin Response Timeout):10s
- 試行回数(Origin Connection Attempts):2回
に変更してみます。
$ time curl -I dummy.cloudfront.net/block HTTP/1.1 403 Forbidden Content-Type: application/xml Connection: keep-alive Date: Sat, 06 Jun 2020 18:32:59 GMT Server: AmazonS3 X-Cache: Error from cloudfront Via: 1.1 adb1b226e6965f6206603ba087bd4a0a.cloudfront.net (CloudFront) X-Amz-Cf-Pop: FRA2-C1 X-Amz-Cf-Id: xux6ssGdyu4Q90q6rQEIAw1bkk0XYXk18WSE_2neuxCZHtM7Cu8zxw== real 0m20.229s user 0m0.003s sys 0m0.005s
レスポンスを受け取るまで20秒かかり、S3にフェイルオーバーしています。
サーバーには、CloudFrontで設定したタイムアウト(10秒)間隔で、試行回数(2回)のリクエストが来ています。
1.2.3.4 - - [06/Jun/2020 18:37:39] "HEAD /block HTTP/1.1" 200 - 1.2.3.4 - - [06/Jun/2020 18:37:48] "HEAD /block HTTP/1.1" 200 -
- 18:32:39 頃にプライマリオリジンにリクエスト
- 10秒後にタイムアウト、再度リクエストを2回繰り返す
- 初回リクエストの20秒後の18:32:59にセカンダリオリジンにリクエストし、その時のレスポンスが「Date: Sat, 06 Jun 2020 18:32:59 GMT」
- 18:32:39 頃のプライマリオリジンへのリクエストの300秒後のレスポンスが「06/Jun/2020 18:37:39」
というようなことが起きていたと考えられます。
最後に
CloudFront のオリジンフェイルオーバー機能において、フェイルオーバー判定用のタイムアウト条件を細かく制御できるようになりました。
動画ストリーミング配信のように、素早い切り替えが必要なケースでご活用ください。
それでは。