【AWS初心者向け】システム監視スクリプトを使ってAWS SNSで通知を受け取る実装手順

どうも、クラ本部の黒田です。
大変お久しぶりですね。
あっという間で、今年は残り僅かとなりました。

涼しくなってきましたところ、そろそろ来年に向けて、オフラインで会社説明会を開こうかと考えております。
協栄情報にご興味のある方、是非、ご連絡いただければ幸いです。
file

さて、今回は、システム監視スクリプトを作成してAWS SNSで通知を受け取る実装手順を解説します。

スクリプトは以下の機能を提供します。

  • メモリ使用状況の監視
  • CPU使用率の監視
  • ディスク使用率の監視
  • 条件を満たした際の通知の送信
  • システム情報のログ記録

はじめに

AWS CloudWatch アラーム通知 と シェルスクリプトによるシステム監視の区別について

< AWS CloudWatch アラーム通知 >

AWS CloudWatchアラームは、Cloudwatchのメトリクスやログを収集して、メールなどで通知を行うことができる機能です。
主な特徴は以下の通りです。
■ AWSリソースへの統合:EC2インスタンス、RDSデータベースなどのAWSリソースを監視できる。
■ メトリクスに基づく警告: ユーザー定義の閾値を超えた場合に通知を送信できる。
■ 自動的なリカバリー: 通知を受け取った場合に、自動的なリカバリーアクションを実行できる。

< シェルスクリプトによるシステム監視 >

シェルスクリプトを使用したシステム監視は、AWS CloudWatchアラームとは異なり、以下の特徴があります。

■ カスタマイズ性: ユーザーは特定のメトリクスや条件を自由に定義できる。
■ 独自の通知方法: AWS SNS以外にも、メール、Slack、APIコールなどさまざまな通知方法が利用可能。
■ 非AWSリソースの監視: AWS以外のサーバーやシステムも監視可能。

システムの安定稼働は非常に重要です。特にサーバーやクラウドインフラの場合、リソースの適切な管理が必要です。
AWS CloudWatchアラーム通知は良く使われているかと思いますが、サーバーが数多く存在する場合、それぞれのサーバーごとにアラームを作成するのにも、人件費がかかっております。
そこで、この記事では、システム監視スクリプトを作成し、AWS SNS(Simple Notification Service)を使用して異常時に通知を受け取る手順をご紹介します。

シェルスクリプトによるシステム監視の実装手順

以下に、Linux環境でシステム監視スクリプトを作成し、AWS SNSを使った通知を設定する手順を説明します。

事前準備

実装する前に、以下の事前準備が必要です。

  • EC2 インスタンスが起動している状態
  • rootユーザーでログイン出来ている状態
    A newer release of "Amazon Linux" is available.
    Version 2023.1.20230906:
    Version 2023.1.20230912:
    Version 2023.2.20230920:
    Run "/usr/bin/dnf check-release-update" for full release and version update info
    ,     #_
    ~\_  ####_        Amazon Linux 2023
    ~~  \_#####\
    ~~     \###|
    ~~       \#/ ___   https://aws.amazon.com/linux/amazon-linux-2023
    ~~       V~' '->
    ~~~         /
      ~~._.   _/
         _/ _/
       _/m/'
    Last login: Sun Sep 24 01:10:46 2023 from 111.111.122.212
    [root@kuroda ~]#

■ 手順1: AWS SNSトピックの作成

まず最初に、AWSコンソールにログインし、SNSのダッシュボードに移動し、そこで新しいトピックを作成します。

  • SNSダッシュボードで「トピックの作成」をクリックします。
  • トピックの名前を入力し、適切な設定を選びます。
  • トピックが作成されたら、ARN(Amazon Resource Name)を控えておきます。
    file

■ 手順2: システム監視スクリプトの作成

  • 新規ファイルの作成

    vi system_monitor.sh 下記スクリプト内容を貼り付けてください。
  • スクリプトの実行権限を付与

    chmod +x system_monitor.sh
  • スクリプト内容にある AWS SNS メールを送信部分をご自身の設定内容に入れ替えてください。

#!/bin/bash

# 6秒ごとに3回の使用状況表示
vmstat  6 3

# 現在のメモリ情報を取得
mem_total=$(free -m | grep "Mem" | awk '{print $2}')
mem_used=$(free -m | grep "Mem" | awk '{print $3}')

# メモリの合計値と使用中の値を表示
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
echo "現在のメモリ合計容量は $mem_total MB "
echo "$mem_used MB が使用されています."

# 使用率を計算して表示
mem_usage=$(awk "BEGIN {printf \"%.2f\", ($mem_used / $mem_total) * 100}")
echo "現在のメモリ使用率は $mem_usage% "

# CPU使用率を取得
cpu_usage=$(mpstat | awk '$12 ~ /[0-9.]+/ {print 100 - $12}')

# コアごと負荷情報
mpstat -P ALL

# CPU使用率を表示
echo "現在のCPU使用率は $cpu_usage% "

# ディスク使用率を取得
disk_usage=$(df -h / | awk 'NR==2 {print $5}' | cut -d'%' -f1)

# ディスク使用率を表示
echo "現在のディスク使用率は $disk_usage% "

# メールを送信する関数
send_email() {
    local subject=$1
    local body=$2

    # AWS SNS メールを送信
    aws sns publish --topic-arn arn:aws:sns:ap-northeast-1:AWSアカウントID:SNSトピック名 --message "$body" --subject "$subject"
}

# 条件をチェックして、それぞれの場合にメールを送信
if (( $(echo "$cpu_usage >= 60" | bc -l) )); then
    send_email "CPU使用率が60%以上になりました。" "現在のCPU使用率は $cpu_usage% です。"
fi

if (( $(echo "$mem_usage >= 60" | bc -l) )); then
    send_email "メモリ使用率が60%以上になりました。" "現在のメモリ使用率は $mem_usage% です。"
fi

if (( $(echo "$disk_usage >= 80" | bc -l) )); then
    send_email "ディスク使用率が80%以上になりました。" "現在のディスク使用率は $disk_usage% です。"
fi

# コマンドの実行を変数に格納
CpuRec=$(uptime)
MemRec=$(free -m)
DiskRec=$(df -hT)
LastUserLoginRec=$(last -20)
RecTime=$(date +"%Y-%m-%d %H:%M:%S")

# ログファイルのディレクトリを作成
mkdir -p /var/log/runrec
RecFile="/var/log/runrec/running-$(date +%Y%m%d%H%M)"
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"

# ログの記録
{
  echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
  echo "Record Time: $RecTime"
  echo "Cpu Load information:"
  echo "$CpuRec"
  echo "Memory information:"
  echo "$MemRec"
  echo "Disk use information:"
  echo "$DiskRec"
  echo "Last login 20 users record:"
  echo "$LastUserLoginRec"
} > "$RecFile"

# 出力通知
echo "詳細は$RecFileより確認してください。"

このスクリプトは、システムの使用状況をモニタリングし、特定の条件が満たされた場合にメールで通知するものです。また、定期的にシステムの状態を記録し、ログファイルに保存します。

  • mem_total=$(free -m | grep "Mem" | awk ‘{print $2}’): free -m コマンドを使って現在のメモリ情報を取得し、その結果からメモリの合計容量を抽出し、mem_total に代入します。

  • mem_used=$(free -m | grep "Mem" | awk ‘{print $3}’): 同様に、メモリの使用量を取得し、mem_used に代入します。

  • echo"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++": メッセージをコンソールに出力します。

  • echo "現在のメモリ合計容量は $mem_total MB ": メモリの合計容量をコンソールに出力します。

  • echo "$mem_used MB が使用されています.": 使用中のメモリ量をコンソールに出力します。

  • mem_usage=$(awk "BEGIN {printf \"%.2f\", ($mem_used / $mem_total) * 100}"): メモリの使用率を計算し、mem_usage に代入します。

  • echo "現在のメモリ使用率は $mem_usage% ": メモリの使用率をコンソールに出力します。

  • cpu_usage=$(mpstat | awk ‘$12 ~ /[0-9.]+/ {print 100 – $12}’): mpstat コマンドを使ってCPUの使用率を取得し、cpu_usage に代入します。

  • sudo mpstat: CPUの使用率の詳細情報を表示します。

  • echo "現在のCPU使用率は $cpu_usage% ": CPUの使用率をコンソールに出力します。

  • disk_usage=$(df -h / | awk ‘NR==2 {print $5}’ | cut -d’%’ -f1): ルートディレクトリのディスク使用率を取得し、disk_usage に代入します。

  • echo "現在のディスク使用率は $disk_usage% ": ディスク使用率をコンソールに出力します。

  • send_email() {…}: メールを送信するための関数 send_email を定義します。

  • if (( $(echo "$cpu_usage >= 60" | bc -l) )); then … fi: CPU使用率が60%以上の場合にメールを送信する条件文を設定します。

  • if (( $(echo "$mem_usage >= 60" | bc -l) )); then … fi: メモリ使用率が60%以上の場合にメールを送信する条件文を設定します。

  • if (( $(echo "$disk_usage >= 80" | bc -l) )); then … fi: ディスク使用率が80%以上の場合にメールを送信する条件文を設定します。

  • CpuRec=$(uptime): uptime コマンドを使ってCPUの負荷情報を取得し、CpuRec に代入します。

  • MemRec=$(free -m): メモリ情報を取得し、MemRec に代入します。

  • DiskRec=$(df -hT): ディスク情報を取得し、DiskRec に代入します。

  • LastUserLoginRec=$(last -20): 最後の20人のユーザーのログイン情報を取得し、LastUserLoginRec に代入します。

  • RecTime=$(date +"%Y-%m-%d %H:%M:%S"): 現在の日時を取得し、RecTime に代入します。

  • mkdir -p /var/log/runrec: ログファイルのディレクトリを作成します。

  • RecFile="/var/log/runrec/running-$(date +%Y%m%d%H%M)": ログファイルのパスを指定します。

  • > "$RecFile": ログファイルを作成します。

  • {…}: 波括弧内のコマンドをログファイルに追記します。

  • echo "詳細は$RecFileより確認してください。": ログファイルの場所をコンソールに出力します。


■ 手順3: クーロンジョブの設定

  • 定期的な実行を行うために、cronジョブを設定します。
    crontab -e
  • 例えば、毎時実行する場合は以下のように設定します。
    0 * * * * /infra/script/system_monitor.sh

    以上で、システムの監視とAWS SNSを使用した通知の設定手順が完了しました。


■ 動作確認の準備

  • CPU使用率を一時的に高めて行きます。
    システムのリソースを使用するプロセスを起動する必要があります。以下はその例です:

    yes > /dev/null &

    このコマンドは、yes コマンドを実行し、その出力を /dev/null にリダイレクトします。これにより、CPUに対して常に計算が必要なタスクが生成され、使用率が上昇します。
    検証完了後、このプロセスを停止するには、次のコマンドを使用します:

    pkill yes
  • ディスク使用率を一時的に高めて行きます。
    システムのリソースを使用するプロセスを起動する必要があります。以下はその例です:

    dd if=/dev/zero of=6G.dummy bs=1MD count=6000

    このコマンドは、/dev/zero デバイスから読み取りを行い、それを 6G.dummy という名前のファイルに 1MB のブロックサイズで合計 6000 回書き込むものです。この結果、サイズが約 6GB のダミーファイルが作成されます。
    検証完了後、削除するのをおわすれずに!

  • メモリー使用率を一時的に高めて行きます。
    システムのリソースを使用するプロセスを起動する必要があります。以下はその例です:

    stress --vm 1 --vm-bytes 100M --vm-hang 0

    stress コマンドが利用できない場合:
    stress コマンドは一般的にLinuxシステムで利用できるツールですが、特定の環境やOSによっては事前にインストールする必要がある場合があります。
    Amazon LinuxやAmazon Linux 2の場合、stress パッケージはデフォルトで提供されていないため、手動でインストールする必要があります。
    以下はAmazon Linux 2で stress をインストールする手順です。

  1. パッケージリストを更新します。

    sudo yum update -y
  2. stress パッケージをインストールします。

    sudo yum install stress -y

    以上の手順で stress コマンドが利用可能になるはずです。それ以外の環境やOSの場合は、環境に応じた手順で stress をインストールしてください。

■ アラーム通知の受け取り

作成したスクリプトをサーバーに配置し、定期的に実行します。スクリプトはシステムの使用状況を監視し、一定の条件が満たされるとAWS SNSを介して通知を送信します。

  • 以下は今回設定した条件の通知メールとなります。

file
file
file


最後に

この手順を実行することで、シェルスクリプトを使用してシステムの監視を行い、AWS SNSを介して通知を受け取ることができます。

これにより、システムの異常な状態が検出された場合に、適切な人物がすばやく通知を受け取ることができます。

以上、システムの監視とAWS SNSを使用した通知の設定が完了しました。
システムの安定性を保つために、定期的な監視と通知の設定を行ってください。


この記事では、システム監視スクリプトを作成し、AWS SNSを使用して通知を受け取る手順を紹介しました。これにより、システムの異常が発生した際に迅速に対応できるようになります。是非、お試しください!

では、皆さん、また次回お会いしましょう。

【AWS初心者向け】CloudWatch AgentでEC2インスタンスを監視・メトリクスの閾値を超えたらSNSで通知を送付

【AWS初心者向け】コマンドの出力結果が変数に格納されない【Shell Script】

【Ubuntu】Let’s Encryptを使って無料でHTTPS通信を実現しよう

more…

↑↑↑クラ本部メンバーが書いた記事のご紹介 ↑↑↑、合わせてやってみるのもいいかと

Last modified: 2023-10-23

Author