# Ansible for Network Automation

> Chapter 104 of the Courseiva CCNA curriculum — https://courseiva.com/learn/ccna/ansible-networking

**Official objective:** 6.5 — CCNA 200-301 v2.0 Objective 5.5

## Introduction

In the modern network, manual CLI configuration simply doesn't scale. Ansible is the leading automation framework that allows you to define your entire network state as code and push it reliably to hundreds of devices. For the CCNA 200-301 exam, objective 6.5 requires you to understand the basic components of Ansible and how it interacts with Cisco IOS devices — a skill that separates junior engineers from automation-ready professionals.

## Orchestra Conductor and Sheet Music

Suppose you find yourself standing before a 100-piece orchestra, ready to conduct. Each musician (network device) knows how to play their instrument (run IOS), but they need sheet music (configuration) to play the correct notes at the right time. In a traditional network, you would walk to each musician and hand-write their sheet music — that's CLI configuration. With Ansible, you write a single master score (the playbook) that contains the part for every instrument. The conductor (Ansible control node) distributes the correct sheet music to each musician automatically. Crucially, the conductor does not need to know how to play every instrument; they only need to read the score and wave the baton. Similarly, Ansible does not run on the network devices; it runs on a control node (typically a Linux server) and uses SSH to send commands to the devices. The playbook is written in YAML, a human-readable data serialization language. Each task in the playbook calls a module — a small program that executes a specific operation, like configuring an interface or verifying an OSPF neighbor. The musicians (devices) play the notes and the conductor (Ansible) listens for the result, reporting any wrong notes (failed tasks). This analogy captures Ansible's push model, agentless architecture, and idempotent nature — playing the same sheet music twice produces the same result, ensuring consistent network state.

## Core explanation

### What is Ansible and Why Does It Exist?

Ansible is an open-source automation tool developed by Red Hat. It is designed to automate IT tasks such as configuration management, application deployment, and task orchestration. For networking, Ansible allows engineers to manage network devices (routers, switches, firewalls) in a consistent, repeatable, and scalable way. Before Ansible, network automation was often done with custom scripts (Python, Expect, TCL) that were brittle and hard to maintain. Ansible provides a standardized framework with reusable modules, idempotent operations (applying the same configuration multiple times yields the same result), and a simple YAML syntax that even non-programmers can learn.

### How Ansible Works Step by Step

Ansible uses a **push model**: the control node (where Ansible is installed) connects to managed nodes (network devices) via SSH and executes tasks. Here is the step-by-step flow:

1. **Inventory**: The control node reads an inventory file that lists all managed devices and their connection parameters. The inventory can be static (INI or YAML file) or dynamic (script that queries an external source like AWS or a CMDB).

2. **Playbook**: The administrator writes a playbook in YAML. A playbook contains one or more plays. Each play targets a group of hosts (from the inventory) and defines tasks to execute. Each task calls a specific module with parameters.

3. **Connection**: Ansible uses the `ansible_connection` variable to determine how to connect. For network devices, this is usually `network_cli` (SSH) or `ansible.netcommon.network_cli`. The control node opens an SSH session to the device and executes commands.

4. **Module Execution**: Ansible transfers the module (a Python script) to the managed node via the SSH connection. However, for network devices that cannot run Python, Ansible uses a different approach: the module runs on the control node and sends CLI commands to the device over SSH. The module then parses the output and returns structured JSON data.

5. **Idempotency**: Before making changes, the module checks the current state of the device. If the desired state already exists, the module does nothing (reports `ok`). If not, it applies the change (reports `changed`). This is idempotent — running the playbook multiple times will not cause unintended changes.

6. **Facts Gathering**: Ansible can gather facts about the device (e.g., OS version, interfaces, neighbors) using modules like `ios_facts`. These facts are stored in variables for use in the playbook.

### Key Components and Defaults

- **Control Node**: Any machine with Python and Ansible installed. Linux is preferred; Windows can be used via WSL. No agents are installed on managed nodes.
- **Managed Nodes**: Network devices that support SSH. No additional software is required.
- **Inventory File**: Default location `/etc/ansible/hosts`. Example:
  ```
  [routers]
  R1 ansible_host=192.168.1.1 ansible_user=admin ansible_ssh_pass=cisco ansible_connection=network_cli ansible_network_os=ios
  R2 ansible_host=192.168.1.2 ansible_user=admin ansible_ssh_pass=cisco ansible_connection=network_cli ansible_network_os=ios
  ```
- **Playbook**: Written in YAML. Example:
  ```yaml
  ---
  - name: Configure OSPF on routers
    hosts: routers
    gather_facts: no
    tasks:
      - name: Enable OSPF
        ios_config:
          lines:
            - router ospf 1
            - network 10.0.0.0 0.255.255.255 area 0
          provider: "{{ cli }}"
  ```
- **Modules**: Cisco-specific modules are in the `cisco.ios` collection. Key modules:
  - `ios_config`: Sends configuration commands.
  - `ios_command`: Sends show commands and returns output.
  - `ios_facts`: Gathers device facts.
- **Vault**: Ansible Vault encrypts sensitive data like passwords. Use `ansible-vault create secrets.yml`.

### Verification Commands

To verify Ansible is working correctly:

1. **Ping module**: Tests SSH connectivity.
   ```
   ansible routers -m ping -i inventory.ini
   ```
   Output:
   ```
   R1 | SUCCESS => {
       "changed": false,
       "ping": "pong"
   }
   R2 | SUCCESS => {
       "changed": false,
       "ping": "pong"
   }
   ```

2. **Gather facts**:
   ```
   ansible routers -m ios_facts -i inventory.ini
   ```
   Output (truncated):
   ```
   R1 | SUCCESS => {
       "ansible_facts": {
           "ansible_net_hostname": "R1",
           "ansible_net_version": "15.7(3)M",
           "ansible_net_interfaces": {
               "GigabitEthernet0/0": {
                   "macaddress": "aabb.cc00.0100",
                   "ipv4": [{"address": "192.168.1.1", "masklen": 24}]
               }
           }
       },
       "changed": false
   }
   ```

3. **Run a playbook**:
   ```
   ansible-playbook ospf.yml -i inventory.ini
   ```

### Interaction with Related Protocols

Ansible relies on SSH (TCP/22) for connectivity. It does not use SNMP or NETCONF by default (though it can use them via specific collections). For Cisco devices, the `network_cli` connection plugin emulates a terminal session, sending commands and waiting for prompts. This is similar to how a human would use SecureCRT or PuTTY. Ansible also supports `ansible_connection=local` for older devices, but `network_cli` is preferred for IOS.

## Real-world context

In a real enterprise network, Ansible is used to automate repetitive tasks that are error-prone when done manually. For example, a global company with 500 branch routers needs to add a new loopback interface for management on every device. Instead of SSHing to each router and typing `interface loopback0`, `ip address 10.0.0.x 255.255.255.255`, a network engineer writes a playbook that loops through an inventory and configures each device. The playbook can also generate unique IPs using a variable from the inventory (e.g., `{{ inventory_hostname }}`). This reduces a week-long task to a few minutes and eliminates typos.

Another scenario: compliance auditing. A financial institution must ensure that every switch has SSH version 2 enabled and no telnet access. An engineer writes a playbook that checks the running config and reports any violations. The playbook can even auto-remediate by applying the correct configuration. This is done daily via a cron job on the Ansible control node. The results are logged to a file for audit trails.

Common pitfalls include misconfigured inventory (wrong IP or credentials), playbook syntax errors (YAML is whitespace-sensitive), and network issues (SSH timeouts). When a playbook fails halfway, Ansible reports the failure but does not roll back changes. Engineers must implement error handling using `rescue` blocks or manually revert. Also, Ansible's push model means the control node must have network access to all devices; in a segmented network, you may need a jump box. Despite these challenges, Ansible is widely adopted because it is agentless and uses existing SSH infrastructure.

## Exam focus

The CCNA 200-301 exam objective 6.5 is titled "Describe the characteristics of automation tools like Ansible." This is a low-weight objective, but it appears in multiple-choice questions. The exam does not require you to write playbooks or run Ansible commands. Instead, you must understand the concepts: What is Ansible? How does it connect to devices? What is a playbook? What is a module? What is idempotency? What is the difference between push and pull models?

Common wrong answers:
1. "Ansible uses a pull model where agents are installed on devices." — This is incorrect. Ansible is push-based and agentless. Candidates confuse it with Puppet/Chef which use pull and agents.
2. "Ansible requires Python on the managed network device." — False. For network devices, modules run on the control node and push CLI commands. The device only needs SSH.
3. "Ansible uses YAML for inventory files." — While YAML is an option, the default inventory format is INI. Both are valid, but the exam may expect INI as the standard.
4. "The `ios_config` module sends SNMP commands." — No, it sends CLI commands over SSH.

Specific values: Know that Ansible uses SSH port 22 by default. The `ansible_connection=network_cli` is the correct setting for Cisco IOS. The `ansible_network_os=ios` specifies the OS. The `ios_facts` module gathers device information.

Decision rule: If a question asks about agentless automation that pushes configs, choose Ansible. If it mentions pull model or agents, it's likely Puppet or Chef. Also, remember that Ansible playbooks are YAML files, and modules are reusable units of code.

## Step by step

1. **Install Ansible on Control Node** — On a Linux control node (Ubuntu 20.04+), update package lists and install Ansible: `sudo apt update && sudo apt install ansible -y`. Verify with `ansible --version`. The output shows the Ansible version, Python version, and location of config file (default `/etc/ansible/ansible.cfg`). For CCNA, you don't need to install on a router — Ansible runs externally. Ensure Python 3.6+ is installed. If using Windows, install WSL with Ubuntu. The control node must have network connectivity to the managed devices on port 22.
2. **Create Inventory File** — Create a file named `inventory.ini`. Define groups like `[routers]` and list devices. Each device entry includes `ansible_host` (IP), `ansible_user`, `ansible_ssh_pass` (or use SSH keys), `ansible_connection=network_cli`, and `ansible_network_os=ios`. Example: `R1 ansible_host=10.1.1.1 ansible_user=admin ansible_ssh_pass=cisco ansible_connection=network_cli ansible_network_os=ios`. For security, use `ansible_ssh_private_key_file` or encrypt passwords with Ansible Vault. Test connectivity with `ansible routers -m ping -i inventory.ini`. Expect `SUCCESS` with `"ping": "pong"`.
3. **Write a Simple Playbook** — Create a playbook file `configure_ospf.yml`. Start with `---` and a play definition. Example: `- name: Configure OSPF` `hosts: routers` `gather_facts: no` `tasks:`. Add a task using `ios_config` module: `- name: Enable OSPF` `ios_config:` `lines:` `  - router ospf 1` `  - network 10.0.0.0 0.255.255.255 area 0` `provider: "{{ cli }}"`. The `provider` is a variable that contains connection details; you can define it in the inventory or playbook. Alternatively, use `connection: network_cli` and omit `provider`. Save the file.
4. **Run the Playbook** — Execute the playbook: `ansible-playbook configure_ospf.yml -i inventory.ini`. Ansible will connect to each device, check current config, and apply changes if needed. Output shows each task with status: `ok` (no change), `changed` (change applied), or `failed` (error). For example: `TASK [Enable OSPF] ************************************ changed: [R1]`. If a device is unreachable, you'll see `UNREACHABLE`. Check connectivity and credentials. Use `-v` for verbose output to see raw commands sent.
5. **Verify Configuration on Device** — After running the playbook, verify the configuration on the router. Use `ios_command` module to run show commands: `- name: Verify OSPF` `ios_command:` `commands:` `  - show ip ospf neighbor` `  - show ip route ospf`. The output is captured and can be displayed or saved. Alternatively, SSH to the device manually: `ssh admin@10.1.1.1` and run `show running-config | section router ospf`. Confirm OSPF is enabled and neighbors are formed. Ansible's idempotency means running the playbook again will report `ok` instead of `changed`.
6. **Use Ansible Vault for Secrets** — Store sensitive data like passwords in an encrypted file. Create a vault file: `ansible-vault create secrets.yml`. Enter a vault password and then add variables: `ansible_ssh_pass: cisco` `enable_password: cisco`. Reference the vault file in the playbook: `vars_files: - secrets.yml`. When running the playbook, use `--ask-vault-pass` to prompt for the vault password. Example: `ansible-playbook playbook.yml -i inventory.ini --ask-vault-pass`. This keeps passwords out of plain text. For exam, know that Ansible Vault encrypts the file using AES-256.

## Comparisons

### Ansible vs Puppet

**Ansible:**
- Push model: control node pushes config to devices
- Agentless: no software on managed nodes
- Uses SSH for network devices
- Playbooks written in YAML
- Idempotent by default

**Puppet:**
- Pull model: agents on nodes pull config from master
- Requires agent software on managed nodes
- Uses HTTPS for communication
- Manifests written in Puppet DSL (based on Ruby)
- Also idempotent

## Common misconceptions

- **Misconception:** Ansible requires an agent installed on each network device. **Reality:** Ansible is agentless. It connects to devices via SSH (or other protocols) and executes tasks remotely. No agent software is needed on the device. (Candidates confuse Ansible with Puppet/Chef, which use pull models with agents.)
- **Misconception:** Ansible playbooks are written in JSON. **Reality:** Ansible playbooks are written in YAML, a human-readable data serialization language. JSON can be used for variables but not for playbooks. (YAML is less common than JSON, so candidates assume JSON is used.)
- **Misconception:** Ansible modules run on the managed network device. **Reality:** For network devices, Ansible modules run on the control node and send CLI commands to the device. The device does not execute the module code. (Candidates think modules run on the target because that's how it works for servers.)
- **Misconception:** Ansible uses SNMP to configure network devices. **Reality:** Ansible uses SSH (or NETCONF) to send configuration commands. SNMP is typically read-only and not used for configuration in Ansible. (SNMP is a common network management protocol, so candidates assume it's used.)

## Key takeaways

- Ansible uses a push model: the control node pushes configurations to devices via SSH.
- Ansible is agentless: no software needs to be installed on managed network devices.
- Playbooks are written in YAML and contain plays with tasks that call modules.
- The `ios_config` module sends CLI configuration commands to Cisco IOS devices.
- Idempotency means applying the same configuration multiple times yields the same result (no unintended changes).
- Inventory files list managed devices and can be in INI or YAML format.
- Ansible Vault encrypts sensitive data like passwords using AES-256.

## FAQ

**Do I need to install Ansible on my Cisco router?**

No. Ansible is agentless. You install it on a control node (Linux server or workstation) and it connects to your router via SSH. The router only needs SSH enabled and a user account with appropriate privileges. No additional software is required on the router.

**What is the difference between Ansible and Puppet?**

The key difference is the model: Ansible is push-based (control node pushes configs), while Puppet is pull-based (agents on nodes pull configs from a master). Ansible is agentless; Puppet requires agents. Ansible uses YAML for playbooks; Puppet uses its own DSL. For CCNA, focus on Ansible's push/agentless characteristics.

**How do I handle passwords securely in Ansible?**

Use Ansible Vault to encrypt sensitive variables. Create an encrypted file with `ansible-vault create secrets.yml`, store passwords there, and reference the file in your playbook using `vars_files`. When running the playbook, use `--ask-vault-pass` to enter the vault password. This keeps passwords out of plain text.

**What is an Ansible module?**

A module is a reusable, standalone script that Ansible runs to perform a specific task. For network devices, modules like `ios_config` send CLI commands and parse the output. Modules run on the control node (for network devices) and return structured JSON data. They are the building blocks of playbooks.

**Can Ansible be used to backup router configurations?**

Yes. Use the `ios_config` module with the `backup: yes` option. This will save a backup of the running config to the control node before making changes. The backup filename includes the hostname and timestamp. You can also use `ios_command` with `show running-config` and save the output.

**What is the default port for Ansible SSH connections?**

Port 22. Ansible uses SSH to connect to network devices. You can change the port by setting `ansible_port` in the inventory. For CCNA, remember that Ansible relies on SSH (TCP/22) for connectivity.

**What does 'idempotent' mean in Ansible?**

Idempotent means that applying the same configuration multiple times produces the same result. Ansible modules check the current state before making changes. If the desired state already exists, no changes are made. This prevents duplicate configurations and ensures consistency.

---

Interactive version with quiz and diagrams: https://courseiva.com/learn/ccna/ansible-networking
