"Human Error vs. Deterministic Deployments: Transitioning from Manual CLI configs to Network IaC deployments"

"Human Error vs. Deterministic Deployments: Transitioning from Manual CLI configs to Network IaC deployments"


From Manual CLI to Infrastructure as Code: Automating My Network Lab with Ansible

Imagine a network where adding a new VLAN, changing an interface description, or deploying a complex routing protocol across hundreds of routers takes seconds, is perfectly consistent, and is done from a single text file. This isn't a dream; it’s Infrastructure as Code (IaC), and Ansible is the engine that makes it possible.

I have been working with Ansible playbooks for a couple of day, and it transformed the way I think about network management. I went from copying and pasting commands into individual terminal windows to deploying entire configurations with a single command.

Here’s a deep dive into the Ansible components—Inventory, Host Variables, and Playbooks—that make this scalability and efficiency a reality.



The Lab Topology:


There are 3 Routers R1, R2 and R3 which are the Managed Nodes, they are in the same LAN (192.168.21.0/24) as the Control Node which is our Linux (Ubuntu) Server.


Article content
Topology




The Foundation: Your Inventory and Source of Truth

The first step in any automation journey is knowing who you are talking to. In Ansible, this is your Inventory, and it is the single source of truth for your network.

In my lab setup, I used the INI format to create a clear, hierarchical structure.


Article content
Inventory File

  1. Functional Groups: I created a [routers] group for my Cisco IOS devices (R1, R2, R3). This allows me to target all routers in a single playbook run.
  2. Parent Groups: I used [ios:children] to make routers a child of a larger [ios] group. This is crucial for managing common credentials for different vendors (e.g., Cisco vs. Juniper) or different sites.
  3. Group Variables ([ios:vars]): This is where inheritance shines. Instead of defining the username, password, and connection type for every single IP, I defined them once for the entire [ios] group. This ensures that any device added to a child group automatically knows how to be managed.

Why this is better: A manual spreadsheet of IPs is static and prone to error. This dynamic inventory is actionable data. You can't run an automation script on a spreadsheet, but you can on this file.


Separation of Concerns: Mastering host_vars

This is what gives Ansible the edge. It’s tempting to put all your variables—VLAN IDs, IP addresses, descriptions—directly into your playbook. But what happens when you need to change R1’s IP? You have to edit the code.

The "Host Variables" folder (host_vars/) is the professional best practice for decoupling data from logic.

Look at host_vars/R1.yml. This file only contains the data that makes R1 unique:

Article content
R1.yml in host_vars folder


  • Its specific ansible_host IP for management.
  • The unique Loopback IP (Loop_ip) and description (Loop_des).

Why this is better: My playbook (the "logic") now only knows how to configure a Loopback interface. It has no idea what the specific IP is. When I run the playbook for R1, Ansible automatically pulls the unique data from R1's host_vars file. This is reusable code at its finest.





The Blueprint: myfirstplaybook.yml

This is the "instruction manual" for the network. myfirstplaybook.yml (Image below) acts as a declarative blueprint for the desired state of my routers.

Article content
myfirstplaybook.yml

Why this is the Future: Scalability and IaC


By moving to Ansible, I adopted an IaC model. This approach is fundamentally better for several reasons:

  • Scalability: To add a new router to my lab, I don't need to write a new Python script. I just add its IP to my inventory file and create a single YAML file in host_vars. I can now push the same OSPF config to 100 routers as easily as I did for 3.
  • Idempotency: This is a key IaC concept. If I run the OSPF task twice, Ansible won't try to add network 192.168.0.0... again. It checks the current state, sees it's already configured, and reports "OK" without making any unnecessary changes. A raw Netmiko script would just keep running the commands, potentially causing problems.
  • Declarative, Not Imperative: Netmiko would: "Step 1: Type ssh admin@10.0.1.1. Step 2: Type conf t." Ansible : "I want the running configuration to have router ospf 1 enabled". Ansible handles all the connection details (network_cli, ansible_become) for me.

While API-based protocols like RESTCONF and NETCONF are excellent for programmatic access, Ansible provides a higher-level, vendor-agnostic framework that is easier for traditional network engineers to adopt. It leverages the tools we are already comfortable with (YAML, JSON) to provide a powerful and repeatable Infrastructure as Code solution.

My lab is now a collection of text files that define its entire identity. And that, to me, is the true meaning of Network Automation.


Output and Verification


Linux Server Terminal running the Ansible playbook:

Article content
Linux Server Terminal
Article content
R1
Article content
R2
Article content
R3

Routers R1, R2 and R3 Interface and OSPF configuration above.



To view or add a comment, sign in

More articles by Priyanshu Pathak

Others also viewed

Explore content categories