Lesson 3 · Terraform fundamentals
State
Terraform's memory of the real world — the file that makes plan/apply possible, and the one you must not lose.
Your win: explain what Terraform state is and why it's the source of truth, why it must be remote and locked for a team, and what drift is — using this repo's GCS backend.
Why Terraform needs to remember
When you run plan, Terraform compares three things: your config
(desired), the real infrastructure (actual), and its state —
its own record of what it created last time.1 Without
state, Terraform couldn't tell "create a new bucket" from "this bucket already exists, leave it"
— every apply would try to recreate everything. State is Terraform's memory, and its
source of truth for the diff.
Remote state — one shared truth
A local terraform.tfstate file works for one person. A team (and an automation
like Atlantis) needs remote state: a shared backend — here a
GCS bucket — so everyone diffs against the same truth, with versioning and
encryption.2
remote_state block: backend = "gcs", bucket
manabie-terraform-state-2 (default, per-env-overridable to e.g.
manabie-staging-terraform-state), and a per-component prefix
path_relative_to_include(). Because it's in the Terragrunt root, every
leaf inherits it — each component (each env×org cell's GKE, apps, etc.) gets its own
isolated state path in the shared bucket. So a mistake in one cell's state can't corrupt
another's.
Locking & drift
apply the same state simultaneously, they'd race and corrupt it.
The GCS backend locks automatically — it takes a lock object before writing,
so the second apply waits. (No separate lock database needed, unlike some AWS setups.) It's
the reason Atlantis (Lesson 12) also locks state during a PR's plan/apply.
terraform plan detects it (it'll show a diff you didn't cause), and you
reconcile by either applying the config back (revert the manual change) or
importing reality into state. This is the IaC version of the "push-based drift"
idea from Course 5 — infrastructure only matches code as of the last apply.
Terraform — State, the GCS backend & drift
Why state exists, remote state + locking, and detecting/managing drift.
→ hashicorp — State ·
Backend: gcs
→ hashicorp — Manage resource drift
Check yourself (from memory)
Q1. Terraform state is…
plan diffs against —
config vs real infra vs state. Lose it and Terraform forgets what it owns.
Q2. Remote state (in GCS) is needed so that…
Q3. Drift is detected by…
plan
surfaces it. Reconcile via apply or import.
plan diffs (config vs real infra vs state). Without it, every apply recreates
everything. PRECIOUS: maps config→real IDs, can hold SECRETS; lose it → Terraform forgets what
it owns. REMOTE STATE (backend = GCS here) → a team + Atlantis share one truth, versioned +
encrypted; local tfstate doesn't scale. LOCKING: GCS backend locks AUTOMATICALLY (lock object)
→ no concurrent-apply corruption. DRIFT = reality ≠ state (a console click); plan
detects it, reconcile via apply (revert) or import (adopt). REPO:
root.hcl:11-23 gcs backend, bucket manabie-terraform-state-2,
per-component prefix path_relative_to_include() = isolated state per cell/component.terraform import adopts existing infra, or why secrets in state
argue for encrypting the bucket? Ask me.