1
1

More than 1 year has passed since last update.

CloudwatchのEC2自動復旧をlambdaで自動一括設定

Posted at

Cloudwatchの機能を使ってEC2の自動復旧(オートリカバリー)を設定することができますが、管理しているEC2が増えてくるとアラーム設定自体がとても面倒で、かつ設定漏れのリスクも出てきます
そこで、EC2自動復旧の自動一括設定ができるようにします

前提条件

lambdaを使ってEC2のオートリカバリーを自動設定する

Cloudwatchで、EC2の「StatusCheckFailed_System」を検知し自動再起動する設定ができます
lambdaを使って、特定のタグを設定したEC2に対して、オートリカバリーのCloudwatchアラームを自動一括設定できるようにします

まずは、lambdaを作成します

python 3.9でlambda関数を作成しました

putcloudwatchalarm.py
import json
import boto3
import config

# Cloudwatchアラーム設定関数
def put_cwalarm(instanceId, ec2_name):

    print ("instanceId = ", instanceId)
    print ("ec2 name tag = ", ec2_name)
    cloudWatch   = boto3.client('cloudwatch')
    result = cloudWatch.put_metric_alarm(
        AlarmName          = config.ALARM_NAME + "_" + instanceId,
        AlarmDescription   = ec2_name + config.ALARM_DESC,
        AlarmActions       = [
            config.ALARM_TOPIC,
            config.ALARM_ACTION
        ],
        OKActions       = [
            config.ALARM_TOPIC
        ],
        MetricName         = config.METRIC_NAME,
        Namespace          = config.NAMESPACE ,
        Statistic          = config.STATISTICS,
        Dimensions         = [{"Name": "InstanceId", "Value": instanceId}],
        Period             = config.ALARM_PERIOD,
        EvaluationPeriods  = config.EVALUATION_PERIOD,
        Threshold          = config.THRESHOLD,
        ComparisonOperator = config.COMPARISON
    )

    print ("responce = ", result)
    #put metric alarmに対する戻り値の中のHTTPStatusCodeのみをリターンする
    return result["ResponseMetadata"]["HTTPStatusCode"]

def lambda_handler(event, context):

    msg = ""
    err_msg = ""
    ins_id = ""

    #TAG KEYが設定されているEC2に対しCloudwatchアラーム設定関数を実行する
    for reservation in boto3.client('ec2').describe_instances(Filters=[{'Name': 'instance-state-name','Values': ['running']}])["Reservations"]:
        for instance in reservation["Instances"]:
            for tag in instance["Tags"]:
                if(tag["Key"] == config.TAG_KEY and tag["Value"] == config.TAG_VALUE):
                    #InstanceIdを取得する
                    ins_id  = instance["InstanceId"]
                    #Name tagを取得する
                    ec2_tags = dict([(tag['Key'], tag['Value']) for tag in instance['Tags']])
                    name_tag = ec2_tags['Name']
                    #alarmを設定する
                    res = put_cwalarm(ins_id, name_tag)

                    #200OK以外はエラーをメッセージに入れておく
                    if(res == 200) :
                        msg = "[OK]" + ins_id + " : created/updated alert" + msg + " / "
                    else :
                        err_msg = "[ERROR]" + ins_id + " : failed alert create" + err_msg + " / "

    return {
        'statusCode': 200,
        'body': msg,
        'err': err_msg 
    }

環境設定値は別ファイルにしました
対象のタグ名、閾値等はお好みで設定してください、下記は参考です

config.py
 ALARM_ACTION       = "arn:aws:automate:ap-northeast-1:ec2:recover"
 METRIC_NAME        = "StatusCheckFailed_System"
 NAMESPACE          = "AWS/EC2"
 STATISTICS         = "Maximum"
 ALARM_PERIOD       = 60
 EVALUATION_PERIOD  = 2
 THRESHOLD          = 1
 COMPARISON         = "GreaterThanOrEqualToThreshold"

lambdaの設定

  • 対象のEC2が多い場合は実行時間がかかるので、lambdaのタイムアウトを長く設定しておいた方がタイムアウトエラーを回避できます
  • EC2とCloudwatchへのアクセスが必要なので、ロールを付与しておいてください
  • アラーム通知先のSNSを先に作成しておいてください

EC2の設定

  • TAGを設定しておいてください

実行

上記のlambda関数に引数は必要ないので、トリガー設定なしでそのまま実行すればOK
lambdaのコンソールからTestで実行してしまいましょう

結果

Cloudwatchコンソールを確認し、アラームが設定されていれば成功です
スクリーンショット 2022-02-10 20.51.22.png

閾値等の設定値を変更したい時、対象のEC2が増えた時

lambdaの設定値を変更して、再度lambdaを実行するだけでOKです
既存のアラームは更新され、そうではない場合は新規アラームが作成されます
アラーム名などCloudwatchで変更不可能の要素は変更できないので注意です

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1