Skip to content

Ansible — Theory

Modules report ok / changed / failed. Re-running playbooks should converge without unintended changes. command/shell break this guarantee — use creates: / changed_when: to fix.

  • Ansible is push by default — control node SSHes to targets.
  • Ansible Pull mode: hosts pull from git. Used in immutable/edge contexts.
  • Compare to Puppet / Chef / Salt — agent-based pull.
- name: only run if file missing
shell: ./bootstrap.sh
args: { creates: /opt/.bootstrapped }
- name: run + interpret success
shell: kubectl apply -f manifest.yml
register: kubectl_out
changed_when: "'configured' in kubectl_out.stdout or 'created' in kubectl_out.stdout"
  • Per concern: nginx, postgres, monitoring.
  • Use Ansible Collections for distribution (replaces older Galaxy roles).
  • Pin versions in requirements.yml.
  • SSH multiplexing on (default).
  • mitogen strategy plugin — significant speedup.
  • forks: N parallelism.
  • gather_facts: false if not needed.
  • Use async for long tasks running in parallel.
  • Terraform — provisioning cloud resources (VMs, networks, IAM).
  • Ansible — configuring inside the resources (install packages, files, services).

Often used together: TF creates VMs, Ansible configures them. Or use cloud-init for first-boot config and Ansible for subsequent changes.

  1. Why might a task report changed=true on every run? Non-idempotent module (shell/command without changed_when), or the resource keeps drifting.
  2. How to handle secrets in Ansible? Vault, or fetch from KMS at runtime via lookup.
  3. Rolling restart 50 servers without outage. serial: 5, max_fail_percentage, drain LB before restart.
  4. What’s a handler — when does it run? End of play, only if notified by a changed task. Use to restart services after config changes.
  5. Difference role vs collection? Collection is the modern bundle (modules + plugins + roles); role is just tasks/handlers.
  6. When NOT use Ansible? K8s reconciliation; immutable infra; very large fleets.
  7. Test playbooks? Molecule (containers as test hosts), syntax-check, ansible-lint.
  • command/shell everywhere instead of modules.
  • Hard-coded paths, secrets in playbooks.
  • One playbook for everything → unmaintainable.
  • Skipping --check before applying.
  • Mixing config and one-off ops in same play.
  • Storing inventory in code without protecting credentials.