What is configuration management, and how does Ansible's agentless, push-based model implement it differently from agent-based tools like Chef or Puppet?
Quick Answer
Configuration management is the practice of defining a server's desired state — packages, files, services, users — as code, so that state can be applied consistently and repeatedly instead of configured by hand. Ansible implements this over plain SSH with no agent installed on target machines, pushing changes out on demand, whereas Chef and Puppet run a persistent agent on every managed node that periodically pulls its configuration from a central server.
Detailed Answer
Think of configuration management like a restaurant chain's standard recipe book: instead of every location's chef improvising a burger from memory (and getting slightly different results in every city), every kitchen follows the exact same written recipe, so the burger is identical whether you're in Chicago or Miami, and updating the recipe once updates it everywhere. Before configuration management, ops teams configured servers by hand or with ad hoc shell scripts, so no two 'identical' servers were ever actually identical — a problem known as configuration drift.
Ansible was designed specifically to avoid requiring any software installed on the machines it manages, using SSH (which nearly every Linux server already has running) as its only transport. This was a deliberate reaction to Chef and Puppet's model, which requires installing and maintaining an agent daemon on every single managed server, plus a central server (a Chef server or Puppet master) that agents check in with on a schedule, typically every 30 minutes. Ansible's agentless design trades that recurring pull cycle for an explicit push: you run a playbook when you want changes applied, and nothing happens on the target machines outside of that run.
Mechanically, when you run an Ansible playbook, the control machine connects to each target over SSH, copies over small Python modules, executes them, and removes them — leaving no persistent process running afterward. Each task in a playbook describes desired state (e.g., 'nginx should be installed and running') rather than imperative steps, and Ansible's modules are idempotent: running the same playbook twice produces the same end state without re-executing changes unnecessarily, checking first whether the target already matches the desired state.
In production, this push-based model means configuration changes happen exactly when you trigger them — during a deploy, in a CI/CD pipeline, or via a scheduled cron-triggered playbook run — rather than silently drifting into place over the next 30-minute agent pull window like Chef or Puppet. This makes Ansible easier to reason about for deploy-time configuration changes, but it also means nothing enforces state between runs; if someone manually edits a config file on a server, Ansible won't notice or correct it until the next explicit run, whereas an agent-based tool's continuous pull cycle would self-heal that drift within its next check-in.
The gotcha: Ansible's lack of a persistent agent is usually pitched as pure simplicity, but it means Ansible provides no built-in continuous drift correction — teams that need servers to self-heal from manual changes between runs either need to schedule playbook runs frequently via cron/CI, or accept that Ansible is better suited to deploy-time and provisioning-time configuration than to continuous enforcement the way Puppet's agent model is.