
Citadel Cloud Management
Ansible Automation Playbook Collection
DevOps PipelinesCreated by Kenny Ogunlowo
Product Description
Ansible Automation Playbook Collection
Ansible playbooks running from a developer's laptop are one SSH connection failure away from a half-configured server. I watched this happen at an energy sector client: the playbook was configuring a 12-node cluster, got to node 7, lost the VPN connection, and left 5 nodes in a partially configured state that did not match the other 7. The team spent a day figuring out which tasks had run on which nodes. This template wraps Ansible in a CI pipeline with idempotency verification, diff mode for change preview, and per-environment inventory management.
Pipeline Stages
-
lint —
ansible-lintwith custom rules. Catches deprecated modules, missingbecomedirectives, and tasks without names. -
syntax-check —
ansible-playbook --syntax-checkagainst all playbooks. Verifies variable references, role dependencies, and task structure. -
molecule-test —
molecule testruns playbooks against Docker or Vagrant instances. Verifies idempotency: second run produces zero changes. Tests both Debian and RHEL family targets. -
diff-plan —
ansible-playbook --diff --checkagainst staging. Shows exactly what would change without applying. Output posted as PR comment for review. - deploy-staging — Full playbook run against staging inventory. Post-run verification playbook validates service health, port connectivity, and configuration file contents.
-
deploy-prod — Manual approval gate. Serial execution:
serial: 1for rolling updates. Health check between each host. Automatic stop on first failure to prevent cascading bad configuration.
Security Gates
-
Ansible Vault for secrets — All credentials encrypted with
ansible-vault encrypt. Vault password injected from CI secret store at runtime, never committed to the repository. - SSH key rotation — Pipeline uses short-lived SSH certificates from HashiCorp Vault instead of static SSH keys. Certificate TTL: 1 hour.
-
Least-privilege become — Tasks specify
become_userper task, not globally. Only the tasks that need root run as root.
What Breaks First
-
SSH connection timeout to bastions — Long playbook runs exceed the SSH session timeout on jump hosts. Fix: configure
ServerAliveInterval 60andServerAliveCountMax 10in the pipeline's SSH config. -
Idempotency failure from shell tasks —
shell:andcommand:modules always report "changed" even if the command is idempotent. Fix: usecreates:orwhen:conditions to make shell tasks conditional. -
Inventory group variable precedence — A variable defined in
group_vars/allis overridden bygroup_vars/webserversin staging but not production because the host group membership differs. Fix: use explicithost_varsfor environment-specific values and reservegroup_varsfor truly global defaults.