Backend / IaC / 02_ansible.md

Ansible

Updated 6 interview angles 4 min read source
On this page8
  1. The model
  2. Terraform vs Ansible
  3. Idempotency
  4. Structure at scale
  5. Secrets
  6. Practical notes
  7. Where it fits in
  8. Interview angle

Ansible

Configuration management. Less central than it was — containers absorbed much of its job — but still standard for VM fleets, on-prem, and anything Terraform provisions but doesn’t configure.

The model

Agentless: Ansible connects over SSH, pushes modules, runs them, removes them. Nothing to install on targets beyond Python.

yaml
# playbook.yml
- hosts: webservers
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.package:
        name: nginx
        state: present

    - name: Deploy config
      ansible.builtin.template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        # verify BEFORE replacing
        validate: nginx -t -c %s
      notify: reload nginx

  handlers:
    - name: reload nginx
      ansible.builtin.service:
        name: nginx
        state: reloaded

The validate parameter is the detail worth knowing: it checks the rendered config before installing it, so a bad template fails the task instead of breaking the service on reload.

Handlers run once at the end, only if notified. That’s how you avoid restarting a service five times in one playbook run.

Terraform vs Ansible

The comparison you’ll be asked for:

Terraform Ansible
Job provision infrastructure configure what exists
Model declarative, with state procedural tasks, idempotent modules
State file yes — tracks reality no
Drift detection plan shows it only if you re-run
Destroys things yes, deliberately rarely
Best at cloud resources, networks, managed services packages, files, services, app deploys

They compose: Terraform creates the VMs and outputs their IPs; Ansible configures them. Using Terraform to install packages via remote-exec, or Ansible to manage cloud resources, is possible and worse at both.

The stronger 2026 answer: if you’re building images or containers, you often need neither for configuration. Packer or a Dockerfile bakes the configuration in, and instances become immutable. Ansible earns its place where you have long-lived mutable servers.

Idempotency

The property that makes re-running safe. Modules declare desired state, not commands:

yaml
# Idempotent - describes the end state
- ansible.builtin.package: { name: nginx, state: present }

# NOT idempotent - runs every time, reports "changed" every time
- ansible.builtin.shell: apt-get install -y nginx

shell and command are escape hatches that break idempotency. When you must use them, guard with creates:, removes: or a when: condition, and set changed_when: honestly so your change reporting means something.

A playbook that reports changes on every run is a playbook nobody can use to detect drift.

Structure at scale

text
inventory/
  production/hosts.yml
  staging/hosts.yml
roles/
  nginx/{tasks,handlers,templates,defaults,vars}/
group_vars/
  webservers.yml
host_vars/
  web-01.yml

Roles are the reuse unit. Inventory separates environments. Variable precedence is deep and a genuine source of confusion — roughly: role defaults lose to group vars, which lose to host vars, which lose to -e extra vars. When a variable “isn’t taking effect”, precedence is the first thing to check.

Secrets

bash
ansible-vault encrypt group_vars/production/secrets.yml
ansible-playbook site.yml --ask-vault-pass

Ansible Vault encrypts files at rest in the repo. It works, and it’s inferior to a real secrets manager: rotation is manual, access is all-or-nothing per file, and there’s no audit trail. Prefer pulling from Vault, AWS Secrets Manager or similar at runtime; use Ansible Vault when you have no other option. See Secrets and configuration.

Practical notes

  • --check --diff is your dry run. Not all modules support it faithfully, so it’s indicative rather than authoritative.
  • --limit to target a subset; combine with serial: for rolling deploys across a fleet.
  • Performance: Ansible is slow on large inventories. Increase forks, enable pipelining, and use gather_facts: false where you don’t need facts — fact gathering is often the single biggest cost.
  • Testing: Molecule spins up containers and verifies roles. Rare in practice, valuable when playbooks are load-bearing.

Where it fits in 2026

Use it for Prefer something else
long-lived VMs and on-prem fleets containerised workloads (image build)
network devices, appliances cloud resources (Terraform)
ad-hoc fleet operations ephemeral autoscaled instances (bake the image)
bootstrapping Kubernetes nodes app config in K8s (ConfigMaps, Helm)

Being clear that immutable infrastructure has narrowed Ansible’s scope is a better answer than presenting it as the default.

Interview angle 6

  • “Terraform or Ansible?” — different jobs. Terraform provisions infrastructure and holds state so it can detect drift and destroy; Ansible configures existing machines and holds no state. They compose: Terraform creates the VMs, Ansible configures them.
  • “What makes a playbook idempotent, and how does it break?” — modules declare desired state, so re-running is a no-op. shell and command break it because they always execute; guard them with creates:/when: and set changed_when: honestly, or your change reporting becomes meaningless.
  • “Why is Ansible less central than it used to be?” — immutable infrastructure. If you bake configuration into an image or container, there’s nothing to configure at runtime. Ansible earns its place with long-lived mutable servers, network devices and on-prem fleets.
  • “A variable isn’t taking effect. Where do you look?” — precedence. Role defaults are weakest, then group vars, then host vars, then extra vars on the command line. It’s the most common source of confusion in a large inventory.
  • “Is Ansible Vault adequate for secrets?” — workable, not good. No rotation, no per-secret access control, no audit trail. Prefer fetching from a real secrets manager at runtime.
  • “Your playbook takes 20 minutes across 200 hosts. Speed it up?” — raise forks, enable pipelining, and disable fact gathering where it isn’t needed; fact gathering is usually the dominant cost.