実践Python:ネットワーク機器のパフォーマンス統計自動収集と簡易分析
はじめに
システムエンジニアやインフラエンジニアの皆様にとって、サーバーやアプリケーションのパフォーマンス監視は日常的な業務の一部かと思います。しかし、その基盤となるネットワーク機器のパフォーマンス(CPU利用率、メモリ使用率、インターフェースのトラフィック統計など)についても、継続的に把握し、異常検知やキャパシティプランニングに活用することが重要です。
手動でのデータ取得は非効率であり、特に多数の機器を管理している環境では現実的ではありません。Pythonを活用することで、これらのパフォーマンス統計情報を自動で収集し、簡単な分析や閾値監視を行うシステムを構築できます。
本記事では、Pythonを用いてネットワーク機器のパフォーマンス統計を自動収集する基本的な手法と、取得したデータを簡易的に分析する方法について、具体的なスクリプト例を交えながら解説します。ネットワーク機器の深い知識がなくても、お持ちのPythonスキルを活かして自動化に取り組める内容となっています。
ネットワーク機器のパフォーマンス統計取得方法
ネットワーク機器からパフォーマンス統計を取得するには、主に以下の方法があります。
- CLI (Command Line Interface) コマンドの実行:
- 機器にログインし、
show process cpu
やshow interfaces statistics
といったコマンドを実行して出力を取得します。 - ほとんどの機器で利用可能ですが、出力フォーマットがベンダーやOSバージョンによって異なるため、パース(解析)処理が必要です。
- Pythonでは、NetmikoやParamikoといったライブラリを使用してSSH経由でコマンドを実行し、出力を取得することが一般的です。
- 機器にログインし、
- SNMP (Simple Network Management Protocol):
- ネットワーク機器の状態を管理・監視するための標準プロトコルです。
- CPU利用率、メモリ使用率、インターフェースの送受信バイト数などをOID (Object Identifier) で指定して取得できます。
- 構造化されたデータで取得できるためパースは比較的容易ですが、対象機器でSNMPエージェントが有効になっており、適切な設定(Community StringやACL)が必要です。
- Pythonでは、PySNMPなどのライブラリを利用します。
- API (Application Programming Interface):
- 最近のネットワーク機器は、RESTConfやNETConfといったAPIをサポートしている場合があります。
- APIを利用することで、構造化されたデータ(JSONやXMLなど)で情報を取得できます。
- プログラムからの操作が容易ですが、機器がAPIをサポートしていること、およびAPIに関する知識が必要です。
この記事では、汎用性が高いCLI経由での取得と、構造化データ取得の代表例であるSNMP経由の取得を中心に解説します。
PythonによるCLI経由でのパフォーマンス統計収集
CLI経由での情報収集は、netmiko
ライブラリを利用すると非常に効率的です。netmiko
は、様々なネットワーク機器ベンダーのCLIに対応しており、SSH/Telnet接続、コマンド実行、プロンプト待機などを自動化できます。
準備
netmiko
と、CLI出力のパースによく使われるtextfsm
ライブラリをインストールします。
pip install netmiko textfsm
スクリプト例:CPU利用率の取得とパース
Cisco IOS機器のCPU利用率を取得する例を示します。
import textfsm
from netmiko import ConnectHandler
import os
# 接続情報の定義(実際には安全な方法で管理してください)
device = {
'device_type': 'cisco_ios',
'host': 'YOUR_DEVICE_IP', # 実際の機器IPアドレスに置き換えてください
'username': 'YOUR_USERNAME', # 実際のユーザー名に置き換えてください
'password': 'YOUR_PASSWORD', # 実際のパスワードに置き換えてください
# 'secret': 'YOUR_ENABLE_PASSWORD', # 必要に応じてenableパスワードも設定
}
# textfsmテンプレートのパス
# 適切なテンプレートファイル(cisco_ios_show_process_cpu.textfsmなど)が必要です
# https://github.com/networktocode/ntc-templates からダウンロードできます
template_file = 'cisco_ios_show_process_cpu.textfsm'
if not os.path.exists(template_file):
print(f"エラー: {template_file} が見つかりません。ntc-templatesからダウンロードしてください。")
exit()
try:
# ネットワーク機器に接続
print(f"機器 {device['host']} に接続中...")
with ConnectHandler(**device) as net_connect:
print("接続成功。")
# コマンド実行
command = "show process cpu"
print(f"コマンド '{command}' 実行中...")
output = net_connect.send_command(command)
print("コマンド実行完了。")
# print("\n--- CLI出力 ---")
# print(output)
# print("--------------\n")
# TextFSMで出力をパース
print("出力パース中...")
with open(template_file, 'r') as f:
template = textfsm.TextFSM(f)
parsed_output = template.ParseText(output)
print("パース結果:")
# パース結果はリスト形式で返されます。通常、プロセスごとにリストの要素が増えます。
# CPU利用率は通常、全体のサマリー行に含まれます。
# テンプレートによっては、結果の構造が異なりますので、実際の出力とテンプレートを確認してください。
# 例として、最初の結果エントリを表示します。
if parsed_output:
# NTCテンプレートの場合、通常はリストの最後の要素に集計値が入ることが多いですが、
# テンプレートに依存するため、ここでは単に最初の要素を例示します。
# 適切なエントリを見つけてください。例えば 'five_sec' など。
# 正確なキーは使用するTextFSMテンプレートに依存します。
print(parsed_output[0])
# より実用的な例として、過去5秒間のCPU利用率を取り出す場合(テンプレート依存)
# for entry in parsed_output:
# if 'five_sec' in entry and entry['five_sec'] is not None:
# print(f"過去5秒間のCPU利用率: {entry['five_sec']}%")
# break # 最初に見つかった値を採用する場合
# あるいは、特定のプロセス名でフィルタリングする場合など
else:
print("パースされたデータがありません。")
except Exception as e:
print(f"エラーが発生しました: {e}")
解説:
ConnectHandler
に機器の接続情報を辞書形式で渡します。device_type
はnetmiko
が提供する対応機器リストから適切なものを選択してください。send_command()
メソッドで任意のCLIコマンドを実行し、その出力を文字列として取得します。textfsm.TextFSM
クラスを使って、取得したCLI出力を構造化データ(通常は辞書のリスト)に変換します。これには、対象機器のコマンド出力に対応したTextFSM
テンプレートファイルが必要です。ntc-templates
プロジェクトで多くのテンプレートが公開されています。- パースされたデータから、必要な情報(例: CPU利用率の値)を取り出します。TextFSMテンプレートによって出力されるフィールド名(例:
five_sec
,one_min
,five_min
など)が異なるため、使用するテンプレートの仕様を確認してください。
PythonによるSNMP経由でのパフォーマンス統計収集
SNMPを利用すると、より定義された構造で情報を取得できます。pysnmp
ライブラリがPythonでSNMP通信を行うための標準的なライブラリです。
準備
pysnmp
ライブラリをインストールします。
pip install pysnmp
スクリプト例:インターフェーストラフィック統計の取得
SNMP v2cを使用して、特定のインターフェースの入力トラフィック量(ifInOctets
)を取得する例を示します。ifInOctets
のOIDは .1.3.6.1.2.1.2.2.1.10
です。特定のインターフェース(例: indexが1の場合)を指定する場合は、OIDの最後にインターフェースインデックスを追加します (例: .1.3.6.1.2.1.2.2.1.10.1
)。インターフェースインデックスはifIndex
(.1.3.6.1.2.1.2.2.1.1) を取得するなどして事前に調べる必要があります。
from pysnmp.hlapi import *
# SNMP接続情報の定義
target_ip = 'YOUR_DEVICE_IP' # 実際の機器IPアドレスに置き換えてください
community_string = 'YOUR_COMMUNITY_STRING' # 実際のCommunity Stringに置き換えてください
# 取得したいデータのOID (例: ifInOctets for interface index 1)
# 正確なOIDは機器やMIBに依存します。ここでは例としてifInOctetsのOIDを使用。
# ifIndex=1のインターフェースのifInOctetsを取得する場合の例
oid_to_get = '1.3.6.1.2.1.2.2.1.10.1' # SNMP OID (例: ifInOctets.1)
def get_snmp_data(host, community, oid):
"""
指定されたホストからSNMP GETでデータを取得する関数
"""
errorIndication, errorStatus, errorIndex, varBinds = next(
getCmd(SnmpEngine(),
CommunityData(community, mpModel=1), # SNMP v2cを使用 (mpModel=1)
UdpTransportTarget((host, 161)),
ContextData(),
ObjectType(ObjectIdentity(oid)))
)
if errorIndication:
print(f"SNMP GET エラー: {errorIndication}")
return None
elif errorStatus:
print(f"SNMP GET エラー: {errorStatus.prettyPrint()} at {errorIndex and varBinds[int(errorIndex) - 1][0] or '?'}")
return None
else:
for varBind in varBinds:
# varBindは tuple (OID, Value) のリストです
print(f"{varBind[0]} = {varBind[1]}")
return varBind[1] # 取得した値を返す (通常、リストの最初の要素)
# SNMPデータ取得を実行
print(f"機器 {target_ip} からOID {oid_to_get} のSNMPデータを取得中...")
performance_value = get_snmp_data(target_ip, community_string, oid_to_get)
if performance_value is not None:
print(f"取得した値: {performance_value}")
# 例: 取得したバイト数(カウンタ)を処理
# トラフィックレートを計算するには、一定時間間隔で値を取得し、差分を時間で割る必要があります。
# これは単一の値取得の例です。
else:
print("SNMPデータの取得に失敗しました。")
解説:
pysnmp.hlapi
モジュールのgetCmd
関数を使用してSNMP GETリクエストを送信します。CommunityData
でCommunity StringとSNMPバージョン(ここではv2c)を指定します。UdpTransportTarget
で宛先ホストとポート(通常161)を指定します。ObjectType(ObjectIdentity(oid))
で取得したいデータのOIDを指定します。next()
関数でSNMPエンジンを実行し、結果を取得します。errorIndication
やerrorStatus
を確認してエラーハンドリングを行います。- 成功した場合、
varBinds
リストに取得したデータが含まれます。varBind
は(OID, Value)
のタプルです。
取得した統計データの簡易分析と実践的な考慮事項
取得した生データ(CPU利用率の数値、バイトカウンタの値など)は、そのままでは情報として扱いにくい場合があります。Pythonを使ってこれらのデータを加工し、簡易的な分析を行うことができます。
データの構造化と集計
CLIやSNMPで複数のデータポイントを取得した場合、それらをPythonの辞書やリスト、あるいはPandas DataFrameとして構造化すると、後の処理が容易になります。
例えば、複数機器から取得したCPU利用率をリストに格納し、平均値を計算したり、最大値を特定したりできます。
# 複数の機器から取得したCPU利用率データ(例)
cpu_data = {
'device1': {'five_sec': 5, 'one_min': 4, 'five_min': 3},
'device2': {'five_sec': 12, 'one_min': 10, 'five_min': 8},
'device3': {'five_sec': 8, 'one_min': 7, 'five_min': 6},
}
# 過去5秒間のCPU利用率の平均を計算
five_sec_values = [data['five_sec'] for data in cpu_data.values()]
average_five_sec = sum(five_sec_values) / len(five_sec_values)
print(f"全機器の過去5秒間の平均CPU利用率: {average_five_sec:.2f}%")
# 最大値を持つ機器を特定
max_cpu_device = max(cpu_data, key=lambda device: cpu_data[device]['five_sec'])
print(f"過去5秒間のCPU利用率が最も高い機器: {max_cpu_device} ({cpu_data[max_cpu_device]['five_sec']}%)")
閾値監視
取得したデータに対して閾値を設定し、超過した場合にアラートを出すなどの処理を追加できます。
def check_cpu_threshold(device_name, cpu_value, threshold=80):
"""
CPU利用率が閾値を超えているかチェックする関数
"""
if cpu_value > threshold:
print(f"!!! アラート: 機器 {device_name} のCPU利用率 ({cpu_value}%) が閾値 ({threshold}%) を超えました。")
# ここに通知処理(メール送信、Slack通知、ログ記録など)を追加
else:
print(f"機器 {device_name} のCPU利用率は正常です ({cpu_value}%)。")
# 各機器のCPU利用率をチェック
for device_name, data in cpu_data.items():
check_cpu_threshold(device_name, data['five_sec'])
実践的な考慮点
- データ収集頻度: 高頻度なデータ収集は機器やネットワークに負荷をかける可能性があります。監視対象の項目や目的(リアルタイム監視かキャパシティプランニング用かなど)に応じて適切な頻度を設定してください。
- データの保存: 収集したデータは、ファイル(CSV, JSONなど)、リレーショナルデータベース、あるいは時系列データベース(InfluxDBなど)に保存することで、長期的なトレンド分析や可視化が可能になります。
- 認証情報の管理: 機器へのログイン情報やSNMP Community Stringは機密情報です。スクリプト内に直書きせず、環境変数、設定ファイル、または専用の認証情報管理システム(HashiCorp Vaultなど)を利用して安全に管理してください。
- エラーハンドリング: ネットワークの問題、機器の応答なし、コマンド実行失敗、パース失敗など、様々なエラーが発生する可能性があります。適切にエラーハンドリングを行い、スクリプトが途中で停止しないように頑健性を高める必要があります。
- 並列実行: 多数の機器からデータを収集する場合、逐次実行では時間がかかりすぎます。
concurrent.futures
モジュールや、ネットワーク自動化に特化したフレームワークであるNornirなどを利用して、複数の機器に対して並列で処理を実行することで効率を向上できます。
IaC/CI/CD文脈での活用
ネットワーク機器のパフォーマンス統計自動収集は、Infrastructure as Code (IaC) や CI/CD パイプラインの文脈でも有効活用できます。
- 設定変更後の検証: 設定変更をデプロイするCI/CDパイプラインにおいて、デプロイ前後のネットワーク機器のCPU/メモリ利用率やトラフィック統計を自動収集・比較することで、変更による予期せぬパフォーマンス劣化が発生していないかを確認できます。これは、単なる設定内容のチェックだけでなく、実際の「状態」に基づいた重要な検証フェーズとなり得ます。
- キャパシティプランニング: 定期的に収集したインターフェースのトラフィック統計データなどを分析することで、帯域増強が必要な箇所を早期に特定したり、ハードウェアリソースの利用状況を把握したりするための基礎データとして活用できます。
- 自動修復のトリガー: 高いCPU利用率や特定のインターフェースでのエラー増加などを検知した場合、それをトリガーとしてアラート通知だけでなく、設定のロールバックや機器の再起動といった自動修復アクションを実行する(あるいは、承認ワークフローを開始する)システムと連携させることが考えられます。
まとめ
本記事では、Pythonを使用してネットワーク機器のパフォーマンス統計情報(CPU、メモリ、トラフィックなど)を自動収集し、簡易分析を行う基本的な手法について解説しました。CLI経由(Netmiko + TextFSM)とSNMP経由(PySNMP)のスクリプト例を示し、それぞれのアプローチの特徴や、取得したデータの活用方法、そして現場で利用する上での実践的な考慮事項について触れました。
Pythonの豊富なライブラリを活用することで、ネットワーク機器に関する深い専門知識がなくとも、運用やキャパシティ管理に役立つ自動化スクリプトを開発することが可能です。今回紹介した内容は基本的なステップですが、これを応用してより高度な分析や、他の監視・運用ツールとの連携に進めることもできます。
ネットワーク自動化は、単なる設定投入の自動化に留まらず、機器の状態把握、パフォーマンス監視、障害対応、そしてIaC/CI/CDパイプラインへの組み込みなど、その応用範囲は広がり続けています。ぜひ、皆様の現場でのネットワーク自動化に、本記事の内容をご活用いただければ幸いです。