てくなべ (tekunabe)

ansible / network / automation

[Ansible] NetBox をインベントリーとして利用する


これは Ansible 3 Advent Calendar 2019 の21日目の記事です。


■ はじめに

f:id:akira6592:20191215212622p:plain:w500
NetBox を インベントリーとして利用する

以前「[Ansible] NetBox モジュールで Site や Device を登録する(Collection モジュール編) - てくなべ (tekunabe)」で、Ansible から NetBox の Device を登録する方法をご紹介しました。

今回は NetBox に登録された Device を、Ansible のインベントリーとして利用する方法をご紹介します。 Ansible 2.8 で追加された、NetBox Inventory Plugin を利用します。 YAML で簡単な設定ファイルを書くだけで、動的なインベントリとして扱えるようになります。


■ NeBox上の状態

まず、今回インベントリとして利用する NetBox 上の Device 登録状態を示します。

前回の記事の「目指すゴール」で示した内容です。

f:id:akira6592:20191215212725p:plain
Device 一覧

念のため表でも示します。

Name Site Role Manufacture Type IP Address
cat1 my_site core Cisco Catalyst 10.0.1.1
cat2 my_site core Cisco Catalyst 10.0.1.2
veos1 my_site aggregation Arista veos 10.0.3.1
veos2 my_site aggregation Arista veos 10.0.3.2

ポイントは、IP Address の列で示されているアドレスです。これは 各 Device でPrimary Address として選出したアドレスです。このアドレスが、インベントリ変数の ansible_host に変換され、Ansible が接続する先の情報として利用されます。

f:id:akira6592:20191215212850p:plain
Device 登録画面の Primary IPv4 設定部分


■ 環境の準備

以下のものを利用します。

  • Ansible 2.9.1
  • NetBox 2.6.7
  • pynetbox 4.2.2
  • Python 3.6

NetBox は、以前の記事の「NetBox の準備」で構築済みです。

Ansible 側には pip install pynetboxpynetbox をインストールしておきます。

なお、Ansible で利用するのはあくまでも NetBox Inventory Plugin であるため、標準、Collection に関わらず NetBox モジュールは利用しません。


■ インベントリ設定ファイルの準備

NetBox をインベントリーとして利用するために、NetBox Inventory Plugin のお作法に従って簡単なインベントリ設定ファイルを準備します。この設定ファイルを ansible-playbook コマンドの -i オプションに指定するという流れです。

以下、簡単なサンプルです。ファイル名は任意です。

  • netbox.yml
---
plugin: netbox
api_endpoint: http://localhost:32768
token: 0123456789abcdef0123456789abcdef01234567
group_by:
  - manufacturers

各設定の意味は以下の通りです。

設定名 必須 概要
plugin 必須 NetBox をインベントリーとして利用する場合は netbox 固定
api_endpoint 必須 NetBox API のベースURL
token 必須 NetBox API の接続に必要なトーク
group_by グループ化する単位を指定、sitemanufacturers などを指定可

他にも、https で接続する際の証明書検証の有無を指定する validate_certs や、フィルターする query_filters などのオプションもあります。詳細は公式ドキュメントの NetBox Inventory Plugin を参照して下さい。

基本的な準備はここまでです。


ansible-inventory コマンドによる確認

正しく NetBox をインベントリーとして利用できるか確認します。

ここではいきなり Playbook で試さずに、インベントリー単体の確認するためのコマンド ansible-inventory を利用します。

ホストリストの確認

ansible-inventory コマンドに --list をプションをつけると、インベントリのリストを確認できます。 どのような変数が割り当てられているかも確認できます。

  • 実行例
$ ansible-inventory -i inventory_nb.yml --list
{
    "_meta": {
        "hostvars": {
            "cat1": {
                "ansible_host": "10.0.1.1",
                "device_roles": [
                    "core"
                ],
                "device_types": [
                    "Catalyst"
                ],
                "manufacturers": [
                    "Cisco"
                ],
                "primary_ip4": "10.0.1.1",
                "sites": [
                    "my_site"
                ]
            },
            "cat2": {
                "ansible_host": "10.0.1.2",
                "device_roles": [
                    "core"
                ],
                "device_types": [
                    "Catalyst"
                ],
                "manufacturers": [
                    "Cisco"
                ],
                "primary_ip4": "10.0.1.2",
                "sites": [
                    "my_site"
                ]
            },
            "veos1": {
                "ansible_host": "10.0.3.1",
                "device_roles": [
                    "aggregation"
                ],
                "device_types": [
                    "veos"
                ],
                "manufacturers": [
                    "Arista"
                ],
                "primary_ip4": "10.0.3.1",
                "sites": [
                    "my_site"
                ]
            },
            "veos2": {
                "ansible_host": "10.0.3.2",
                "device_roles": [
                    "aggregation"
                ],
                "device_types": [
                    "veos"
                ],
                "manufacturers": [
                    "Arista"
                ],
                "primary_ip4": "10.0.3.2",
                "sites": [
                    "my_site"
                ]
            }
        }
    },
    "all": {
        "children": [
            "manufacturers_Arista",
            "manufacturers_Cisco",
            "ungrouped"
        ]
    },
    "manufacturers_Arista": {
        "hosts": [
            "veos1",
            "veos2"
        ]
    },
    "manufacturers_Cisco": {
        "hosts": [
            "cat1",
            "cat2"
        ]
    }
}

cat1cat2veos1veos2 という 4つの Device があり、それぞれ ansible_hostdevice_roles などの経数が割り当てられていることが確認できます。ansible_host 変数の値が、Ansible が接続に利用する宛先です。

また、インベントリー設定ファイルの group_bymanufacturers を指定したことから、manufacturers_Aristamanufacturers_Cisco グループと所属ホストの定義がされていることも確認できます。

グループ化の確認

ansible-inventory コマンドに --graph をプションをつけると、グループと所属ホストを確認できます。

  • 実行例
$ ansible-inventory -i inventory_nb.yml --graph
@all:
  |--@manufacturers_Arista:
  |  |--veos1
  |  |--veos2
  |--@manufacturers_Cisco:
  |  |--cat1
  |  |--cat2

スタティックなインベントリファイルで表すと

イメージを湧きやすくするため、NetBox で定義されて動的なインベントリを、スタティックなインベントリファイル(ini形式)で表してみます。変数は抜粋してます。

[manufacturers_Arista]
veos1 ansible_host=10.0.3.1
veos2 ansible_host=10.0.3.2

[manufacturers_Cisco]
cat1 ansible_host=10.0.1.1
cat2 ansible_host=10.0.1.2

ここまでで、ansible-inventory コマンドによって、正常にインベントリとして認識できていることが確認できました。


ansible-playbook コマンドによる利用

今度は、インベントリを Playbook 実行時に利用します。

変数ファイルによる補足

ここまでの作業で、インベントリ名や ansible_host 変数などは NetBox 上の情報を利用できようになしました。しかし、まだパスワードなど接続に必要な情報がありません。NetBox 本体や、NetBox Inventory Plugin を活用すれば、NetBox 上に情報を集約できるかもしれません。ただ、現時点で実現方法がまだ分からなかったので、Ansible 側に別途変数ファイルを準備して補足することにします。

ここでは、manufacturers_Cisco グループに所属するホストを対象とします。

  • group_vars/manufacturers_Cisco.yml
---
ansible_network_os: ios
ansible_connection: network_cli
ansible_user: testuserxxx
ansible_password: testpaswordxxx

Playbook の作成

manufacturers_Cisco グループを対象にした簡単な Playbook を作成します。

  • iso_show.yml
- hosts: manufacturers_Cisco
  gather_facts: no

  tasks:
    - name: show test
      ios_command:
        commands:
          - show version    # show version を実行
      register: result

    - name: debug test
      debug:
        msg: "{{ result }}"  # コマンド実行結果を表示

Playbook の実行

それでは、Playbook を実行します。

$ ansible-playbook -i inventory_nb.yml ios_show.yml 

PLAY [manufacturers_Cisco] ******************************************************************************************

TASK [show test] ****************************************************************************************************
ok: [cat2]
ok: [cat1]

TASK [debug test] ***************************************************************************************************
ok: [cat1] => {
    "msg": {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        },
        "changed": false,
        "failed": false,
        "stdout": [
            "Cisco IOS XE Software, Version 16.11.01a\n...(略)...
        ],
        "stdout_lines": [
            [
                "Cisco IOS XE Software, Version 16.11.01a",
                "Cisco IOS Software [Gibraltar], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.11.1a, RELEASE SOFTWARE (fc1)",
                "Technical Support: http://www.cisco.com/techsupport",
                "Copyright (c) 1986-2019 by Cisco Systems, Inc.",
                "Compiled Thu 11-Apr-19 23:59 by mcpre",
                ...(略)...
            ]
        ],
        "warnings": [
            "Platform darwin on host cat1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information."
        ]
    }
}
ok: [cat2] => {
    "msg": {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        },
        "changed": false,
        "failed": false,
        "stdout": [
            "Cisco IOS XE Software, Version 16.11.01a\n...(略)...
        ],
        "stdout_lines": [
            [
                "Cisco IOS XE Software, Version 16.11.01a",
                "Cisco IOS Software [Gibraltar], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.11.1a, RELEASE SOFTWARE (fc1)",
                "Technical Support: http://www.cisco.com/techsupport",
                "Copyright (c) 1986-2019 by Cisco Systems, Inc.",
                "Compiled Thu 11-Apr-19 23:59 by mcpre",
                ...(略)...
            ]
        ],
        "warnings": [
            "Platform darwin on host cat2 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information."
        ]
    }
}

PLAY RECAP **********************************************************************************************************
cat1                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
cat2                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

$

無事に、NetBox 上の Device 情報をインベントリとして利用して Playbook を実行できました。


■ おわりに

NetBox Inventory Plugin を利用することで、NetBox をインベントリとして利用できました。

今回の私のやり方ですが、情報を NetBox に集約しきれなかったのでいまいちかもしれませんが、もっと活用すると良い感じになるかも知れません。