Pythonicなネットワーク自動化:Nornirで実現するAnsibleを超えたスケーリング

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

クイックスタート:5分で稼働させる

50台のスイッチに対して手動でVLAN変更を行うのは、単に退屈な作業であるだけでなく、午前2時の障害発生を招く要因にもなります。Ansibleは業界標準ですが、その YAMLベースのDSLは、複雑なロジックが必要な場合には制約(拘束衣)のように感じられることがあります。Nornirは、その状況を一変させます。これは軽量でプラグイン可能なフレームワークであり、ネットワークをPythonオブジェクトの集合として扱い、数千のノードに対してタスクを同時に実行することを可能にします。

まず、クリーンな仮想環境を構築します。SSH通信の重い処理を担当させるために、NornirとNetmikoプラグインが必要になります。

pip install nornir nornir_utils nornir_netmiko

Nornirは、config.yamlhosts.yamlgroups.yamlという3つのシンプルなYAMLファイルを使用してデータを整理します。テスト用のルーターからバージョン情報を取得して、実際に動かしてみましょう。

hosts.yaml

---
router-01:
  hostname: 192.168.1.10
  groups:
    - cisco_ios

groups.yaml

---
cisco_ios:
  platform: cisco_ios
  username: admin
  password: cisco123

次に、実行スクリプトを main.py に記述します。

from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_command
from nornir_utils.plugins.functions import print_result

nr = InitNornir(config_file="config.yaml")

def get_info(task):
    # "show version" コマンドを実行
    task.run(task=netmiko_send_command, command_string="show version")

results = nr.run(task=get_info)
print_result(results)

python main.py を実行してください。数秒以内にデバイスのハードウェア詳細が表示されます。これまで手動で10分かかっていたログインプロセスを、データセンター全体までスケール可能なスクリプトに置き換えることができました。

アーキテクチャ:大規模環境でNornirが選ばれる理由

Nornirは、使い勝手の悪いCLIを備えたスタンドアロンのアプリケーションではありません。ライブラリです。Pythonコードに直接インポートすることで、pdb のような標準的なデバッグツールやIDEのフルサポートを利用できます。YAMLのインデントエラーでデプロイ全体が失敗した原因を推測する必要はもうありません。

インベントリの階層構造

データは、Host(ホスト)、Group(グループ)、Default(デフォルト)の3層システムによってクリーンに保たれます。これにより、設定をDRY(Don’t Repeat Yourself:重複を避ける)に保つことができます。固有のIPアドレスは hosts.yaml で定義し、共通の認証情報は groups.yaml に保存します。500台のデバイスに対してグローバルなSNMP文字列を更新する必要がある場合、変更するのは defaults.yaml のわずか1行だけです。

本番環境において、この構造は救世主となります。私が1,200台のスイッチ群を管理していた際、この階層的アプローチにより、デバイスレベルでの変数ハードコーディングを止めたことで、設定の乖離(コンフィグドリフト)を40%近く削減できました。

超高速なフィルタリング

特定のハードウェアをターゲットにするのも簡単です。ロンドンオフィスのコアリミットルーターだけをアップグレードしたいですか?filter メソッドを使えば、メモリ上のインベントリを瞬時に抽出できます。

# 特定のサイトとロールをターゲットにする
london_routers = nr.filter(site="LON", role="router")

# またはパッチ適用のためにソフトウェアバージョンでフィルタリングする
legacy_switches = nr.filter(version="15.2(E)")

Nornirはデフォルトで ThreadedRunner を使用します。Ansibleのフォークベースのモデルはオーバーヘッドが大きくなりがちですが、NornirはCPUへの負荷を最小限に抑えつつ、100以上の同時接続を処理します。大規模なポーリングタスクにおいて、一貫してAnsibleより5倍から10倍高速です。

複雑なデプロイのマスター

単一のコマンドを実行するのは始まりに過ぎません。現実世界のネットワーキングには、状態管理とエラーハンドリングが必要です。Nornirはタスクベースのシステムを採用しており、各「タスク」は標準的なPython関数にすぎません。

Jinja2:プロのようなテンプレート活用

設定をハードコーディングするのは災難の元です。Jinja2テンプレートを使用して、デバイス固有のデータに基づいて動的に設定を生成しましょう。

from nornir_jinja2.tasks import template_file
from nornir_netmiko.tasks import netmiko_send_config

def deploy_vlan(task):
    # テンプレートから設定を生成
    config_data = task.run(task=template_file, 
                           template="vlan_config.j2", 
                           path="templates")
    
    # ハードウェアに流し込む
    task.run(task=netmiko_send_config, 
             config_commands=config_data.result.splitlines())

不可避な事態への対処:本番環境のエラー

大規模な環境では、いずれスイッチがオフラインになったり、パスワードが拒否されたりすることがあります。Nornirは単にクラッシュするのではなく、これらの失敗を TaskResults オブジェクトにキャプチャします。これにより、カスタムの再試行ロジックを構築したり、特定のエラーをデータベースに記録したりできます。

if results.failed:
    for host, result in results.items():
        if result.failed:
            print(f"致命的エラー: {host} がタイムアウトしました。例外: {result.exception}")

この粒度の細かさこそが、開発者がNornirを選ぶ理由です。ブラックボックスの実行エンジンと戦うのではなく、標準的で読みやすいPythonを書いているのです。

現場で役立つ実践的なヒント

CLIからNornirへ移行するには、戦術的な転換が必要です。高可用性が求められる環境で自動化

Share: