[AWS]S3オブジェクトのHTTPステータスコードをカスタマイズして計画メンテナンスページを構築

aws_logo

計画メンテナンスでサイトを一時的に閉じる時、ブラウザでアクセスしてくる一般ユーザにはメンテナンスページを返せば十分だけれども、
検索ボットにはメンテナンスページの HTTP ステータスコードを 503:Service Unavailable で返すのが好ましい。

Official Google Webmaster Central Blog: How to deal with planned site downtime

メンテナンスページは静的という前提のもと、AWS の DNS サービス route53 と CDN サービス CloudFront とストレージサービス S3 を組み合わせで実現してみる。

route53-ELB-EC2 というようなサーバ構成の場合、メンテナンスの前後で route53 の Alias Target を本番用の ELB からメンテナンスページ用の CloudFront にかえるだけで済む。

route53-cdn-s3-custom-error

S3 の設定

メンテナンスページ用のバケットを作成。(名前は bucket-4-maintenance とする)

メンテナンスページを 503.html というキーでアップロードする。

S3 バケットは検証しやすいように Static Website Hosting する。

s3_static-website-hosting

存在する/しないキーにアクセスした時のステータスを確認

存在するキー(503.html) にアクセスすると、 200 OK がかえってくる

] $ curl -D - http://bucket-4-maintenance.s3-website-ap-northeast-1.amazonaws.com/503.html
HTTP/1.1 200 OK
x-amz-id-2: Le4RMNGtAOaPTIT+W1U4ZOeGdROlwKvpP4JNQC92PN3ry2KNIE3TA9tCzeG7m1163d4YVeLQHog=
x-amz-request-id: ED7863C9455D2903
Date: Sat, 24 Jan 2015 15:52:47 GMT
Last-Modified: Sat, 10 Jan 2015 13:44:56 GMT
ETag: "a3076cabbe20cb3498db339dd5fca8d4"
Content-Type: text/html
Content-Length: 37
Server: AmazonS3

<html>
<body>
503
</body>
</html>

存在しないキー(404) にアクセスすると、 403 Forbidden がかえってくる

] $ curl -D - http://bucket-4-maintenance.s3-website-ap-northeast-1.amazonaws.com/404
HTTP/1.1 403 Forbidden
x-amz-request-id: 41B0885DD66A2F2D
x-amz-id-2: iyDQcN6770EeLkQnWV8QHiwbcrJ+Ujbd3djpxKsbKClrHZpdGUyjFRXF3PrFpjFJpi+YFsmCAFk=
Content-Type: text/html; charset=utf-8
Content-Length: 303
Date: Sat, 24 Jan 2015 15:55:55 GMT
Server: AmazonS3

<html>
<head><title>403 Forbidden</title></head>
<body>
<h1>403 Forbidden</h1>
<ul>
<li>Code: AccessDenied</li>
<li>Message: Access Denied</li>
<li>RequestId: 41B0885DD66A2F2D</li>
<li>HostId: iyDQcN6770EeLkQnWV8QHiwbcrJ+Ujbd3djpxKsbKClrHZpdGUyjFRXF3PrFpjFJpi+YFsmCAFk=</li>
</ul>
<hr/>
</body>
</html>

S3 レイヤーで各オブジェクトの HTTP ステータスコードをカスタマイズできると楽なのだけれど、 S3 だけではカスタマイズできないので、CloudFront の力を借りる。

CloudFront の設定

メンテナンスするドメインをほぼ空っぽの S3 バケットに向けると、リクエストに対応する S3 オブジェクトが存在しないので 403 エラーが発生する。
S3 の前段に CloudFront を挟み、S3 の 403 エラーのレスポンスコードとレスポンスボディーをメンテナンス向けのものにカスタマイズさせる。

ディストリビューションの追加

メンテナンスページ用の web distribution を新規追加する。

cloudfront-create-distribution

  • Origin SettingsOrigin Domain Name には先ほど作成した S3 バケットを指定する。
  • Distribution SettingsAlternate Domain Names(CNAMEs) にメンテナンス対象のサイトのドメインを指定する。

エラーページのカスタマイズ

追加したディストリビューションの Error Pages タブの「Create Custom Error Response」ボタンからエラーレスポンスをカスタマイズ(Customize Error Response=Yes)する。

cloudfront-customize-http-status-edit

  • HTTP Error Code には S3 でオブジェクトが見つからなかった時に返ってくる 403:Forbidden を指定。
  • Resonse Page Path には先ほど追加したバケットにあるメンテナンスページのパスを指定。
  • HTTP Response Code には 503:Service Unavailable を指定。

この機能はあくまでも Custom Error Response なので、 2xx, 3xx 系の正常系レスポンスはカスタマイズできない。

CloudFront にアクセス

S3 に存在するキーで CloudFront にアクセスする。

] $ curl -D - http://subdomain-4-maintenance-s3.cloudfront.net/503.html
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 37
Connection: keep-alive
Date: Sat, 24 Jan 2015 16:10:47 GMT
Last-Modified: Sat, 10 Jan 2015 13:44:56 GMT
ETag: "a3076cabbe20cb3498db339dd5fca8d4"
Server: AmazonS3
Age: 933
X-Cache: Hit from cloudfront
Via: 1.1 7462cb1e6b64f411620ece43e93d9999.cloudfront.net (CloudFront)
X-Amz-Cf-Id: YRmDRbUnWube9vyEODb-plyqvgKG9oSTCDke8YdAnhUZQkb9Zi4iSA==

<html>
<body>
503
</body>
</html>

ステータス 200:OK

S3 に存在しないキーでCloudFront にアクセスする。

] $ curl -D - http://subdomain-4-maintenance-s3.cloudfront.net/404
HTTP/1.1 503 Service Temporarily Unavailable
Content-Type: text/html
Content-Length: 37
Connection: keep-alive
Date: Sat, 24 Jan 2015 16:10:47 GMT
Last-Modified: Sat, 10 Jan 2015 13:44:56 GMT
ETag: "a3076cabbe20cb3498db339dd5fca8d4"
Server: AmazonS3
Age: 918
X-Cache: Hit from cloudfront
Via: 1.1 3f60678c2a9a9452e31c453bab6c8888.cloudfront.net (CloudFront)
X-Amz-Cf-Id: rM0M6FSqjp5gZc1DDDXexOFxEzAiRgwW_GMhybeKsL_kH-d_pTNxhg==

<html>
<body>
503
</body>
</html>

HTTP ステータス 503 Service Temporarily Unavailable で Custom Error ResponseResponse Page Path で指定した 503.html のボディーがかえってきている。

Route 53 の設定

作成した CloudFront をメンテナンス先ドメインに紐付ける。

route53-cloudfront

Alias を Yes にすると、 Alias Target に設定可能な ELB, S3, CloudFront などの一覧が表示される。
先ほど追加した CloudFront の Domain Name を指定する。

Route53 にアクセス

S3 に存在するキーでアクセスする。

] $ curl -D - http://cdn.example.com/503.html
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 37
Connection: keep-alive
Date: Sat, 24 Jan 2015 16:10:47 GMT
Last-Modified: Sat, 10 Jan 2015 13:44:56 GMT
ETag: "a3076cabbe20cb3498db339dd5fca8d4"
Server: AmazonS3
Age: 20
X-Cache: Hit from cloudfront
Via: 1.1 f09dadf7d4655585583b2883d9900000.cloudfront.net (CloudFront)
X-Amz-Cf-Id: WtAPpRDippH58m6XPjAkpr63blrQczWG_MSk5Ep1yzU9bg0CkwRPAw==

<html>
<body>
503
</body>

S3 に存在しないキーでアクセスする。

] $ curl -D - http://cdn.example.com/404
HTTP/1.1 503 Service Temporarily Unavailable
Content-Type: text/html
Content-Length: 37
Connection: keep-alive
Date: Sat, 24 Jan 2015 16:10:47 GMT
Last-Modified: Sat, 10 Jan 2015 13:44:56 GMT
ETag: "a3076cabbe20cb3498db339dd5fca8d4"
Server: AmazonS3
X-Cache: Miss from cloudfront
Via: 1.1 ae575387dd32f9e6aae0bb6e63f51111.cloudfront.net (CloudFront)
X-Amz-Cf-Id: c7FxjqWyW-soYNqN_zPZaIq-h9YQcBTIhgx2sRrIQo8-tSRhHmAzVA==

<html>
<body>
503
</body>
</html>

HTTP ステータス 503 Service Temporarily Unavailable で Custom Error Response の Response Page Path で指定した 503.html のボディーがかえってきている。

References

Leave a comment