Elastic-Load-Balancing

ELB(ALB)でターゲットグループのヘルスチェックに失敗したらSorryページを表示したい

はじめに

こんにちは、ディーネットの山田です。

表題にもあるとおり、ELB(ALB)でターゲットグループに参加している全ホストがヘルスチェックに失敗したら、ELB(ALB)単体でSorryページを表示できないか調べてみました。

ちなみにですが、全ホストがヘルスチェックに失敗した場合、ELB(ALB)の動作としてはフェイルオープンという形になりヘルスチェックに失敗しているターゲットであってもリクエストを投げる形になります。

環境の構成図

AWS環境の構成としては、一般的によく用いられる以下の構成を作成いたしました。

インターネットからはELB(ALB)が面しており、その配下がEC2となっております。

万が一、ELB(ALB)のターゲットグループで全ホストがヘルスチェックに失敗したら、ALBの固定レスポンス機能を使って簡易的なSorryページを表示させる形となります。

やりたいこと

ELB(ALB)のターゲットグループで全ホストがヘルスチェックに失敗したら(正常なホストが0になったら)、ALBの固定レスポンス機能で簡易的なSorryページを訪問者に対して表示させる。

構成要素

  • Amazon CloudWatch
    • Application Load Balancerの”HealthyHostCount”が”0”になった場合にアラーム状態となるように監視します。
  • AWS Step Functions
    • Application Load Balancerのリスナールールを入れ替えて、EC2へ転送するか、もしくは固定レスポンスでSorryページを表示するかを自動的に行います。
  • Amazon EventBridge
    • CloudWatchで設定したアラームの状態に応じて、Step Functionsを実行します。

実際に設定していきます

前提として、環境の構成図にあるインフラ環境はできあがっているものと仮定しております。

Application Load Balancerのリスナールールについて

リスナーのリスナールールにて、それぞれ優先度が異なるリスナールールを作成します。

優先度のみで、アクションを制御(ターゲットグループへ転送 or 固定レスポンス)したいため条件には、送信元IPアドレスで全て(0.0.0.0/0)を対象とします。

優先度については、Step Functionsで利用するので、今回の検証においては以下と決めます。

優先度 用途
1 Sorryページの固定レスポンスを有効化したい場合
10 EC2へリクエストを転送したいルール
99 Sorryページの固定レスポンスを無効化したい場合

ターゲットグループ(EC2)へリクエスト内容を転送するルール

  1. ルールに好きな名前を決めます(ここでは分かりやすいようにGotoEC2としています)

  1. ルールの条件を決めます(ここでは送信元IP全てを対象としています)

  1. 条件に合致したリクエストをどこに転送するのか決めます(ここではwebserver-tgというターゲットグループを対象としています)

  1. ルールの優先度を決めます(ここでは10とします)

  1. 最終確認をして問題なければ、作成します

固定レスポンス機能でSorryページを表示するルール

  1. ルールに好きな名前を決めます(ここでは分かりやすいようにGotoSorryとしています)

  1. ルールの条件を決めます(ここでは送信元IP全てを対象としています)

  1. 条件に合致したリクエストに固定レスポンスを返すように決めます

レスポンスコード、コンテンツタイプ、レスポンス本文に好きな内容を入れます。

注意点としては、レスポンス本文は1024文字制限があるので、凝ったSorryページとしたい場合は、文字数を気にかけておいて下さい。

  1. ルールの優先度を決めます(ここでは99とします)

  1. 最終確認をして問題なければ、作成します。

最終的にリスナールールは、以下のようになりました。

★ポイント★

リスナールールは、リスナー毎に設定する必要があるため、HTTP(80)とHTTPS(443)それぞれ存在している場合は、双方に同様の設定をしてください。

今回の検証では、HTTP(80)のみを対象として行っています。

CloudWatchのアラーム設定について

Application Load Balancerの”HealthyHostCount”メトリクスが、”0”になった場合にアラーム状態となるルールを作成します。

  1. 対象となるメトリクスを選択します。

“HealthyHostCount”のメトリクスを利用します。

正常と見なされるターゲットの数。
レポート条件: ヘルスチェックが有効になっている場合にレポートされます
統計値: 最も有用な統計値は?AverageMinimum、および?Maximum?です。

Application Load Balancerのメトリック

統計については、”最小”とします。

期間については、”1分”とします。

条件を定義します。

  1. アクションについては、不要なので何も設定しない

  1. アラーム名については任意で設定します

  1. 最終確認して問題なければ、アラームを作成します。

Step Functionsの設定について

Application Load Balancerのリスナールールを変更するステートマシンを2つ作成します。

具体的な作成方法は割愛いたしますが、定義のみご紹介いたします。

なお、定義にはリスナールールのARNを使用しますので、”GotoSorry”のARNを控えて下さい。

ターゲットグループ(EC2)へリクエスト内容を転送するルールの優先度を高くする

{
  "Comment": "A description of my state machine",
  "StartAt": "SetRulePriorities HTTP:80",
  "States": {
    "SetRulePriorities HTTP:80": {
      "Type": "Task",
      "Parameters": {
        "RulePriorities": [
          {
            "RuleArn": "arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXXX:listener-rule/app/webserver-lb/ec7bXXXXXXXXXXXX/2a6bXXXXXXXXXXXX/1b1dXXXXXXXXXXXX",
            "Priority": 99
          }
        ]
      },
      "Resource": "arn:aws:states:::aws-sdk:elasticloadbalancingv2:setRulePriorities",
      "End": true
    }
  }
}

固定レスポンス機能でSorryページを表示するルールの優先度を高くする

{
  "Comment": "A description of my state machine",
  "StartAt": "SetRulePriorities HTTP:80",
  "States": {
    "SetRulePriorities HTTP:80": {
      "Type": "Task",
      "Parameters": {
        "RulePriorities": [
          {
            "RuleArn": "arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXXX:listener-rule/app/webserver-lb/ec7bXXXXXXXXXXXX/2a6bXXXXXXXXXXXX/1b1dXXXXXXXXXXXX",
            "Priority": 1
          }
        ]
      },
      "Resource": "arn:aws:states:::aws-sdk:elasticloadbalancingv2:setRulePriorities",
      "End": true
    }
  }
}

EventBridgeの設定について

CloudWatchのアラーム状態に応じたイベントを受信するEventBridgeを2つ作成します。

具体的な作成方法は割愛いたしますが、イベントパターンとターゲットのみご紹介いたします。

なお、定義にはCloudWatchアラームのARNを使用しますので、”webserver-lb-target-healthyhost-zero”のARNを控えて下さい。

アラーム状態が異常の場合

Sorryページを固定レスポンス機能で返却する形となります。

  1. イベントパターン

このイベントパターンでは、”webserver-lb-target-healthyhost-zero”がアラーム状態であることを検知できます。

{
  "source": ["aws.cloudwatch"],
  "detail-type": ["CloudWatch Alarm State Change"],
  "resources": ["arn:aws:cloudwatch:ap-northeast-1:XXXXXXXXXXXX:alarm:webserver-lb-target-healthyhost-zero"],
  "detail": {
    "state": {
      "value": ["ALARM"]
    }
  }
}
  1. ターゲット

ターゲットには、「固定レスポンス機能でSorryページを表示するルールの優先度を高くする」Step Functionsのステートマシンを設定します。

アラーム状態が正常の場合のイベントパターン

ターゲットグループ(EC2)へリクエスト内容を転送する形となります。

  1. イベントパターン

このイベントパターンでは、”webserver-lb-target-healthyhost-zero”が正常状態であることを検知できます。

{
  "source": ["aws.cloudwatch"],
  "detail-type": ["CloudWatch Alarm State Change"],
  "resources": ["arn:aws:cloudwatch:ap-northeast-1:XXXXXXXXXXXX:alarm:webserver-lb-target-healthyhost-zero"],
  "detail": {
    "state": {
      "value": ["OK"]
    }
  }
}
  1. ターゲット

ターゲットには、「ターゲットグループ(EC2)へリクエスト内容を転送するルールの優先度を高くする」Step Functionsのステートマシンを設定します。

動作テスト

ヘルスチェックに成功し、EC2へリクエストが転送されている場合

EC2に設置しているページが表示されました。

ヘルスチェックに失敗し、Sorryページが返却されている場合

ELB(ALB)の固定レスポンス機能で設定したページが表示されました。

ヘルスチェックに失敗した直後(リスナールールが切り替わるまでの間)

リスナールールが自動的に変更されるまでは、”504 Gateway Timeout”が発生しました。

ここについては、制御できないので”504”を見せたくない場合は、CloudFrontの活用をおすすめいたします。

まとめ

  • AWSの各種サービスを組み合わせることで、ELB(ALB)のヘルスチェックに失敗した場合Sorryページを自動的に表示することができました。
  • CloudFrontを使ったSorryページのパターンと比べて、CloudWatchアラームやリスナールールで切り替えを実装している関係上、Sorryページに切り替わるまで数分(体感は3分程度)のタイムラグが発生しました。
  • 一時的に、504 Gateway Timeoutが表示されることもあるので、障害時にSorryページへの自動切り替えを想定している場合は、CloudFrontも可能な限り組み合わせた方がよさそうですね。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA