CloudWatch Events で Sorry ページを切り替える
こんにちは、米須です。
このブログを開設して1年になりました。ちょっと忙しくて投稿が止まっていましたが、今後も色々なネタをお届けできたらと思っていますので、引き続きよろしくお願いします(^0^)ノ
さて、前回は ALB の「固定レスポンスアクション」を利用した Sorry ページの表示方法について説明しました。このままだとずっと Sorry ページが表示されてしまうので、CloudWatch Events を利用して特定の時間だけ Sorry ページが表示されるような仕組みを作ってみたいと思います。
今回の構成
下記の構成図にある赤い矢印の流れが今回構築するところです。
CloudWatch Events を利用して Lambda 関数を実行し、ALB に設定されているルールの優先度を変更することで、特定の時間だけ Sorry ページが表示されるようになります。

Lambda の設定
まずは Lambda から見ていきましょう。
ソース
主な流れは下記のとおりです。
① 環境変数からリスナーの ARN を取得
② リスナーの情報を取得
③ 変更対象のルールを判別
④ 優先度(Priority)を設定
import json
import boto3
import os
def lambda_handler(event, context):
listener = os.environ['LISTENER_ARN']
client = boto3.client('elbv2')
# 現在のルールのプロパティを確認
result = client.describe_rules(ListenerArn=listener, )
for rule in result['Rules']:
rule_arn = rule['RuleArn']
priority = rule['Priority']
type = rule['Actions'][0]['Type']
#fixed-response タイプのルールが存在したら、優先度を変更する
if type == "fixed-response":
if priority == "1":
set_priority = 99
else:
set_priority = 1
client.set_rule_priorities(
RulePriorities=[{'RuleArn': rule_arn, 'Priority': set_priority},]
)
① 環境変数からリスナーの ARN を取得
リスナーの ARN はロードバランサーのリスナータブで取得できます。下記の赤枠にある▼を押すと表示されるので、丸ごとコピーします。

コピーした内容は Lambda の設定タブにある環境変数に設定します。今回はキー名を「LISTENER_ARN」としており、プログラムの中で
listener = os.environ['LISTENER_ARN’]
とすることで取得できます。

② リスナーの情報を取得
① でリスナーの ARN が取得できたので、下記のようにしてリスナーの情報を取得します。
result = client.describe_rules(ListenerArn=listener, )
[boto3 ドキュメント]
describe_rules
https://boto3.amazonaws.com/v1/documentation/api/1.9.42/reference/services/elbv2.html#ElasticLoadBalancingv2.Client.describe_rules
このメソッドにより取得できるデータは、上記ドキュメントの Returns を見ると分かります。
③ 変更対象のルールを判別
今回の仕組みのポイントは、「どうやって Sorry ページを設定しているルールを判別するか」という点にあると思います。② で取得した情報の中から判別に使えそうな項目を探すのですが、「固定レスポンスアクション」を設定しているルールは1つしかなかったので、type が 「fixed-response」かどうかで判別することにしました。
(今考えると、ルールの ARN もあるので、それを利用するという手もあると思います)
④ 優先度(Priority)を設定
対象のルールが判別できたら、set_rule_priorities メソッドを使用してルールの優先度を設定します。
[boto3 ドキュメント]
set_rule_priorities
https://boto3.amazonaws.com/v1/documentation/api/1.9.42/reference/services/elbv2.html#ElasticLoadBalancingv2.Client.set_rule_priorities
ここで注意点が2つあります。
【 注意点1 】
ALB のルール設定画面において赤枠部分に数字が表示されていますが、これは優先度ではありません。ただの順番です。実際の優先度は ② で取得したデータの「Priority」の項目から取得できます。(画面上では確認できないっぽいです)

マネコンからルールを作成したり削除したりしていると各ルールの優先度に何が設定されているか分からなくなるので、プログラム内で設定する優先度は 1 or 99 にしました。(ルールを全部舐めて優先度を設定するのがちょっと面倒だったので、1 or 99 なら一番前か一番後ろになるだろうという安易な考えです(^^;)
【 注意点2 】
下記画像で説明したいのですが、1つ目のルール(ARN の末尾が b3a45)の優先度が2、2つ目のルール(ARN の末尾が 06006)の優先度が 99 になっていたとします。この状態でマネコンから1つ目のルールを2つ目のルールの下に来るよう順番を入れ替えると、2つめのルールの優先度である 99 より大きい値(100)が設定されます。

プログラムの中では 1 or 99 として設定しているので、こうなってしまうと何度 Lambda を実行しても通常のサイトを表示するルールと「固定レスポンスアクション」を設定しているルールは入れ替わらなくなってしまいます。優先度を 1 or 99 と決め打ちで設定するようなプログラムにする場合は、マネコンでルールを変更しないようにしましょう(^^;
IAM ロールの設定
プログラムができたら、Lambda が実行できるよう IAM ロールを設定します。
describe_rules メソッドと set_rule_priorities メソッドを使っているので、忘れずに下記の権限を追加しておきましょう。
elasticloadbalancing:DescribeRules
elasticloadbalancing:SetRulePriorities
ここまで出来たら Lambda のテスト機能を使って動作確認してみてください。
CloudWatch Events の設定
動作確認ができたら、CloudWatch Events でルールを作成します。
スケジュールの Cron式:通常のページから Sorry ページへ切り替える時間を設定
Lambda 関数:今回作成した Lambda を指定

同様に、Sorry ページから通常のページへ切り替える時間を設定したルールをもう一つ作ると、Sorry ページを切り替えられる仕組みが完成します。
さいごに
若干決め打ちな所はありますが、夜間 EC2 を止めても Sorry ページが表示できるなんて、クラウドならではの構成ですよね。
ではまた。