Terraform Fundamentals¶
Declarative infrastructure: desired state, reconciled¶
resource "aws_instance" "web" {
ami = "ami-0abcd1234"
instance_type = "t3.micro"
tags = {
Name = "web-server"
}
}
This block declares what should exist, not the steps to create
it — the same declarative model as a Kubernetes Deployment's spec.
Terraform's job is to compare this desired state against what it
believes actually exists (tracked in the state file),
compute the difference, and make the minimum set of API calls needed
to close that gap. This is the same
reconciliation idea already covered for Kubernetes —
compare desired vs. actual, act on the difference — just run on-demand
(terraform plan/apply) instead of continuously in a background
loop.
The plan/apply cycle¶
terraform plan is deliberately a read-only, side-effect-free
step — it computes and displays the diff without changing anything,
specifically so a human (or a CI pipeline) can review exactly what
would happen before anything real is created, modified, or destroyed.
terraform apply executes that plan, and — critically — updates the
state file to match afterward, so the next plan compares against an
accurate picture of what now exists.
Providers: the plugins that talk to real APIs¶
Terraform's core has no built-in knowledge of AWS, GCP, or Kubernetes
— every resource type is implemented by a provider plugin, which
translates a resource block into actual API calls (create an EC2
instance, create a GKE cluster, apply a Kubernetes manifest) and knows
how to read back that resource's current attributes for future plans.
This plugin architecture is why the exact same core workflow
(plan/apply, state, modules) works identically whether the resources
being managed are AWS infrastructure, Kubernetes objects, or a SaaS
product's API-managed settings — the provider is what's different, the
core mechanics aren't.
Common pitfall¶
Manually changing a Terraform-managed resource through a cloud
console — resizing an instance, adding a tag, adjusting a
security-group rule directly in the AWS console — creates drift:
the real infrastructure no longer matches what the state file
believes. The next plan either shows a confusing diff (Terraform
wants to "fix" the console change back to the declared config,
undoing a change someone made for a real reason) or, worse, apply
silently reverts it without anyone realizing that was about to happen.
Any change to Terraform-managed infrastructure should go through
Terraform — editing the HCL and running plan/apply — specifically
so the state file and reality never diverge in the first place. See
State Management for what to do once drift has
already happened.