| |

LFCE 147 ๐Ÿง Ansible โ€” Concepts

โฑ๏ธ Estimated read: 10 min | |

Ansible is an agentless IT automation engine. It connects to managed nodes over SSH, pushes a small module payload to each node, executes it using the node’s existing Python interpreter, and parses the JSON result that comes back. Nothing is installed on the managed node, nothing runs between executions, and nothing is left behind after the task completes . The control node holds the inventory, the playbooks, the modules, and the plugins. The managed nodes hold only an SSH server and a Python interpreter.

This chapter covers the conceptual foundation of Ansible: the control-node and managed-node model, the inventory that defines the targets, the module that performs the work, the playbook that orchestrates the modules, and the idempotency property that makes a playbook safe to run repeatedly. It also covers the push-based execution lifecycle and the agentless trade-off that distinguishes Ansible from Puppet and Chef.

Key point: Ansible is not a configuration management daemon. It is a push-based tool that runs when you invoke it. The managed node has no agent, no daemon, and no persistent process. The configuration is enforced when the playbook runs, and the state is checked again on the next run.


Why Ansible is agentless

The daemon problem. Puppet and Chef require an agent daemon on every managed node. The daemon must be installed, upgraded, secured, and monitored. It runs continuously and enforces the desired state between runs. The operational overhead is real: a fleet of a thousand servers has a thousand agents to maintain .

The SSH problem. Ansible replaces the agent with SSH. The control node connects to the managed node using the same OpenSSH that the administrator already uses. The module is transferred, executed, and removed. The connection is reused across tasks with ControlPersist, and the module payload is streamed with pipelining to reduce round trips . The security model is the SSH model, not a separate PKI.

The Python problem. The module is a Python script. It requires a Python interpreter on the managed node. Modern distributions have Python 3 installed by default. A minimal host that does not have Python can be bootstrapped with the raw module, which runs a shell command without Python . Windows hosts use WinRM and PowerShell instead of SSH and Python. Network devices run the module logic on the control node and send CLI or API commands to the device.


a. The control node and the managed node

The control node is the machine where Ansible is installed and where the ansible and ansible-playbook commands are run. It can be a laptop, a shared desktop, a server, or a container. It cannot be a Windows machine; WSL is the workaround for Windows users . The control node needs Python 3 and an SSH client.

The managed node is the target host. It needs an SSH server and a Python interpreter. It does not need Ansible installed, and it does not need a daemon. The inventory lists the managed nodes, and the playbook targets them.


b. The inventory

The inventory is the list of managed nodes, organized into groups. It can be an INI file or a YAML file. The INI format is the simpler one.

[webservers]
www1.example.com
www2.example.com

[dbservers]
db0.example.com
db1.example.com

The group names are used in the playbook’s hosts line. The webservers group is targeted with hosts: webservers . The inventory can also define host-specific variables like ansible_host, ansible_user, and ansible_port .

A dynamic inventory pulls the host list from a cloud provider’s API instead of a static file. The inventory plugin queries EC2, GCP, Azure, or OpenStack and returns the hosts and groups at runtime .


c. The module

A module is the unit of work. It is a small program that Ansible pushes to the managed node, executes, and removes. The module receives parameters that describe the desired state, checks the current state, and makes the change only if the current state differs from the desired state .

The common modules are apt and dnf for packages, copy and template for files, service and systemd for services, user and group for accounts, and file for permissions and directories . The module reports one of three statuses: changed if it modified the system, ok if no change was needed, or failed if the operation could not complete.


d. The playbook and idempotency

A playbook is a YAML file with one or more plays. Each play maps a group of hosts to an ordered list of tasks. Each task invokes a module with parameters.

- name: Configure web servers
  hosts: webservers
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.apt:
        name: nginx
        state: present

    - name: Ensure nginx is running
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: true

The become: true uses sudo to run the tasks as root . The state: present means “install the package if it is not already installed.” The state: started means “start the service if it is not already running.” These are desired-state declarations, not imperative commands.

Idempotency is the property that makes the playbook safe to run repeatedly. The first run reports changed for the package installation and the service start. The second run reports ok for both, because the desired state is already satisfied . The module checked the current state before acting. The result is that a playbook can be run on a schedule, in a CI pipeline, or after a configuration change without introducing duplicate side effects.


Complete Example Session

# ============================================
# PART 1: THE CONTROL NODE
# ============================================
# The machine where ansible is installed.
# Runs ansible and ansible-playbook.
# Needs Python 3 and SSH client.
# ============================================
# PART 2: THE MANAGED NODE
# ============================================
# The target host.
# Needs SSH server and Python interpreter.
# No Ansible installed, no daemon.
# ============================================
# PART 3: THE INVENTORY
# ============================================
[webservers]
www1.example.com
www2.example.com

[dbservers]
db0.example.com
# ============================================
# PART 4: THE MODULE
# ============================================
# The unit of work.
# Pushed to the node, executed, removed.
# Reports changed, ok, or failed.
# ============================================
# PART 5: THE PLAYBOOK
# ============================================
- name: Configure web servers
  hosts: webservers
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.apt:
        name: nginx
        state: present
# ============================================
# PART 6: THE IDEMPOTENCY PROPERTY
# ============================================
# First run: changed (package installed)
# Second run: ok (package already present)
# The module checked the state before acting.
# ============================================
# PART 7: THE PUSH-BASED MODEL
# ============================================
# The control node initiates the connection.
# The module is transferred and executed.
# The result is returned as JSON.
# ============================================
# PART 8: THE AGENTLESS TRADE-OFF
# ============================================
# No daemon to install or maintain.
# No continuous enforcement between runs.
# State is checked when the playbook runs.
# ============================================
# PART 9: THE EXECUTION LIFECYCLE
# ============================================
# Inventory parsed.
# Play compiled.
# Module packaged as AnsiballZ.
# SSH transfer.
# Python execution.
# JSON result parsed.
# Temporary files removed.
# ============================================
# PART 10: THE COMPLETE PICTURE
# ============================================
# Control node: inventory, playbooks, modules.
# Managed node: SSH + Python.
# Execution: push, execute, remove.
# Property: idempotent.

The ten parts covered the control node, the managed node, the inventory, the module, the playbook, idempotency, the push model, the agentless trade-off, the execution lifecycle, and the complete picture.


Quick Reference

Core components

ComponentRole
Control nodeRuns ansible and ansible-playbook
Managed nodeTarget host, SSH + Python
InventoryList of hosts and groups
ModuleUnit of work, idempotent
PlaybookYAML file of plays and tasks
RoleReusable bundle of tasks, handlers, templates

Common modules

ModulePurpose
apt / dnfPackage management
copy / templateFile management
service / systemdService management
user / groupAccount management
filePermissions and directories

Idempotency states

StateMeaning
changedThe module modified the system
okThe desired state was already present
failedThe operation could not complete

The agentless model

RequirementControl nodeManaged node
AnsibleYesNo
PythonYesYes
SSH serverNoYes
SSH clientYesNo
DaemonNoNo

Best Practices

โœ… Do This:

# Use state: present for packages
state: present                                              # โœ…
# Use state: started for services
state: started                                              # โœ…
# Use become for privilege escalation
become: true                                                # โœ…
# Test the connection before running the playbook
ansible all -m ping                                         # โœ…

โŒ Don’t Do This:

# Use shell or command for tasks that have a module
shell: apt install nginx                                    # โŒ (loses idempotency)
# Use state: latest for every package
state: latest                                               # โŒ (upgrades unexpectedly)
# Run a playbook without a syntax check
ansible-playbook site.yml                                   # โŒ (use --syntax-check)

Common Pitfalls

PitfallWhy It HappensFix
Playbook reports changed every runshell or command used instead of a moduleUse the module that matches the task
Connection failsSSH key not configured or host not in inventoryCheck ansible all -m ping
Module fails on PythonPython not installed on the managed nodeUse raw to bootstrap Python
become failsSudo requires a password or is misconfiguredConfigure passwordless sudo or use --ask-become-pass
Idempotency brokenImperative command instead of desired stateUse state: present or state: started

Real-World Examples

1. Ping all hosts

ansible all -m ping

2. Install a package

ansible.builtin.apt:
  name: nginx
  state: present

3. Start a service

ansible.builtin.service:
  name: nginx
  state: started
  enabled: true

4. Copy a file

ansible.builtin.copy:
  src: files/nginx.conf
  dest: /etc/nginx/nginx.conf

5. Template a file

ansible.builtin.template:
  src: templates/app.conf.j2
  dest: /etc/app/app.conf

6. Create a user

ansible.builtin.user:
  name: deploy
  state: present

7. The inventory group

[webservers]
www1.example.com

8. The playbook hosts line

hosts: webservers

9. The become flag

become: true

10. The idempotency check

First run: changed
Second run: ok

Visual

The agentless architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  CONTROL NODE                                                โ”‚
โ”‚    โ”œโ”€โ”€ ansible / ansible-playbook                            โ”‚
โ”‚    โ”œโ”€โ”€ inventory                                             โ”‚
โ”‚    โ”œโ”€โ”€ playbooks                                             โ”‚
โ”‚    โ””โ”€โ”€ modules                                               โ”‚
โ”‚                                                              โ”‚
โ”‚  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  โ”‚
โ”‚                                                              โ”‚
โ”‚  MANAGED NODES                                               โ”‚
โ”‚    โ”œโ”€โ”€ SSH server                                            โ”‚
โ”‚    โ””โ”€โ”€ Python interpreter                                    โ”‚
โ”‚                                                              โ”‚
โ”‚  No agent. No daemon. Nothing running between runs.          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The execution lifecycle

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  ansible-playbook site.yml                                   โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Parse inventory                                             โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Compile play, resolve variables                             โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Package module as AnsiballZ                                 โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  SSH transfer to managed node                                โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Execute with Python                                         โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  JSON result returned                                        โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Temporary files removed                                     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Idempotency

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  First run:                                                  โ”‚
โ”‚    apt: state=present โ”€โ”€โ–บ package not installed โ”€โ”€โ–บ install  โ”‚
โ”‚    changed                                                    โ”‚
โ”‚                                                              โ”‚
โ”‚  Second run:                                                 โ”‚
โ”‚    apt: state=present โ”€โ”€โ–บ package already installed โ”€โ”€โ–บ ok   โ”‚
โ”‚    ok                                                         โ”‚
โ”‚                                                              โ”‚
โ”‚  The module checks the current state before acting.          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The push model

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Control node โ”€โ”€โ–บ SSH โ”€โ”€โ–บ Managed node                       โ”‚
โ”‚       โ”‚                      โ”‚                              โ”‚
โ”‚       โ”‚  module payload      โ”‚                              โ”‚
โ”‚       โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บโ”‚                              โ”‚
โ”‚       โ”‚                      โ”‚ execute with Python          โ”‚
โ”‚       โ”‚  JSON result         โ”‚                              โ”‚
โ”‚       โ”‚โ—„โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค                              โ”‚
โ”‚       โ”‚                      โ”‚                              โ”‚
โ”‚       โ–ผ                      โ–ผ                              โ”‚
โ”‚  Report changed/ok/failed    Temp files removed              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
ArchitectureAgentless, push-based
TransportSSH (Linux/Unix), WinRM (Windows)
Control nodeRuns ansible and ansible-playbook
Managed nodeSSH server + Python interpreter
InventoryHosts and groups, INI or YAML
ModuleUnit of work, idempotent
PlaybookYAML file of plays and tasks
IdempotencyRe-running produces the same end state
Statuschanged, ok, failed

Key takeaways:

  • Ansible is agentless. The managed node needs only an SSH server and a Python interpreter. No daemon is installed, no process runs between executions, and nothing is left behind after a task completes .
  • The push-based model is the execution model. The control node initiates the connection, transfers the module payload, executes it with the managed node’s Python, and parses the JSON result. The model is the opposite of a pull-based agent that enforces state continuously .
  • The inventory defines the targets. The hosts and groups in the inventory file determine which machines a playbook acts on. The group names are referenced in the playbook’s hosts line .
  • The module is the unit of work. It accepts parameters that describe the desired state, checks the current state, and makes the change only if the state differs. The changed and ok statuses are the report of whether a change was needed .
  • Idempotency is the property that makes a playbook safe. The first run reports changed for the tasks that modified the system. The second run reports ok for the same tasks because the desired state is already present. The playbook can be run on a schedule or in a pipeline without duplicate side effects .
  • The trade-off is enforcement timing. The agentless model has no continuous convergence. The state is enforced when the playbook runs, not between runs. The advantage is the absence of a daemon to maintain; the cost is that drift is only corrected on the next run .

Remember: Ansible is a push-based, agentless automation engine. The control node holds the inventory, the playbooks, and the modules. The managed node holds only SSH and Python. The module is the unit of work, and it is idempotent: it checks the current state and changes it only if the desired state is not already present. The playbook orchestrates the modules across a group of hosts. The agentless model removes the daemon from the managed node, at the cost of enforcing the state only when the playbook runs.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!