6. cisco config backup with ansible playbook

Preview

So far, in the course of Ansible for Cisco Network Engineers, we’ve seen Ansible being used in monitoring and troubleshooting with both raw modules and Cisco-specific modules. But Ansible’s power lies mostly in the ansible playbook. therefore from now on we will mainly be using Ansible playbooks. For our first example, we want to use an ansible playbook to get backups of Cisco devices (cisco config backup with ansible playbook).

cisco config backup with ansible playbook

It is a good idea to back up all your network devices with different vendors like Cisco and Juniper and different appliances like switch, router and firewall with Ansible at the same time. It seems that all of your infrastructure is now classified in a code so called “Infrastructure as Code” or IaC and you can restore the whole infrastructure with just one click with running Ansible Playbook.

access ansible codes of this course in github

this is a video-based training therefore the output of running commands are not show in the text.

In this section, I will back up Cisco devices using two methods. In the first method, I use the “show running-config” command with the ios_command module and also some other Linux modules like “file” module to create a directory and the Linux command module to run the “copy” command to copy the result of “show running-config” in the created directory. This method is not recommended as a whole, but it will work for different vendors and devices that do not have specific parameters or modules for getting backups.

In the second method, I’ll be using the ios_config module and certain embedded backup parameters to make the backup as easy as possible. This method works just for the vendors and devices that give you such option. I know that juniper devices also have this option since I have already implemented it in real networks.

cisco ios_command module in Ansible website

cisco ios_config module in Ansible website

Now let’s see how we create a playbook in Ansible. Rather than theoretically explaining how playbooks are made, let’s take a look at our first real playbook and explain various components of that playbook before we run and see the result.

root@debian:~/ansible-project1# cat backup.yaml
---
- name: backup configuration
  hosts: csr
  gather_facts: false
  connection: network_cli

  vars:
    backup_root: ./backups

    cli:
      host: "{{ inventory_hostname }}"
      username: rayka
      password: rayka-co.com
      authorize: true

  tasks:
    - name: run show running-config on remote devices
      ios_command:
        commands: "show running-config"
        provider: "{{ cli }}"
      register: config

    - name: ensure backup folder is created
      file:
        path: "{{ backup_root }}"
        state: directory
      run_once: yes

    - name: ensure device rolder is created
      file:
        path: "{{ backup_root }}/{{ inventory_hostname }}"
        state: directory

    - name: get timestamp
      command: date +%Y%m%d
      register: timestamp

    - name: get/copy backup
      copy:
        content: "{{ config.stdout[0] }}"
        dest: "{{ backup_root }}/{{ inventory_hostname }}/running-config_{{ timestamp.stdout }}"

Playbooks are in Yaml format, so they start with three dashes, which are the character of Yaml files.

Then it has a list of plays. The components of the list are indicated with a dash. Our playbooks list contains just one component and therefore one play. Each play runs on a different set of managed nodes. In other words, if you get backup of Cisco and Juniper devices in a different way and with different tasks, so you will need two plays, one for Cisco devices and one for Juniper devices.

Do not forget that indentation is very important in yaml files. In general, indentation is defined as a zero or more space characters at the start of a line. That means every bock must have the same space length from beginning of the line. The suggested syntax for YAML files is to use 2 spaces for indentation, but YAML will follow whatever indentation system that the individual file uses.

Every play has three main sections: headers, variables, and tasks.

The most important parameter in the header is hosts where we specify the list of managed devices through which this playback should be performed. We don’t need the “gather_facts” parameter here. So I have set the value to false. I just wrote here to explain you how we can use this parameter and what is the application of  this parameter. As you saw in the last video, you use gather_facts to collect metadata information from the managed nodes. You set the value of gather_facts to true when your tasks are based on information gathered. For example, suppose you want to run a task differently when the managed node operating system is ios or junos. So you can write takes that behave differently based on the gathered_fact information. we will see in the future how conditions are written in playbook.

With connection we indicate the connection type, which for network engineers is usually local or network_cli. If you are using network_cli as the connection type, don’t forget to set the ansible_network_os parameter in the configuration file or in the inventory file as we did in the previous video.

In the variables section of playbook, we define variables that are to be used in the tasks. We have a special video to show how we can create variables in ansible in different ways. Here I have defined two variables. The backup_root variable,  which is the name of the folder that we create in one task and where our backups are stored. The second variable is the cli variable, which contains the information needed to connect to devices like username and password. I have already defined these variables in the hosts inventory file, but the variables defined in the ansible playbook have a higher priority as we will see in the future.

The third section is for the tasks. Each task uses a specific module. First Task Use the ios_command module to run show running-config on devices. The output of this task is saved in config variable via the register ansible command. The second and third task use linux file module to create a backup root directory and also a subfolder for each managed node. The fourth task uses the Linux command module to get the time of running ansible playbook, and the final task copies the saved config output to the appropriate subfolder.

Now we can test our playbook with ansible-paybook command.

# ansible-playbook ./backup.yml

As you can see in the output of running the Ansible playbook, it is sometimes green and sometimes yellow. Green means no changes and yellow means changes. This is due to an capability in Ansible called idempotency.

If a module is idempotent in Ansible, it means that after one iteration of running a playbook to get things into a desired state, further iterations of the same playbook should change nothing.

Now we do the same task with another playbook with only one task and with the help of the cisco specific module called ios_config in ansible. In the module we have a certain parameter to get backups of devices easily. Just we say to get backup and give the credential to connect to the devices. The backup files are written automatically inside backup folder.  If the directory does not exist, it is created.

# ansible-playbook ./backup1.yml
root@debian:~/ansible-project1# cat backup1.yaml
---
- hosts: csr
  gather_facts: false
  connection: network_cli
  vars:
    cli:
      host: "{{ inventory_hostname }}"
      username: rayka
      password: rayka-co.com

  tasks:
    - name: backup config
      ios_config:
        backup: yes
        provider: "{{ cli }}"

In the next video we will take a closer look at used modules.

Back to: Ansible for Network Engineers > ansible playbook

Leave a comment

Your email address will not be published. Required fields are marked *