LFCE 147 ๐ง Ansible โ Concepts
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
| Component | Role |
|---|---|
| Control node | Runs ansible and ansible-playbook |
| Managed node | Target host, SSH + Python |
| Inventory | List of hosts and groups |
| Module | Unit of work, idempotent |
| Playbook | YAML file of plays and tasks |
| Role | Reusable bundle of tasks, handlers, templates |
Common modules
| Module | Purpose |
|---|---|
apt / dnf | Package management |
copy / template | File management |
service / systemd | Service management |
user / group | Account management |
file | Permissions and directories |
Idempotency states
| State | Meaning |
|---|---|
changed | The module modified the system |
ok | The desired state was already present |
failed | The operation could not complete |
The agentless model
| Requirement | Control node | Managed node |
|---|---|---|
| Ansible | Yes | No |
| Python | Yes | Yes |
| SSH server | No | Yes |
| SSH client | Yes | No |
| Daemon | No | No |
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
| Pitfall | Why It Happens | Fix |
|---|---|---|
Playbook reports changed every run | shell or command used instead of a module | Use the module that matches the task |
| Connection fails | SSH key not configured or host not in inventory | Check ansible all -m ping |
| Module fails on Python | Python not installed on the managed node | Use raw to bootstrap Python |
become fails | Sudo requires a password or is misconfigured | Configure passwordless sudo or use --ask-become-pass |
| Idempotency broken | Imperative command instead of desired state | Use 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
| Item | Value |
|---|---|
| Architecture | Agentless, push-based |
| Transport | SSH (Linux/Unix), WinRM (Windows) |
| Control node | Runs ansible and ansible-playbook |
| Managed node | SSH server + Python interpreter |
| Inventory | Hosts and groups, INI or YAML |
| Module | Unit of work, idempotent |
| Playbook | YAML file of plays and tasks |
| Idempotency | Re-running produces the same end state |
| Status | changed, 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
hostsline . - 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
changedandokstatuses are the report of whether a change was needed . - Idempotency is the property that makes a playbook safe. The first run reports
changedfor the tasks that modified the system. The second run reportsokfor 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.
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!