どうやらAnsible 2.7.0.0からMikrotikのRouterOS機器が対応したらしいので試してみました。
はじめに
Ansible 2.7でRouterOSが対応になりました。RBUG JP Portal Site
大雑把な手順については書いてありますが、自分はNTP設定とRIP設定をAnsibleのplaybookで設定する手順を考えてみました。
確認環境:
- Python 3.5以上
- Ansible 2.7.0.0以上
- RouterOS機器
とりあえずやってみた
SNTP Client設定
SNTP client設定(mikrotik_ntp_google.yml
):
外部のNTPサービス(ここではGoogleとNICT)を指定し、設定されたかをprintで出力し確認する。
忘れてはいけないのは、“connection: network_cli
“と“ansible_network_os: routeros
“ですかね。
これが無いと、RouterOS機器に接続できないと思いますし、また設定も出来ないと思います。
- hosts: all
gather_facts: no
connection: network_cli
vars:
ansible_network_os: routeros
tasks:
- name: set sntp client
routeros_command:
commands:
- /system ntp client set enabled=yes server-dns-names=time.google.com,ntp.nict.jp
- name: check sntp client
routeros_command:
commands:
- /system ntp client print
register: result
- name: print sntp client
debug:
msg: "{{ result.stdout_lines }}"
実行結果
$ ansible-playbook -i 192.168.88.3, mikrotik_ntp_google.yml -u admin -k
SSH password:
PLAY [all] *********************************************************************************************************
TASK [set sntp client] *********************************************************************************************
ok: [192.168.88.3]
TASK [check sntp client] *******************************************************************************************
ok: [192.168.88.3]
TASK [print sntp client] *******************************************************************************************
ok: [192.168.88.3] => {
"msg": [
[
"enabled: yes",
" primary-ntp: 0.0.0.0",
" secondary-ntp: 0.0.0.0",
" server-dns-names: time.google.com,ntp.nict.jp",
" mode: unicast"
]
]
}
PLAY RECAP *********************************************************************************************************
192.168.88.3 : ok=3 changed=0 unreachable=0 failed=0
これだと機器単体にしか設定できなかったので、複数の機器にRIPを設定してみます。
対象機器を設定するため、インベントリファイルを設定します。
[rb]
192.168.88.[3:19] ansible_user=admin ansible_connection=network_cli
[rb:vars]
ansible_network_os=routeros
ここでは、192.168.88.3~192.168.88.19までの範囲にRouterOS機器があり、それに対して接続するためのパラメータとして、“ansible_user”、“ansible_connection”、“ansible_network_os”をインベントリファイルに記述することで、別途playbookに書かなくても共通の設定事項として記述しておくことが可能になります。
RIP設定
次にplaybook(mikrotik_rip.yml
)です。長くなり申し訳ありません。
- hosts: all
gather_facts: no
tasks:
- name: set rip settings
routeros_command:
commands:
- /routing rip set distribute-default=if-installed
- name: set rip interface
routeros_command:
commands:
- /routing rip interface remove [find name=bridge1]
- /routing rip interface add interface=bridge1 send=v2 receive=v2 passive=yes
- name: set rip network
routeros_command:
commands:
- /routing rip network remove [find]
- /routing rip network add network=192.168.88.0/24
- name: set rip neighbor
routeros_command:
commands:
- /routing rip neighbor remove [find]
- /routing rip neighbor add address=192.168.88.1
- /routing rip neighbor add address=192.168.88.4
- /routing rip neighbor add address=192.168.88.5
- /routing rip neighbor add address=192.168.88.6
- /routing rip neighbor add address=192.168.88.8
- /routing rip neighbor add address=192.168.88.9
- /routing rip neighbor add address=192.168.88.10
- /routing rip neighbor add address=192.168.88.12
- /routing rip neighbor add address=192.168.88.15
- /routing rip neighbor add address=192.168.88.16
- /routing rip neighbor add address=192.168.88.17
- /routing rip neighbor add address=192.168.88.18
- /routing rip neighbor add address=192.168.88.19
- name: show routing rip
routeros_command:
commands:
- /routing rip route print
register: result
- name: print rip route
debug:
msg: "{{ result.stdout_lines }}"
Interfaceの設定、どのネットワークに対するRIP設定か、また、neighborの指定も行います。neighborについては複数回記述していますが、通常であればwith_item
などを使いたいところですが、network_cliでは非対応のためかエラーになることを確認しています。
実行結果
出力結果は以下の通りです。(実行エラーな結果が混じっていて申し訳ない)
$ ansible-playbook -l rb mikrotik_rip.yml -k
SSH password:
[WARNING]: Found both group and host with same name: localhost
PLAY [all] *********************************************************************************************************
TASK [set rip settings] ********************************************************************************************
fatal: [192.168.88.7]: FAILED! => {"msg": "[Errno None] Unable to connect to port 22 on 192.168.88.7"}
fatal: [192.168.88.11]: FAILED! => {"msg": "[Errno None] Unable to connect to port 22 on 192.168.88.11"}
fatal: [192.168.88.13]: FAILED! => {"msg": "[Errno None] Unable to connect to port 22 on 192.168.88.13"}
ok: [192.168.88.4]
ok: [192.168.88.6]
ok: [192.168.88.3]
ok: [192.168.88.12]
ok: [192.168.88.9]
ok: [192.168.88.10]
ok: [192.168.88.8]
ok: [192.168.88.5]
ok: [192.168.88.14]
fatal: [192.168.88.16]: FAILED! => {"msg": "[Errno None] Unable to connect to port 22 on 192.168.88.16"}
ok: [192.168.88.15]
ok: [192.168.88.17]
ok: [192.168.88.18]
ok: [192.168.88.19]
TASK [set rip interface] *******************************************************************************************
ok: [192.168.88.5]
ok: [192.168.88.4]
ok: [192.168.88.3]
ok: [192.168.88.6]
ok: [192.168.88.12]
ok: [192.168.88.10]
ok: [192.168.88.8]
ok: [192.168.88.9]
ok: [192.168.88.15]
ok: [192.168.88.14]
ok: [192.168.88.17]
ok: [192.168.88.18]
ok: [192.168.88.19]
TASK [set rip network] *********************************************************************************************
ok: [192.168.88.4]
ok: [192.168.88.5]
ok: [192.168.88.6]
ok: [192.168.88.3]
ok: [192.168.88.12]
ok: [192.168.88.8]
ok: [192.168.88.10]
ok: [192.168.88.15]
ok: [192.168.88.9]
ok: [192.168.88.14]
ok: [192.168.88.19]
ok: [192.168.88.17]
ok: [192.168.88.18]
TASK [set rip neighbor] ********************************************************************************************
ok: [192.168.88.3]
ok: [192.168.88.4]
ok: [192.168.88.6]
ok: [192.168.88.14]
ok: [192.168.88.5]
ok: [192.168.88.10]
ok: [192.168.88.15]
ok: [192.168.88.9]
ok: [192.168.88.12]
ok: [192.168.88.8]
ok: [192.168.88.17]
ok: [192.168.88.18]
ok: [192.168.88.19]
TASK [show routing rip] ********************************************************************************************
ok: [192.168.88.3]
ok: [192.168.88.4]
ok: [192.168.88.14]
ok: [192.168.88.6]
ok: [192.168.88.9]
ok: [192.168.88.10]
ok: [192.168.88.15]
ok: [192.168.88.8]
ok: [192.168.88.12]
ok: [192.168.88.5]
ok: [192.168.88.17]
ok: [192.168.88.18]
ok: [192.168.88.19]
TASK [print rip route] *********************************************************************************************
ok: [192.168.88.5] => {
"msg": [
[
"Flags: C - connect, S - static, R - rip, O - ospf, B - bgp ",
" # DST-ADDRESS GATEWAY FROM METRIC",
" 0 R 0.0.0.0/0 192.168.88.1 192.168.88.14 2",
" 1 R xxx.0.0.1/32 192.168.88.1 2",
" 2 R xxx.xxx.xxx.xxx/32 192.168.88.1 2",
" 3 R xxx.xxx.xxx.xxx/32 192.168.88.1 2",
" 4 R 192.168.88.0/24 1"
]
]
}
ok: [192.168.88.3] => {
"msg": [
[
"Flags: C - connect, S - static, R - rip, O - ospf, B - bgp ",
" # DST-ADDRESS GATEWAY FROM METRIC",
" 0 S 0.0.0.0/0 192.168.88.1 1",
" 1 R 10.0.0.0/8 192.168.88.1 2",
" 2 R 10.0.0.1/32 192.168.88.1 2",
" 3 R xxx.0.0.0/8 192.168.88.1 2",
" 4 R xxx.xxx.xxx.xxx/32 192.168.88.1 2",
" 5 R xxx.xxx.xxx.xxx/16 192.168.88.1 2",
" 6 R xxx.xxx.xxx.xxx/32 192.168.88.1 2",
" 7 R 192.168.88.0/24 1"
]
]
}
<snip>
}
PLAY RECAP *********************************************************************************************************
192.168.88.10 : ok=6 changed=0 unreachable=0 failed=0
192.168.88.11 : ok=0 changed=0 unreachable=0 failed=1
192.168.88.12 : ok=6 changed=0 unreachable=0 failed=0
192.168.88.13 : ok=0 changed=0 unreachable=0 failed=1
192.168.88.14 : ok=6 changed=0 unreachable=0 failed=0
192.168.88.15 : ok=6 changed=0 unreachable=0 failed=0
192.168.88.16 : ok=0 changed=0 unreachable=0 failed=1
192.168.88.17 : ok=6 changed=0 unreachable=0 failed=0
192.168.88.18 : ok=6 changed=0 unreachable=0 failed=0
192.168.88.19 : ok=6 changed=0 unreachable=0 failed=0
192.168.88.3 : ok=6 changed=0 unreachable=0 failed=0
192.168.88.4 : ok=6 changed=0 unreachable=0 failed=0
192.168.88.5 : ok=6 changed=0 unreachable=0 failed=0
192.168.88.6 : ok=6 changed=0 unreachable=0 failed=0
192.168.88.7 : ok=0 changed=0 unreachable=0 failed=1
192.168.88.8 : ok=6 changed=0 unreachable=0 failed=0
192.168.88.9 : ok=6 changed=0 unreachable=0 failed=0
このようにRIP設定まで出来ていることを確認できると思います。最初の“TASK [set rip settings]”でFATALが出力されているのは、そのIPアドレスにはRouterOS機器が存在しないためです。きっちり設定するべきですが、面倒くさかったので範囲指定しまったためです。
RouterOS機器が20台弱もあれば、このrip設定を手で設定していくのは工数がかかります。RouterOSには設定ファイルをexport/import出来るからといっても、やはり労力はかかりますし、結局は一台一台の結果を確認する必要があることから、Ansibleから設定および結果の確認を出来るのはかなり楽になると思います。
また、playbookを別途管理することによって、設定の変更管理も出来るようになるため、あのときどのように設定変更したかな、などが確認しやすくなると思います。
公式ドキュメント
公式ドキュメントは以下になります。
routeros_command – Run commands on remote devices running MikroTik RouterOS — Ansible Documentation
中の人の自作自演じゃないよ。