PythonでSNMP監視を自動化|systemd・Gmail通知・CSV保存

ネットワーク

前回はCisco C1812JのCPU・メモリ・インターフェース状態をSNMPで取得する方法を紹介しました。

Raspberry PiでCiscoルータをSNMP監視する方法|OID調査と取得コマンド | Yuu Log

今回は、その取得処理をPythonで自動化し、Raspberry Piから1分ごとに監視する仕組みを構築します。

監視プログラムの配置、環境変数ファイル、systemd timer、Gmail通知、CSVログ保存までを解説します。

Python監視プログラムのディレクトリ構成

今回のシステムでは、プログラム、設定ファイル、状態ファイル、ログを別々のディレクトリに配置しています。

Linuxの一般的なディレクトリ構成に合わせることで、保守やバックアップがしやすくなります。

ディレクトリ階層

/
├── opt/
│   └── pi-monitor/
│       ├── monitor.py
│       ├── test_mail.py
│       └── test_interface.py
│
├── etc/
│   ├── pi-monitor.env
│   ├── systemd/
│   │   └── system/
│   │       ├── pi-monitor.service
│   │       └── pi-monitor.timer
│   └── logrotate.d/
│       └── pi-monitor
│
├── var/
│   ├── lib/
│   │   └── pi-monitor/
│   │       └── state.json
│   │
│   └── log/
│       └── pi-monitor/
│           └── metrics.csv

テスト時に作成したバックアップファイルなどは省略しています。

各ファイルの役割

ファイル役割
monitor.pySNMP取得・閾値判定・メール送信を行うメインプログラム
test_mail.pyGmail SMTPの送信確認
test_interface.pyインターフェースDOWNの模擬テスト
pi-monitor.envSNMP・SMTP接続情報
pi-monitor.servicePythonプログラムの実行定義
pi-monitor.timer1分ごとの自動実行設定
state.json前回の監視値や障害状態の保存
metrics.csv監視履歴の保存
logrotate.d/pi-monitorCSVログのローテーション

特に重要なのが、state.jsonです。

今回のPythonプログラムは常駐型ではなく、systemdによって毎分起動されます。

プロセスが終了するとPythonの変数も消えるため、連続障害回数や前回の通信量カウンタをファイルに保存する必要があります。

state.jsonを利用することで、複数回の監視結果を比較できるようにしています。

SNMP監視プログラム「monitor.py」を作成する

ここまでで、Cisco C1812JからSNMPでCPU使用率やメモリ使用率、インターフェースの状態を取得する方法を確認しました。

次に、これらの処理を自動化するPython監視プログラムを作成します。

今回使用するmonitor.pyは、実際にRaspberry Pi上で動作させ、障害通知や復旧通知を検証したプログラムです。

SNMP監視だけでなく、Raspberry Pi自身のリソース監視、CSVへのログ保存、Gmailによるメール通知までを1つのPythonファイルで実行します。

監視プログラムの主な機能

monitor.pyには、以下の機能を実装しています。

機能内容
SNMP死活監視CiscoルータへのSNMP応答を確認
CPU監視Cisco CPU MIBから5分平均使用率を取得
メモリ監視2つのメモリプールの使用率を計算
インターフェース監視6つのインターフェースのUP・DOWNを確認
トラフィック監視64bitカウンタから送受信bpsを計算
Raspberry Pi監視CPU負荷・メモリ・ディスク・温度・低電圧
障害判定WARNING・CRITICAL・RECOVERY
メール通知Gmail SMTPで状態変化を通知
履歴保存CSVとJSONに監視結果を保存

監視用ディレクトリを作成する

まず、Pythonスクリプト、状態ファイル、ログを保存するディレクトリを作成します。

sudo mkdir -p /opt/pi-monitor
sudo mkdir -p /var/lib/pi-monitor
sudo mkdir -p /var/log/pi-monitor

monitor.pyを配置する

/opt/pi-monitor/配下にmonitor.pyを配置します。

今回のプログラムはPython標準ライブラリとNet-SNMPのsnmpgetコマンドを使用しているため、追加のPythonパッケージを大量にインストールする必要はありません。

配置したらmonitor.pyのアクセス権を制限します。

sudo chmod 755 /opt/pi-monitor/monitor.py

monitor.pyの処理の流れ

監視処理は次の順序で実行されます。

monitor.py 起動
    │
    ├── 前回の状態をstate.jsonから読み込み
    │
    ├── Raspberry Piのリソース情報を取得
    │
    ├── Cisco C1812JへSNMPでアクセス
    │
    ├── CPU・メモリ・IF状態を判定
    │
    ├── 前回カウンタとの差分からbpsを計算
    │
    ├── WARNING・CRITICAL・RECOVERYを判定
    │
    ├── state.jsonを更新
    │
    ├── metrics.csvへ監視結果を追記
    │
    └── 状態変化があればGmailで通知

SNMP取得処理:poll_router()

CiscoルータへのSNMPアクセスは、poll_router()関数で実行しています。

この関数では、取得対象のOIDを10個ずつに分割してsnmpgetを実行します。

古いCisco IOSでは、大量のOIDを一度に要求するとUDP応答が大きくなる場合があります。

そこで、1回の要求で取得するOID数を制限しています。

また、SNMP応答が取得できない場合は例外を発生させ、メイン処理側で連続失敗回数をカウントします。

Raspberry Pi監視:pi_metrics()

pi_metrics()では、Raspberry Pi自身のリソースを取得します。

メモリ情報は/proc/meminfo、ディスク使用率はPythonのshutil.disk_usage()、CPU温度は/sys/class/thermal/thermal_zone0/tempから取得します。

また、vcgencmd get_throttledを使用して、現在の低電圧状態も確認します。

障害状態の保存:state.json

今回のプログラムで重要なのが、前回の監視状態をJSONファイルに保存する仕組みです。

/var/lib/pi-monitor/state.json

このファイルには、SNMPの連続失敗回数、インターフェースDOWNの連続回数、現在のアラート、通知済みアラート、前回の通信量カウンタなどを保存します。

これにより、systemd timerが毎分Pythonを新しく起動しても、前回の監視結果を引き継げます。

また、JSONの更新には一時ファイルを使い、ファイル置換によって保存する方式を採用しています。

WARNING・CRITICAL・RECOVERYの通知を実装する

監視システムでは、単純に閾値を超えるたびにメールを送信すると、大量の通知が発生してしまいます。

例えば、インターフェースがDOWNした状態で毎分メールを送信すると、1時間で60通ものメールが届くことになります。

そこで、今回のシステムでは障害状態の変化に応じてメールを送信するようにしました。

SNMP障害の通知条件

状態条件
OKSNMP応答あり
WARNING2回連続でSNMP取得失敗
CRITICAL3回連続でSNMP取得失敗
RECOVERYSNMP応答が正常に復旧

インターフェース障害の通知条件

状態条件
OKifOperStatus = 1
WARNING1回DOWN
CRITICAL3回連続DOWN
RECOVERYDOWNからUPへ復旧

メール通知の重複を防止する

メール送信処理では、現在の障害状態と、前回メール通知した状態を比較します。

例えば、インターフェースがDOWNした場合、1回目はWARNING、3回連続でDOWNするとCRITICALを通知します。

その後、DOWNが継続しても同じ通知を繰り返しません。

インターフェースがUPへ復旧した場合には、RECOVERYメールを送信します。

さらに、SMTP送信に失敗した場合は、通知済み状態を更新せずに異常終了します。

そのため、次回の監視実行時に通知を再試行できる設計です。

Pythonの構文チェックを実行する

ファイルを保存したら、構文エラーがないか確認します。

sudo python3 -m py_compile /opt/pi-monitor/monitor.py

エラーが表示されなければ構文チェックは完了です。

SNMP・SMTP接続情報ファイル「pi-monitor.env」を作成する

メインプログラム「monitor.py」の作成が完了しました。

次は接続情報をまとめたファイル「pi-monitor.env」を作成します。

Googleアカウントでアプリパスワードを発行

障害時の通知にはGmailを使用します。

そのためまずアプリパスワードを発行します。

Google アプリパスワード設定

環境変数ファイルを作成する

sudo nano /etc/pi-monitor.env

設定例:

ROUTER_IP=192.168.20.1
SNMP_COMMUNITY=コミュニティ文字列

SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=youraddress@gmail.com
SMTP_APP_PASSWORD=アプリパスワード
ALERT_TO=notify@example.com

パスワードなどの認証情報をPythonスクリプトへ直接記述しないようにしています。

設定ファイルには、管理者以外が読み取れないようアクセス権限を設定します。

sudo chown root:root /etc/pi-monitor.env
sudo chmod 600 /etc/pi-monitor.env

systemdで1分ごとに実行

メインプログラム「monitor.py」、接続情報ファイル「pi-monitor.env」の作成が完了しました。
次に以下を作成します。

  • サービスファイル「pi-monitor.service」(monitor.pyの実行定義)
  • タイマーファイル「pi-monitor.timer」(1分ごとの自動実行設定)

サービスファイル

sudo nano /etc/systemd/system/pi-monitor.service

[Unit]
Description=C1812J and Raspberry Pi Monitoring
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
EnvironmentFile=/etc/pi-monitor.env
WorkingDirectory=/opt/pi-monitor
ExecStart=/usr/bin/python3 /opt/pi-monitor/monitor.py
TimeoutStartSec=120

タイマーファイル

sudo nano /etc/systemd/system/pi-monitor.timer

[Unit]
Description=Run Network Monitor Every Minute

[Timer]
OnCalendar=*-*-* *:*:00
AccuracySec=10s
Persistent=true
Unit=pi-monitor.service

[Install]
WantedBy=timers.target

有効化

準備が整いました。設定を読み込んでサービスを起動しましょう。

sudo systemctl daemon-reload
sudo systemctl enable --now pi-monitor.timer

実行状況の確認:

systemctl list-timers --all pi-monitor.timer

Gmailへのメール送信テスト

サービス起動が完了しました。

まずはGmailのSMTP送信だけをテストします。

そのためにテスト用のプログラム「test_mail.py」を作成します。

sudo nano /opt/pi-monitor/test_mail.py

以下を張り付けて保存。

from monitor import send_mail

send_mail(
    "[TEST] Raspberry Pi Monitor",
    "Gmail SMTPの送信テストです。\n"
    "このメールが届けばSMTP設定は正常です。"
)

print("メール送信成功")

systemdと同じ環境変数を使って実行します。

sudo bash -c '
set -a
source /etc/pi-monitor.env
set +a
cd /opt/pi-monitor
python3 test_mail.py
'

メールが届けばSMTPの基本設定は完了です。

メール送信成功と表示されても、受信トレイへの配信まで保証するものではないため、実際の受信も確認してください。

監視結果を確認する

サービスが正常動作している場合、1分ごとにCSVファイルが保存されます。

/var/log/pi-monitor/metrics.csv

CSVには、取得日時、SNMP応答状態、CPU・メモリ使用率、インターフェース状態、通信速度などが記録されます。

CSVファイルはExcelやPythonなどで後から集計・グラフ化することが可能です。

例えば、CPU使用率の推移を確認したり、特定の時間帯にトラフィックが増加していないか分析したり。

ログの肥大化を防ぐ

24時間監視する場合、CSVのサイズがどんどん増え続けてしまします。

そのため増え続けないよう、logrotateも設定しておきます。

sudo nano /etc/logrotate.d/pi-monitor

設定例:

/var/log/pi-monitor/*.csv {
    weekly
    rotate 12
    compress
    missingok
    notifempty
    copytruncate
}

この設定では、CSVログを週単位でローテーションし、12世代保存します。

まとめ

monitor.py、pi-monitor.env、systemd timerを組み合わせ、1分ごとのSNMP監視とGmail通知、CSVログ保存を構築しました。

次回は、障害を模擬してメール通知が正しく届くか確認します。

タイトルとURLをコピーしました