The automation of network infrastructure has transitioned from a luxury to a fundamental requirement for modern enterprise environments. Within the Cisco ecosystem, the Cisco IOS (Internetwork Operating System) remains the most widely deployed network operating system globally, powering everything from small branch office routers to massive campus switches. The integration of Ansible into this environment allows network engineers to transition from manual, error-prone Command Line Interface (CLI) entries to a rigorous, repeatable, and fully auditable Infrastructure as Code (IaC) model. Central to this transformation is the cisco.ios.ios_config module, a powerful tool designed specifically to manage the configuration state of Cisco devices. By leveraging this module, organizations can push configuration changes, enforce compliance, and ensure consistency across their entire fleet in a fraction of the time required for manual implementation.
Architectural Overview of the cisco.ios Collection
The cisco.ios collection provides a suite of purpose-built modules tailored for the nuances of Cisco IOS. To begin utilizing these capabilities, the collection must be installed via the Ansible Galaxy CLI using the following command:
ansible-galaxy collection install cisco.ios
The operational foundation of this collection relies on a properly configured inventory. An inventory file, such as inventory/ios-devices.ini, must define the device groups and the specific connection variables required for Ansible to communicate with the hardware.
Inventory Configuration and Connection Variables
A robust inventory structure ensures that playbooks are applied to the correct sets of devices, such as core routers versus access switches. The following table outlines the critical variables required for successful Cisco IOS connectivity.
| Variable | Description | Required Value/Example |
|---|---|---|
ansible_network_os |
Defines the target operating system | cisco.ios.ios |
ansible_connection |
Specifies the connection plugin | ansible.netcommon.network_cli |
ansible_user |
The SSH username for authentication | admin |
ansible_password |
The encrypted password for the user | {{ vault_ios_password }} |
ansible_become |
Enables privilege escalation | yes |
ansible_become_method |
Specifies the method to enter privileged mode | enable |
ansible_become_password |
The password for the enable secret | {{ vault_enable_password }} |
The use of ansible_become is essential because the majority of configuration commands in Cisco IOS require privileged EXEC mode. By setting the ansible_become_method to enable, Ansible automatically handles the transition into the privileged state, ensuring that the subsequent configuration commands are executed with the necessary authority.
Deep Dive into the ios_config Module
The cisco.ios.ios_config module serves as the primary engine for configuration management. Its primary responsibility is to send a set of configuration commands to the device. A critical functional aspect of this module is that it automatically handles the entry into global configuration mode (configure terminal) and the subsequent exit from that mode (end), removing the need for the user to manually include these commands in their playbooks.
The Lines and Commands Parameters
In the evolution of Ansible, specifically starting with version 2.1, the ios_config module introduced flexibility in how commands are passed. The commands parameter is an alias for the lines parameter. This means that any functionality attributed to lines can be achieved using commands.
The lines parameter is defined as an ordered set of commands that should be configured in a specific section of the device configuration. When Ansible processes these lines, it ensures they are sent to the device in the exact order specified, which is critical for commands where sequence matters, such as Access Control List (ACL) entries or complex policy maps.
Configuration Contexts and the Parents Parameter
One of the most sophisticated features of the ios_config module is the parents parameter. In Cisco IOS, many commands are context-specific; for example, a description or an IP address cannot be applied in global configuration mode but must be applied within an interface configuration mode.
The parents parameter allows the user to specify the configuration context. When a value is provided to parents, Ansible enters that specific context before sending the lines.
For example, to configure an interface, the playbook would look like this:
yaml
- name: Configure interface settings
cisco.ios.ios_config:
lines:
- description test interface
- ip address 172.31.1.1 255.255.255.0
parents: interface Ethernet1
This mechanism can be scaled using Ansible loops (with_items) to apply the same set of commands across multiple interfaces.
yaml
- name: Configure ip helpers on multiple interfaces
cisco.ios.ios_config:
lines:
- ip helper-address 172.26.1.10
- ip helper-address 172.26.3.8
parents: "{{ item }}"
with_items:
- interface Ethernet1
- interface Ethernet2
- interface GigabitEthernet1
The parents parameter also supports a list of strings to handle deeply nested configurations, such as policy maps and class maps. This is essential for implementing Quality of Service (QoS) settings.
yaml
- name: Configure policer in Scavenger class
cisco.ios.ios_config:
lines:
- conform-action transmit
- exceed-action drop
parents:
- policy-map Foo
- class Scavenger
- police cir 64000
Advanced Configuration Logic and State Management
The ios_config module provides several advanced parameters to ensure that configurations are applied accurately and that the device state remains consistent.
Handling ACLs and the Before Parameter
When managing Access Control Lists (ACLs), simply adding lines may not be sufficient if the existing ACL needs to be completely replaced. The before parameter allows the user to execute a command prior to the main configuration lines. This is frequently used to delete an existing ACL before applying a new one to ensure a clean state.
yaml
- name: Load new acl into device
cisco.ios.ios_config:
lines:
- 10 permit ip host 192.0.2.1 any log
- 20 permit ip host 192.0.2.2 any log
- 30 permit ip host 192.0.2.3 any log
- 40 permit ip host 192.0.2.4 any log
- 50 permit ip host 192.0.2.5 any log
parents: ip access-list extended test
before: no ip access-list extended test
match: exact
The match: exact parameter ensures that Ansible compares the desired state with the actual state precisely. If a discrepancy is found, Ansible will perform the necessary actions to align the device configuration with the specified lines.
Configuration Validation and Comparison
To prevent accidental outages, Ansible provides mechanisms to validate changes before they are committed.
- Diff Mode: Using the
--checkand--diffflags during playbook execution allows operators to see exactly which lines would be added or removed from the configuration. This provides a critical layer of safety and auditability. - Comparison Against Master: The
diff_againstparameter can be used to compare the current running configuration against an intended configuration file.
yaml
- name: Check the running-config against master config
cisco.ios.ios_config:
diff_against: intended
intended_config: "{{ lookup('file', 'master.cfg') }}"
Complementary Modules and Resource-Based Management
While ios_config is the "workhorse" for general settings, it is a generic tool. For specific network entities, Cisco provides "resource modules" that offer a declarative approach to management.
The ios_facts Module
Before applying configurations, it is often necessary to gather the current state of the device. The cisco.ios.ios_facts module collects structured data, which can then be used for conditional logic in playbooks.
yaml
- name: Gather Cisco IOS facts
cisco.ios.ios_facts:
gather_subset:
- all
register: facts
The gathered facts include:
- ansible_net_hostname: The device hostname.
- ansible_net_model: The hardware model.
- ansible_net_version: The IOS version.
- ansible_net_serialnum: The hardware serial number.
- ansible_net_image: The image file used to boot the device.
Specialized Resource Modules
Resource modules like ios_interfaces, ios_vlans, and ios_acls should be used whenever possible instead of ios_config because they provide a structured way to manage specific features.
For example, managing VLANs is more efficient using the ios_vlans module:
yaml
- name: Create VLANs
cisco.ios.ios_vlans:
config:
- vlan_id: 10
name: SERVERS
- vlan_id: 20
name: WORKSTATIONS
state: merged
Similarly, interface management can be handled via ios_interfaces to define speed, duplex, and enabled status without writing raw CLI commands.
Operational Best Practices and Troubleshooting
To maximize the reliability of Cisco IOS automation, engineers should adhere to specific operational patterns.
Handling Confirmation Prompts
Certain IOS commands, such as crypto key generate rsa, trigger interactive confirmation prompts. Since ios_config is designed for non-interactive configuration, these prompts can cause the module to hang or fail. In such cases, the ios_command module should be used, as it includes a prompt parameter specifically designed to handle these interactions.
Persistence and the Startup Config
Changes made via ios_config are applied to the running configuration. In Cisco IOS, the running configuration is stored in volatile memory (RAM). If the device reboots, these changes are lost unless they are saved to the startup configuration (NVRAM).
A best practice is to use a handler that executes a save command only when changes have actually been made. This prevents unnecessary writes to the NVRAM, which can prolong the lifespan of the hardware flash memory.
Comparison of Configuration Methods
| Method | Module | Approach | Best Use Case |
|---|---|---|---|
| Generic Config | ios_config |
Imperative/Lines | Unique settings, banners, global config |
| Resource Config | ios_vlans / ios_interfaces |
Declarative/Structured | VLANs, IP addresses, Interface states |
| Fact Gathering | ios_facts |
Read-only | Audit, Inventory, Conditional logic |
| Direct Command | ios_command |
Interaction | show commands, prompt-based config |
Conclusion
The cisco.ios.ios_config module, when combined with the broader cisco.ios collection, transforms the management of Cisco network devices from a manual task into a scalable software process. By utilizing the lines and parents parameters, engineers can precisely control the configuration context of their devices, while tools like diff_against and match: exact ensure that the actual state of the network perfectly mirrors the intended state. While resource modules should be prioritized for standard entities like VLANs and interfaces, ios_config remains an indispensable tool for all other configuration requirements. The ability to test changes with --check and --diff and to automate the enable process through ansible_become allows for a level of speed, safety, and auditability that is impossible to achieve through manual CLI management.