Lambda 関数を利用して EC2 Auto Scaling グループの、最小の希望する容量が 0 になったことをトリガーに SNS 通知するように実装してみた

Lambda 関数を利用して EC2 Auto Scaling グループの、最小の希望する容量が 0 になったことをトリガーに SNS 通知するように実装してみた

Clock Icon2025.02.08

はじめに

テクニカルサポートの 片方 です。
今回は Lambda 関数を利用して EC2 Auto Scaling グループの、最小の希望する容量が 0 になったことをトリガーに SNS から通知する仕組みを実装してみました。

実装してみた

以下の順番で実装します。

  • SNS 作成
  • 実行ロール作成
  • Lambda 関数作成

EC2 Auto Scaling の作成については省かせていただきます。弊社ブログを参考に作成してください。
https://dev.classmethod.jp/articles/how-to-create-ec2-auto-scaling-group/

SNS

通知機能として SNS を利用します。SNS トピックおよびサブスクリプションを作成します。
Protocol (プロトコル) として Email (E メール) を選択して作成しました。後に arn が必要なので控えます。

https://docs.aws.amazon.com/ja_jp/sns/latest/dg/sns-getting-started.html

0001

実行ロール

信頼関係
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
アタッチするポリシー例
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "logs:CreateLogGroup",
            "Resource": "arn:aws:logs:${AWS_REGION}:${ACCOUNT_ID}:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:${AWS_REGION}:${ACCOUNT_ID}:log-group:/aws/lambda/${FUNCTION_NAME}:*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "autoscaling:DescribeAutoScalingGroups"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "sns:Publish"
            ],
            "Resource": "arn:aws:sns:${AWS_REGION}:${ACCOUNT_ID}:*"
        }
    ]
}

※ 適宜修正してください。

Lambda 関数

Python 3.13 で作成しました。
実行ロールでは、既存のロールを使用するを選択し、先ほど作成したロールを指定します。

Lambda 関数例
import os
import boto3
import json
from datetime import datetime

def lambda_handler(event, context):
    # 環境変数から設定を取得
    asg_name = os.environ['ASG_NAME']
    sns_topic_arn = os.environ['SNS_TOPIC_ARN']

    try:
        # Auto Scalingクライアントの初期化
        autoscaling = boto3.client('autoscaling')

        # Auto Scalingグループの情報を取得
        response = autoscaling.describe_auto_scaling_groups(
            AutoScalingGroupNames=[asg_name]
        )

        # Auto Scalingグループが存在しない場合のエラーハンドリング
        if not response['AutoScalingGroups']:
            raise Exception(f"Auto Scaling Group '{asg_name}' not found")

        asg = response['AutoScalingGroups'][0]
        min_size = asg['MinSize']

        # MinSizeが0の場合、SNS通知を送信
        if min_size == 0:
            sns = boto3.client('sns')

            # 通知メッセージの作成
            message = {
                'timestamp': datetime.now().isoformat(),
                'asg_name': asg_name,
                'alert': 'Auto Scaling Group MinSize is set to 0',
                'current_min_size': min_size,
                'current_desired_capacity': asg['DesiredCapacity'],
                'current_max_size': asg['MaxSize']
            }

            # SNS通知の送信
            sns.publish(
                TopicArn=sns_topic_arn,
                Subject=f"Alert: {asg_name} MinSize is 0",
                Message=json.dumps(message, indent=2)
            )

            return {
                'statusCode': 200,
                'body': json.dumps({
                    'message': 'Alert sent successfully',
                    'asg_name': asg_name,
                    'min_size': min_size
                })
            }

        # MinSizeが0でない場合
        return {
            'statusCode': 200,
            'body': json.dumps({
                'message': 'ASG MinSize is not 0',
                'asg_name': asg_name,
                'min_size': min_size
            })
        }

    except Exception as e:
        # エラーハンドリング
        error_message = str(e)
        print(f"Error: {error_message}")

        return {
            'statusCode': 500,
            'body': json.dumps({
                'error': error_message
            })
        }

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/autoscaling.html

環境変数を利用しているため、作成している EC2 Auto Scaling グループ名と、SNS トピック arn を記載ください。

  • ASG_NAME: Auto Scaling グループの名前
  • SNS_TOPIC_ARN: 通知先 SNS トピック ARN

0002

※ 適宜修正してください。

検証してみた

最小の希望する容量が 2 の状況です。

0003

作成した、Lambda 関数をテストします!成功です。
しかしながら、最小の希望する容量が 0 ではないので、SNS からの通知は発生しません。
0004

では、最小の希望する容量が 0 の状態でテストします。

0005

こちらも、問題なく成功しました!

0006

では、通知内容を確認します。

0007

成功です!

まとめ

EventBridge のスケジュール機能を利用して、当該 Lambda 関数を定期実行させるなど合わせてご検討ください。
また、本ブログでは最小の希望する容量を監視対象にしていますが、"希望するキャパシティ" や "最大の希望する容量" などご自身の環境に合わせて使用することも良いと思います。本ブログが誰かの参考になれば幸いです。

https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-create-rule-schedule.html

ルールは、イベントに応じて実行したり、一定の時間間隔で実行したりすることができます。例えば、AWS Lambda 関数を定期的に実行するには、スケジュールに従って実行するルールを作成します。

参考資料

アノテーション株式会社について

アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.