マルチベンダー・ネットワークの混沌
昨年、私たちのインフラチームは限界を迎えました。40台のJuniper MXルーター、150台のCisco Catalystスイッチ、そしてMikrotik CCRを稼働させている72の遠隔拠点を管理していました。新しいVLANのプロビジョニングやNTPサーバーの更新が必要になるたびに、3人のエンジニアが3つの異なるCLI環境にログインしなければなりませんでした。Ciscoのdescription構文はJuniperのdescriptionとは異なり、Mikrotikのcommentとは似ても似つきません。
単純なタイポ(入力ミス)が頻繁に障害を引き起こしました。Juniperでのcommit忘れや、Ciscoスイッチでのwrite memory忘れにより、再起動後に設定が消失してしまうこともありました。手動管理は単に遅いだけでなく、リスクそのものでした。私たちはルーターを「ペット」のように扱うのをやめ、「コード」として扱う必要がありました。
手動CLIとカスタムスクリプトが限界に達した理由
最初の解決策として、ParamikoやNetmikoを使用したカスタムPythonスクリプトを試みました。これらのライブラリは強力ですが、すぐに1,400行を超える脆弱なボイラープレートコードを保守していることに気づきました。ネットワークの管理よりも、SSHのタイムアウト処理やベンダー固有のエラーパースに多くの時間を費やしていました。私たちはネットワークを構築していたのではなく、単に現状を維持するためだけにソフトウェアアプリケーションを開発していたのです。
本当のボトルネックは、抽象化レイヤーの欠如でした。混在環境において、「DNSサーバーを8.8.8.8に設定する」といった「意図(Intent)」は共通です。しかし、その実装はベンダーごとに断片化されています。私たちが必要としていたのは、CLIを超えて、すべてのOSの構文エキスパートにならなくても、ネットワークの「あるべき状態(State)」を定義できるツールでした。
適切なツールの選択:Python vs. Ansible
私たちは主に3つの道を検討しました:
- 手動CLI:初期費用はかかりませんが、運用リスクが高く、拡張性はゼロです。
- カスタムPythonスクリプト:柔軟性は非常に高いですが、ジュニア管理者が不足しがちなプロレベルのプログラミングスキルを必要とします。
- Ansible:エージェントレスで、人間が読みやすいYAMLを使用し、ベンダーが直接メンテナンスしている膨大なNetwork Modulesのエコシステムを備えています。
Ansibleが選ばれた理由は、データ(IPアドレスやVLAN IDなど)をロジック(それらを適用するために必要な特定のコマンド)から分離できるからです。この分離こそが、Ansible Network ModulesとJinja2テンプレートの組み合わせが決定的な利点となる理由です。より大規模な環境や複雑な要件がある場合は、Pythonicなネットワーク自動化を可能にするNornirのような選択肢も検討に値します。
本番環境のワークフロー:モジュール + テンプレート
実環境で6ヶ月運用した結果、私たちのワークフローはクリーンな3層アーキテクチャに落ち着きました。このアプローチにより、焦点は「どう入力するか」から「ネットワークはどうあるべきか」へと移ります。
1. マルチベンダー・インベントリの定義
Ansibleは、各デバイスにどのドライバーを使用するかを知る必要があります。これはhosts.iniで定義します。ansible_network_os変数を設定することで、各ハードウェアタイプに対してどのモジュールセットをロードすべきかをAnsibleに正確に伝えます。
[campus_switches]
sw-cisco-01 ansible_host=10.0.1.10 ansible_network_os=cisco.ios.ios
sw-juniper-01 ansible_host=10.0.1.20 ansible_network_os=junipernetworks.junos.junos
sw-mikrotik-01 ansible_host=10.0.1.30 ansible_network_os=community.general.routeros
2. Jinja2による設定の抽象化
Jinja2テンプレートを使用することで、ベンダー固有のプレイブックを避けることができます。1つのYAMLデータ構造を作成し、それを各ベンダーの特定の構文にマッピングします。例えば、標準的なシステムバナーを考えてみましょう。
まず、group_vars/all.ymlで変数を定義します:
system_banner: "許可されたアクセスのみ可能です。すべての操作はログに記録されます。"
snmp_community: "itfromzero_readonly"
次に、特定のテンプレートを作成します。こちらがCisco版(templates/cisco_ios.j2)です:
banner motd ^
{{ system_banner }}
^
そしてJuniper版(templates/juniper_junos.j2)です:
set system login message "{{ system_banner }}"
3. プレイブック:すべてが繋がる場所
プレイブックは、レンダリングされたテンプレートをプッシュするために専用のconfigモジュールを使用します。これらのモジュールは「べき等性(Idempotency)」を持っています。現在の状態を確認し、デバイスの設定がテンプレートと一致しない場合にのみコマンドを送信します。
- name: マルチベンダー・システム設定のデプロイ
hosts: campus_switches
gather_facts: false
tasks:
- name: Cisco設定のプッシュ
cisco.ios.ios_config:
src: templates/cisco_ios.j2
when: ansible_network_os == 'cisco.ios.ios'
- name: Juniper設定のプッシュ
junipernetworks.junos.junos_config:
load: merge
src: templates/juniper_junos.j2
when: ansible_network_os == 'junipernetworks.junos.junos'
- name: Mikrotik設定のプッシュ
community.general.routeros_command:
commands:
- /system identity set name={{ inventory_hostname }}
- /snmp community set [find default=yes] name={{ snmp_community }}
when: ansible_network_os == 'community.general.routeros'
現場で得た教訓
このモデルへの移行は完全にスムーズだったわけではありません。この道のりを始めるなら、事前にネットワークラボシミュレーションなどを活用して十分に検証し、以下の4つのポイントを念頭に置いてください。
check_modeで確認する:常に最初に--checkを付けてプレイブックを実行してください。これによりドライランが行われ、本番トラフィックに影響を与えることなく、変更される内容の正確な差分(diff)を確認できます。- ファクト収集はパフォーマンスを低下させる:ネットワークデバイスは低速です。ハードウェアのシリアル番号などが特に必要でない限り、デフォルトで
gather_factsを無効にしてください。この変更だけで、実行時間が約40%短縮されました。 - シークレットを保護する:SSHパスワードやSNMP文字列をプレーンテキストで保存しないでください。
ansible-vaultを使用して機密変数を暗号化しましょう。設定には5分もかかりませんが、重大なセキュリティ漏洩を防ぐことができます。 - 命名規則を標準化する:自動化は、インターフェース名が厳格なパターンに従っているときに最も効果を発揮します。あるスイッチが
GigabitEthernet0/1を使用し、別のスイッチがge-0/0/0を使用している場合、Jinja2のロジックはすぐにネストされたif文の塊になってしまいます。
結果:Infrastructure as Code(コードとしてのインフラ)
最大の変革はソフトウェアではなく、私たちのマインドセットでした。もはや「スイッチにログインする」ことはありません。代わりに、YAMLファイルを修正し、Gitのプルリクエストを送信し、CI/CDパイプラインにAnsibleプレイブックを実行させます。これにより、コンフィグバックアップを自動化し、すべての変更に対する完璧な監査トレイル(証跡)が作成されます。
Ansibleの専用モジュールを活用することで、新しい拠点の展開時間は2日間からわずか20分に短縮されました。さらに重要なことに、過去のダウンタイムの90%を占めていたヒューマンエラーを排除できました。もし、今でもマルチベンダー環境を手動で管理しているなら、それは災害を待っているようなものです。まずはDNS設定のような簡単なものの自動化から始めてみてください。週末までには、そのメリットを実感できるはずです。

