unit 1 · Orientation

What Ansible is & isn't

Declarative desired state, not a script runner

essential · 6 min · linux + windows

tl;dr

  • Ansible is declarative: you state the end state, modules work out the how — Bicep thinking, not PowerShell.
  • Push-based and agentless, with no state file — "changed" is computed fresh against the real machine each run.
  • Bare shell tasks drag it back to scripting. Reach for a purpose-built module first.

why it matters Treat Ansible like a script runner and every rerun reports changes, reviewers bounce your shell tasks, and you fight the tool instead of describing what prod should look like.

Here’s the beginner mistake that tops the list, and the one your background makes most tempting: treating Ansible as a scripting language. It isn’t. A playbook looks like a script — YAML tasks, read top to bottom — but each task is a declarative statement of an end state, not an instruction to execute. You say what the machine should look like; the

module behind the task works out how to get there, and whether anything needs doing at all.

Watch the two mindsets on the same job:

- name: MOTD file is in place
  ansible.builtin.copy: # a module: this file, with this content, exists
    src: files/motd # what the file must contain
    dest: /etc/motd # where it must live
Declarative: state the end state, let the module decide

The copy module inspects what’s actually on the host first. Matches? It reports ok and touches nothing. Differs? It fixes it and reports changed. Run it once or fifty times and you converge on the same machine — that property is called being idempotent , and modules give it to you for free. (Those dotted module names are FQCNs — lesson 4 explains them; copy the style for now.)

Now the scripting reflex:

old — don't write this · anti-pattern — scripting in YAML clothing
- name: Write the MOTD
  ansible.builtin.shell: echo "Welcome" > /etc/motd

This runs. It even works. But a shell task always executes and always reports changed, because Ansible can’t see inside your command to know whether the host actually moved. Chain a dozen of these together and you’ve written a PowerShell script with worse ergonomics — every guarantee Ansible offers, thrown away.

What will surprise a Terraform and Bicep brain

Three things about this model won’t match your instincts:

  • There is no state file. Unlike Terraform, Ansible stores nothing between runs. Every run inspects the actual machines and computes changed fresh — the real system is the state. Nothing to lock, nothing to drift from, nothing to corrupt.
  • Ordering is top-down and looks imperative. Tasks run in the order you wrote them — no dependency graph like Bicep’s. The tasks are declarative; the sequence is yours to control, and later you’ll use that deliberately.
  • Facts are gathered fresh each run unless you cache them: Ansible re-asks every host what it is before doing anything. Lesson 17 covers facts.

If you know DSC, one more calibration: DSC is Windows desired state through an agent (the Local Configuration Manager); Ansible is agentless, cross-platform, and can even drive DSC when it needs to.

So the honest one-line definition: agentless, push-based, declarative automation. That’s the mindset. One habit from day one makes it stick: before you type shell:, ask what end state you’re actually describing — there is almost always a module for it.

at work, this sounds like

“It's not idempotent.”
Re-running the playbook keeps making changes (or reporting them) when nothing should change — usually a raw shell task.

self-check — recall, not a test

  1. 1 A colleague calls Ansible "a nicer way to run scripts". What is wrong with that?

  2. 2 Your playbook reports "changed" on every run even though nothing differs. Likely culprit?

  3. 3 Coming from Terraform: where does Ansible keep its state file?

PLAY RECAP ************************** 01-what-ansible-is-and-isnt : ok=1 next=02-architecture-agentless-push read=6m