Infrastructure as Code (IaC) means defining servers, networks, databases, and permissions in files you can review, test, and roll back—instead of clicking through a console and hoping every environment matches. Terraform is one of the most widely used IaC tools: you declare what should exist, and Terraform figures out how to create or change resources through provider plugins.
This chapter is the first in the Terraform series. It stays at the conceptual level; hands-on steps on Google Cloud come next in Getting started with Terraform on Google Cloud.
What problem IaC solves
Manual provisioning does not scale with team size or release cadence. A staging VPC that was cloned from production six months ago may still differ in firewall rules, service accounts, or region settings. IaC makes the desired shape of infrastructure explicit: the same configuration can drive development, staging, and production with different variable values.
Version control applies to infrastructure the same way it applies to application code. Pull requests show diffs of CIDR blocks, IAM bindings, and instance types before anyone runs terraform apply. Rollback is a revert plus a planned apply, not a scramble to remember which console changes were made on a Friday night.
Declarative versus imperative
Imperative tools expect a sequence of steps: create a network, then a subnet, then attach a firewall rule. Declarative tools expect a target end state: here is the network, subnet, and rule; reconcile reality to match.
Terraform is declarative. You write HashiCorp Configuration Language (HCL) describing resources and their relationships; Terraform builds a dependency graph, compares the graph to state (what it believes already exists), and produces a plan of creates, updates, and deletes. You do not script API call order yourself—the references between resources imply order.
Configuration management tools such as Ansible often configure software on machines that already exist. Terraform typically provisions cloud objects (VMs, buckets, load balancers). Many teams use both: Terraform for the platform, Ansible or cloud-init for packages and daemons inside VMs.
Core components
Terraform CLI — The terraform binary runs init, plan, apply, and other commands. It reads your .tf files, talks to backends for state, and invokes provider plugins.
Configuration — .tf files in HCL (or .tf.json) define providers, resources, variables, and outputs. Syntax and block types are covered in HCL structure in Terraform.
Providers — Plugins that implement the mapping between HCL resource types and cloud APIs. For Google Cloud you use the hashicorp/google provider; each resource type (for example google_storage_bucket) is implemented inside that plugin.
State — Terraform stores a snapshot of resource IDs and attributes so the next plan knows what it manages. Local state lives in terraform.tfstate; teams usually store state remotely (for example in a GCS bucket). State is easy to get wrong if committed to git or edited by hand—see State data in Terraform.
Lock file — After terraform init, .terraform.lock.hcl records exact provider versions, similar in spirit to a lockfile in npm or pnpm. Commit it so every machine and CI job uses the same provider builds.
The workflow
The day-to-day loop looks like this:
flowchart LR write[Write HCL] --> init[terraform init] init --> plan[terraform plan] plan --> apply[terraform apply] apply --> write
- Write — Edit configuration to match the infrastructure you want.
- Init —
terraform initdownloads providers, configures the backend, and prepares the.terraform/directory. Run it again when providers, modules, or backend settings change. - Plan —
terraform planshows proposed changes without applying them. Review the plan before production changes. - Apply —
terraform applyexecutes the plan (or prompts you to confirm). Resources are created or updated through the provider APIs. - Destroy —
terraform destroy(orterraform apply -destroy) removes all resources tracked in state for that configuration. Use with care in shared accounts.
Formatting and static checks belong in the loop before plan: Formatting and validating Terraform files describes terraform fmt, terraform validate, and CI patterns.
Initialization and the lock file
terraform init creates the .terraform/ directory (not a single file). That directory holds downloaded provider binaries and module caches. It is safe to delete locally and recreate with another init; do not commit .terraform/ to version control.
.terraform.lock.hcl pins provider version selections and checksums. When a teammate runs init, Terraform installs the same provider versions the lock file specifies, which reduces “works on my laptop” drift.
Authenticating to Google Cloud
The Google provider uses Application Default Credentials (ADC). Common approaches:
| Method | When it fits |
|---|---|
gcloud auth application-default login |
Local development on a workstation with your user credentials |
Service account JSON key via GOOGLE_APPLICATION_CREDENTIALS |
CI or legacy automation (prefer workload identity over long-lived keys when possible) |
| Service account impersonation | Your user or a CI identity assumes a dedicated Terraform service account with least privilege |
| Workload Identity Federation | GitHub Actions, GitLab CI, or other OIDC issuers authenticate without storing GCP keys in the pipeline |
Set the project explicitly in the provider block or with GOOGLE_PROJECT / GOOGLE_CLOUD_PROJECT. The runbook in the next chapter uses ADC from the Cloud SDK.
Variables at a glance
Input variables parameterize configuration (region, environment name, machine type). Output values export useful attributes after apply (bucket URL, instance IP).
Define variables in variables.tf (or any .tf file); assign values in terraform.tfvars or *.auto.tfvars, not by confusing variables.tf with a tfvars file. When the same variable is set in multiple places, later sources override earlier ones: TF_VAR_* environment variables, then terraform.tfvars, then *.auto.tfvars, then -var and -var-file on the CLI (highest among these). Defaults in the variable block apply only when nothing else sets a value. Details and examples live in HCL structure in Terraform.
Next: Getting started with Terraform on Google Cloud walks through a storage bucket, a small VPC, and a Compute Engine VM.
Check your understanding
Question 1 of 7
0 of 7 checked