複数のサーバやクラウドの構成管理に使われる 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
設定の最後に、無事コンフィグが保存されているのが分かります。
次回は、もう少し具体的なユースケースを検討してみたいと思います。