Ansibleのnetwork moduleを使ってCisco IOS機器を制御する
複数台のCisco IOSルータから定期的にコマンドを取得する必要があったので、せっかくなのでAnsibleを使って制御してみました。
Ansibleは標準で多くのネットワーク機器をサポート
Ansible 2.0から多くのNetwork Moduleに対応しています。
Network Modules — Ansible Documentation
CiscoはもちろんJuniperやArista、F5などなど一般的なベンダーは一通りサポートしています。
数台の機器であれば、がんばって1台ずつ設定するのもアリですが、数十台、数百台の設定となるとこれはもう機械的にやった方が楽ですし間違いも起きないので、コードを書くことが苦手なインフラエンジニアも覚えておいて損はないと思います。
実行環境
- mac OSX
10.11.x - Ansible
2.1.0.0
Ansibleのインストールはbrew installを使います。
まず、brew infoコマンドでパッケージのバージョン情報を確認します。
% brew info ansible
ansible: stable 2.1.0.0 (bottled), HEAD
Ansibleのバージョンは1.xではなく、2.xを使いたいので、ここでもし1.xが表示された場合はHomebrewを更新します。
% brew update
再度brew infoコマンドでバージョンが更新されたことを確認して、Ansibleをインストールします。
% brew install ansible
インストールが完了したらバージョンを確認します。
% ansible --version
ansible 2.1.0.0
Config収集用サンプルコード
hosts
[cisco]
10.0.0.1 name=cisco1
[cisco:vars]
enable_secret=cisco
user=itbook
password=cisco
[arista]
192.168.56.100 name=arista1
[arista:vars]
enable_secret=arista
user=itbook
password=arista
hostsには対象ノードのホストをグループごとに記載します。実行結果を保存するファイル名には機器のホスト名にしたいので、「name」変数を定義してホスト名を記載しています。また、併せてログインするための情報(ホスト名、パスワード)も変数varsとして記載します。
show_cmd.yml
---
- hosts: cisco
gather_facts: no
tasks:
- name: cisco show command run
local_action:
module: ios_command
commands:
- show run
- show int des
- show ip ro
- show logg
- show version
host: "{{ inventory_hostname }}"
username: "{{ user }}"
password: "{{ password }}"
authorize: true
auth_pass: "{{ enable_secret }}"
register: result
#- debug: msg="{{ result.stdout }}"
- name: log write out
local_action: template src=./cmd.j2 dest=./{{ name }}.log
- hosts: arista
gather_facts: no
tasks:
- name: arista show command run
local_action:
module: eos_command
commands:
- show run
- show int des
- show ip ro
- show logg
- show version
host: "{{ inventory_hostname }}"
username: "{{ user }}"
password: "{{ password }}"
authorize: true
auth_pass: "{{ enable_secret }}"
register: result
- name: log write out
local_action: template src=./cmd.j2 dest=./{{ name }}.log
moduleでそれぞれのベンダーのモジュールを呼び出します。今回はciscoとAristaのshowコマンドを使用するため、ios_command/eos_commandを使いましたが、設定変更を行いたい場合は、xxx_configモジュールを使用します。他のベンダーの場合も同様にmodule変数でモジュールを呼び出します。
実際に実行したいコマンドは、commands内に列挙していきます。
ログの保存はtemplete機能を使って、外部ファイル(cmd.j2)経由で吐き出すようにしています。
cmd.j2
{% for id in range(0,4) %}
{{ result.stdout[id] }}
{% endfor %}
実行結果は「result.stdout」に配列として保存されています。今回は5つのコマンドを実行しましたので配列の要素数0~4までを吐き出すようにしています。ただし、この方法は美しくないのでもっとシンプルに吐き出す方法をご存じの方はぜひ教えてください。
上記のコードはGithubにも上げていますので、興味があれば使ってみてください。
実行結果
% ansible-playbook -i hosts show_cmd.yml
PLAY [cisco] *******************************************************************
TASK [cisco show command run module] **************************************
ok: [10.0.0.1 -> localhost]
TASK [log write out] ***********************************************************
changed: [10.0.0.1 -> localhost]
PLAY [arista] ******************************************************************
TASK [arista show command run module] **************************************
ok: [192.168.56.100 -> localhost]
TASK [log write out] ***********************************************************
changed: [192.168.56.100 -> localhost]
PLAY RECAP *********************************************************************
10.0.0.1 : ok=2 changed=1 unreachable=0 failed=0
192.168.56.100 : ok=2 changed=1 unreachable=0 failed=0
まとめ
前回はAnsibleのrowを使ってネットワーク機器を制御する記事を書きましたが、今回はnetwork moduleを使ってネットワーク機器を制御してみました。
showコマンド程度であれば、rowでもnetwork moduleでも変わらないですが、Ansibleを使って設定変更を行いたい場合は、network moduleを使った方が格段に効率が良くなります。次回はios_configモジュールを使った設定変更を試してみたいと思います。