ALBのリスナールールを自動で切り替えて、更新中だけメンテナンス画面を表示する方法


CloudFormationによるリリース時にメンテナンス画面とEC2のサイトを自動で切り替えるために、ALBによるリスナールールを使用しました。CloudFormationからでなくても自動切り替えは可能だと思うので、参考になれば幸いです。

経緯

Auto Scalingグループ内のEC2インスタンスが常時1台という要件のもと、CloudFormationによるリリース時に、一時的にALB配下に2台のEC2インスタンスが起動するタイミングがあり、新旧どちらのインスタンスにも接続できてしまう状況が発生しました。これを解決するために、リリース中(CloudFormationによる更新中)はメンテナンス画面を表示し、更新が完了したら新しいEC2に接続するという挙動を目指しました。更新が完了した時点で古いEC2インスタンスはALBから登録解除されているので、更新完了後は新しいEC2インスタンスにのみ接続されるようになります。

構成図


かなりざっくりですが、リソースの流れとしては上記がすべてです。
ALBのリスナールールの順序の入れ替えはLambdaからAPIで行います。

設定

各リソースにおける設定を紹介します。

CloudFormation

スタック作成時や更新時の通知先にSNSトピックを指定できるので、この機能を利用します。

SNS

SNSから処理を担当するLambda関数と連携します。
Lambdaについてはこちらにまとめてありますので参考までにご覧ください。

ALB

リスナールールを作成します。
とりあえずALBのコンソールまで移動しましょう。

ALBコンソールで対象のロードバランサーを選択して「リスナー」タブを選択し、「ルールの表示/編集」をクリックします。

何も設定しなければデフォルトアクションのみとなっています。
今回はターゲットグループへの転送ルールと固定レスポンスを返すルールを作成します。
画面上部の追加アイコンをクリックし、「ルールの挿入」をクリックします。

IF条件を指定します。「パス」を選択し、*ですべてのリクエストを指定します。

THENでアクションの追加をクリックし、「転送先」にターゲットグループを指定します。

これで、ターゲットグループへの転送ルールができました。一度「保存」をクリックしましょう。

続いて、メンテナンス画面用の固定レスポンスを返すルールを作成します。

IF条件は先ほどと同様にパスが*ですべてのリクエストです。
THENは、「固定レスポンスを返す」を選択し、レスポンスコードで200を返します。
Content-Typeはtext/htmlを選択し、レスポンス本文にメンテナンス画面用のhtmlを貼り付けます。

ちなみに今回貼り付けたhtmlは以下のようなシンプルな画面です。

index.html
<!DOCTYPE html>
<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
    <title>システムメンテナンスのお知らせ</title>
  </head>
  <body>
    <div style="width: 640px; margin: 50px auto">
      <div style="border: 1px solid #ccc; padding: 30px; margin-top: 30px">
        <h2 style="color: #f00">システムメンテナンスのお知らせ</h2>
        <p>
          いつもご利用いただき、ありがとうございます。<br />
          このたびサービス向上のため、システムメンテナンスを実施いたします。<br />
          お客さまには大変ご迷惑をおかけいたしますが、何卒ご了承いただけますようよろしくお願い申し上げます。
        </p>
        <p>ご不便をおかけいたしますがよろしくお願い申し上げます。</p>
      </div>
    </div>
  </body>
</html>

設定できたら「保存」をクリックします。
ルールは優先順位の高いほうから評価されるため、この順位の入れ替えを使ってメンテナンス画面との切り替えを行います。

とりあえずターゲットグループへの転送ルールを1番にしておきます。


これでルールの追加が完了しました。

実際にALBにアクセスするとEC2に転送されていることがわかります。

それではコンソール上で優先順位を入れ替えてみましょう。
固定レスポンスを1番にしてみます。

再度ALBにアクセスしてみると、今度はメンテナンス画面が表示されました。
こんなかんじでルールの優先順位を変更することで表示を切り替えることができます。

以上のようにコンソールから切り替えることもできますが、SetRulePriorities APIを使えば自動切り替えができるので、後述するLambdaからAPIで切り替えます。

Lambda

ALBのリスナールールを切り替える処理を記述します。
詳しくはこちらにまとめてありますので参考までにご覧ください。

まとめ

今回はALBのリスナールールを自動で切り替えることで、EC2のサイトとメンテナンスページを自動で切り替える方法を紹介しました。
APIで切り替えられるので、フロントエンドからAPI GatewayからLambdaを起動すれば、ボタンによる切り替えも可能です。リリース時以外にも想定外の障害時にすぐに切り替えることもできます。切り替えにかかる時間は10~20秒ほどだったので、これを許容できるかどうかにもよるかと思いますが、参考になれば幸いです。

参考資料

Application Load Balancer のリスナールール - Elastic Load Balancing
AWS まだS3でSorryページを表示してる? | 技術者のブログ
SetRulePriorities - Elastic Load Balancing