📚
ansible で ios機器の設定の練習
ansible
ansible はエージェントレスの構成管理ツールです。
puppet のように、エージェントをインストールする必要がありません。
参考
sshサーバ設定
r1(config)#int f0/0
r1(config-if)#ip address 10.2.0.254 255.255.255.0
r1(config-if)#no shut
r1(config)#ip domain-name localdomain.local
r1(config)#crypto key generate rsa
The name for the keys will be: r1.localdomain.local
Choose the size of the key modulus in the range of 360 to 2048 for your
General Purpose Keys. Choosing a key modulus greater than 512 may take
a few minutes.
How many bits in the modulus [512]: 2048
% Generating 2048 bit RSA keys, keys will be non-exportable...[OK]
r1(config)#ip ssh version 2
r1(config)#username ccna password cisco
(ログを残していなかったのですが、line vty で login localを実行する必要があるはずです。)
ansible を動かす端末から疎通確認します。
$ ping 10.2.0.254 -c 5
PING 10.2.0.254 (10.2.0.254) 56(84) bytes of data.
64 bytes from 10.2.0.254: icmp_seq=1 ttl=255 time=2.39 ms
64 bytes from 10.2.0.254: icmp_seq=2 ttl=255 time=8.41 ms
64 bytes from 10.2.0.254: icmp_seq=3 ttl=255 time=6.33 ms
64 bytes from 10.2.0.254: icmp_seq=4 ttl=255 time=3.81 ms
64 bytes from 10.2.0.254: icmp_seq=5 ttl=255 time=10.2 ms
--- 10.2.0.254 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 10ms
rtt min/avg/max/mdev = 2.385/6.221/10.169/2.861 ms
admin@ip-10-0-0-144:~/zenn$
仮想ラボで利用しているios では古いアルゴリズムにしか対応していません。
ssh 接続テストを実施するにあたり、古いアルゴリズムを許可するように設定します。
$ cat ~/.ssh/config
Host 10.2.0.254
KexAlgorithms diffie-hellman-group1-sha1
Ciphers aes192-cbc
ssh 接続テストをします。
$ ssh ccna@10.2.0.254
Password:
r1>
r1>exit
Connection to 10.2.0.254 closed.
ansible の準備
hosts ファイル
$ cat hosts
[r1]
10.2.0.254
[r1:vars]
ansible_ssh_user=ccna
ansible_connection = network_cli
ansible_network_os = ios
ansible のテスト
疎通確認
$ ansible -v -i hosts -m ping r1 --ask-pass
[DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the controller starting with Ansible 2.12. Current version: 3.7.3 (default, Oct 31 2022, 14:04:00) [GCC 8.3.0]. This feature will be removed from ansible-core in version
2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
No config file found; using defaults
SSH password:
10.2.0.254 | SUCCESS => {
"changed": false,
"ping": "pong"
}
実行テスト
$ ansible -v -i hosts -m ios_command -a "commands='show ip int bri'" r1 --ask-pass
[DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the controller starting with Ansible 2.12. Current version: 3.7.3 (default, Oct 31 2022, 14:04:00) [GCC 8.3.0]. This feature will be removed from ansible-core in version
2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
No config file found; using defaults
SSH password:
10.2.0.254 | SUCCESS => {
"changed": false,
"stdout": [
"Interface IP-Address OK? Method Status Protocol\nFastEthernet0/0 10.2.0.254 YES manual up up \nFastEthernet0/1 unassigned YES unset administratively down down \nSerial1/0 unassigned YES unset administratively down down \nSerial1/1 unassigned YES unset administratively down down \nSerial1/2 unassigned YES unset administratively down down \nSerial1/3 unassigned YES unset administratively down down"
],
"stdout_lines": [
[
"Interface IP-Address OK? Method Status Protocol",
"FastEthernet0/0 10.2.0.254 YES manual up up ",
"FastEthernet0/1 unassigned YES unset administratively down down ",
"Serial1/0 unassigned YES unset administratively down down ",
"Serial1/1 unassigned YES unset administratively down down ",
"Serial1/2 unassigned YES unset administratively down down ",
"Serial1/3 unassigned YES unset administratively down down"
]
]
}
playbook
show ip int briを実行するプレイブックを用意します。
$ cat r1.yaml
---
- hosts: r1
gather_facts: false
connection: local
tasks:
- name: run show version on remote devices
cisco.ios.ios_command:
commands: show ip int bri
事前確認
$ ansible-playbook -v -i hosts r1.yaml --check --ask-pass
[DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the controller starting with Ansible 2.12. Current version: 3.7.3 (default, Oct 31 2022, 14:04:00) [GCC 8.3.0]. This feature will be removed from ansible-core in version
2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
No config file found; using defaults
SSH password:
[WARNING]: An error occurred while calling ansible.utils.display.initialize_locale (unsupported locale setting). This may result in incorrectly calculated text widths that can cause Display to print incorrect line lengths
PLAY [r1] ***********************************************************************************************************************************************************************************************************************************
TASK [run show version on remote devices] ***************************************************************************************************************************************************************************************************
ok: [10.2.0.254] => {"changed": false, "stdout": ["Interface IP-Address OK? Method Status Protocol\nFastEthernet0/0 10.2.0.254 YES manual up up \nFastEthernet0/1 unassigned YES unset administratively down down \nSerial1/0 unassigned YES unset administratively down down \nSerial1/1 unassigned YES unset administratively down down \nSerial1/2 unassigned YES unset administratively down down \nSerial1/3 unassigned YES unset administratively down down"], "stdout_lines": [["Interface IP-Address OK? Method Status Protocol", "FastEthernet0/0 10.2.0.254 YES manual up up ", "FastEthernet0/1 unassigned YES unset administratively down down ", "Serial1/0 unassigned YES unset administratively down down ", "Serial1/1 unassigned YES unset administratively down down ", "Serial1/2 unassigned YES unset administratively down down ", "Serial1/3 unassigned YES unset administratively down down"]]}
PLAY RECAP **********************************************************************************************************************************************************************************************************************************
10.2.0.254 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
適用します。(show コマンドしか実行されないので、事実上、ルータでの設定変更は発生しません)
$ ansible-playbook -v -i hosts r1.yaml --ask-pass
[DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the controller starting with Ansible 2.12. Current version: 3.7.3 (default, Oct 31 2022, 14:04:00) [GCC 8.3.0]. This feature will be removed from ansible-core in version
2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
No config file found; using defaults
SSH password:
[WARNING]: An error occurred while calling ansible.utils.display.initialize_locale (unsupported locale setting). This may result in incorrectly calculated text widths that can cause Display to print incorrect line lengths
PLAY [r1] ***********************************************************************************************************************************************************************************************************************************
TASK [run show version on remote devices] ***************************************************************************************************************************************************************************************************
ok: [10.2.0.254] => {"changed": false, "stdout": ["Interface IP-Address OK? Method Status Protocol\nFastEthernet0/0 10.2.0.254 YES manual up up \nFastEthernet0/1 unassigned YES unset administratively down down \nSerial1/0 unassigned YES unset administratively down down \nSerial1/1 unassigned YES unset administratively down down \nSerial1/2 unassigned YES unset administratively down down \nSerial1/3 unassigned YES unset administratively down down"], "stdout_lines": [["Interface IP-Address OK? Method Status Protocol", "FastEthernet0/0 10.2.0.254 YES manual up up ", "FastEthernet0/1 unassigned YES unset administratively down down ", "Serial1/0 unassigned YES unset administratively down down ", "Serial1/1 unassigned YES unset administratively down down ", "Serial1/2 unassigned YES unset administratively down down ", "Serial1/3 unassigned YES unset administratively down down"]]}
PLAY RECAP **********************************************************************************************************************************************************************************************************************************
10.2.0.254 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
各種モジュールの利用
ios 機器側では enable パスワードの設定が必要です。
ansible 側では ansible_become_method = enable の指定が必要です。
$ cat hosts
[r1]
10.2.0.254
[r1:vars]
ansible_ssh_user=ccna
ansible_connection = network_cli
ansible_network_os = ios
ansible_become_method = enable
$ cat r1.yaml
---
- hosts: r1
vars:
- address: 1.1.1.1/32
gather_facts: false
connection: local
become: true
tasks:
- name: configure motd banner message
cisco.ios.ios_banner:
banner: motd
text: |
This is the 1st line of the motd message.
This is the 2nd line of the motd message.
state: present
- name: configure interface address
cisco.ios.ios_l3_interfaces:
config:
- name: Loopback0
ipv4:
- address: "{{ address }}"
state: merged
- name: configure interface description
cisco.ios.ios_interfaces:
config:
- name: Loopback0
description: Configured and Merged by Ansible Network
state: merged
- name: configure timezone
cisco.ios.ios_config:
commands:
- clock timezone JST +9
事前確認
$ ansible-playbook -v -i hosts r1.yaml --check --diff --ask-pass --ask-become-pass
[DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the controller starting with Ansible 2.12. Current version: 3.7.3 (default, Oct 31 2022, 14:04:00) [GCC 8.3.0]. This feature will be removed from ansible-core in version
2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
No config file found; using defaults
SSH password:
BECOME password[defaults to SSH password]:
[WARNING]: An error occurred while calling ansible.utils.display.initialize_locale (unsupported locale setting). This may result in incorrectly calculated text widths that can cause Display to print incorrect line lengths
PLAY [r1] ***********************************************************************************************************************************************************************************************************************************
TASK [configure motd banner message] ********************************************************************************************************************************************************************************************************
changed: [10.2.0.254] => {"changed": true, "commands": ["banner motd @\nThis is the 1st line of the motd message.\nThis is the 2nd line of the motd message.\n@"]}
TASK [configure interface address] **********************************************************************************************************************************************************************************************************
changed: [10.2.0.254] => {"after": [{"ipv4": [{"address": "10.2.0.254/24"}], "name": "FastEthernet0/0"}, {"name": "FastEthernet0/1"}, {"name": "Serial1/0"}, {"name": "Serial1/1"}, {"name": "Serial1/2"}, {"name": "Serial1/3"}], "before": [{"ipv4": [{"address": "10.2.0.254/24"}], "name": "FastEthernet0/0"}, {"name": "FastEthernet0/1"}, {"name": "Serial1/0"}, {"name": "Serial1/1"}, {"name": "Serial1/2"}, {"name": "Serial1/3"}], "changed": true, "commands": ["interface loopback0", "ip address 1.1.1.1 255.255.255.255"]}
TASK [configure interface description] ******************************************************************************************************************************************************************************************************
changed: [10.2.0.254] => {"after": [{"duplex": "auto", "enabled": true, "name": "FastEthernet0/0", "speed": "auto"}, {"duplex": "auto", "enabled": false, "name": "FastEthernet0/1", "speed": "auto"}, {"enabled": false, "name": "Serial1/0"}, {"enabled": false, "name": "Serial1/1"}, {"enabled": false, "name": "Serial1/2"}, {"enabled": false, "name": "Serial1/3"}], "before": [{"duplex": "auto", "enabled": true, "name": "FastEthernet0/0", "speed": "auto"}, {"duplex": "auto", "enabled": false, "name": "FastEthernet0/1", "speed": "auto"}, {"enabled": false, "name": "Serial1/0"}, {"enabled": false, "name": "Serial1/1"}, {"enabled": false, "name": "Serial1/2"}, {"enabled": false, "name": "Serial1/3"}], "changed": true, "commands": ["interface loopback0", "description Configured and Merged by Ansible Network", "no shutdown"]}
TASK [configure timezone] *******************************************************************************************************************************************************************************************************************
[WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they appear if present in the running configuration on device
changed: [10.2.0.254] => {"banners": {}, "changed": true, "commands": ["clock timezone JST +9"], "updates": ["clock timezone JST +9"]}
PLAY RECAP **********************************************************************************************************************************************************************************************************************************
10.2.0.254 : ok=4 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
適用
$ ansible-playbook -v -i hosts r1.yaml --diff --ask-pass --ask-become-pass
[DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the controller starting with Ansible 2.12. Current version: 3.7.3 (default, Oct 31 2022, 14:04:00) [GCC 8.3.0]. This feature will be removed from ansible-core in version
2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
No config file found; using defaults
SSH password:
BECOME password[defaults to SSH password]:
[WARNING]: An error occurred while calling ansible.utils.display.initialize_locale (unsupported locale setting). This may result in incorrectly calculated text widths that can cause Display to print incorrect line lengths
PLAY [r1] ***********************************************************************************************************************************************************************************************************************************
TASK [configure motd banner message] ********************************************************************************************************************************************************************************************************
changed: [10.2.0.254] => {"changed": true, "commands": ["banner motd @\nThis is the 1st line of the motd message.\nThis is the 2nd line of the motd message.\n@"]}
TASK [configure interface address] **********************************************************************************************************************************************************************************************************
changed: [10.2.0.254] => {"after": [{"ipv4": [{"address": "10.2.0.254/24"}], "name": "FastEthernet0/0"}, {"name": "FastEthernet0/1"}, {"ipv4": [{"address": "1.1.1.1/32"}], "name": "Loopback0"}, {"name": "Serial1/0"}, {"name": "Serial1/1"}, {"name": "Serial1/2"}, {"name": "Serial1/3"}], "before": [{"ipv4": [{"address": "10.2.0.254/24"}], "name": "FastEthernet0/0"}, {"name": "FastEthernet0/1"}, {"name": "Serial1/0"}, {"name": "Serial1/1"}, {"name": "Serial1/2"}, {"name": "Serial1/3"}], "changed": true, "commands": ["interface loopback0", "ip address 1.1.1.1 255.255.255.255"]}
TASK [configure interface description] ******************************************************************************************************************************************************************************************************
changed: [10.2.0.254] => {"after": [{"description": "Configured and Merged by Ansible Network", "enabled": true, "name": "loopback0"}, {"duplex": "auto", "enabled": true, "name": "FastEthernet0/0", "speed": "auto"}, {"duplex": "auto", "enabled": false, "name": "FastEthernet0/1", "speed": "auto"}, {"enabled": false, "name": "Serial1/0"}, {"enabled": false, "name": "Serial1/1"}, {"enabled": false, "name": "Serial1/2"}, {"enabled": false, "name": "Serial1/3"}], "before": [{"enabled": true, "name": "loopback0"}, {"duplex": "auto", "enabled": true, "name": "FastEthernet0/0", "speed": "auto"}, {"duplex": "auto", "enabled": false, "name": "FastEthernet0/1", "speed": "auto"}, {"enabled": false, "name": "Serial1/0"}, {"enabled": false, "name": "Serial1/1"}, {"enabled": false, "name": "Serial1/2"}, {"enabled": false, "name": "Serial1/3"}], "changed": true, "commands": ["interface loopback0", "description Configured and Merged by Ansible Network"]}
TASK [configure timezone] *******************************************************************************************************************************************************************************************************************
[WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they appear if present in the running configuration on device
changed: [10.2.0.254] => {"banners": {}, "changed": true, "commands": ["clock timezone JST +9"], "updates": ["clock timezone JST +9"]}
PLAY RECAP **********************************************************************************************************************************************************************************************************************************
10.2.0.254 : ok=4 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ansible では同じプレイブックを再実行しても同じ状態になる冪等性を持っています。
なにも設定変更しなければ、再実行したときは changed=0 となるはずです。
$ ansible-playbook -v -i hosts r1.yaml --check --diff --ask-pass --ask-become-pass
[DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the controller starting with Ansible 2.12. Current version: 3.7.3 (default, Oct 31 2022, 14:04:00) [GCC 8.3.0]. This feature will be removed from ansible-core in version
2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
No config file found; using defaults
SSH password:
BECOME password[defaults to SSH password]:
[WARNING]: An error occurred while calling ansible.utils.display.initialize_locale (unsupported locale setting). This may result in incorrectly calculated text widths that can cause Display to print incorrect line lengths
PLAY [r1] ***********************************************************************************************************************************************************************************************************************************
TASK [configure motd banner message] ********************************************************************************************************************************************************************************************************
ok: [10.2.0.254] => {"changed": false, "commands": []}
TASK [configure interface address] **********************************************************************************************************************************************************************************************************
ok: [10.2.0.254] => {"before": [{"ipv4": [{"address": "10.2.0.254/24"}], "name": "FastEthernet0/0"}, {"name": "FastEthernet0/1"}, {"ipv4": [{"address": "1.1.1.1/32"}], "name": "Loopback0"}, {"ipv4": [{"address": "10.2.1.254/24"}], "name"
: "Serial1/0"}, {"name": "Serial1/1"}, {"name": "Serial1/2"}, {"name": "Serial1/3"}], "changed": false, "commands": []}
TASK [configure interface description] ******************************************************************************************************************************************************************************************************
ok: [10.2.0.254] => {"before": [{"description": "Configured and Merged by Ansible Network", "enabled": true, "name": "loopback0"}, {"duplex": "auto", "enabled": true, "name": "FastEthernet0/0", "speed": "auto"}, {"duplex": "auto", "enabl
ed": false, "name": "FastEthernet0/1", "speed": "auto"}, {"enabled": false, "name": "Serial1/0"}, {"enabled": false, "name": "Serial1/1"}, {"enabled": false, "name": "Serial1/2"}, {"enabled": false, "name": "Serial1/3"}], "changed": fals
e, "commands": []}
TASK [configure timezone] *******************************************************************************************************************************************************************************************************************
[WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they appear if present in the running configuration on device
changed: [10.2.0.254] => {"banners": {}, "changed": true, "commands": ["clock timezone JST +9"], "updates": ["clock timezone JST +9"]}
PLAY RECAP **********************************************************************************************************************************************************************************************************************************
10.2.0.254 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
が、ここでは changed=1 となりました。
running-config にある通りに、 clock timezone JST 9
でプレイブックを記載することで、差分が生じなくなります。
コンフィグ内容レベルで同じ状態になるようなプレイブックを記載してあげる必要があります。
$ cat r1.yaml
---
- hosts: r1
vars:
- address: 1.1.1.1/32
gather_facts: false
connection: local
become: true
tasks:
- name: configure motd banner message
cisco.ios.ios_banner:
banner: motd
text: |
This is the 1st line of the motd message.
This is the 2nd line of the motd message.
state: present
- name: configure interface address
cisco.ios.ios_l3_interfaces:
config:
- name: Loopback0
ipv4:
- address: "{{ address }}"
state: merged
- name: configure interface description
cisco.ios.ios_interfaces:
config:
- name: Loopback0
description: Configured and Merged by Ansible Network
state: merged
- name: configure timezone
cisco.ios.ios_config:
commands:
- clock timezone JST 9
確認
$ ansible-playbook -v -i hosts r1.yaml --check --diff --ask-pass --ask-become-pass
[DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the controller starting with Ansible 2.12. Current version: 3.7.3 (default, Oct 31 2022, 14:04:00) [GCC 8.3.0]. This feature will be removed from ansible-core in version
2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
No config file found; using defaults
SSH password:
BECOME password[defaults to SSH password]:
[WARNING]: An error occurred while calling ansible.utils.display.initialize_locale (unsupported locale setting). This may result in incorrectly calculated text widths that can cause Display to print incorrect line lengths
PLAY [r1] ***********************************************************************************************************************************************************************************************************************************
TASK [configure motd banner message] ********************************************************************************************************************************************************************************************************
ok: [10.2.0.254] => {"changed": false, "commands": []}
TASK [configure interface address] **********************************************************************************************************************************************************************************************************
ok: [10.2.0.254] => {"before": [{"ipv4": [{"address": "10.2.0.254/24"}], "name": "FastEthernet0/0"}, {"name": "FastEthernet0/1"}, {"ipv4": [{"address": "1.1.1.1/32"}], "name": "Loopback0"}, {"ipv4": [{"address": "10.2.1.254/24"}], "name": "Serial1/0"}, {"name": "Serial1/1"}, {"name": "Serial1/2"}, {"name": "Serial1/3"}], "changed": false, "commands": []}
TASK [configure interface description] ******************************************************************************************************************************************************************************************************
ok: [10.2.0.254] => {"before": [{"description": "Configured and Merged by Ansible Network", "enabled": true, "name": "loopback0"}, {"duplex": "auto", "enabled": true, "name": "FastEthernet0/0", "speed": "auto"}, {"duplex": "auto", "enabled": false, "name": "FastEthernet0/1", "speed": "auto"}, {"enabled": false, "name": "Serial1/0"}, {"enabled": false, "name": "Serial1/1"}, {"enabled": false, "name": "Serial1/2"}, {"enabled": false, "name": "Serial1/3"}], "changed": false, "commands": []}
TASK [configure timezone] *******************************************************************************************************************************************************************************************************************
ok: [10.2.0.254] => {"changed": false}
PLAY RECAP **********************************************************************************************************************************************************************************************************************************
10.2.0.254 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Discussion