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

現場で使えるPython:ネットワーク障害発生時の初動対応を自動化

Tags: Python, ネットワーク自動化, 障害対応, Netmiko, 運用自動化

はじめに

システム運用において、ネットワーク障害は避けられない課題の一つです。障害発生時には、原因究明と復旧のために迅速かつ正確な情報収集が求められます。しかし、障害発生は突発的であり、限られた時間の中で複数のネットワーク機器から必要な情報を手動で収集することは、担当者にとって大きな負担となる場合があります。特に、ネットワーク機器の操作に不慣れな場合、必要なコマンドの実行やその結果の解釈に時間を要し、復旧までの時間が長期化するリスクも伴います。

本記事では、Pythonのスキルを活かして、ネットワーク障害発生時の初動対応、特に情報収集プロセスを自動化する手法についてご紹介します。Pythonライブラリを利用してネットワーク機器から必要な情報を効率的に収集し、障害対応を迅速化するための実践的なスクリプト例と考慮事項について解説します。

なぜネットワーク障害対応の情報収集を自動化するのか

ネットワーク障害対応における情報収集を自動化することには、以下のようなメリットがあります。

開発ライフサイクルやインフラ自動化の文脈では、迅速な問題検知と対応はサービスの可用性を維持するために不可欠です。ネットワーク障害発生時の情報収集を自動化し、標準化されたプロセスとして組み込むことは、Ops側面の効率化に大きく貢献します。

自動化の対象となる初動対応

ネットワーク障害発生時の初動対応として自動化が有効な主な項目は、以下の通りです。

これらの情報を自動的に収集することで、障害発生時に何が起きているのかを素早く把握するための材料を得ることができます。

Pythonによる情報収集スクリプトの実装

ここでは、Pythonのネットワーク自動化ライブラリであるNetmikoを使用して、指定したネットワーク機器から複数の情報を収集する基本的なスクリプト例をご紹介します。Netmikoは、SSH経由で様々なベンダーのネットワーク機器に接続し、CLIコマンドを実行するための便利なライブラリです。

実行環境と準備

サンプルスクリプト:複数情報の一括収集

以下のスクリプトは、指定したネットワーク機器に対して、CPU/メモリ使用率、インターフェースのサマリー、および最近のログを収集する例です。機器タイプはここではCisco IOSを想定していますが、device_type パラメータを変更することで他の多くの機器にも対応可能です。

from netmiko import ConnectHandler
import os
import time
import datetime

# 接続情報(実際には環境変数やVault等で安全に管理してください)
DEVICE_IP = os.environ.get('NET_DEVICE_IP') or 'YOUR_DEVICE_IP' # 例: '192.168.1.1'
USERNAME = os.environ.get('NET_USERNAME') or 'your_username'
PASSWORD = os.environ.get('NET_PASSWORD') or 'your_password'
DEVICE_TYPE = 'cisco_ios' # 機器タイプに応じて変更してください

# 収集するコマンドリスト
commands = [
    'show processes cpu history',
    'show processes memory',
    'show ip interface brief',
    'show logging | include %', # 最近のエラーログなどを抽出する例
]

def collect_device_info(ip, username, password, device_type, commands_list):
    """
    指定された機器からコマンド出力を収集する関数
    """
    device_info = {
        'device_type': device_type,
        'host': ip,
        'username': username,
        'password': password,
        'port': 22, # 標準的なSSHポート
    }

    collected_data = {}
    start_time = time.time()

    try:
        print(f"Connecting to device: {ip}...")
        with ConnectHandler(**device_info) as net_connect:
            net_connect.enable() # 特権EXECモードに移行する場合
            print("Connection successful.")

            for cmd in commands_list:
                print(f"Executing command: '{cmd}'...")
                try:
                    output = net_connect.send_command(cmd, delay_factor=2) # 状況に応じてdelay_factorを調整
                    collected_data[cmd] = output
                    print(f"Successfully executed '{cmd}'")
                    time.sleep(1) # コマンド間に適切な遅延を入れる
                except Exception as cmd_err:
                    print(f"Error executing command '{cmd}': {cmd_err}")
                    collected_data[cmd] = f"Error: {cmd_err}"

        print(f"Finished collecting data from {ip}. Total time: {time.time() - start_time:.2f} seconds.")
        return collected_data

    except Exception as e:
        print(f"Error connecting to device {ip}: {e}")
        return None

def save_collected_data(device_ip, data):
    """
    収集したデータをファイルに保存する関数
    """
    if not data:
        print("No data to save.")
        return

    timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"network_info_{device_ip}_{timestamp}.txt"

    with open(filename, 'w') as f:
        f.write(f"--- Information collected from {device_ip} on {timestamp} ---\n\n")
        for cmd, output in data.items():
            f.write(f"--- Command: {cmd} ---\n")
            f.write(output)
            f.write("\n\n")
        f.write("--- End of data ---\n")

    print(f"Data saved to {filename}")

# --- メイン処理 ---
if __name__ == "__main__":
    if DEVICE_IP == 'YOUR_DEVICE_IP':
        print("Please configure DEVICE_IP, USERNAME, and PASSWORD.")
    else:
        collected_info = collect_device_info(DEVICE_IP, USERNAME, PASSWORD, DEVICE_TYPE, commands)

        if collected_info:
            # 収集したデータを表示または処理
            # for cmd, output in collected_info.items():
            #     print(f"\n--- Output for '{cmd}' ---")
            #     print(output)

            # ファイルに保存
            save_collected_data(DEVICE_IP, collected_info)
        else:
            print("Failed to collect information.")

コードの解説

このスクリプトは、障害発生を検知した監視システムや、手動実行トリガーによって起動されることを想定しています。取得した情報は、ファイルとして保存するだけでなく、Slackなどのコミュニケーションツールに通知したり、チケット管理システムに連携したりすることで、障害対応のプロセスにスムーズに組み込むことができます。

簡易復旧操作について

前述の「自動化の対象となる初動対応」には簡易復旧操作も含まれると述べましたが、ネットワーク機器の設定変更を自動化することは、意図しない影響を与えるリスクを伴います。特に障害発生時という異常な状況下では、自動化された変更がかえって状況を悪化させる可能性もゼロではありません。

したがって、障害対応における「簡易復旧操作」の自動化は、以下のような点に細心の注意を払う必要があります。

例えば、特定のインターフェースが論理的にダウンした場合に、物理的な状態(回線断かどうかの検知など)を確認した上で、状況に応じてshutdownコマンドを発行して物理リンクを再確立させ、その後no shutdownで再度有効化するような操作が考えられます。しかし、これは対象インターフェースや物理回線の状態に大きく依存するため、自動化の難易度とリスクが高くなります。まずは情報収集の自動化から着手し、運用に慣れてきた段階で、リスクを十分に評価した上で限定的な簡易復旧操作の自動化を検討することをおすすめします。

実践的な考慮事項

ネットワーク障害対応の自動化スクリプトを現場で運用するにあたり、以下の点を考慮することが重要です。

これらの考慮事項は、単にスクリプトを作成するだけでなく、それを信頼性の高い自動化ツールとして現場で活用するために不可欠です。

まとめ

本記事では、ネットワーク障害発生時の初動対応として、Pythonを用いた情報収集自動化スクリプトの実装に焦点を当てて解説しました。PythonライブラリであるNetmikoを利用することで、ネットワーク機器からの必要な情報収集を効率化し、障害対応の迅速化と担当者の負担軽減を図ることが可能です。

ネットワーク機器の操作に不慣れな方でも、Pythonのスキルを活かせば、障害発生時の情報収集という、運用現場で非常に役立つ自動化ツールを開発できます。ご紹介したスクリプト例を参考に、まずは基本的な情報収集の自動化から着手してみてください。簡易復旧操作の自動化はリスクを伴うため、情報収集の自動化による効果を実感し、十分な評価を行った上で慎重に検討することをおすすめします。

ネットワーク自動化は、障害対応だけでなく、日常的な運用、設定変更、コンプライアンスチェックなど、様々なシーンでその効果を発揮します。今後もPythonを活用したネットワーク自動化の可能性を探求し、現場の課題解決に役立てていきましょう。