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

実践Pythonネットワーク自動化:Ansibleとの連携パターンとコード例

Tags: Python, Ansible, ネットワーク自動化, IaC, スクリプト連携

はじめに

ネットワーク機器の設定や運用の自動化は、現代のITインフラ運用において不可欠な要素となっています。Pythonは豊富なライブラリと高い柔軟性から、ネットワーク自動化の強力なツールとして広く利用されています。一方、Ansibleのような構成管理ツールは、宣言的なアプローチと冪等性により、インフラの状態をDesired Stateに保つことを得意としています。

Pythonスキルを高くお持ちのエンジニアの皆様の中には、既存のPythonベースの自動化ワークフローやIaCツールによるインフラ管理プロセスに、どのようにネットワーク自動化を組み込むかに関心をお持ちの方もいらっしゃるかと存じます。特に、ネットワーク機器の直接的な操作に慣れていない場合でも、Pythonのスキルを活かしてネットワーク部分を効率化したい、とお考えかもしれません。

この記事では、PythonとAnsibleを連携させることで、それぞれの強みを活かした効率的かつ堅牢なネットワーク自動化を実現する方法について解説します。具体的な連携パターンとコード例を通じて、皆様の現場での自動化スクリプト開発の一助となれば幸いです。

なぜPythonとAnsibleを連携させるのか

PythonとAnsibleは、それぞれ異なる特性を持つツールです。これらを連携させることには、以下のようなメリットがあります。

Ansibleは「状態を定義し、それを実現する」タスク指向の自動化に適しています。一方、Pythonは「複雑なデータを処理し、条件に基づいて判断を行い、外部システムと連携する」ような、よりプログラマブルな処理に適しています。

これらの強みを組み合わせることで、例えば以下のようなシナリオを実現できます。

PythonとAnsibleの連携パターン

PythonとAnsibleを連携させる主なパターンをいくつかご紹介します。

パターン1: Ansible PlaybookからPythonスクリプトを呼び出す

このパターンでは、Ansible Playbookのタスクの一部としてPythonスクリプトを実行します。PythonスクリプトはAnsibleの管理対象ホスト上、またはAnsibleコントローラー上(Delegate to localhostなどを使用)で実行できます。

これは、Ansibleの標準モジュールでは実現できない複雑なデータ処理、外部API連携、または特定の計算などをPythonで行いたい場合に便利です。

使用するAnsibleモジュール:

コード例: scriptモジュールを使用した例

ここでは、管理対象ホスト(この例ではローカルホストを想定)でPythonスクリプトを実行し、その出力をAnsibleで取得する例を示します。

まず、実行するPythonスクリプト get_system_info.py を作成します。

#!/usr/bin/env python3

import sys
import platform
import json

# 標準出力にJSON形式で情報を出力
info = {
    "python_version": platform.python_version(),
    "system": platform.system(),
    "node_name": platform.node(),
    "release": platform.release(),
    "version": platform.version(),
    "machine": platform.machine()
}

json.dump(info, sys.stdout)
print() # Ensure newline at the end

次に、このスクリプトを呼び出すAnsible Playbook run_python_script.yml を作成します。

---
- name: Run Python script and process output
  hosts: localhost # または適切なネットワーク機器ホスト
  connection: local # またはnetwork_cliなど、適切な接続タイプ
  gather_facts: false

  tasks:
    - name: Execute Python script
      script: ./get_system_info.py # 実行するスクリプトへのパスを指定
      # registerでスクリプトの実行結果を格納
      register: script_output

    - name: Parse JSON output from script
      # stdoutは文字列として取得されるため、from_jsonフィルターでパース
      ansible.builtin.set_fact:
        system_info: "{{ script_output.stdout | from_json }}"

    - name: Display parsed information
      debug:
        msg: "System Information: {{ system_info }}"

    - name: Display specific info (e.g., Python version)
      debug:
        msg: "Python Version: {{ system_info.python_version }}"

このPlaybookを実行すると、get_system_info.py が実行され、その標準出力がAnsibleの script_output.stdout に格納されます。from_json フィルターを使ってこれをPythonオブジェクト(Ansibleではディクショナリ)に変換し、set_fact で変数に格納しています。これにより、Pythonスクリプトで生成した構造化データをAnsible Playbook内で後続のタスクで利用することが可能になります。

ネットワーク自動化の文脈では、Pythonスクリプト内でnetmikoなどを使って機器から情報を取得し、その結果をJSONなどで出力し、Ansibleで受け取って処理する、といった応用が考えられます。

パターン2: PythonスクリプトからAnsible Playbook/モジュールを呼び出す

このパターンは、より複雑な自動化ワークフローをPythonで構築し、その中でネットワーク機器への設定投入や状態確認などのタスクを実行するためにAnsibleを利用する場合に有効です。例えば、外部のイベント(監視アラート、チケットシステム連携など)をトリガーにPythonスクリプトが起動し、状況を判断した上で必要なネットワーク操作をAnsibleに実行させる、といったことができます。

PythonからAnsibleを実行するには、Ansibleが提供するPython APIやツールを利用します。主なものとして ansible-runner や内部API (ansible.inventory, ansible.playbook など) があります。公式には ansible-runner の利用が推奨されています。

ansible-runner を使用した例:

ansible-runner は、Ansible PlaybookやRoleをプログラムから実行するためのインターフェースを提供します。実行環境の隔離や、結果の構造化された取得が容易になります。

まず、実行したいAnsible Playbook configure_vlan.yml を作成します(これは一般的なネットワーク機器設定のPlaybookを想定)。

---
- name: Configure VLAN
  hosts: network_devices # 設定対象のホストグループ
  connection: network_cli
  gather_facts: false

  tasks:
    - name: Ensure VLAN exists
      # 使用するベンダーに応じたモジュールを使用
      # 例: Cisco IOSの場合
      cisco.ios.ios_vlan:
        vlan_id: "{{ vlan_id }}"
        name: "{{ vlan_name }}"
        state: present
      # 変数はPythonスクリプトから渡される

次に、このPlaybookをPythonスクリプトから呼び出す例を示します。

import ansible_runner
import os

# Playbookが存在するディレクトリ
playbook_dir = './ansible'
# 実行するPlaybookファイル名
playbook_file = 'configure_vlan.yml'

# Playbookディレクトリとvarsディレクトリを作成 (必要に応じて)
os.makedirs(os.path.join(playbook_dir, 'vars'), exist_ok=True)

# PythonスクリプトからAnsibleに渡す変数
# この例では、どのVLANを設定するかを動的に決定することを想定
vlan_vars = {
    "vlan_id": 100,
    "vlan_name": "Sales_VLAN"
}

# ansible-runner を使用してPlaybookを実行
# private_data_dir: runnerが作業に使用するディレクトリ
# playbook: 実行するPlaybookのファイル名
# extravars: Playbookに渡す追加変数
r = ansible_runner.run(
    private_data_dir=playbook_dir,
    playbook=playbook_file,
    extravars=vlan_vars
)

# 実行結果の確認
print(f"Playbook execution status: {r.status}")
if r.status == 'successful':
    print("Playbook executed successfully.")
    # 詳細な結果は r.stats, r.events などから取得可能
else:
    print(f"Playbook failed. Error: {r.stdout.read()}")
    # より詳細なエラー情報は r.events などから取得

このPythonスクリプトでは、ansible_runner.run() 関数を使って指定したPlaybookを実行しています。extravars パラメータを通じて、Pythonスクリプト内で定義した変数をPlaybookに渡すことができます。これにより、Pythonで生成した動的なデータをAnsibleのタスクに適用することが可能です。

このパターンは、ネットワーク自動化をより広範な自動化ワークフローやアプリケーションに組み込む場合に非常に強力です。

パターン3: カスタムAnsibleモジュールをPythonで作成

Ansibleに標準で用意されていない機能や、非常に特定の処理をネットワーク機器に対して行いたい場合、Pythonでカスタムモジュールを作成することができます。作成したカスタムモジュールは、標準モジュールと同様にPlaybookから呼び出すことができます。

カスタムモジュール開発にはAnsibleモジュールの構造に関する理解が必要ですが、これによりAnsibleの機能をPythonの柔軟性で拡張することが可能になります。このパターンに関する詳細な解説は別記事で行う予定ですが、Ansibleの公式ドキュメントや関連情報を参照していただくことを推奨いたします。

連携における考慮事項

PythonとAnsibleを連携させる際には、以下の点に留意することで、より堅牢で運用しやすい自動化を実現できます。

実践的な応用例

PythonとAnsibleの連携は、様々なネットワーク自動化シナリオに応用できます。

まとめ

この記事では、PythonとAnsibleを連携させたネットワーク自動化の手法について、そのメリット、主要な連携パターン、そして実践における考慮事項を解説しました。Pythonの柔軟性とAnsibleの堅牢性を組み合わせることで、より複雑で、かつメンテナンス性の高いネットワーク自動化ワークフローを構築することが可能です。

ネットワーク機器の直接的な操作に不慣れな場合でも、Pythonでデータ処理や外部連携を担当し、ネットワーク機器との具体的な通信や設定適用はAnsibleの豊富なモジュールに任せる、といった役割分担により、皆様がお持ちのPythonスキルをネットワーク自動化の分野で最大限に活かすことができるはずです。

今回ご紹介したコード例やパターンが、皆様の現場でのネットワーク自動化の取り組みを推進する一助となれば幸いです。今後も、より具体的なスクリプト例や応用シナリオについてご紹介していく予定です。