PythonとNetmikoではじめるネットワーク機器への設定投入
はじめに
ネットワーク機器への設定作業は、手動で行うと時間と労力がかかり、ヒューマンエラーのリスクも伴います。特に、多くの機器に対して繰り返し行う定型的な作業は、自動化の恩恵が非常に大きい領域です。Pythonは豊富なライブラリエコシステムを持ち、サーバー、クラウド、アプリケーション開発など幅広い分野で自動化に活用されており、ネットワーク自動化においてもその強力なツールとして広く利用されています。
開発やインフラ自動化のご経験がある方々の中には、Pythonスキルを活かしてネットワーク領域の効率化を図りたいと考えている方もいらっしゃるかと思います。しかし、ネットワーク機器の操作やCLI(コマンドラインインターフェース)に慣れていない場合、どこから手を付ければ良いか迷うこともあるかもしれません。
本記事では、Pythonを用いてネットワーク機器へ設定を投入する基本的なスクリプトの作成方法を解説します。特に、SSH接続による機器操作のデファクトスタンダードとも言えるNetmikoライブラリに焦点を当て、その基本的な使い方から複数機器への展開、そして実践的な考慮点についても触れていきます。
Netmikoとは?
Netmikoは、SSH接続を介して様々なネットワーク機器のCLIを操作するためのPythonライブラリです。Paramikoをベースとしていますが、多くのデバイスタイプ(Cisco IOS, Juniper Junos, Arista EOSなど)に対応しており、プロンプトの判定や改ページ(--More--
など)の自動処理、configモードへの移行、設定の投入といった、ネットワーク機器操作に特化した便利な機能を提供しています。
開発者やインフラエンジニアが、ネットワーク機器固有の複雑なCLI操作を抽象化し、Pythonスクリプトとして扱いやすくするために設計されています。
準備
Netmikoを使用するには、まずPythonがインストールされている環境が必要です。Python 3.6以上を推奨します。
-
Netmikoのインストール pipを用いて簡単にインストールできます。
bash pip install netmiko
-
接続情報の準備 接続対象のネットワーク機器に関する以下の情報が必要です。
- ホスト名またはIPアドレス
- ユーザー名
- パスワード
- (必要に応じて)有効化パスワード (enable password)
- 機器のタイプ(Cisco IOS, Juniper Junosなど。Netmikoが対応しているdevice_typeを指定します)
これらの情報は、スクリプト内に直接記述する代わりに、ファイルや環境変数、構成管理ツールなどを用いて安全に管理することが実際の運用では重要です。本記事のコード例ではシンプルにするため一部をスクリプト内に記述する箇所がありますが、あくまで解説のためであり、本番環境ではより安全な方法を検討してください。
Netmikoを使った基本的な設定投入スクリプト
まずは、単一のネットワーク機器に対してSSH接続し、設定コマンドを投入する基本的なスクリプトを見てみましょう。
単一機器への接続と設定投入
以下のスクリプトは、指定した機器に接続し、基本的な設定コマンドを投入する例です。
from netmiko import ConnectHandler
from netmiko.exceptions import NetMikoTimeoutException, NetMikoAuthenticationException
# 接続情報(実際の運用では安全な方法で管理してください)
device = {
'device_type': 'cisco_ios', # 機器のタイプを指定
'host': 'YOUR_DEVICE_IP', # 機器のIPアドレスまたはホスト名
'username': 'YOUR_USERNAME', # ユーザー名
'password': 'YOUR_PASSWORD', # パスワード
'secret': 'YOUR_ENABLE_PASSWORD', # 有効化パスワード(enable password)
'port' : 22, # SSHポート番号 (デフォルトは22)
}
# 投入する設定コマンドのリスト
# 実際の機器に合わせて適切なコマンドを指定してください
config_commands = [
'hostname Netmiko-Test-Router',
'banner motd # Welcome to Netmiko Automation #',
'line vty 0 4',
' exec-timeout 15 0',
' logging synchronous',
' transport input ssh',
'end',
'write memory' # 設定の保存
]
print(f"Connecting to device {device['host']}...")
try:
# ConnectHandlerを使用して機器に接続
with ConnectHandler(**device) as net_connect:
print("Connection successful.")
# 有効化モードへの移行(必要な場合)
# Netmikoは多くのdevice_typeで自動的に処理しますが、明示的に行うことも可能
# net_connect.enable()
print("Entering configuration mode and sending commands...")
# send_config_set()を使用して設定コマンドリストを投入
output = net_connect.send_config_set(config_commands)
print("\nConfiguration commands sent:")
print(output)
except NetMikoTimeoutException:
print(f"Error: Connection timed out to {device['host']}")
except NetMikoAuthenticationException:
print(f"Error: Authentication failed for {device['host']}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
print("Script finished.")
コードの解説
from netmiko import ConnectHandler
: Netmikoの主要なクラスであるConnectHandler
をインポートします。このクラスがSSH接続を管理します。from netmiko.exceptions import ...
: Netmiko固有の例外クラスをインポートしておくと、接続や認証のエラーを適切に捕捉できます。device = { ... }
: 接続情報を辞書形式で定義します。device_type
は非常に重要で、指定した機器の種類に応じてNetmikoが内部的に処理を調整します。config_commands = [ ... ]
: 投入したい設定コマンドを文字列のリストとして定義します。各要素が1行のコマンドに対応します。ConnectHandler(**device)
: 辞書形式の接続情報をアンパックしてConnectHandler
に渡すことで接続を確立します。with
ステートメントを使用することで、処理終了時に自動的に接続が閉じられるようにしています。net_connect.send_config_set(config_commands)
: 定義した設定コマンドのリストを機器に投入するメソッドです。通常、自動的にconfigモードに移行してコマンドを実行し、元のモードに戻ります。実行結果(各コマンドの出力を含む)が文字列として返されます。try...except
: 接続タイムアウトや認証失敗などのエラーが発生した場合にスクリプトが異常終了しないよう、例外処理を記述しています。
複数機器への設定投入
実際の現場では、複数の機器に対して同じ、または一部異なる設定を投入するケースがよくあります。Netmikoを使えば、機器リストを作成し、ループ処理で順番に接続・設定投入を行うスクリプトを簡単に作成できます。
以下のスクリプトは、機器情報をリストとして定義し、各機器に対して先ほどのスクリプトと同様の設定投入を行う例です。
from netmiko import ConnectHandler
from netmiko.exceptions import NetMikoTimeoutException, NetMikoAuthenticationException
import yaml # YAMLファイルから機器リストを読み込む場合に使用
# 機器リスト(YAMLファイルから読み込む例)
# devices.yaml ファイルの例:
# - device_type: cisco_ios
# host: 192.168.1.101
# username: your_user
# password: your_password
# secret: your_enable_password
# - device_type: cisco_ios
# host: 192.168.1.102
# username: your_user
# password: your_password
# secret: your_enable_password
# ...
def load_devices_from_yaml(file_path):
"""YAMLファイルから機器リストを読み込む関数"""
try:
with open(file_path, 'r') as f:
devices = yaml.safe_load(f)
return devices
except FileNotFoundError:
print(f"Error: Device list file not found at {file_path}")
return []
except Exception as e:
print(f"Error loading device list: {e}")
return []
# 機器リストのファイルパスを指定
device_list_file = 'devices.yaml'
devices = load_devices_from_yaml(device_list_file)
if not devices:
print("No devices loaded. Exiting.")
exit()
# 投入する設定コマンドのリスト(全ての機器に共通)
# 実際の機器に合わせて適切なコマンドを指定してください
config_commands = [
'hostname Netmiko-Automated', # ホスト名は各機器で異なる場合、ループ内で動的に生成する必要あり
'banner motd # This device was automated by Netmiko #',
'line vty 0 4',
' exec-timeout 15 0',
' logging synchronous',
' transport input ssh',
'end',
'write memory' # 設定の保存
]
print(f"Loaded {len(devices)} devices from {device_list_file}")
# 各機器に対して設定を投入
for device in devices:
# ホスト名やIPアドレスを取得
host = device.get('host', 'N/A')
print(f"\n--- Connecting to {host} ({device.get('device_type', 'unknown')}) ---")
try:
# ConnectHandlerを使用して機器に接続
with ConnectHandler(**device) as net_connect:
print("Connection successful.")
# send_config_set()を使用して設定コマンドリストを投入
# config_commands リストは共通だが、必要に応じて機器ごとにリストを生成・変更することも可能
output = net_connect.send_config_set(config_commands)
print("Configuration commands sent. Output:")
print(output)
except NetMikoTimeoutException:
print(f"Error: Connection timed out to {host}")
except NetMikoAuthenticationException:
print(f"Error: Authentication failed for {host}")
except Exception as e:
print(f"An unexpected error occurred for {host}: {e}")
print("\n--- Script finished processing all devices ---")
コードの解説
import yaml
: YAMLファイルからデータを読み込むためにpyyaml
ライブラリを使用しています(pip install pyyaml
でインストールが必要です)。機器リストを外部ファイルとして管理すると、スクリプト本体を変更せずに複数の機器に対応できるようになります。load_devices_from_yaml(file_path)
: 指定されたパスのYAMLファイルから機器リストを読み込む関数です。ファイルが見つからない場合などの基本的なエラーハンドリングを含んでいます。for device in devices:
: 読み込んだ機器リストをループ処理します。リストの各要素は、先ほどの単一機器の例で使った接続情報と同じ辞書形式であることを想定しています。- ループ内で、各
device
辞書をConnectHandler(**device)
に渡して接続を確立し、send_config_set()
で設定を投入します。 - 各機器ごとの接続エラーやその他の例外を捕捉し、処理中の機器を特定できるようにエラーメッセージを工夫しています。
このスクリプトを基盤として、機器ごとに異なる設定を適用したり、成功/失敗をログファイルに出力したり、設定投入前後に機器の状態を確認するコマンドを実行したりといった機能を追加していくことで、より実用的な自動化スクリプトに発展させることが可能です。
実践的な考慮点
Netmikoを使ったネットワーク自動化スクリプトを現場で利用する上で、いくつか考慮すべき重要な点があります。
- 認証情報の管理: スクリプト内にユーザー名やパスワードをハードコーディングするのはセキュリティ上のリスクが非常に高いです。環境変数、安全な設定ファイル(権限を適切に設定)、Pythonの
secrets
モジュール、あるいはAnsible VaultやHashiCorp Vaultのようなツールを利用することを強く推奨します。 - エラーハンドリングの強化: 接続エラー、認証エラーだけでなく、コマンド実行時のエラー(例: 存在しないコマンドを入力した、権限がない、設定内容に構文エラーがある)に対するハンドリングも重要です。
send_config_set
は、コマンドが成功したかどうかの厳密な判定は難しい場合もありますが、出力文字列を解析したり、try...except
ブロックで特定のCLIメッセージ(例:% Invalid input detected
)を捕捉したりすることで、エラーを検知できる場合があります。 - 冪等性: Netmikoの
send_config_set
メソッドは、基本的に与えられたコマンドを機器に流し込むだけです。このため、同じスクリプトを複数回実行した場合に、常に同じ最終状態になることを保証する「冪等性」は、単純な利用では担保されません。すでに設定が存在する場合に重複したり、意図しない状態になったりする可能性があります。より高度な設定管理や冪等性を求める場合は、NAPALM(Network Automation and Programmability Abstraction Layer with Multiprovider support)や、ネットワークモジュールが充実している構成管理ツール(Ansible, Puppet, Chefなど)と連携することを検討してください。これらのツールは、設定の「状態」を定義し、機器がその状態になるように必要な操作を判断して実行します。 - 出力の取得と検証: 設定変更が正しく行われたかを確認するために、設定投入後に
send_command
メソッドを使ってshow running-config
や特定の設定を確認するコマンドを実行し、その出力を取得して解析することが有効です。期待通りの出力が得られているかを確認することで、設定投入の成否をより確実に判断できます。 - ロギング: スクリプトの実行状況、成功/失敗、エラーメッセージ、機器からの出力などをログファイルに記録することは、トラブルシューティングや監査のために不可欠です。Pythonの
logging
モジュールを利用して、適切なレベルで詳細な情報を記録するようにしましょう。 - バージョン管理: 作成したスクリプトや機器リスト(YAMLファイルなど)は、Gitなどのバージョン管理システムで管理することが重要です。変更履歴を追跡し、必要に応じて過去のバージョンに戻せるようにします。
インフラ自動化全体の中での位置づけ
Netmikoを使ったスクリプトは、ネットワーク自動化の強力な一歩となります。しかし、より広範なインフラ自動化の文脈では、単なるスクリプト実行を超えたツールやプロセスとの連携が考えられます。
- IaCツールとの連携: Ansible, TerraformといったIaC(Infrastructure as Code)ツールは、ネットワーク機器を含めたインフラ全体の状態管理を得意としています。NetmikoはAnsibleのネットワークモジュールのバックエンドとしても利用されており、IaCツールからNetmikoの機能を利用することで、サーバー、クラウド、ネットワークを一元的に自動化することが可能です。
- CI/CDパイプラインへの組み込み: ネットワーク設定の変更も、アプリケーションコードと同様にCI/CDパイプラインに組み込むことで、テストの自動化やデプロイメントの標準化を図ることができます。Pull Requestをトリガーに自動テスト(設定構文チェック、ネットワーク接続テストなど)を実行し、承認後に本番環境への設定適用を自動化するといったワークフローが構築可能です。
- API連携: 近代的なネットワーク機器やコントローラー(SDNコントローラーなど)は、RESTConf, NETConfといったAPIを提供しています。APIを利用することで、CLI操作よりも構造化されたデータを扱い、より洗練された自動化が可能になります。Pythonの
requests
ライブラリなどを使用してAPI連携を行うことも、ネットワーク自動化の重要な手法の一つです。
Netmikoは、CLIベースの機器に対するSSH自動化の基礎として非常に有用ですが、自動化の目的や対象に応じて、他のツールやAPI連携といった手法も組み合わせていくことが、より堅牢でスケーラブルな自動化システムを構築する鍵となります。
まとめ
本記事では、PythonとNetmikoを用いたネットワーク機器への基本的な設定投入スクリプトの作成方法について解説しました。Netmikoは、SSH接続による様々な自動化タスクにおいて、ネットワーク機器の多様性やCLI操作の複雑さを吸収してくれる強力なライブラリです。
単一機器への基本的な接続から、機器リストを使った複数機器への展開、そして認証情報の安全な管理やエラーハンドリング、冪等性といった実践的な考慮点についても触れました。
ここで紹介したスクリプトはあくまで出発点です。実際の現場では、エラーリカバリ、設定の差分適用、複数バージョンへの対応、テスト自動化など、さらに多くの要件が出てくることが予想されます。これらの課題に対して、Netmikoの機能をより深く活用したり、他のPythonライブラリ、あるいはAnsibleのような構成管理ツールやAPI連携といった手法と組み合わせていくことで、より高度なネットワーク自動化を実現していくことが可能です。
今後の記事では、Netmikoを使った情報取得や監視スクリプト、NAPALMによる状態管理、ネットワークAPI連携、IaCツールとの連携など、さらに実践的なネットワーク自動化のトピックを掘り下げていく予定です。Pythonスキルをネットワーク自動化に活かしたい皆様の、はじめの一歩となれば幸いです。