【AWS】CloudWatch でEC2 上にある プロセスのアラームを作成する

 ■ はじめに

https://dk521123.hatenablog.com/entry/2019/10/21/230004

の続き。

 今度は、対象のEC2内に、
アラーム作成・削除するスクリプトをサービス化し、
管理する

 ■ 公式サイト

 CloudWatch Metrics API : put-metric-alarm

アラームの作成
https://docs.aws.amazon.com/cli/latest/reference/cloudwatch/put-metric-alarm.html

 CloudWatch Metrics API : delete-alarms

アラームの削除
https://docs.aws.amazon.com/cli/latest/reference/cloudwatch/delete-alarms.html

 CloudWatch Metrics API : describe-alarms / describe-alarms-for-metric

アラームの取得
https://docs.aws.amazon.com/cli/latest/reference/cloudwatch/describe-alarms.html
https://docs.aws.amazon.com/cli/latest/reference/cloudwatch/describe-alarms-for-metric.html

 AWS::CloudWatch::Alarm

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html

 ■ 環境構築手順

【1】アラーム作成・削除するシェルスクリプトの設定
【2】アラーム作成・削除するシェルスクリプトをサービス化

設定環境

 * OS : CentOS7

 【1】アラーム作成・削除するシェルスクリプトの設定

[1-1] アラーム作成・削除するシェルスクリプトを作成する
 => 以下「/opt/aws/cloudwatch/create-delete-alarm.sh」を参考に。

[1-2] シェルスクリプトを配置し、権限を付与する
~~~~~~~~
sudo mv ~/create-delete-alarm.sh /opt/aws/cloudwatch/.

sudo chown root:root /opt/aws/cloudwatch/create-delete-alarm.sh
sudo chmod 744 /opt/aws/cloudwatch/create-delete-alarm.sh
~~~~~~~~

[1-3] 直接、スクリプトを実行し、アラームが作成されるか確認する
~~~~~~~~
sudo /opt/aws/cloudwatch/create-delete-alarm.sh start

# 実行後、AWSマネジメントコンソールからアラームが作成されていることを確認するか
# 以下を実行し確認する
sudo aws cloudwatch describe-alarms
~~~~~~~~

[1-4] 直接、スクリプトを実行し、アラームが削除されるか確認する
~~~~~~~~
sudo /opt/aws/cloudwatch/create-delete-alarm.sh stop

# 実行後、AWSマネジメントコンソールからアラームが削除されることを確認するか
# 以下を実行し確認する
sudo aws cloudwatch describe-alarms
~~~~~~~~
/opt/aws/cloudwatch/create-delete-alarm.sh (※「--alarm-actions」) 
#!/bin/bash

# description: Create & Delete Cloud Watch Alarm

PROCESS_NAME="clamav"
METRIC_NAME="ProcessNumberOf${PROCESS_NAME}"
HOST_NAME=$(hostname)
NAMESPACE="Sample/Ec2/${PROCESS_NAME}"
INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
ALARM_NAME=VirusScanProcessZero-${INSTANCE_ID}
UNIT="Count"

notify () {
  TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%S.000Z)
  VALUE=$(ps aux | grep -v grep | grep -v "$0" | grep ${PROCESS_NAME} | wc -l)
  DIMENSIONS="Hostname=${HOST_NAME},InstanceId=${INSTANCE_ID}"

  aws cloudwatch put-metric-data \
   --metric-name "${METRIC_NAME}" \
   --namespace "${NAMESPACE}" \
   --dimensions "${DIMENSIONS}" \
   --value "${VALUE}" \
   --unit "${UNIT}" \
   --region "${REGION}" \
   --timestamp "${TIMESTAMP}"
}

case "$1" in
  start)
      
      notify

      # wait...
      sleep 2m

      DESCRIPTION="Alarm when ${PROCESS_NAME} process become zero."
      DIMENSIONS_TO_CREATE_ALARM="Hostname=${HOST_NAME},InstanceId=${INSTANCE_ID}"

      # Create alarm
      aws cloudwatch put-metric-alarm \
      --datapoints-to-alarm 1 \
      --actions-enabled \
#      --alarm-actions "arn:aws:sns:ap-northeast-1:246xxxxxxxx:xxxxxxx" \
      --alarm-name ${ALARM_NAME} \
      --alarm-description "${DIMENSIONS_TO_CREATE_ALARM}" \
      --metric-name ${METRIC_NAME} \
      --namespace ${NAMESPACE} \
      --statistic Minimum \
      --dimensions ${DIMENSIONS} \
      --period 900 \
      --unit ${UNIT} \
      --evaluation-periods 1 \
      --treat-missing-data breaching \
      --threshold 0.0 \
      --comparison-operator LessThanOrEqualToThreshold

# 「--alarm-actions」は、アラームになった場合の動作を設定する

      ;;
  stop)
      # Delete alarm
      aws cloudwatch delete-alarms --alarm-names ${ALARM_NAME}

      ;;
  notify)

      notify

      ;;
  restart)
      ;;
  *)
      echo $"Usage: $0 {start|stop}"
      exit 2
esac

exit

補足:put-metric-alarmの前にput-metric-dataを行うことについて

 put-metric-alarmを行うと、
「--treat-missing-data breaching(欠落データでしきい値を超過しているデータポイントとして処理される)」をしているためEC2作成直前ではデータがないため、アラームが発生してしまう。

 「--treat-missing-data ignore (現在のアラーム状態が維持される)」を指定すると
例えば、crondが停止状態時にプロセスが通知されない状態でもアラームにならない。
この場合、crondが停止という異常事態なので、アラームをあげたい。

そこで、put-metric-dataで通知しておき、データをあげておく。
その後(数分をおいて)、put-metric-alarmを行う。

 【2】アラーム作成・削除するシェルスクリプトをサービス化

[2-1] 設定ファイル「***.service」を作成する
 => 以下「/etc/systemd/system/cloudwatch-alarm.service」を参考に。

[2-2] 設定ファイル「***.service」を配置し、権限を付与する
~~~~~~~~
sudo mv ~/cloudwatch-alarm.service /etc/systemd/system/.

sudo chown root:root /etc/systemd/system/cloudwatch-alarm.service
sudo chmod 0644 /etc/systemd/system/cloudwatch-alarm.service
~~~~~~~~

[2-3] アラーム作成・削除するシェルスクリプトをサービス化する
~~~~~~~~
systemctl list-unit-files --type=service | grep alarm
# 「/cloudwatch-alarm.service disable」になっているはず

sudo systemctl enable cloudwatch-alarm

# 修正などを繰り返した場合は、「sudo systemctl daemon-reload」を実行する
sudo systemctl start cloudwatch-alarm
~~~~~~~~

[2-4] サービス化できたか確認する
~~~~~~~~
sudo systemctl is-enabled cloudwatch-alarm

sudo systemctl status cloudwatch-alarm
~~~~~~~~
/etc/systemd/system/cloudwatch-alarm.service 
[Unit]
Description = Create & Delete Cloud Watch Alarm
After=cloud-config.target syslog.target network.target clamav.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/opt/aws/cloudwatch/create-delete-alarm.sh start
ExecStop=/opt/aws/cloudwatch/create-delete-alarm.sh stop
KillMode=none

[Install]
WantedBy=multi-user.target

補足:「After」の指定

 * Afterには、監視したい関連のサービスを指定しておいた方がいい
  => 今回の場合、「cloud-config.target」と「clamav.service」

【After=cloud-config.targetについて】
 * AMIからEC2を新規作成した場合、「cloud-config.target」の処理で、ホスト名の更新が行われるため
   「After=cloud-config.target」の指定がないと、サービスの起動順序によって
   AMI作成の古いホスト名を取得してしまう可能性があるため。

 ■ 補足

 パーセンタイル (Percentile)

 * データを小さい順に並べたとき、初めから数えて全体の %に位置する値

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html#percentiles-with-low-samples

 サービスがうまくたちあがらなかった話

 * 今回のサービス化で、はまった事があったのだが、それは、以下の関連記事を参照のこと

https://dk521123.hatenablog.com/entry/37395394

 参考文献

https://qiita.com/cs_sonar/items/c2f7435ad0057f660eaa
http://swfz.hatenablog.com/entry/2016/02/08/223420
https://qiita.com/yuji_saito/items/bb9633ffa0de4f3aa89e
http://ubw.hatenablog.com/entry/2016/11/23/193111

関連記事

Amazon EC2 ~ 基本編 / EC2メタデータ取得 ~
https://dk521123.hatenablog.com/entry/2018/02/03/120200
CloudWatch ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2022/03/08/145856
CloudWatch で、EC2 上にある プロセスを監視することを考える
https://dk521123.hatenablog.com/entry/2018/02/10/115436
systemd で、systemctl start xxx.service 実行後、Active: inactive (dead) になってしまう
https://dk521123.hatenablog.com/entry/37395394