Ansible is an open-source agentless automation tool that configures servers, deploys applications and orchestrates multi-step operations by running tasks described in YAML playbooks. In infrastructure as code, it is the most widely used tool for configuration management: it brings existing machines to a defined state, while provisioning tools such as Terraform and OpenTofu create the machines and cloud resources in the first place.
Ansible connects to managed hosts over SSH on Linux and Unix systems and over WinRM or SSH on Windows, copies small modules to the target, runs them and removes them. No permanent agent, database or message queue is required on the managed nodes, which makes Ansible easy to introduce into existing cloud and on-premises environments.
How Ansible executes automation
Ansible runs from a control node, any Linux or macOS machine with Python and the Ansible package installed. The control node reads an inventory of target hosts, a playbook of tasks and variable files, then pushes work to the hosts in parallel. By default, it handles five hosts at a time, a value set by the forks parameter and often raised to 20-50 or more for large fleets.
Each task calls a module, a small unit of code such as apt, template, service or user. Modules are written to be idempotent: they check the current state first and change it only when it differs from the desired state. Running the same playbook twice should therefore report changes on the first run and no changes on the second.
| Component | Role | Typical form |
|---|---|---|
| Inventory | Lists managed hosts and groups | INI or YAML file, or a dynamic cloud plugin |
| Playbook | Maps host groups to ordered tasks | YAML file with one or more plays |
| Module | Performs one action on a host | Python or PowerShell code shipped at runtime |
| Role | Packages tasks, templates, handlers and defaults | Standard directory structure |
| Collection | Distributes modules, roles and plugins | Versioned bundle installed from a repository |
| Handler | Runs only when notified by a change | Service restart after a configuration update |
In cloud environments, static inventory files are usually replaced by dynamic inventory plugins that query the provider API and group instances by tags, regions or roles. This keeps the inventory accurate when autoscaling adds or removes machines.
Ansible compared with other infrastructure as code tools
Ansible occupies a different position from declarative provisioning tools. Terraform and OpenTofu keep a state file and compute a plan of differences between that state and the desired configuration. Ansible keeps no state: it evaluates each target at runtime and executes tasks in the order written, so it is procedural in structure even though most modules behave declaratively.
| Tool | Primary purpose | Model | Agent required |
|---|---|---|---|
| Ansible | Configuration and orchestration | Ordered tasks, push | No |
| Terraform or OpenTofu | Provisioning cloud resources | Declarative with state file | No |
| Puppet | Continuous configuration enforcement | Declarative catalog, pull | Yes |
| Chef | Configuration management | Ruby recipes, pull | Yes |
| Salt | Configuration and remote execution | Declarative states, event bus | Usually yes |
The practical consequence is a common division of labor: Terraform provisions, Ansible configures. A pipeline creates networks, virtual machines and managed services with a provisioning tool, then hands the new host addresses to Ansible, which installs packages, hardens the operating system and deploys the application.
Key settings and execution options
Most Ansible behavior is tuned through a small set of execution parameters in ansible.cfg, on the command line or in the playbook. Choosing them well determines speed, safety and the blast radius of a mistake.
| Parameter | What it controls | Typical values |
|---|---|---|
| forks | Number of hosts handled in parallel | 5 by default, 20-100 in larger fleets |
| serial | Batch size for rolling changes | 1 host, a fixed number or a percentage |
| become | Privilege escalation on the target | sudo to root for system tasks |
| check mode | Dry run that reports intended changes | Used before risky runs |
| strategy | How tasks progress across hosts | linear by default, free for speed |
| pipelining | Reduces SSH operations per task | Enabled for performance when sudo allows it |
Secrets such as passwords and API keys are kept in Ansible Vault, which encrypts variable files with AES-256, or are fetched at runtime from an external secrets manager. Committing plaintext secrets to playbook repositories is one of the most serious mistakes in Ansible projects.
Where Ansible fits and where it does not
Ansible is strongest for day-two operations: patching, configuration changes, application deployment, certificate rotation and coordinated rolling restarts. Its readable YAML makes it accessible to operations teams that do not write general-purpose code daily.
| Situation | Good choice | Reason |
|---|---|---|
| Configuring long-lived virtual machines | Ansible roles | Idempotent tasks keep hosts consistent |
| Creating cloud networks and databases | Terraform or OpenTofu | State tracking handles dependencies and deletion |
| Immutable container workloads | Image builds and Kubernetes manifests | Hosts are replaced, not reconfigured |
| Network device configuration | Ansible network collections | Agentless access to switches and routers |
| Orchestrating a multi-step upgrade | Ansible playbook with serial batches | Explicit ordering across tiers |
Limitations and common mistakes
Because Ansible is stateless, it does not know about resources it no longer manages. Removing a task does not remove the package or file it once created; the playbook must explicitly declare state: absent. This is a frequent source of configuration drift between hosts built at different times.
- Overusing shell and command modules, which bypass idempotency and report changes on every run.
- Running without check mode before changing production fleets.
- Huge monolithic playbooks instead of reusable roles with clear defaults.
- Unpinned collection versions, which make runs behave differently over time.
- Slow runs over large fleets caused by low forks values and disabled pipelining.
Ansible also runs only when someone or something triggers it. Unlike agent-based tools that enforce state continuously, drift between runs remains invisible unless the playbook is scheduled or a pipeline runs it regularly.
Understanding it simply
Ansible is a way to give written instructions to many computers at once. Instead of logging into fifty servers and typing the same commands fifty times, an administrator writes the desired setup in a readable text file, and Ansible connects to each server and makes it match.
It works like a careful checklist. Before doing anything, it checks whether each item is already done, and it only changes what is missing. Running it again is safe, because servers that are already correct stay untouched.
Applied in practice
A hosting team manages 120 Linux web servers across two cloud regions. A critical OpenSSL update must be installed and the web service restarted without taking the site offline. The team writes a short playbook that updates the package, validates the web server configuration and restarts the service through a handler.
They first run it in check mode to confirm which hosts would change, then execute it with serial: 10%, so only twelve servers restart at a time while the load balancer keeps serving traffic from the rest. A health check task stops the run if any batch fails. The entire fleet is patched in under 30 minutes, with a complete log of every change and no visible downtime for users.