Git, CI/CD & GitOpsCVIII · Infrastructure-as-Code IntegrationAnsible
Ansible in the pipeline — the role, the limits, the dry-run
What you'll learn
- Place Ansible at the host-configuration layer of the IaC model
- Explain why idempotent execution is not the same as plan-then-apply
- Use ansible-playbook --check as a CI gate
- Recognise the cases where Ansible is the wrong tool in a modern pipeline
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
Ansible belongs at the host-configuration layer of the IaC model. It runs after Terraform has provisioned a host and before the orchestrator has work to do. Its posture is idempotent execution over a fleet: run the same playbook twice and the world should look the same as after the first run. This posture is useful, but it is not the same as Terraform’s plan-then-apply or Kubernetes’s reconcile-loop, and conflating them is a recurring source of pipeline confusion.
Where Ansible sits in the flow
flowchart LR
A["Git commit of playbook"] --> B["ansible-lint"]
B --> C["ansible-playbook --check"]
C --> D["ansible-playbook with diff mode"]
D --> E["Inventory and credentials"]
E --> F["Apply against target hosts"]
F --> G["Callback and audit log"]
Three properties of this flow are worth pulling out:
- The dry-run is not the artefact.
ansible-playbook --checkreports what would change; it does not produce a serialised change set. The apply re-derives intent at run time. This is the architectural difference from Terraform. - Lint and check are CI gates. They run on every pull request. The apply runs after merge, against a real inventory, with real credentials.
- Inventory and credentials are not in the playbook. The playbook describes intent; the inventory says which hosts; the credentials say who may apply. All three live in different places and join at run time.
The dry-run gate
The CI gate for Ansible is ansible-playbook --check:
ansible-playbook --check playbook.yml
In check mode, Ansible reports what it would change without
making the change. Tasks that support it report changed or
ok per host; tasks that do not are skipped. A --check run that
reports no changes is a strong signal that the hosts already match
the playbook’s desired state.
ansible-playbook --check --diff playbook.yml
Adding --diff makes the change visible: file edits as unified
diffs, package installs as version transitions, service state
as before-and-after. --check --diff is the closest Ansible
comes to Terraform’s plan output, but the apply still
re-derives intent at run time. The check is a gate, not an
artefact.
The limits
Ansible is the wrong tool in three recurring cases:
- Declarative workload orchestration. When the desired state
is a set of pods, services, and replicas, the right tool is
Kubernetes with a GitOps controller. Ansible can call
kubectl apply, but at that point it is an imperative wrapper that has lost the reconcile-loop. - Cloud resource provisioning. When the desired state is a VPC, subnet, or IAM role, the right tool is Terraform. Ansible collections exist but model cloud APIs imperatively.
- Immutable image construction. When the desired state is a base image with packages baked in, the right tool is Packer (or Dockerfile). Ansible can run inside a Packer build, but Packer is producing the artefact.
The pipeline is the right place to sequence these tools. Ansible
runs against the host Terraform provisioned; the host image is
baked by Packer; the workload is declared in Kubernetes.
Wrong-tool Ansible shows up as a playbook wrapping a cloud call,
calling kubectl apply, or building a Docker image.
Production discipline
The production framing of Ansible in a pipeline has three rules:
- Lint, check, diff, apply - in that order. A CI job that
skips
ansible-lintand--checkships untested configuration. The same gate sequence runs on every PR. - The inventory is per-environment. Staging and production inventories are different files, both in the repository, both reviewed, both with their own credential scope.
- AWX or Automation Controller is the production entry point. The controller brokers credentials, records audit logs, schedules runs, and gates approvals.
Cross-course references
- Ansible for Production Sysadmins - Parts XXXVII-XL (RepoArch) cover the playbook, inventory, and credentials layout this lesson assumes.
- Terraform for Production Sysadmins - Parts IX-XII (State) cover the Terraform-to-Ansible handoff.
- Containers for Production Sysadmins - Parts IV-VI (Immutability) cover baking hosts with Packer.
- Observability for Production Sysadmins - Parts XV-XVIII (Audit) cover the AWX callback and audit log.
Quiz
Knowledge check · 4 questions
Q1. What does `ansible-playbook --check playbook.yml` do in a CI pipeline?
Q2. Ansible is the right tool to declaratively manage a Kubernetes cluster's workload set in a CI/CD pipeline.
Q3. Which of the following is a real architectural limitation of Ansible in a CI/CD pipeline?
Q4. Diagnose a pipeline that runs Ansible without check mode and applies directly from a developer's laptop.
A team runs Ansible directly from a developer's laptop using a personal SSH key. The playbook manages 30 production hosts and was last edited six months ago. Last week, a task that does not declare itself idempotent ran twice on a host and added the same line to /etc/hosts twice, producing a duplicate entry that broke a service mesh sidecar.
Passing score: 75%. Answers are checked in this browser.