Infrastructure as Code: A Practical Tutorial

Infrastructure as Code (IaC) transforms how we manage network infrastructure by applying software development principles to configuration management. In this tutorial, I’ll walk through implementing IaC for a typical enterprise network environment.

Prerequisites

  • Basic understanding of Git
  • Familiarity with a configuration management tool (we’ll use Ansible)
  • Access to network devices or a virtual lab environment

Setting Up Your Environment

Start by creating a version-controlled repository:

mkdir network-iac
cd network-iac
git init

Create the basic structure:

mkdir -p inventories/{production,staging}/group_vars
mkdir -p inventories/{production,staging}/host_vars
touch inventories/{production,staging}/hosts
mkdir -p roles/common/{tasks,templates,defaults,vars}
touch ansible.cfg

Defining Network Configuration as Code

Create a sample inventory file at inventories/staging/hosts:

[access_switches]
sw-access-01 ansible_host=192.168.1.101
sw-access-02 ansible_host=192.168.1.102

[distribution_switches]
sw-dist-01 ansible_host=192.168.1.201
sw-dist-02 ansible_host=192.168.1.202

[all:vars]
ansible_network_os=ios
ansible_connection=network_cli
ansible_user=admin

Define common configurations in roles/common/tasks/main.yml:

---
- name: Configure common settings
  ios_config:
    lines:
      - service timestamps debug datetime msec
      - service timestamps log datetime msec
      - logging buffered 16384

- name: Configure NTP
  ios_config:
    lines:
      - ntp server {{ item }}
  loop: "{{ ntp_servers }}"

- name: Configure SNMP
  ios_config:
    lines:
      - snmp-server community {{ snmp_ro_community }} RO
      - snmp-server location "{{ snmp_location }}"
      - snmp-server contact {{ snmp_contact }}

Create default variables in roles/common/defaults/main.yml:

---
ntp_servers:
  - 10.0.0.1
  - 10.0.0.2

snmp_ro_community: public
snmp_location: "Data Center"
snmp_contact: "[email protected]"

Creating a Playbook

Create a playbook at configure_network.yml:

---
- name: Configure network devices
  hosts: all
  gather_facts: no
  roles:
    - common

- name: Configure access switches
  hosts: access_switches
  gather_facts: no
  tasks:
    - name: Configure VLANs
      ios_config:
        lines:
          - name {{ item.name }}
        parents: vlan {{ item.id }}
      loop: "{{ vlans }}"
      vars:
        vlans:
          - { id: 10, name: DATA }
          - { id: 20, name: VOICE }
          - { id: 30, name: GUEST }

Version Control Integration

Commit your changes:

git add .
git commit -m "Initial network configuration as code"

Testing Your Code

Before applying changes, test your playbook:

ansible-playbook configure_network.yml --check --diff -i inventories/staging/hosts

Next Steps

This is just the beginning of an IaC journey. Future enhancements include:

  1. Implementing CI/CD pipelines
  2. Integrating automated testing (using tools like Batfish or pyATS)
  3. Creating modular templates for different device types
  4. Developing backup and restoration procedures

By treating your network configuration as code, you gain the benefits of version control, peer review, and automated testing while making your infrastructure more maintainable and consistent.