実践ネット自動化スクリプト集

実践Python:ネットワーク機器のパフォーマンス統計自動収集と簡易分析

Tags: Python, ネットワーク自動化, パフォーマンス監視, SNMP, CLI自動化

はじめに

システムエンジニアやインフラエンジニアの皆様にとって、サーバーやアプリケーションのパフォーマンス監視は日常的な業務の一部かと思います。しかし、その基盤となるネットワーク機器のパフォーマンス(CPU利用率、メモリ使用率、インターフェースのトラフィック統計など)についても、継続的に把握し、異常検知やキャパシティプランニングに活用することが重要です。

手動でのデータ取得は非効率であり、特に多数の機器を管理している環境では現実的ではありません。Pythonを活用することで、これらのパフォーマンス統計情報を自動で収集し、簡単な分析や閾値監視を行うシステムを構築できます。

本記事では、Pythonを用いてネットワーク機器のパフォーマンス統計を自動収集する基本的な手法と、取得したデータを簡易的に分析する方法について、具体的なスクリプト例を交えながら解説します。ネットワーク機器の深い知識がなくても、お持ちのPythonスキルを活かして自動化に取り組める内容となっています。

ネットワーク機器のパフォーマンス統計取得方法

ネットワーク機器からパフォーマンス統計を取得するには、主に以下の方法があります。

  1. CLI (Command Line Interface) コマンドの実行:
    • 機器にログインし、show process cpushow interfaces statistics といったコマンドを実行して出力を取得します。
    • ほとんどの機器で利用可能ですが、出力フォーマットがベンダーやOSバージョンによって異なるため、パース(解析)処理が必要です。
    • Pythonでは、NetmikoやParamikoといったライブラリを使用してSSH経由でコマンドを実行し、出力を取得することが一般的です。
  2. SNMP (Simple Network Management Protocol):
    • ネットワーク機器の状態を管理・監視するための標準プロトコルです。
    • CPU利用率、メモリ使用率、インターフェースの送受信バイト数などをOID (Object Identifier) で指定して取得できます。
    • 構造化されたデータで取得できるためパースは比較的容易ですが、対象機器でSNMPエージェントが有効になっており、適切な設定(Community StringやACL)が必要です。
    • Pythonでは、PySNMPなどのライブラリを利用します。
  3. 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}")

解説:

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データの取得に失敗しました。")

解説:

取得した統計データの簡易分析と実践的な考慮事項

取得した生データ(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'])

実践的な考慮点

IaC/CI/CD文脈での活用

ネットワーク機器のパフォーマンス統計自動収集は、Infrastructure as Code (IaC) や CI/CD パイプラインの文脈でも有効活用できます。

まとめ

本記事では、Pythonを使用してネットワーク機器のパフォーマンス統計情報(CPU、メモリ、トラフィックなど)を自動収集し、簡易分析を行う基本的な手法について解説しました。CLI経由(Netmiko + TextFSM)とSNMP経由(PySNMP)のスクリプト例を示し、それぞれのアプローチの特徴や、取得したデータの活用方法、そして現場で利用する上での実践的な考慮事項について触れました。

Pythonの豊富なライブラリを活用することで、ネットワーク機器に関する深い専門知識がなくとも、運用やキャパシティ管理に役立つ自動化スクリプトを開発することが可能です。今回紹介した内容は基本的なステップですが、これを応用してより高度な分析や、他の監視・運用ツールとの連携に進めることもできます。

ネットワーク自動化は、単なる設定投入の自動化に留まらず、機器の状態把握、パフォーマンス監視、障害対応、そしてIaC/CI/CDパイプラインへの組み込みなど、その応用範囲は広がり続けています。ぜひ、皆様の現場でのネットワーク自動化に、本記事の内容をご活用いただければ幸いです。