複数のEC2にシェルスクリプトとAWS CLIを利用してCloudWatch Alarmを設定してみた

2021.01.05

こんにちは、コンサル部@大阪オフィスのTodaです。

EC2のステータスチェックが失敗した場合、CloudWatch Alarmを利用した自動再起動で復旧する方法がございます。 今回、たくさんあるインスタンスに設定を行うケースでシェルスクリプトとAWS CLIを使って対応してみます。

EC2ステータスチェックの詳細と発生するケースについては下記記事をご覧ください。

やりたいこと

  • 複数あるインスタンスにID指定でCloudWatch Alarmを設定する。
  • 設定前に正しい対象インスタンスか確認をする。

AWS CLIで必要なコマンドを確認

describe-instances
EC2インスタンスの情報を表示します。
Queryを利用して表示する項目の指定と対象インスタンスを絞るようにします。
出力は見やすいようにTableにするようにします。

put-metric-alarm
CloudWatch Alarmの作成ならびに更新をします。
IAMユーザの権限によってはAmazonEC2権限が必要な場合があります。
詳細は[put-metric-alarm]のリファレンスをご確認ください。

やってみる

シェルスクリプト作成

シェルスクリプトにてAWS CLIを呼び出すように設定をおこない対象インスタンスのIDは変数に格納するようにします。 格納した変数はfor文で1点ずつ処理するようにしました。 また、[describe-instances]を実行後は Y/n の選択を入れるようにして 「Y」の場合のみ[put-metric-alarm]を実行するようにします。

今回、監視の間隔は60秒単位でアラーム実行の条件として2分内の2データポイントにて判定をするようにしています。 上記は運用ルールに合わせて調整頂く必要がございます。

#!/bin/bash

# 設定対象のインスタンス
instance_ids=(
    "i-XXXXXXXXXXXXXXXXX"
    "i-XXXXXXXXXXXXXXXXX"
)

# オプション設定
period=60            # 監視間隔 (60:1分間隔)
evaluation_periods=2 # アラーム実行のデータポイント (2:2分内の2データポイント / 3:3分内の3データポイント) 
profile="[プロファイル]"    # プロファイル指定

for instance_id in ${instance_ids[@]}
do
    # インスタンス詳細表示
    aws ec2 describe-instances \
    --output=table \
    --query 'Reservations[].Instances[?InstanceId==`'${instance_id}'`][].{InstanceId: InstanceId, PrivateIp: join(`, `, NetworkInterfaces[].PrivateIpAddress), GlobalIP: join(`, `, NetworkInterfaces[].Association.PublicIp), Platform:Platform, State: State.Name,Name: Tags[?Key==`Name`].Value|[0]}' \
    --profile ${profile}

    # インスタンス確認表示
    echo '上記インスタンスにCloudWatch Alarmを設定していいですか? (StatusCheckFailed時に再起動) : Y/n'
    read USER_ANS

    case $USER_ANS in
        [Yy]* )
           echo Set ${instance_id} '<=' CloudWatch Alarm ec2_StatusCheck_${instance_id}

            # インスタンスにCloudWatchアラーム設定
            aws cloudwatch put-metric-alarm \
            --alarm-name ec2_StatusCheck_${instance_id} \
            --alarm-description "If EC2 is StatusCheckFailed, reboot" \
            --alarm-actions arn:aws:automate:ap-northeast-1:ec2:reboot \
            --metric-name StatusCheckFailed \
            --namespace AWS/EC2 \
            --statistic Maximum \
            --period ${period} \
            --evaluation-periods ${evaluation_periods} \
            --threshold 1 \
            --comparison-operator GreaterThanOrEqualToThreshold \
            --dimensions  Name=InstanceId,Value=${instance_id} \
            --profile ${profile}
            ;;
        * )
            # 設定スキップ
            echo Skip ${instance_id}
            ;;
    esac
    echo ''
    echo ''
done

シェルスクリプトをファイル名を決めて保存します。
今回、私は「Ec2-SetCloudWatchAlearm.sh」にて保存するようにしています。
保存後、chmod等で実行権限を付与するようにします。

シェルスクリプト実行

シェルスクリプトを実行すると設定をしたインスタンスID毎に詳細内容が表示されて設定を進めて良いか、確認が表示されます。
問題がなければ「Y」を押してEnterをすることで設定が反映されます。
※MFAを利用している場合は、スクリプト実行時にコードの入力が必要になります。

$ ./Ec2-SetCloudWatchAlearm.sh
-------------------------------------------------------------------------------------------------
|                                       DescribeInstances                                       |
+----------------+----------------------+---------------+-----------+---------------+-----------+
|    GlobalIP    |     InstanceId       |     Name      | Platform  |   PrivateIp   |   State   |
+----------------+----------------------+---------------+-----------+---------------+-----------+
| XXX.XXX.XXX.XXX|  i-XXXXXXXXXXXXXXXXX |  XXX_NAME_XXX |  None     |  XX.XX.XX.XX  |  running  |
+----------------+----------------------+---------------+-----------+---------------+-----------+
上記インスタンスにCloudWatch Alarmを設定していいですか? (StatusCheckFailed時に再起動) : Y/n

(Yの場合)
Set i-XXXXXXXXXXXXXXXXX <= CloudWatch Alarm ec2_StatusCheck_i-XXXXXXXXXXXXXXXXX

(nの場合)
Skip i-XXXXXXXXXXXXXXXXX

複数インスタンスがある場合は、インスタンス確認 => 設定 を繰り返すようになっています。

さいごに

今回はシェルスクリプトとAWS CLIを利用して多数のインスタンスにCloudWatch Alarmを設定してみました。
少しでもお客様の作りたい物の参考になればと考えております。