Lesson 12 · Identity, secrets & operations
Terraform ops & Atlantis
How an infrastructure change actually ships — and the capstone that closes the whole track.
Your win: explain how Terraform changes are applied here (Atlantis PR automation, not GitHub Actions), the review/approval gate, and — the finale — how all seven courses stack into one system.
How a Terraform change ships — Atlantis, not CI/CD
Course 5's app deploys were push-based GitHub Actions. Terraform is deliberately
different: the CI workflows skip deployments/terraform/**, and infra
changes flow through Atlantis — Terraform PR automation.1
terragrunt plan -out=$PLANFILE
(:50) then, on comment, terragrunt apply $PLANFILE
(:64). Two gates: apply_requirements: [approved]
(:32) — the PR must be approved — and a team allowlist
"dev:plan, func-platform:unlock, terraform-approvers:apply"
(:135): anyone can plan, but only the
terraform-approvers team can apply. Terraform pinned
1.9.8. Atlantis itself runs as a GSA via Workload Identity (Lesson 9) — of course
it does.
apply, reality can drift from state (a console
click, Lesson 3). The next plan surfaces it — Atlantis will show a diff nobody
intended in the PR. The fix is the same: apply the config back, or import reality.
Same push-based-drift trade-off as Course 5, at the infrastructure layer.
🏛️ The whole track, in one view
This is the last lesson of the last course. Here's how all seven stack — each course is a layer, and this one is the foundation:
| Course | Layer | The one idea |
|---|---|---|
| 1 · Containers | the artifact | an isolated process from an image |
| 2 · Kubernetes | the orchestrator | declared desired state, reconciled |
| 3 · Helm | the generator | one library chart → every object |
| 4 · Istio | the mesh | routing + edge TLS + telemetry (not zero-trust) |
| 5 · CI/CD | delivery | push → tag → cron → build → deploy |
| 6 · Observability | seeing it | metrics alert · traces localize · logs explain |
| 7 · IaC | the foundation | the clusters/networks/identities/keys, as code |
iam.gke.io annotation (L9),
the SOPS + binauthz KMS keys (L10), the VPC + Cloudflare certs + Cloud SQL (L11). And the
recurring characters finally connect: Workload Identity is one IAM binding
reused for pods (C3/C6) and CI (C5); the env×org matrix is one idea expressed
as Helm values (C3), K8s namespaces (C2), CI matrices (C5), and Terragrunt dirs (C6/C7);
declarative desired state is Kubernetes (C2) and Terraform (C7), the same
shape. You didn't learn seven tools — you learned one system, seven layers deep.
Atlantis + the Terraform core workflow
PR-driven plan/apply, and the write/plan/apply discipline this whole course rests on.
→ runatlantis.io — Guide ·
Using Atlantis
→ hashicorp — Core workflow
Check yourself (from memory)
Q1. Terraform changes in this repo are applied by…
terraform/**; Atlantis runs plan
on open and apply on comment, gated by approval.
Q2. Who can run atlantis apply?
apply_requirements: [approved] + team allowlist
(terraform-approvers:apply). Anyone can plan; only approvers apply.
Q3. Infra deploys are gated harder than app deploys because…
terragrunt plan as a comment → review (destroy column!) +
approve → comment atlantis apply → terragrunt apply (state-locked).
GATES (atlantis/production-values.yaml): apply_requirements: [approved]
(:32) + team allowlist terraform-approvers:apply (:135); TF 1.9.8; Atlantis runs as
a GSA via Workload Identity. Gated harder than apps because a bad apply DESTROYS. Drift: reality
≠ state until next apply (like C5). WHOLE TRACK: 1 Containers (artifact) → 2 K8s (orchestrate,
declarative) → 3 Helm (generate) → 4 Istio (mesh) → 5 CI/CD (deliver) → 6 Observability (see) →
7 IaC (FOUNDATION). Recurring: Workload Identity (one binding, pods+CI), env×org (values/ns/
matrix/dirs), declarative desired state (K8s + Terraform). One system, seven layers.1. Atlantis — Guide; in-repo deployments/helm/platforms/atlantis/production-values.yaml:32,50-64,135.