Cooking Juniper Network with Ansible

One fine day, I decided to switch from the usual rsyslog collecting logs from all devices to something else, the selection and other have little relevance to this topic (they chose Graylog2), but as a result, the task appeared to replace the syslog host settings with all Juniper devices.
In principle, running through the handles (or throwing a script on perl) over a hundred devices and clicking on a command is not a problem, but a good pack of tasks on automating the management of both network devices and a couple of hundred servers was already hanging in my head. If there are no problems with Windows in my environment (we use SCCM), then with a Linux environment mass operations are surrounded by either manual operations or bash scripts (you can also manage SCCM, but this option is mildly inconvenient).
And since I have long wanted to start using Ansible, then it was chosen as the start for this task (for Chef and Puppet, however, the tasks are not so large, and the entry threshold is already larger).
Install Ansible
Installing Ansible is simple, since everything is out of the box (for this task we used ubuntu server 04.16.03):
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get install ansible#Каталог для ролей по умолчанию
roles_path = /etc/ansible/roles
#Проверка при подключении, можно и оставить, но предварительно к хостам придется подключится по SSH и подтвердить отпечаток.
host_key_checking = False
#Журнал
log_path = /var/log/ansible.log
Данные настройки сугубо личные для меня, у себя вы можете использовать свои.Module for Juniper
Juniper in the subject and great guys, they developed their module. Information about him can be found on the off site: Ansible for JunOS . Starting with version Ansible 2.1, it is natively included in core modules Ansible .
Install this module and check it in the list:
sudo ansible-galaxy install Juniper.junos
ansible-galaxy listAlso to use the module we need nccclient
sudo apt-get install python-pip
pip install ncclientConnect to devices
Ansible can connect to Juniper devices in several ways, the default protocol is Netconf and port 830. You can also use telnet and serial console connection, but telnet is relatively unsafe, and serial is a little for specific tasks, although the initial configuration of bare metal in the presence of a connection can be automated with its help.
Netconf can also be used in the usual 22 ssh port, and just use cli as a transport.
For authorization on devices, I would like to immediately configure authorization by key. For convenience, we generate the RSA key as root (why not DSA will be understood further). After copying it to the previously created /etc/ansible/.ssh for ease of use.
ssh-keygen -t rsa
cp /root/.ssh/id_rsa.pub /etc/ansible/.ssh/ansible.pub
cp /root/.ssh/id_rsa /etc/ansible/.ssh/ansibleAs a result, on target devices, it would be necessary to manually create a user with a public key:
set system login user ansible class super-user authentication ssh-rsa "" But we will also automate this further.
Hosts
To whom we connect, we describe in the file / etc / ansible / hosts.
It is possible to describe device groups and variables in it, since I use different Juniper devices, so I will immediately create several groups:
[junex2200]
192.168.111.101
[junex3300]
192.168.111.51
[junexcore]
192.168.111.4
[junexdc]
192.168.111.11
[alljuniper:children]
junex2200
junex3300
junexcore
junexdc
[alljuniper:vars]
ansible_jun_username=ansible
ansible_jun_port=22
ansible_jun_timeout=60
ansible_ssh_private_key_file=/etc/ansible/.ssh/ansibleIn this file, I defined 4 groups, added 1 device to each group. Then he made a general group and added variables for authorization, which will be used in the playbook. The user we have will be “ansible” , we will use the port 22, since 830 is not enabled by default, and also increase the timeout to 60, since with commit the time can easily be longer than the standard 10 seconds.
Playbook initial setup
I made the initial setup in a separate playbook . Since I have a user for connection on all devices, I will use the login / password in the playbook to create the user “ansible” with our key. Also, if you wish, you can enable Netconf on port 830, but I did not notice the difference, so I consider this unnecessary.
Let's create the directory / etc / ansible / playbooks / juniper and in it our first playbook init.yml
Let's analyze the contents:
---
- name: juniper initialization playbook #название PB
hosts: alljuniper #на какие hosts будем его применять
#подключаем модуль juniper
roles:
- Juniper.junos
connection: local
gather_facts: no
#далее объявим переменные логин/пароль для ввода, пароль скрытый
vars_prompt:
- name: "DEVICE_USERNAME"
promt: "Device username"
private: no
- name: "DEVICE_PASSWORD"
promt: "Device password"
private: yes
#объявим переменную для определения настроек подключения
vars:
provider_info:
host: "{{ inventory_hostname }}"
username: "{{ DEVICE_USERNAME }}"
password: "{{ DEVICE_PASSWORD }}"
port: "{{ ansible_jun_port }}"
timeout: "{{ ansible_jun_timeout }}"
#дальше блок самих задач
tasks:
#проверка доступности нашего порта
- name: junos check connection
wait_for:
host: "{{ inventory_hostname }}"
port: "{{ ansible_jun_port }}"
timeout: 10
#создание пользователя
- name: junos create ansible user with key-auth
junos_user:
provider: "{{ provider_info }}"
name: "{{ ansible_jun_username }}"
role: super-user
sshkey: "{{lookup('file', '/etc/ansible/.ssh/ansible.pub') }}"
state: present
To create a user, we use the junos_user module . The module can only create a user with the rsa key, and therefore we generated it. In principle, you can use junos_config and write our line directly with the dsa key.
set system login user ansible class super-user authentication ssh-dsa "" Launch playbook
We launch the playbook init.yml created by us:
sudo ansible-playbook init.ymlDEVICE_USERNAME: megaswitchuser
DEVICE_PASSWORD:
PLAY [juniper initialization playbook] ********************************************************************************
TASK [junos check connection] ********************************************************************************
ok: [192.168.111.101]
ok: [192.168.111.51]
ok: [192.168.111.4]
ok: [192.168.111.11]
TASK [junos create ansible user with key-auth] ********************************************************************************
changed: [192.168.111.101]
changed: [192.168.111.51]
changed: [192.168.111.4]
changed: [192.168.111.11]
PLAY RECAP ********************************************************************************
192.168.111.101 : ok=2 changed=1 unreachable=0 failed=0
192.168.111.51 : ok=2 changed=1 unreachable=0 failed=0
192.168.111.4 : ok=2 changed=1 unreachable=0 failed=0
192.168.111.11 : ok=2 changed=1 unreachable=0 failed=0
changed = 1
means a successful change, you can go to any device and yes the user will already be created there.
When you restart the playbook, the changes will not be made again, and he will write
changed = 0
Syslog setup
We have a junos_logging module . In principle, in most cases you can use it, but I need to enter advanced parameters for the host, and they are not supported in this module. Therefore, we will use the universal tool, the junos_config module to add a new host, and the junos_logging module to delete the old one.
We create a playbook syslog.yml, in it we will already use key authorization for our user ansible.
---
- name: juniper set syslog to graylog2 #название PB
hosts: alljuniper #на какие hosts будем его применять
#подключаем модуль juniper
roles:
- Juniper.junos
connection: local
gather_facts: no
#объявим переменную для определения настроек подключения, уже используем параметр пользователя определенный в hosts, keyfile подтянется оттуда же сам
vars:
provider_info:
host: "{{ inventory_hostname }}"
username: "{{ ansible_jun_username }}"
port: "{{ ansible_jun_port }}"
timeout: "{{ ansible_jun_timeout }}"
#дальше блок самих задач
tasks:
#проверка доступности нашего порта
- name: junos check connection
wait_for:
host: "{{ inventory_hostname }}"
port: "{{ ansible_jun_port }}"
timeout: "{{ ansible_jun_timeout }}"
#настройка конфигурации
- name: set juniper syslog host
junos_config:
provider: "{{ provider_info }}"
#дальше идет блок строк конфигурации
lines:
- set system syslog host 192.168.111.210 any any
- set system syslog host 192.168.111.210 port 2514
- set system syslog host 192.168.111.210 structured-data brief
#добавляем комментарий к коммиту
comment: update config add syslog graylog2
#удаляем старый сислог с помощью модуля junos_logging
- name: delete old syslog host
junos_logging:
provider: "{{ provider_info }}"
dest: host
name: 192.168.111.208
facility: any
level: any
state: absent
We launch:
sudo ansible-playbook syslog.yml
PLAY [juniper set syslog to graylog2] ********************************************************************************
TASK [junos check connection] ********************************************************************************
ok: [192.168.111.101]
ok: [192.168.111.51]
ok: [192.168.111.4]
ok: [192.168.111.11]
TASK [set juniper syslog host] ********************************************************************************
changed: [192.168.111.101]
changed: [192.168.111.51]
changed: [192.168.111.4]
changed: [192.168.111.11]
TASK [delete old syslog host] ********************************************************************************
changed: [192.168.111.101]
changed: [192.168.111.51]
changed: [192.168.111.4]
changed: [192.168.111.11]
PLAY RECAP ********************************************************************************
192.168.111.4 : ok=3 changed=1 unreachable=0 failed=0
192.168.111.11 : ok=3 changed=1 unreachable=0 failed=0
192.168.111.51 : ok=3 changed=1 unreachable=0 failed=0
192.168.111.101 : ok=3 changed=1 unreachable=0 failed=0
Having visited any of the Junipers, it is obvious that our new syslog server was registered in the settings, and the old one was deleted.
Optionally, you can see the commit history with a comment from the playbook:
show system commit0 2018-03-07 15:12:49 KRAT by ansible via netconf
update config add syslog graylog2
Recalling the playbook will also not change the configuration, but will report that everything is OK and there are no changes.
Summary
We set up the environment to automate the settings in our network, now you can easily manage our network. The tasks that can be solved using the Juniper module for Ansible are not limited only to a configuration change, we can also update the software version, reboot devices, make backup configurations and much more.
Plans
The following plans I have identified for myself on this topic with Ansible in the near future.
- Bring the settings of other Juniper parameters into a single view.
- Bring the software version on all Juniper devices to one view.
- Add a Linux server to Ansible with key authorization.
- Prescribe rsyslog settings on a Linux server to a new collector.
- Update / Install fresh Zabbix agents on Linux servers.
The tool is really excellent and I really regret only that I did not start using it earlier. Whether you have one Linux machine or 100 different switches, it is never too late or too early to start automating your actions.
Tested Equipment List
Juniper: EX3300, EX2200, EX4550
JunOS: 12.2R6.4, 12.3R3.4, 12.3R4.6, 12.3R6.6, 12.3R6.6, 12.2R9.4, 12.2R12.4
PS: already in the process of writing the article I came across an article on the same topic on Habré, so I tried to more fully disclose the topic.