boto3を使ってEC2のCloudWatchアラームを一括設定する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、菊池です。

EC2の基本的な監視として、CloudWatchのアラームを使うことはよくあると思います。EC2のステータスチェックや、CPU利用率などを監視して閾値超過時にSNSへ通知することなどは、マネージメントコンソールからも簡単に設定可能です。

しかし、EC2のインスタンス数が増えてくると、1つ1つアラートをマネジメントコンソールから設定するのは面倒になりますので、一括で設定するPythonスクリプトを作成しました。

設定内容と事前準備

今回設定するアラームは以下の2つです。

  • StatusCheckFailed_System
    • 5分ごとにチェックし、2回連続で検知したらアラート発生
    • SNS Topicへの通知と、AutoRecoverによる復旧を行う
  • CPU_Utilization
    • 5分ごとにチェックし、2回連続で80%を超過したらアラート発生
    • SNS Topicへの通知を行う

また、事前準備として以下の設定を実施しておきます。

  • 通知先のSNS Topicの作成
  • アラーム設定対象のインスタンスにTagを付与
    • Key:Alert
    • Value:Enable

スクリプト

Tagが設定されたEC2インスタンスに一括でアラームを作成するPythonスクリプトです。実行環境は、Amazon Linuxで試しました。事前にboto3をpipでインストールしておく必要があります。

#!/usr/bin/env python

import boto3

# 対象とするインスタンスを指定するTag
TARGET_TAG_KEY            = "Alert"
TARGET_TAG_VALUE          = "Enable"

# StatusCheckアラームのパラメータ
STATUS_ALARM_NAME         = "STATUS_ALERT"
STATUS_ALARM_DESC         = "STATUS_CHECK_FAILED"
STATUS_ALARM_TOPIC        = "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:testTopic"
STATUS_ALARM_ACTION       = "arn:aws:automate:ap-northeast-1:ec2:recover"
STATUS_METRIC_NAME        = "StatusCheckFailed_System"
STATUS_NAMESPACE          = "AWS/EC2"
STATUS_STATISTICS         = "Average"
STATUS_ALARM_PERIOD       = 300
STATUS_EVALUATION_PERIOD  = 2
STATUS_THRESHOLD          = 1
STATUS_COMPARISON         = "GreaterThanOrEqualToThreshold"

# CPU利用率アラームのパラメータ
CPU_ALARM_NAME            = "CPU_ALERT"
CPU_ALARM_DESC            = "CPU_Utilization_ALERT"
CPU_ALARM_TOPIC           = "arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:testTopic"
CPU_METRIC_NAME           = "CPUUtilization"
CPU_NAMESPACE             = "AWS/EC2"
CPU_STATISTICS            = "Average"
CPU_ALARM_PERIOD          = 300
CPU_EVALUATION_PERIOD     = 2
CPU_THRESHOLD             = 80
CPU_COMPARISON            = "GreaterThanOrEqualToThreshold"

# StatusCheckアラームの設定
def put_status_alarm(instanceId):
    cloudWatch   = boto3.client('cloudwatch')
    cloudWatch.put_metric_alarm(
        AlarmName          = STATUS_ALARM_NAME + "_" + instanceId,
        AlarmDescription   = STATUS_ALARM_DESC,
        AlarmActions       = [
            STATUS_ALARM_TOPIC,
            STATUS_ALARM_ACTION
        ],
        MetricName         = STATUS_METRIC_NAME,
        Namespace          = STATUS_NAMESPACE ,
        Statistic          = STATUS_STATISTICS,
        Dimensions         = [{"Name": "InstanceId", "Value": instanceId}],
        Period             = STATUS_ALARM_PERIOD,
        EvaluationPeriods  = STATUS_EVALUATION_PERIOD,
        Threshold          = STATUS_THRESHOLD,
        ComparisonOperator = STATUS_COMPARISON
    )

# CPU利用率アラームの設定
def put_cpu_alarm(instanceId):
    cloudWatch   = boto3.client('cloudwatch')
    cloudWatch.put_metric_alarm(
        AlarmName          = CPU_ALARM_NAME + "_" + instanceId,
        AlarmDescription   = CPU_ALARM_DESC,
        AlarmActions       = [
            CPU_ALARM_TOPIC
        ],
        MetricName         = CPU_METRIC_NAME,
        Namespace          = CPU_NAMESPACE ,
        Statistic          = CPU_STATISTICS,
        Dimensions         = [{"Name": "InstanceId", "Value": instanceId}],
        Period             = CPU_ALARM_PERIOD,
        EvaluationPeriods  = CPU_EVALUATION_PERIOD,
        Threshold          = CPU_THRESHOLD,
        ComparisonOperator = CPU_COMPARISON
    )

# EC2のTagをチェックし、アラート設定を実行
instance_id = ""
for reservation in boto3.client('ec2').describe_instances()["Reservations"]:
    for instance in reservation["Instances"]:
        for tag in instance["Tags"]:
            if(tag["Key"] == TARGET_TAG_KEY and tag["Value"] == TARGET_TAG_VALUE):
                instance_id  = instance["InstanceId"]
                put_status_alarm(instance_id)
                put_cpu_alarm(instance_id)

やってみた

実際に実行してみました。

事前に、対象のインスタンスにTagを設定しておきます。

cw-alert-001

実行すると、以下のようにTagを設定したインスタンスの分だけアラームが作成されます。

cw-alert-002

最後に

いかがでしょうか。

マネジメントコンソールからの操作は直感的で簡単ですが、リソースが増えてくると煩雑になり間違いや設定漏れが発生やすくなりますので、CLIやSDKを使ってうまく省力化するといいでしょう。