クラウドインテグレーション事業部の林です。

今回はLCU(ロードバランサーキャパシティユニット) 予約を予定時刻に事前に設定できるよう以下サービスを利用し実装してみましたのでご紹介します。

・AWS Lambda
・Amazon EventBridge
・Amazon Q Developer in chat applications (旧称: AWS Chatbot)
・Amazon SNS

 

背景

以前はELBで急激なアクセス増加が見込まれる場合、事前にAWSサポートへサポートケースを作成の上、暖気申請を行う必要がありました。

しかしながら、現在は Load Balancer Capacity Unit Reservation (LCU 予約) 機能をご利用いただくことで、AWS サポートにご依頼いただかずとも、ユーザー自身でLCU 予約を実施することで事前にスケールさせることが可能となりました。

Application Load Balancer と Network Load Balancer のロードバランサーキャパシティユニット予約
https://aws.amazon.com/jp/about-aws/whats-new/2024/11/load-balancer-capacity-unit-reservation-application-balancers/

Amazon Web Services ブログ:ロードバランサーキャパシティユニット(LCU)予約を活用したトラフィック急増への備え
https://aws.amazon.com/jp/blogs/news/using-load-balancer-capacity-unit-reservation-to-prepare-for-sharp-increases-in-traffic/

 

しかし、AWSサポートを利用した暖機申請(Pre-warming) と異なり期間指定でスケールさせることはできず、
期間を指定する必要がある場合、 EventBridge Scheduler & Lambda 等を利用した構成を検討しなければならない状況です。

 

事前準備

ロードバランサーキャパシティユニット (LCU) 予約機能を利用するにあたり、

アカウントのService Quotasにてクォータ “Reserved Application Load Balancer Capacity Units (LCU) per Region”の引き上げを事前に行なっておく必要があります。

Service Quotasのサービス画面から該当のクォータが今回の設定するLCU予約数を満たしているかどうか事前に確認してください。

クォータ申請を過去一度も行なってない場合はデフォルトの0になっているため、Service Quotasよりクォータの引き上げ申請を行なってください。

また、記事執筆時点ではLCU 予約の際は最低100LCUの設定が必要となります。

LCU予約設定自動化作業概要

今回の設定作業の目的としてはEventBridgeにてLCU予約設定を事前に設定しておき、予約時間になったらあらかじめ設定していたLCU数でLCU予約を自動的に設定されるように実装することです。

また、LCU予約設定が正常に設定されたかどうかもチームで確認を行いたかったため、Slackで正常に設定されたかどうかの結果を確認できるよう、Amazon SNS と Amazon Q Developer in chat applications (旧称: AWS Chatbot)を使用し、Amazon Q アプリ経由で通知するようにも設定しました。

それでは、作業手順について説明していこうと思います!

1.IAMにてLCU用ポリシー作成

まず、IAM→ポリシー→ポリシーの作成→JSONで作成にて以下のポリシーを作成します。
※SNSに結果を送信するためsns:Publishの権限も追加
※ポリシー名は任意になりますが、今回はLCUPolicyと命名しました。

{
“Version”: “2012-10-17”,
“Statement”: [
{
“Effect”: “Allow”,
“Action”: [
“elasticloadbalancing:ModifyCapacityReservation”,
“sns:Publish”
],
“Resource”: “*”
}
]
}

Lambda作成

以下内容でLambda関数作成しました。

関数の作成 一から作成
関数名 Capacity_reservations_for_Application-Load-Balancer
ランタイム Python 3.13
実行ロール 基本的な Lambda アクセス権限で新しいロールを作成
アーキテクチャ x86_64

 

サンプルコードとしては以下を使用し、正常にLCU予約が実行されたか実行結果をSlackで通知するように設定しました。

また、チーム内でLCU予約が実行されたか通知を確認したいため、Slackのチームメンバー全員のメンション先であるグループIDを指定するようにしました。

import boto3
import json
import os

# SNSトピックのARNを環境変数から取得
SNS_TOPIC_ARN = os.environ.get(‘SNS_TOPIC_ARN’)

def lambda_handler(event, context):
sns_client = boto3.client(‘sns’)
elbv2_client = boto3.client(‘elbv2’)

# 1. イベントから必須パラメータを取得
try:
load_balancer_arn = event[‘load_balancer_arn’]
capacity_units = int(event[‘capacity_units’])
except KeyError as e:
print(f”エラー: 必須パラメータ {str(e)} がイベントに含まれていません。”)
raise

# 2. 予約・変更か、解除かを判定
is_cancel_action = capacity_units < 100
action_description = “解除” if is_cancel_action else “予約”

# 3. メンション文字列を準備(グループIDを指定)
mention_text = “

try:
# 4. LCUの予約または解除を実行
if not is_cancel_action:
# LCUを予約・変更する場合 (100以上)
elbv2_client.modify_capacity_reservation(
LoadBalancerArn=load_balancer_arn,
MinimumLoadBalancerCapacity={
‘CapacityUnits’: capacity_units
}
)
else:
# LCUを解除する場合 (0など100未満)
elbv2_client.modify_capacity_reservation(
LoadBalancerArn=load_balancer_arn,
ResetCapacityReservation=True
)

# — 5. 成功通知の準備 —
subject = f”OK: LCU {action_description} Success”
message_content = {
“version”: “1.0”,
“source”: “custom”,
“content”: {
“title”: f”✅ LCU {action_description} 成功”,
“description”: f”{mention_text}\n\n- **ARN:** `{load_balancer_arn}`\n- **設定LCU数:** `{capacity_units}`”,
“color”: “#28a745″
}
}

# SNSにPublish
if SNS_TOPIC_ARN:
sns_client.publish(
TopicArn=SNS_TOPIC_ARN,
Subject=subject,
Message=json.dumps(message_content)
)

return {
‘statusCode’: 200,
‘body’: json.dumps({‘message’: f'{action_description}に成功し、Slackに通知しました’})
}

except Exception as e:
# — 6. 失敗通知の準備 —
subject = f”ERROR: LCU {action_description} Failed”
message_content = {
“version”: “1.0”,
“source”: “custom”,
“content”: {
“title”: f”🚨 LCU {action_description} 失敗”,
“description”: f”{mention_text}\n\n- **ARN:** `{load_balancer_arn}`\n- **設定LCU数:** `{capacity_units}`\n- **エラー:** `{str(e)}`”,
“color”: “#dc3545”
}
}

# SNSにPublish
if SNS_TOPIC_ARN:
sns_client.publish(
TopicArn=SNS_TOPIC_ARN,
Subject=subject,
Message=json.dumps(message_content)
)

raise e

 

もし、個人をメンションしたい場合以下のようなサンプルコードをご準備していただければ通知可能です。

import boto3
import json
import os

# SNSトピックのARNを環境変数から取得
SNS_TOPIC_ARN = os.environ.get(‘SNS_TOPIC_ARN’)

#【変更点】SlackのメンバーIDを直接指定
SLACK_MENTION_ID = “メンバーID”

def lambda_handler(event, context):
sns_client = boto3.client(‘sns’)
elbv2_client = boto3.client(‘elbv2’)

try:
load_balancer_arn = event[‘load_balancer_arn’]
capacity_units = int(event[‘capacity_units’])
except KeyError as e:
print(f”エラー: 必須パラメータ {str(e)} がイベントに含まれていません。”)
raise

is_cancel_action = capacity_units < 100
action_description = “解除” if is_cancel_action else “予約”

# メンション文字列を準備
mention_text = f”<@{SLACK_MENTION_ID}> ” if SLACK_MENTION_ID else “”

try:
if not is_cancel_action:
elbv2_client.modify_capacity_reservation(
LoadBalancerArn=load_balancer_arn,
MinimumLoadBalancerCapacity={‘CapacityUnits’: capacity_units}
)
else:
elbv2_client.modify_capacity_reservation(
LoadBalancerArn=load_balancer_arn,
ResetCapacityReservation=True
)

# — 成功通知の準備 —
subject = f”OK: LCU {action_description} Success”
message_content = {
“version”: “1.0”,
“source”: “custom”,
“content”: {
“title”: f”✅ LCU {action_description} 成功”,
“description”: f”{mention_text}\n\n- **ARN:** `{load_balancer_arn}`\n- **設定LCU数:** `{capacity_units}`”,
“color”: “#28a745″
}
}

if SNS_TOPIC_ARN:
sns_client.publish(
TopicArn=SNS_TOPIC_ARN,
Subject=subject,
Message=json.dumps(message_content)
)

return {
‘statusCode’: 200,
‘body’: json.dumps({‘message’: f'{action_description}に成功し、Slackに通知しました’})
}

except Exception as e:
# — 失敗通知の準備 —
subject = f”ERROR: LCU {action_description} Failed”
message_content = {
“version”: “1.0”,
“source”: “custom”,
“content”: {
“title”: f”🚨 LCU {action_description} 失敗”,
“description”: f”{mention_text}\n\n- **ARN:** `{load_balancer_arn}`\n- **設定LCU数:** `{capacity_units}`\n- **エラー:** `{str(e)}`”,
“color”: “#dc3545”
}
}

if SNS_TOPIC_ARN:
sns_client.publish(
TopicArn=SNS_TOPIC_ARN,
Subject=subject,
Message=json.dumps(message_content)
)

raise e

Lambdaコードのdeployを行いこちらは完了です。


SNSにてトピック作成

1.Amazon SNS→トピックを作成してください。

基本的にデフォルトの設定で問題ありません。

タイプ スタンダード
名前 lcu-reservation-notifications
表示名 lcu-reservation-notifications
暗号化 オフ

トピック作成後、Lambdaコードの環境変数項目にて、今回作成したSNSトピックのARNを環境変数として設定します。
Lambda->関数->Capacity_reservations_for_Application-Load-Balancer->設定->環境変数より設定できます。

 


Amazon Q Developer in chat applications (旧称: AWS Chatbot)

Amazon Qを使用し、Slackとの連携を設定します。

チャットクライアントを設定より、Slackの連携を行ってください。

Slack の認証ページにリダイレクトされ、連携を行うことができます。

連携後、新しいチャネルを設定より、以下内容でチャネルを設定します。(名称やログ設定等は任意で選択してください。)

設定名 lcu-notification-channel
Amazon CloudWatch Logs にログを発行 ON (すべてのイベント)
チャネル ID 通知をしたいチャンネルのチャネル IDを入力
アクセス許可->ロール設定 チャネルロール
チャネルロール テンプレートを使用して IAM ロールを作成する
IAMロール名 AWSChatbot-role
ポリシーテンプレート
通知のアクセス許可(Amazon Q Developer が Amazon CloudWatch からメトリクスグラフを取得できるようになります。)
Amazon Q Developer のアクセス許可(管理者アクセスなしで Amazon Q Developer とのインタラクションを可能にします。)
チャネルガードレールポリシー ReadOnlyAccess
通知 – オプション SNS トピック
SNS トピック lcu-reservation-notifications

 

通知テスト

1.Amazon Q通知アプリの招待を行います。

対象Slackチャンネルにて@Amazon Q にてメンションしアプリを招待できます。

2.Amazon Q Developer in chat applications (旧称: AWS Chatbot)にて設定済みチャネルの設定名:lcu-notification-channelを選択し、テストメッセージを送信を押下します。

Slackに通知が来ていることを確認できれば、Amazon Q Developer in chat applications との連携は問題ないです。

 

3.SNSトピックへのメッセージの発行を選択し、トピック ARNが正しいことを確認し以下でメッセージの発行を行います。

Slackに通知が来ていることを確認します。

件名 – オプション:test

{
“version”: “1.0”,
“source”: “custom”,
“content”: {
“title”: “✅ 手動テスト成功(メンション付き)”,
“description”: “ \n\nSNSコンソールからのテストメッセージです。\nこの形式で通知が届けば、Lambdaからの通知も正しく表示されます。”,
“color”: “#28a745”
}
}


Amazon EventBridgeにてスケジュール作成する

1.Amazon EventBridge→スケジュールより、以下スケジュールを作成する

スケジュール名 Start-LCU-Reservation
説明 – オプション Start-LCU-Reservation-hayashi-LCU-test-alb
スケジュールグループ default
1 回限りのスケジュール スケジュールのパターン
日付と時刻 実行したい日時
フレックスタイムウィンドウ オフ

 

2.AWS Lambda Invokeを選択

Lambda 関数にて今回作成したLambda 関数を選択します。

Capacity_reservations_for_Application-Load-Balancer

 

ペイロードは以下を選択します。

{
“load_balancer_arn”: “対象のロードバランサーのARNを記入”,
“capacity_units”: 100
}

3.設定 – オプション

スケジュールを有効化 ON
スケジュール完了後のアクション NONE
再試行ポリシー OFF
デッドレターキュー (DLQ) なし
暗号化 なし
このスケジュールの新しいロールを作成 Amazon_EventBridge_Scheduler_LAMBDA

 

4.スケジュールの確認と保存をします。

 

また、同じようにLCU予約の解除のスケジュールも作成します。

1.Amazon EventBridge→スケジュールより、以下スケジュールを作成する

スケジュール名 Stop-LCU-Reservation
説明 – オプション Stop-LCU-Reservation-hayashi-LCU-test-alb
スケジュールグループ default
スケジュールのパターン 1 回限りのスケジュール
日付と時刻 実行したい日時
フレックスタイムウィンドウ オフ

 

2.AWS Lambda Invokeを選択

Lambda 関数にて今回作成したLambda 関数を選択します。

Capacity_reservations_for_Application-Load-Balancer

 

ペイロードは以下を選択します。

{
“load_balancer_arn”: “対象のロードバランサーのARNを記入”,
“capacity_units”: 0
}

 

3.設定 – オプション

スケジュールを有効化 ON
スケジュール完了後のアクション NONE
再試行ポリシー OFF
デッドレターキュー (DLQ) なし
暗号化 なし
既存のロールを使用 Amazon_EventBridge_Scheduler_LAMBDA

4.スケジュールの確認と保存をします。

 

実行確認

LCU予約

設定したスケジュールにて以下のようにLCU予約が実行された通知が行われました。

 

対象のロードバランサーにてLCU予約が問題なく実行されているか確認できました。

※一度キャンセルを実施していたため今日の残りの減少額が 1 に変わっています。(1日あたり2回までの回数制限が存在します)

Application Load Balancer のロードバランサーキャパシティユニット予約をリクエストするhttps://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/request-capacity-unit-reservation.html

 

LCU予約解除

設定したスケジュールにて以下のようにLCU予約の解除が実行された通知が行われました。

また、対象のロードバランサーにてLCUが解除されていることも確認できました。

 

 

 

 

最後に

弊社ではお客様の課題に合わせて、「監視運用保守サービス」等、当社が提供するサービスをご提案することも可能となっております。

ぜひお気軽にアイレットへご相談ください。