Skip to main content
RunBook Academy

Git, CI/CD & GitOpsCVIII · Infrastructure-as-Code IntegrationOverview

The IaC tooling landscape — Terraform, Ansible, Kubernetes, Docker, and the boundaries

Advanced⏱ ~26 mingit

What you'll learn

  • Place Terraform, Ansible, Kubernetes, and Docker on a layered model of infrastructure concerns
  • Identify the boundary between desired-state and imperative execution in each tool
  • Recognise why the four tools have different CI/CD postures
  • Explain why network and OS configuration often fall outside all four

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

Not yet marked complete on this device.

The four infrastructure-as-code tool families that dominate production pipelines are Terraform, Ansible, Kubernetes, and Docker. They look similar from the outside - each has files in a repository, each runs in a pipeline, each produces a change - but they sit at different layers of the stack, model state differently, and integrate with CI/CD in different ways. Treating them as interchangeable is the most common architectural mistake in this part of the course.

The layered model

The four tools cover four distinct concerns. Drawing the layers explicitly is the first step toward a coherent pipeline. Each layer has its own lifecycle, its own state model, and its own place in the delivery chain.

flowchart TB
    subgraph L1["Application layer"]
        D["Docker images and OCI artefacts"]
    end
    subgraph L2["Workload orchestration layer"]
        K["Kubernetes manifests and controllers"]
    end
    subgraph L3["OS and host configuration layer"]
        A["Ansible playbooks and roles"]
    end
    subgraph L4["Cloud and platform resource layer"]
        T["Terraform modules and providers"]
    end
    D --> K
    K --> A
    A --> T
  • Terraform declares cloud and platform resources and talks to the cloud control plane.
  • Ansible describes how a host is configured once it exists and runs commands, files, and services.
  • Kubernetes declares workload shape - pods, services, ingresses, RBAC - on a cluster it manages.
  • Docker produces the artefact a workload runs as. It sits below Kubernetes, not above.

The boundaries

The boundaries are sharp, and the most useful question to ask of any pipeline step is which layer is this step acting on.

  • Terraform does not build images. It cannot run a Dockerfile. When a pipeline calls Docker from inside a Terraform provisioner, it has crossed a boundary the tooling is warning you about.
  • Ansible does not declare desired cluster state. It can call kubectl apply, but at that point it is functioning as an imperative wrapper, not as Ansible.
  • Kubernetes does not configure the host kernel. The node image is built by something else - Packer, cloud-init, Ansible - and Kubernetes only schedules pods onto what already exists.
  • Docker does not provision the cloud. It builds images; what runs them is someone else’s problem.

Why pipelines treat them differently

Each tool has a different CI/CD posture because each tool models change differently. The four postures drive every decision in this part of the course.

  • Terraform is plan-then-apply. The plan is an artefact that lives in the pipeline; the apply consumes it.
  • Ansible is idempotent execution. The same playbook run twice converges to the same state. CI can lint and dry-run.
  • Kubernetes is reconcile-loop. A GitOps controller reads desired state from Git and converges the cluster to it.
  • Docker is deterministic build. Same inputs, same digest out.

These postures determine where the pipeline inserts gating, where human approval lives, and where rollback begins.

Production discipline

The production framing of the tooling landscape has three rules:

  1. Pick the tool by the layer. Cloud resource -> Terraform. Host -> Ansible. Workload -> Kubernetes. Familiarity is a cost-of-change argument, not an architectural one.
  2. Treat the boundaries as load-bearing. When a tool is asked to do another tool’s job, the pipeline loses auditability. Sequence in the pipeline; do not fuse inside a module.
  3. One repo per layer is a sane default. A Terraform repo, an Ansible repo, a Kubernetes repo, and a Docker repo each have their own CI posture. A monorepo is allowed but requires more discipline, not less.

Cross-course references

  • Terraform for Production Sysadmins - Parts V-VIII (Modules) cover the Terraform-specific layer discipline.
  • Ansible for Production Sysadmins - Parts XXI-XXIV (Immutability) cover the case for treating hosts as cattle.
  • Kubernetes for Production Sysadmins - Parts XI-XIV (GitOps controllers) cover the reconcile-loop posture.
  • Containers for Production Sysadmins - Parts VII-X (BuildKit and registries) cover content-addressable caching.

Quiz

Knowledge check · 4 questions

  1. Q1. Which layer does Terraform primarily operate at in a layered IaC architecture?

  2. Q2. A Terraform module can build a Docker image directly without calling out to an external process, and this is the recommended pattern.

  3. Q3. Why do production pipelines treat Terraform, Ansible, Kubernetes, and Docker with different gate semantics?

  4. Q4. Diagnose an architectural mistake in a pipeline that fuses Terraform and Ansible, and prescribe the correction.

    A team has a Terraform module that provisions an EC2 instance and then runs an Ansible playbook inside a `local-exec` provisioner to configure the host. The apply takes 40 minutes, the state file is large, and a junior engineer accidentally committed a change that causes the Ansible run to fail halfway through. The instance is left half-configured, and rolling back means re-running Terraform from scratch.

Passing score: 75%. Answers are checked in this browser.