Cisco Japan Blog

Ansible の IOS 関連モジュールを試してみる

1 min read



複数のサーバやクラウドの構成管理に使われる Ansible が 2.1 にアップデートされ、このバージョンから Network Automation がコア モジュールとして正式サポートされています。その一環として、Cisco IOS、Cisco IOS-XR、Cisco NXOS に関するモジュールも Ansible でサポートされるようになりました。この投稿では Cisco IOS に関するモジュールを試してみて、次回以降で具体的なユースケースをご紹介したいと思っています。

現状、IOSに関するモジュールは以下の3つです。

  • ios_command – Run arbitrary commands on ios devices.
  • ios_config – Manage Cisco IOS configuration sections
  • ios_template – Manage Cisco IOS device configurations over SSH

今回は、このうち ios_command モジュールと ios_config モジュールを使ってみたいと思います。どちらのモジュールも使用感はほぼ同じですが、ios_command が Exec モードのコマンドを実行するのに対して、ios_config は Configuration モードのコマンドを実行するという違いがあります。

なお、本稿の作業は以下の環境で行いました。まだまだ発展途上な機能なので、バージョンによって、細かな挙動の違いがあるかもしれません。

OS Ubuntu: 14.04.5
Ansible: 2.1.1.0

準備

最初の準備として、操作するデバイス側で SSH ログインできるようにしておきます。

次にインベントリ ファイルに対象デバイスの情報を追加します。ここでは、1台 CSR1000V を使用することとし、このホスト名を解決できるようにしておきます。

/etc/ansible/hosts(一部のみ)


[csr]
csr1000v

ios_configモジュール

まずは、ios_config モジュールを使ってみます。ほぼオフィシャルのサンプルそのままですが、簡単なプレイブックを用意します。

~/playbooks/ios-config-1.yml


---
- hosts: csr
gather_facts: false
connection: local

tasks:
- name: configure top level configuration
ios_config:
commands: hostname {{ inventory_hostname }}
provider: "{{ cli }}"

- name: configure interface settings
ios_config:
commands:
- ip address 192.0.2.1 255.255.255.0
- no shutdown
parents: interface GigabitEthernet3
provider: "{{ cli }}"

vars:
cli:
host: "{{ inventory_hostname }}"
authorize: true
username: cisco

特徴的なところだけ取り上げます。

  • 通常のSSHと違うため、connection は local にする必要があるようです。実行するコマンドは commands に書きます。
  • インターフェイスの設定のように、IOS CLI のモードを遷移する箇所は、commands ではなく parent で書きます。冪統性という観点から、running config にはないコマンドのみが実行されます。そのため、commands に書いてしまうと、Interface モードに遷移することなく、Interface モードで実行されるべきコマンドが実行されてしまうため、エラーになります。

では、実行してみます。


$ ansible-playbook playbooks/ios-config-1.yml
PLAY [csr] 
*********************************************************************
TASK [configure top level configuration] 
*************************************** 
changed: [csr1000v] TASK [configure interface settings] 
******************************************** 
changed: [csr1000v] PLAY RECAP 
********************************************************************* 
csr1000v : ok=2 changed=2 unreachable=0 failed=0

ふたつのタスクが changed ステータスで無事終了しました。
デバイスで確認してみても、きちんと設定がされていることが分かります。

Ansible の特長を知るために、もう一度、実行してみましょう。

$ ansible-playbook playbooks/ios-config-1.yml
PLAY [csr]
*********************************************************************
TASK [configure top level configuration] 
***************************************
ok: [csr1000v]
TASK [configure interface settings] 
********************************************
changed: [csr1000v]
PLAY RECAP 
*********************************************************************
csr1000v : ok=2 changed=1 unreachable=0 failed=0

前回とは違って、ひとつ目のタスクがokステータス、ふたつ目のタスクが changed ステータスになりました。前述のとおり、冪等性という観点から、running config と比較して、running config にないコマンドだけ再実行がなされます。ひとつ目のタスクでは、ホスト名の設定がすでになされていると判断されて、再実行されませんでした。ふたつ目のタスクで、インターフェイスの設定が再実行されているのは、no shutdown が running config には表示されていないためです。

このように、running config にない設定のみ再実行される特徴を考慮すると、コマンドは省略形式ではなく、running config に表示されるままに記述するべきです。

○ interface GigabitEthernt3
× int gi3
○ ip address 192.0.2.1 255.255.255.0
× ip add 192.0.2.1 255.255.255.0

次に、より実践的な使い方として、コンフィグ中のパラメータを外出ししてみます。
ふたつ目のタスクのみ以下のようにしました。具体的には、赤字の部分をパラメータ可しました。

~/playbooks/ios-config-2.yml (一部のみ)


- name: configure interface settings
ios_config:
commands:
- ip address {{ wan.address }} {{ wan.mask }}
- no shutdown
parents: interface {{ wan.interface }}
provider: "{{ cli }}"

各パラメータは以下のように設定しました。
デフォルトでは、プレイブックのあるディレクトリの配下のhost_varsディレクトリにある<hostname>.ymlに定義します。

~/playbooks/host_vars/csr1000v.yml


wan: interface: GigabitEthernet3 address: 192.0.2.1 mask: 255.255.255.0

実行結果は前回と同じなので、割愛します。

最後に、設定後にコンフィグを保存するようにします。各タスクにsave configというnotifyハンドラを登録します。save config notify ハンドラでは、ios_command モジュールを使って write コマンドを実行しています。

~/playbooks/ios-config-3.yml (一部のみ)


tasks: - name: configure top level configuration 
ios_config: commands: hostname {{ inventory_hostname }} 
provider: "{{ cli }}" 
notify: save config 
- name: configure interface settings 
ios_config: commands: 
- ip address {{ wan.address }} {{ wan.mask }} 
- no shutdown parents: interface {{ wan.interface }} 
provider: "{{ cli }}" 
notify: save config handlers: 
- name: save config ios_command: 
commands: wr provider: "{{ cli }}"

実行結果は、以下のようになります。

$ ansible-playbook playbooks/ios-config-3.yml
PLAY [csr] 
*********************************************************************
TASK [configure top level configuration] 
***************************************
ok: [csr1000v]
TASK [configure interface settings] 
********************************************
changed: [csr1000v]

RUNNING HANDLER [save config] 
******************************************************** 
ok: [csr1000v] PLAY RECAP 
********************************************************************* 
csr1000v : ok=3 changed=1 unreachable=0 failed=0

設定の最後に、無事コンフィグが保存されているのが分かります。

次回は、もう少し具体的なユースケースを検討してみたいと思います。

Authors

佐藤 哲大

コンサルティング システムズ エンジニア

SDN 応用技術室

コメントを書く