シナプスの技術部ネットワーク課の末吉です。
業務の中でネットワーク機器の設定を独自スクリプトで取得して保存しているのですが、Ansibleでも同様のことができる様でしたので、Cisco/Juniper/YAMAHAの設定をAnsibleで取得してみました。
Ansibleとは
レッドハットが開発するオープンソースの構成管理ツールである。サーバを立ち上げる際、あらかじめ用意した設定ファイルに従って、ソフトウェアのインストールや設定を自動的に実行する事が出来る
引用: Ansible (ソフトウェア) - Wikipedia
早速試してみます。
検証環境
サーバ
- RockyLinux8.7
- Python3.9
- paramiko 2.12.0
- Ansible-core 2.13.3
- ansible.netcommon 4.1
- cisco.ios 3.3.0
- junipernetworks.junos 3.1.0
- yamaha_network.rtx 1.0.1
- Python3.9
- RockyLinux8.7
ネットワーク機器
各機器にはsshで接続するため、ssh接続できることが前提となります。各機器は以下の設定とします。
| 機器 | ログインユーザーID/PW | 管理者PW | IPアドレス |
|---|---|---|---|
| Cisco Catalyst2960G | login / loginpassword | adminpassword | 192.168.1.1 |
| Juniper MX204 | login / loginpassword | ログインユーザーで実施するため無し | 192.168.1.2 |
| YAMAHA RTX830 | login / loginpassword | adminpassword | 192.168.1.3 |
Ansibleセットアップ
AnsibleはEPELリポジトリよりインストールします。
# dnf install epel-release
Python3.9をインストールします。
# dnf install python3.9
Ansibleをインストールします。
# dnf install ansible
Pythonでssh接続に利用するparamikoをインストールします。
# pip3.9 install paramiko
AnsibleでYAMAHA機器に接続するモジュールをインストールします。
# ansible-galaxy collection install yamaha_network.rtx
ssh接続が初めての場合に接続できないため、/etc/ansible/ansible.cfg に以下を追記します。
[defaults] host_key_checking = False
Ansibleのバージョン確認
インストールしたパッケージとバージョンを確認します。
# rpm -q ansible ansible-core ansible-6.3.0-1.el8.noarch ansible-core-2.13.3-1.el8.x86_64 # ansible --version ansible [core 2.13.3] config file = /etc/ansible/ansible.cfg configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python3.9/site-packages/ansible ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections executable location = /usr/bin/ansible python version = 3.9.13 (main, Nov 16 2022, 15:31:39) [GCC 8.5.0 20210514 (Red Hat 8.5.0-15)] jinja version = 3.1.2 libyaml = True
Ansible モジュールバージョン確認
今回利用するモジュールのバージョンを確認します。
# ansible-galaxy collection list # /root/.ansible/collections/ansible_collections Collection Version ------------------ ------- ansible.netcommon 4.1.0 ansible.utils 2.8.0 yamaha_network.rtx 1.0.1 # /usr/lib/python3.9/site-packages/ansible_collections Collection Version ----------------------------- ------- <〜省略〜> cisco.aci 2.2.0 cisco.asa 3.1.0 cisco.dnac 6.5.3 cisco.intersight 1.0.19 cisco.ios 3.3.0 cisco.iosxr 3.3.0 cisco.ise 2.5.0 cisco.meraki 2.10.1 cisco.mso 2.0.0 cisco.nso 1.0.3 cisco.nxos 3.1.0 cisco.ucs 1.8.0 <〜省略〜> junipernetworks.junos 3.1.0
Ansibleの構成
- Ansibleは、2つのファイル群にて構成されています。
| 種類 | ファイル内容 |
|---|---|
| インベントリファイル | 対象機器を記載するファイル。記述形式としてINI形式、YAML形式がある。今回はYAML形式で記述 |
| Playbookファイル | どの様な実行をするのかを記載するファイル。記述形式はYAML形式 |
各機器の設定を取得
各機器の設定を取得するために作成したインベントリファイルとplaybookファイルは以下のとおりです。
| 種類 | 用途 | ファイル名 |
|---|---|---|
| インベントリファイル | Cisco用 | /etc/ansible/ios_hosts.yml |
| インベントリファイル | Juniper用 | /etc/ansible/junos_hosts.yml |
| インベントリファイル | YAMAHA用 | /etc/ansible/rtx_hosts.yml |
| Playbookファイル | Cisco用 | /etc/ansible/ios_get-config.yml |
| Playbookファイル | Juniper用 | /etc/ansible/junos_get-config.yml |
| Playbookファイル | YAMAHA用 | /etc/ansible/rtx_get-config.yml |
Asibleでパスワード等の機密情報を扱う場合は、漏洩などの事故防止のために、インベントリファイルに平文でパスワードを記載せず、Ansible Vault などを利用するのが一般的かと思いますが、今回は検証の為インベントリファイルに平文のまま記載します。
Cisco用ファイル
- /etc/ansible/ios_hosts.yml
---
ios:
hosts:
CiscoL2SW:
ansible_host: 192.168.1.1
vars:
ansible_connection: network_cli
ansible_network_os: cisco.ios.ios
ansible_user: login
ansible_password: loginpassword
ansible_become: True
ansible_become_method: ansible.netcommon.enable
ansible_become_password: adminpassword
- /etc/ansible/ios_get-config.yml
---
- name: ios get config
hosts: ios
gather_facts: no
vars:
show_commands:
- show run
tasks:
# showコマンド実行
- name: exec show commands
cisco.ios.ios_command:
commands: "{{ show_commands }}"
register: res_show_commands
# showコマンド結果を表示
- name: debug show commands
ansible.builtin.debug:
msg: "{{ res_show_commands.stdout_lines[ansible_loop.index0] }}"
loop: "{{ show_commands }}"
loop_control:
extended: true
Juniper用
- /etc/ansible/junos_hosts.yml
---
junos:
hosts:
JuniperRouter:
ansible_host: 192.168.1.2
vars:
ansible_connection: network_cli
ansible_network_os: junipernetworks.junos.junos
ansible_user: login
ansible_ssh_pass: loginpassword
- /etc/ansible/junos_get-config.yml
---
- name: Junos get config
hosts: junos
gather_facts: no
vars:
show_commands:
- show configuration
tasks:
# showコマンドを実行
- name: get show configuration
junos_command:
commands: "{{ show_commands }}"
register: reg_show_commands
# showコマンド結果を表示
- name: show configration
ansible.builtin.debug:
msg: "{{ reg_show_commands.stdout_lines[ansible_loop.index0] }}"
loop: "{{ show_commands }}"
loop_control:
extended: true
YAMAHA用
- /etc/ansible/rtx_hosts.yml
---
rtx:
hosts:
rtx830:
ansible_host: 192.168.1.3
vars:
ansible_connection: network_cli
ansible_network_os: yamaha_network.rtx.rtx
ansible_user: login
ansible_ssh_pass: loginpassword
ansible_become: true
ansible_become_password: adminpassword
- /etc/ansible/rtx_get-config.yml
---
- name: rtx get config
hosts: rtx
tasks:
# showコマンドを実行
- name: get configuration
yamaha_network.rtx.rtx_command:
commands:
- show config
register: result
# showコマンドの結果を表示
- name: show config
debug:
msg: "{{ result.stdout_lines[0] }}"
実行
- 実行コマンド
ansible-playbook -i [インベントリーファイル] [playbookファイル]
- 今回の実行コマンド
ios ansible-playbook -i /etc/ansible/ios_hosts.yml /etc/ansible/ios_get-config.yml junos ansible-playbook -i /etc/ansible/junos_hosts.yml /etc/ansible/junos_get-config.yml rtx ansible-playbook -i /etc/ansible/rtx_hosts.yml /etc/ansible/rtx_get-config.yml
- Ciscoスイッチを設定を取った際の実行例
# ansible-playbook -i /etc/ansible/ios_hosts.yml /etc/ansible/ios_get-config.yml
PLAY [ios get config] ************************************************************************************************
TASK [exec show commands] ********************************************************************************************
[WARNING]: ansible-pylibssh not installed, falling back to paramiko
ok: [CiscoL2SW]
TASK [debug show commands] *******************************************************************************************
ok: [CiscoL2SW] => (item=show run) => {
"msg": [
"Load for five secs: 21%/0%; one minute: 7%; five minutes: 6%",
"Time source is NTP, 22:12:03.652 JST Sat Jan 28 2023",
"",
"Building configuration...",
"",
"Current configuration : 4975 bytes",
"!",
<~省略~>
"end"
]
}
PLAY RECAP ***********************************************************************************************************
CiscoL2SW : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
設定が取得できました。YAMAHAの場合以下の警告が出るようでしたが、設定の取得は問題ありませんでした。
# ansible-playbook -i /etc/ansible/rtx_hosts.yml /etc/ansible/rtx_get-config.yml [WARNING]: Collection yamaha_network.rtx does not support Ansible version 2.13.3
各機器の設定を取得し保存する
各機器の設定内容を取得できたので取得した設定をファイルに保存するようにするplaybookを作成します。インベントリファイルは同じものを利用します。
| 種類 | 用途 | ファイル名 |
|---|---|---|
| Playbookファイル | Cisco用 | /etc/ansible/ios_save-config.yml |
| Playbookファイル | Juniper用 | /etc/ansible/junos_save-config.yml |
| Playbookファイル | YAMAHA用 | /etc/ansible/rtx_save-config.yml |
Cisco用
- /etc/ansible/ios_save-config.yml
---
- name: ios config save
hosts: ios
gather_facts: no
vars:
show_commands:
- show run
tasks:
# ログ保存用ディレクトリ作成
- name: create directory
ansible.builtin.file:
path: "/etc/ansible/config/ios/{{ inventory_hostname }}"
state: directory
register: logdir
# showコマンド実行
- name: exec show commands
cisco.ios.ios_command:
commands: "{{ show_commands }}"
register: res_show_commands
# showコマンド結果ファイル保存
- name: save to file
ansible.builtin.copy:
content: "{{ res_show_commands.stdout[ansible_loop.index0] }}"
dest: "{{ logdir.path }}/{{ inventory_hostname }}.config"
loop: "{{ show_commands }}"
loop_control:
extended: true
Juniper用
- /etc/ansible/junos_save-config.yml
---
- name: Junos config save
hosts: junos
gather_facts: no
vars:
show_commands:
- show configuration | display set
tasks:
# ログ保存用ディレクトリ作成
- name: create directory
ansible.builtin.file:
path: "/etc/ansible/config/junos/{{ inventory_hostname }}"
state: directory
register: logdir
- name: Get show configuration
junos_command:
commands: "{{ show_commands }}"
register: reg_show_configuration
# showコマンド結果ファイル保存
- name: save to file
ansible.builtin.copy:
content: "{{ reg_show_configuration.stdout[ansible_loop.index0] }}"
dest: "{{ logdir.path }}/{{ inventory_hostname }}.config"
loop: "{{ show_commands }}"
loop_control:
extended: true
YAMAHA用
- /etc/ansible/rtx_save-config.yml
---
- name: rtx config save
hosts: rtx
vars:
show_commands:
- show config
tasks:
# ログ保存用ディレクトリ作成
- name: create directory
ansible.builtin.file:
path: "/etc/ansible/config/rtx/{{ inventory_hostname }}"
state: directory
register: logdir
- name: get configuration
yamaha_network.rtx.rtx_command:
commands: "{{ show_commands }}"
register: reg_show_configuration
# showコマンド結果ファイル保存
- name: save to file
ansible.builtin.copy:
content: "{{ reg_show_configuration.stdout[ansible_loop.index0] }}"
dest: "{{ logdir.path }}/{{ inventory_hostname }}.config"
loop: "{{ show_commands }}"
loop_control:
extended: true
実行
- 実行コマンド
ansible-playbook -i [インベントリーファイル] [playbookファイル]
- 今回の実行コマンド
ios ansible-playbook -i /etc/ansible/ios_hosts.yml /etc/ansible/ios_save-config.yml junos ansible-playbook -i /etc/ansible/junos_hosts.yml /etc/ansible/junos_save-config.yml rtx ansible-playbook -i /etc/ansible/rtx_hosts.yml /etc/ansible/rtx_save-config.yml
- Ciscoスイッチを設定を取った際の実行例
PLAY [ios config save] ************************************************************************************************************************************** TASK [create directory] ************************************************************************************************************************************* [WARNING]: ansible-pylibssh not installed, falling back to paramiko changed: [CiscoL2SW] TASK [exec show commands] *********************************************************************************************************************************** ok: [CiscoL2SW] TASK [save to file] ***************************************************************************************************************************************** changed: [CiscoL2SW] => (item=show run) PLAY RECAP ************************************************************************************************************************************************** CiscoL2SW : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- ファイルを確認
# cat /etc/ansible/config/ios/CiscoL2SW/CiscoL2SW.config Load for five secs: 27%/0%; one minute: 8%; five minutes: 6% Time source is NTP, 22:14:57.800 JST Sat Jan 28 2023 Building configuration... Current configuration : 4975 bytes <~省略~> end
設定をファイルに保存する事が出来ている事を確認できました。
まとめ
- Ansibleで各機器の設定を取得する方法を確認することが出来た。
- Ansibleを使う上でYAMLの書き方を学ぶことが出来た。
- Ansibleは冪等性が保たれるため、各機器への設定追加に関しても学習していきたい。