SMS Blog

Setup of Ansible on Eve-NG

By George Djaboury, Senior Network Engineer, SMS 

Introduction

The purpose of this post is to perform a basic setup of Ansible on Eve-NG. If you are a network engineer who has never been exposed to Ansible before, then this is perfect for you. By the end of this tutorial, you will be able to successfully push configurations to network devices via Ansible, and you’ll have the building blocks to begin constructing your own playbooks. Let’s get started!

Prerequisites

  • Eve-NG installed
  • Ubuntu Server VM installed and has IP connectivity to the internet and routers in the lab environment.
  • Router images must support SSH – Cisco images must have “k9” on the OS name

Images Used

  • “Linux-ubuntu-18.04-server” – downloaded from the Eve-NG website. They have several Linux images (mostly out of date). Updating images after installation is always recommended. I updated the image to the latest version – Ubuntu Server 22.04 LTS. Eve-NG also supports custom images.
  • Routers1 and 2 (CSRv): csr1000vng-universalk9.16.03
  • Router3: c7200-adventerprisek9-mz.152-4.M7.bin
  • Switch: i86bi-linux-l2-adventerprise-15.1b.bin – any layer 2 image will be sufficient

Topology

The Eve-NG topology is simple, but you don’t need much get started pushing configurations with Ansible.

ansible1 1

Cloud

Inserting a “Network” type object is required for internet access. The Linux server just needs to be able to pull updates and download Ansible. I used the “Management(Cloud0)” type in this lab.

Add an object -> Network

ansible2 1

Verify Connectivity

Ensure the Linux server can ping all Routers before proceeding

root@ubuntu22-server:~# ping 192.168.1.46
PING 192.168.1.46 (192.168.1.46) 56(84) bytes of data.
64 bytes from 192.168.1.46: icmp_seq=1 ttl=255 time=2.04 ms
64 bytes from 192.168.1.46: icmp_seq=2 ttl=255 time=1.58 ms

root@ubuntu22-server:~# ping 192.168.1.47
PING 192.168.1.47 (192.168.1.47) 56(84) bytes of data.
64 bytes from 192.168.1.47: icmp_seq=1 ttl=255 time=1.97 ms
64 bytes from 192.168.1.47: icmp_seq=2 ttl=255 time=1.66 ms

root@ubuntu22-server:~# ping 192.168.1.48
PING 192.168.1.48 (192.168.1.48) 56(84) bytes of data.
64 bytes from 192.168.1.47: icmp_seq=1 ttl=255 time=1.94 ms
64 bytes from 192.168.1.48: icmp_seq=2 ttl=255 time=1.67 ms

Enable SSH on Routers

A basic configuration is needed to enable SSH. Ansible utilizes SSH by default to connect to all hosts.

Router(config)#username cisco privilege 15 secret cisco
Router(config)#vRouter(config)#hostname R1
R1(config)#ip domain name test.com
R1(config)#line vty 0 15
R1(config-line)#login local
R1(config-line)#transport input ssh
R1(config-line)#exit
R1(config)#crypto key gen rsa
The name for the keys will be: R1.test.com
Choose the size of the key modulus in the range of 360 to 4096 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] (elapsed time was 5 seconds)

R1(config)#ip ssh version 2

Verify crypto keys are generated:

R1#show crypto key mypubkey rsa

Verify SSH from Ubuntu Server to Routers

Ansible requires the crypto keys of the remote devices before it can connect via SSH. Let’s see if we can SSH.

root@ubuntu22-server:~# ssh cisco@192.168.1.47
Unable to negotiate with 192.168.1.47 port 22: no matching key exchange method found. Their offer: diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1

Looks like SSH failed since the images in my lab use older algorithms that is not compatible with Ubuntu Server 22.04 LTS. To get around this, we have to create the user SSH configuration file and insert compatible ciphers/algorithms.

root@ubuntu22-server:~# vi ~/.ssh/config
KexAlgorithms +diffie-hellman-group14-sha1
Ciphers +aes128-cbc
~

Restart SSH and try again.

root@ubuntu22-server:~# sudo service sshd restart
root@ubuntu22-server:~# ssh cisco@192.168.1.47
Unable to negotiate with 192.168.1.47 port 22: no matching host key type found. Their offer: ssh-rsa

SSH still failed. I’ll need to add the ssh-rsa key type in the config file based on what the router is offering

root@ubuntu22-server:# vi ~/.ssh/config
KexAlgorithms +diffie-hellman-group14-sha1
Ciphers +aes128-cbc
PubkeyAcceptedAlgorithms +ssh-rsa
HostKeyAlgorithms +ssh-rsa

Save the file, restart SSH, and give it another try.

root@ubuntu22-server:~# sudo service sshd restart
root@ubuntu22-server:~#
root@ubuntu22-server:~# ssh cisco@192.168.1.46
The authenticity of host '192.168.1.46 (192.168.1.46)' can't be established.
RSA key fingerprint is SHA256:IaXpnjoCJTZv9RKNTCEzHCajJB+ppaLc3VVgzb8ATqs.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.1.46' (RSA) to the list of known hosts.
(cisco@192.168.1.46) Password:

R1#

It worked! Now SSH to your remaining Routers.
If you need to remove a learned key in Ubuntu for some reason (e.g. SSH key changed), then type:

ssh-keygen -f "/root/.ssh/known_hosts" -R "192.168.1.46"

We are now ready to setup the server with Ansible!

Installation and Setup of Ansible on Ubuntu

The first step is to update the server to the latest version.

sudo apt update
sudo apt upgrade

To install Ansible, it’s best to follow instructions on Ansible Documentation website.

sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible

Verify Ansible installation by checking the version:

root@ubuntu22-server:/etc/ansible# ansible --version
ansible [core 2.12.6]
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/dist-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.10.4 (main, Apr 2 2022, 09:04:19) [GCC 11.2.0]
jinja version = 3.0.3
libyaml = True

Additionally, we need to install LibSSH, needed to connect to network devices, and is replacing paramiko.

sudo apt install python3-pip
pip install --user ansible-pylibssh

Creating the inventory file

The /etc/ansible file directory should have been created; if not, create it. Navigate to the ansible directory and view its contents. The ‘hosts’ file is the default Ansible inventory file.

root@ubuntu22-server:~# cd /etc/ansible/
root@ubuntu22-server:/etc/ansible# ls
ansible.cfg hosts

Now let’s add our routers in the hosts file:

root@ubuntu22-server:/etc/ansible# sudo vi hosts

[iosrouters]
r1 ansible_host=192.168.1.46 
r2 ansible_host=192.168.1.47 
r3 ansible_host=192.168.1.48

[iosrouters:vars]
ansible_network_os=cisco.ios.ios
ansible_connection=ansible.netcommon.network_cli
ansible_user=cisco
ansible_password=cisco

It’s a good idea to use groups by enclosing the group name in brackets[]. The first group comprises of all our lab IOS routers. The second group defines the variables for the iosrouters group. For a lab environment, it’s ok to insert plain-text creds in here.

After saving the inventory file, you can verify variables have applied to each host:

root@ubuntu22-server:/etc/ansible# ansible-inventory --list -y
all:
children:
iosrouters:
hosts:
r1:
ansible_connection: ansible.netcommon.network_cli
ansible_host: 192.168.1.46
ansible_network_os: cisco.ios.ios
ansible_password: cisco
ansible_user: cisco
r2:
ansible_connection: ansible.netcommon.network_cli
ansible_host: 192.168.1.47
ansible_network_os: cisco.ios.ios
ansible_password: cisco
ansible_user: cisco
r3:
ansible_connection: ansible.netcommon.network_cli
ansible_host: 192.168.1.48
ansible_network_os: cisco.ios.ios
ansible_password: cisco
ansible_user: cisco
ungrouped: {}

Creating a Playbook

All playboooks must be written in YAML format with .yml or .yaml file extension.
Create a “playbooks” folder and a new playbook file. This playbook is using the “ios_config,” “ios_static_route,” and “ios_banner” modules. This playbook defines 4 different tasks.

root@ubuntu22-server:/etc/ansible# mkdir playbooks/
root@ubuntu22-server:/etc/ansible# vi playbooks/initial-config.yaml
---
- name: initial configuration
hosts: iosrouters
gather_facts: false
connection: local
tasks:
- name: enable ipv6 globally
ios_config:
lines:
- ipv6 unicast-routing

- name: configure ospf
ios_config:
parents: router ospf 1
lines: network 192.168.1.0 0.0.0.255 area 0

- name: configure static
ios_static_route:
prefix: 0.0.0.0
mask: 0.0.0.0
next_hop: 192.168.1.1

- name: configure banner
ios_banner:
banner: login
text: |
this is my awesome
login banner
state: present

Run Ansible playbook

root@ubuntu22-server:/etc/ansible# ansible-playbook -i hosts playbooks/initial-config.yaml 

PLAY [initial configuration] ************************************************************************************************

TASK [enable ipv6 globally] *************************************************************************************************
[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: [r2]
changed: [r1]
changed: [r3]

TASK [configure ospf] *******************************************************************************************************
changed: [r1]
changed: [r2]
changed: [r3]

TASK [configure static] *****************************************************************************************************
changed: [r1]
changed: [r2]
changed: [r3]

TASK [configure banner] *****************************************************************************************************
changed: [r2]
changed: [r1]
changed: [r3]
PLAY RECAP ******************************************************************************************************************
r1                         : ok=4    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
r2                         : ok=4    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
r3                         : ok=4    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

For each task, it displays the status of the task for each device; the state of the task displays “changed.”
Now run the same playbook, but with the –check option. This option simulates what would happen if the playbook was actually pushed, but without making changes.

root@ubuntu22-server:/etc/ansible# ansible-playbook -i hosts playbooks/initial-config.yaml --check

PLAY [initial configuration] ************************************************************************************************

TASK [enable ipv6 globally] *************************************************************************************************
ok: [r2]
ok: [r1]
ok: [r3]

TASK [configure ospf] *******************************************************************************************************
ok: [r2]
ok: [r1]
ok: [r3]

TASK [configure static] *****************************************************************************************************
ok: [r2]
ok: [r1]
ok: [r3]

TASK [configure banner] *****************************************************************************************************
ok: [r2]
ok: [r1]
ok: [r3]

PLAY RECAP ******************************************************************************************************************
r1                         : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
r2                         : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
r3                         : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

Notice the states of the tasks in the left column, which declares “ok” instead of “changed.” Ansible will not execute a task if the desired state is already achieved.

Conclusion

Setup is now complete! While that completes this initial task, I encourage you to keep learning; search for different Ansible modules and use them in different playbooks. Ansible can be a powerful tool in your automation toolbox!
For network engineers just getting started with Ansible, I highly recommend going through the Network Automation resource on the Ansible website.

ansible5 1

1 Comment

  1. krupesha on 12 March 2024 at 7:30 am

    Litterally a life saver article for who are new to Ansible. Awesome Work and its prety clear. Just follow the steps and it works without any single issue. Thank You. 🙂 🙂

Leave a Comment