メンテナンスページを CloudFront + S3 で表示させる方法 (SSL付き)

よーく忘れてしまう、サイトのメンテナンス表示の設定方法をまとめておきました。

CloudFront -> S3 で静的HTMLなメンテ表示サイトをホストして、DNS 切り替えでメンテ表示するという方法です。

他にも ELB で EC2 のターゲットグループを変えてメンテ表示させるとか方法ありますが、一番手っ取り早いこちらの方法を行ます。また、Route53 をお使いの方は、DNS レベルでのヘルスチェックでサーバーが落ちた時の自動表示をするのにも使えるので便利です。

AWS マネージドコンソールな管理画面からの設定手順メモです。

2021.7.5 時点の管理画面の遷移で確認しています。

作業しながらの殴り書きなので、間違っているステップがあったらご指摘くださいませ!

セットアップ

事前準備

  • SSL証明書をゲット
    • 別で用意している場合はファイルをもらえるか
    • Certificate Manager を通じで無料SSL証明書を利用可の場合は、ACM Certificate Manager で取得しておく
      • CloudFront 用なので、N Virginia リージョン (us-east-1) で登録しておくこと
      • メール認証
      • DNS レコード認証 (こちらが楽)
  • メンテナンスページ表示用の静的 HTML ファイル一式
    • maintenance.html の1ページのみをメンテ表示として設定しておく (他に自由に決めてOK。)
    • ただし index.html など、通常ページと同じパスにならないようにしましょう。間違って 200 ステータスコードを返してしまいます。
    • CSS や画像を読み込むときは、ルートからの絶対パスにしておきましょう。相対パスだと下層URLでメンテナンスページを表示するときにCSS や画像が 404 になっちゃいます。
  • DNS お客さんとルートドメインの確認
    • AWS Route53 じゃないと、ルートドメインで、CNAME を設定できないので、 DNS が Route54 以外であれば、A レコードとして登録できるサーバーなどを準備する必要がある。DNS が Route53 か、それ意外であれば対応をどうするか考える
      • A レコードが立てられる EC2 を別に立てる
      • ELB 方式に変える
      • ルートドメインを諦めて www サブドメインなどのみをメンテ表示させる
      • [裏技] CloudFlare を DNS サービスとしてつかう
  • DNS: 対象ドメインレコードの TTL を調べ、長すぎる場合、 事前に 短く設定する。30〜60秒が理想。

S3 バケット作成

  • メンテ表示用静的 HTML ページファイルをホストする S3 バケットを作成
    • バケット名はわかりやすいもので自由に決める
      • e.g, PROJ-maintenance とか
    • リージョンは任意。分かりやすいようにメインのリージョンにおいたらいいと思います。
    • パブリックアクセスを全てブロックチェックを全てはずす
    • バージョニングはお好きな方に。メンテページなので、無効で良いと思います。
    • 暗号化も無効化で良いと思います。メンテページはそんなに秘密じゃ無いと思うので・・・。
    • バケットを作成します
  • バケットの 静的ウェブサイトホスティング をオンにします
    • バケットに入り プロパティ タブをクリック
    • 静的ウェブサイトホスティングを「編集する」をクリック
    • 静的ウェブサイトホスティングを 有効にするを選択し
    • ホスティングタイプは 静的ウェブサイトをホストする を選択します。
    • インデックスドキュメント は index.htmlとします。 S3 上に存在しないのでエラーコードがわざと返されて CloudFront にいくようにします。
    • エラードキュメントを先ほど作成した HTML ファイルにします。(e.g., maintenance.html)

注釈: CloudFront を使った S3 静的ファイルホスティングにおいて、通常は S3 の 静的ウェブサイトをホストする 機能をオンにする必要はありませんが、全ページで 503 ステータスを出力させるためにオン & 追加設定をしています。

CloudFront 作成

メンテナンスページ表示用の Distribution を作成します。

  • Create Distribution ボタンを押す
  • Web の Get Started ボタンを押す (RTMP 無くなったので、ここのステップはいつか無くなるような気がする)
  • Origin Settings の内容を入れる
    • Origin Domain Name で、先程作成した S3 バケットを入力する
    • Origin Path は空欄
    • Origin ID も空欄
    • Origin Access Identity は、正直、設定しても設定しなくても良いと思います。
  • Default Cache Behavior Settings
    • 全てデフォルトのまま。
    • ただし、キャッシュ時間を短くしたい場合があれば適宜変更します。もしかしたら、キャッシュは300秒 (5分) とかでもいいかも。なぜかというと、メンテに時間がかかり、メンテページに何か追加メッセージを表示させたい場合、デフォルトの CloudFront だとキャッシュ時間が6時間なので、メンテHTMLを更新したら、キャッシュを Invalidate をする必要があります。 Invalidate のステップが無駄であるかもであれば、短く設定しても良いです。
  • Distribution Setting
    • Alternate Domain Names にメンテページ対象のドメインを入力。www ありや www なしのドメインなど
    • SSL Certificate は Custom SSL Certificate (exmaple.com) を選び、先程生成した証明書を選択
    • その他はデフォルトのまま
  • 一旦、Distribution を作成し、10分ほど待つ
  • エラーページ設定
    • 先ほど作成した Distrubtion をクリック
    • Error Pages タブをクリック
    • Create Custom Error Response をクリック
    • HTTP Error Code は「403: Forbidden」を選択
    • Error Caching Minimum TTL(Second) は 300 (秒)
    • Customize Error Response は「Yes」
    • Response Page Path は S3 の静的サイトで作成したファイル名 (e.g., /maintenance.html) を入れる
    • HTTP Response Code は 「503: Service Unavailable」にする
      • 503 だと Google さんも、「あ、このサイトはメンテ中なんだな」ということがわかる!

    これで一旦設定完了です!

動作確認

DNS 設定前に動作確認をしてみましょう。

  • CloudFront より先ほど設定した Distrubiton の中に入り General タブをクリック
  • Domain Name にある XXXXXXXX.cloudfront.net というドメイン名をつけます。
  • SSH ターミナルなどで、dig XXXXXXXX.cloudfront.netとコマンドをうつ
  • そこで出てきた A レコードの IP アドレスを取得
  • 自分の PC の Hosts ファイルを書き換えて、先ほどの A レコードの IP アドレスを、メンテ対象ドメインとして設定し適用
  • ブラウザのプライベートモードなどできちんとメンテページが SSL 付きで表示されているか確認する

メンテ当日の手順書

メンテ実施前の手順書

1. [自分] メンテページを作成
2. [自分] 作業手順を作成
3. [お客様] メンテページのテスト表示確認
4. [お客様] or [自分]: DNS の対象ドメインの TTL が30秒になっていることを確認 (既存の TTL x2 以上前に、30秒に変更するのが必要)

メンテ当日の手順書

メンテ当日の手順は以下の通り

# メンテ作業手順

1. [お客様] or [自分]: DNS を以下の編集し、`exmaple.com` のドメインでメンテページが表示されるよう設定する
    - A レコードを削除
    - CNAME レコードを追加 / A Record Alias を追加
    - 値に `EXAMPLE.cloudfront.net` を入力
    - TTL は30秒
    - 変更実施
2. [お客様] or [自分]から C5J にDNS切り替え完了を連絡
3. 双方: メンテナンス表示確認 (DNS 変更後、ブラウザキャッシュなどを行い2〜3分で確認)
4. [自分]: メンテナンスを実施
5. [自分]: C5J から [お客様] に、メンテ完了を連絡
6.[お客様] or [自分] : DNS 情報を元に戻す
    - CNAME レコードを削除
    - A レコードを追加
    - A レコードの値に元の `XXX.XXX.XXX.XXX` を入力 / ELB Alias
    - TTL は30秒
    - 変更実施
7. メンテナンス表示解除を確認

### メンテページに切り替える時

Example のレコードを以下のように変更

Domain | Type | Value | TTL
---------------------------------------------|------------|--------------------------------------------|----
example.com | CNAME | XXXXXXXXXX.cloudfront.net | 30


### メンテページから戻すとき

example.com のレコードを以下のように変更

Domain | Type | Value | TTL
---------------------------------------------|----|---------------------|----
example.com | A | XXX.XXX.XXX.XXX | 30

以上

謝辞

@yousan にトップページでも、503 ステータスコードを表示させるために S3 側で全ページが 404 になるように、S3 で作成するファイルは index.html 以外のファイル名で登録したほうが良いとご意見をいただきました。当記事は修正済みです。ありがとうございます。