Recommended

Ansible Network Automation: Managing Cisco IOS at Scale with NetDevOps

Kunal Nagaria

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.

Network Automation with Ansible: Managing Cisco IOS at Scale

If you’ve ever spent a Friday evening manually pushing configuration changes to 50 Cisco routers, you already understand why network automation exists. One typo, one missed device, one inconsistent ACL entry — and suddenly you’re troubleshooting an outage instead of going home. Ansible has become one of the most widely adopted tools in the NetDevOps movement, and for good reason: it’s agentless, human-readable, and purpose-built for exactly this kind of work.

This post walks through how to use Ansible for managing Cisco IOS devices at scale — from setting up your environment to writing reusable playbooks that actually hold up in production.


Why Ansible Makes Sense for Network Teams

Ansible automating Cisco IOS network configurations across multiple routers in a NetDevOps pipeline.

Before diving into configurations and YAML, it’s worth understanding what makes Ansible a natural fit for network automation compared to alternatives like Python scripts or commercial orchestration platforms.

Agentless Architecture

Unlike Puppet or Chef, Ansible doesn’t require any agent software running on your devices. For Cisco IOS devices, this matters enormously — you’re not installing anything on the router. Ansible connects over SSH (or NETCONF) and issues commands directly, just like a human operator would, but faster and without mistakes.

Human-Readable Playbooks

Ansible playbooks are written in YAML, which means a network engineer who has never written code before can read a playbook and understand what it does. That lowers the barrier for adoption across your team, not just among the engineers who love Python.

Idempotency

When you run the same Ansible playbook twice, it won’t make duplicate changes. If the desired state already exists on the device, Ansible skips that task. This principle of idempotency is foundational to safe automation — you can run your playbooks as many times as needed without fear of compounding errors.


Setting Up Your Ansible Environment

Installation and Dependencies

Getting started with Ansible for Cisco IOS requires a few components beyond a standard Ansible installation.

pip install ansible
pip install ansible-pylibssh   # Recommended SSH library for networking
ansible-galaxy collection install cisco.ios

The cisco.ios collection provides all the modules you need for interacting with IOS and IOS-XE devices. Always install collections from Ansible Galaxy rather than relying on the built-in ios_* modules, which are increasingly deprecated in favor of the collection-based equivalents.

Inventory File

Your inventory file tells Ansible which devices to manage and how to connect to them. For a network environment, a well-organized inventory is critical.

# inventory/hosts.ini

[core_routers]
router01 ansible_host=10.0.1.1
router02 ansible_host=10.0.1.2
router03 ansible_host=10.0.1.3

[access_switches]
switch01 ansible_host=10.0.2.1
switch02 ansible_host=10.0.2.2

[cisco_ios:children]
core_routers
access_switches

[cisco_ios:vars]
ansible_network_os=cisco.ios.ios
ansible_connection=network_cli
ansible_user=netadmin
ansible_password={{ vault_password }}
ansible_become=yes
ansible_become_method=enable
ansible_become_password={{ vault_enable_password }}

Notice the use of {{ vault_password }} — credentials should always be stored in Ansible Vault, never in plain text. You can encrypt your credentials with:

ansible-vault encrypt_string 'YourSecretPassword' --name 'vault_password'

Core Ansible Modules for Cisco IOS

The cisco.ios collection includes a rich set of modules. Here are the ones you’ll reach for most often.

Module Purpose
cisco.ios.ios_command Run arbitrary show commands
cisco.ios.ios_config Push configuration changes
cisco.ios.ios_facts Gather device facts automatically
cisco.ios.ios_vlans Manage VLANs declaratively
cisco.ios.ios_interfaces Configure interface settings
cisco.ios.ios_bgp_global Manage BGP configuration

The distinction between ios_command and ios_config is important. Use ios_command for read-only operations like gathering show output. Use ios_config for making changes to the running configuration. Mixing them up leads to unexpected behavior.


Writing Your First Production Playbook

Gathering Device Facts

Start simple. Before you automate changes, get comfortable pulling data from your devices.

---
- name: Gather Cisco IOS Facts
  hosts: cisco_ios
  gather_facts: false

  tasks:
    - name: Collect device facts
      cisco.ios.ios_facts:
        gather_subset:
          - hardware
          - interfaces
          - config

    - name: Display hostname and IOS version
      debug:
        msg: "{{ inventory_hostname }} is running IOS version {{ ansible_net_version }}"

Running this playbook gives you an immediate, real-time inventory of every device’s software version, serial number, and interface status — data that would take hours to collect manually.

Applying Configuration at Scale

Here’s a more practical example: standardizing NTP and DNS configuration across your entire fleet.

---
- name: Standardize NTP and DNS on all Cisco IOS devices
  hosts: cisco_ios
  gather_facts: false

  vars:
    ntp_servers:
      - 10.0.0.10
      - 10.0.0.11
    dns_servers:
      - 8.8.8.8
      - 8.8.4.4
    dns_domain: corp.example.com

  tasks:
    - name: Configure NTP servers
      cisco.ios.ios_config:
        lines:
          - "ntp server {{ item }}"
      loop: "{{ ntp_servers }}"

    - name: Configure DNS settings
      cisco.ios.ios_config:
        lines:
          - "ip domain-name {{ dns_domain }}"
          - "ip name-server {{ dns_servers | join(' ') }}"

    - name: Save running config to startup config
      cisco.ios.ios_config:
        save_when: modified

The save_when: modified option is a safety net — it only writes copy run start when the playbook actually made a change, preventing unnecessary writes to NVRAM.


Using Roles for Scalable Playbook Organization

As your automation library grows, flat playbooks become unmanageable. Ansible roles let you package tasks, variables, templates, and handlers into reusable units.

Creating a Role Structure

roles/
  cisco_baseline/
    tasks/
      main.yml
    templates/
      banner.j2
      interface.j2
    vars/
      main.yml
    handlers/
      main.yml
    defaults/
      main.yml

Jinja2 Templates for IOS Configuration

One of the most powerful combinations in NetDevOps is Ansible’s Jinja2 templating engine paired with IOS configuration. You can generate device-specific configurations from a single template.

A banner template (roles/cisco_baseline/templates/banner.j2) might look like this:

banner motd ^
=========================================
  Device: {{ inventory_hostname }}
  Location: {{ device_location }}
  Managed by: Network Automation Team
  Unauthorized access is prohibited.
=========================================
^

And the task that deploys it:

- name: Apply login banner
  cisco.ios.ios_config:
    lines:
      - "{{ lookup('template', 'banner.j2') }}"

This scales elegantly — 200 devices all get the correct, consistent banner with the right hostname and location information populated automatically.


Handling Errors and Building Safety Nets

Automation at scale introduces risk. A poorly written playbook that loops over 200 devices can cause an outage in seconds. Build these safety mechanisms into your workflows.

Use Check Mode First

Always test playbooks in check mode before running against production:

ansible-playbook site.yml --check --diff -i inventory/

The --diff flag shows exactly what configuration changes would be made on each device, line by line.

Limit Blast Radius with serial

Control how many devices Ansible touches at once using the serial keyword:

- name: Roll out BGP changes
  hosts: core_routers
  serial: 1   # Process one device at a time
  gather_facts: false

For critical changes, serial: 1 is your best friend. You can also use percentages: serial: "10%" processes 10% of your inventory at a time, giving you time to catch problems before they propagate.

Validate Before Saving

Add a verification task after configuration changes to confirm the expected state before saving:

- name: Verify BGP neighbor is established
  cisco.ios.ios_command:
    commands:
      - show bgp summary
  register: bgp_output

- name: Fail if BGP neighbor is not established
  fail:
    msg: "BGP neighbor check failed. Aborting save."
  when: "'Established' not in bgp_output.stdout[0]"

- name: Save configuration
  cisco.ios.ios_config:
    save_when: modified

Integrating with CI/CD Pipelines

The final step toward true NetDevOps maturity is treating your network configurations like application code. Store your playbooks and role files in Git, use pull requests for change review, and run automated testing pipelines before anything touches production.

A basic GitLab CI pipeline for network automation might:

  1. Lint playbooks with ansible-lint on every commit
  2. Syntax check with ansible-playbook --syntax-check
  3. Run in check mode against a staging inventory
  4. Require approval before running against production
  5. Log all outputs to a centralized ITSM or audit system

This workflow transforms network change management from a manual, risky process into a peer-reviewed, auditable, and repeatable pipeline.


Conclusion

Ansible has fundamentally changed what’s possible for teams managing Cisco IOS environments at scale. What once required a team of engineers working weekend maintenance windows can now be handled by a tested, version-controlled playbook running in a CI pipeline. The combination of agentless architecture, readable YAML syntax, and the rich cisco.ios collection makes it the go-to choice for teams beginning their network automation journey.

Start small — automate one repetitive task, like NTP standardization or banner deployment. Build confidence in the tooling, establish safe practices like check mode and serial execution, and gradually expand into more complex workflows. The path from manual CLI work to full NetDevOps doesn’t happen overnight, but with Ansible, each step forward delivers immediate, measurable value.

Tags :

Kunal Nagaria

Recent News

Recommended

Subscribe Us

Get the latest creative news from BlazeTheme

    Switch on. Learn more

    Gadget

    World News

    @2023 Packet-Switched- All Rights Reserved