19

Terraform Plan, State, Modules, and Physical Effects

Follow Terraform from reviewed configuration through state and AWS APIs to real compute, memory, storage, and network effects.

System map · Day 19

Whole-system design

Five stable layers. Today's work is expanded and linked; the rest stays in context.

Product and authority

Covered — People and product entry points · Identity and policy · HelixWorks control plane · Generated application plane

Delivery and desired state

Covered — Git desired state · CI and immutable artifacts · Argo CD reconciliation

Cloud and orchestration

Covered — Kubernetes or EKS control plane

Terraform and AWS APIs

Source-backed today

Turns reviewed modules and variables into a scoped provider plan before any AWS mutation occurs.

Accounts, VPC, DNS, and private paths

Source-backed today

Materializes module choices as VPCs, subnets, routes, interfaces, and addresses in AWS.

Compute and traffic

Covered — Platform service workloads · Generated app workloadsAhead — Ambient mesh data plane

Worker compute

Source-backed today

Materializes capacity choices as EKS-managed EC2 worker CPU and memory.

Storage and evidence

Covered — Cluster desired and live state · Product data and artifacts · Evidence and observability

Infrastructure state

Source-backed today

Binds Terraform addresses to real AWS identities so future plans compare the correct resources.

The enterprise problem and today’s slice

Enterprise problem: A small Terraform edit—Terraform is a stateful Infrastructure as Code (IaC) engine—can replace an Elastic Kubernetes Service (EKS) node group, expose a secret through state, race another operator, or leave paid AWS resources partly changed while HelixWorks remains unavailable. Whole-course context: The incoming evidence assigns one owner to infrastructure, cluster lifecycle, Kubernetes workloads, and GitOps; today examines Terraform as the IaC implementation for the infrastructure boundary. Today’s slice: We connect HashiCorp Configuration Language (HCL), modules, plan, approval, locked remote state, providers, AWS APIs, physical effects, drift, import, and guarded state repair. End-of-day evidence: A dev run binds commit, fresh plan, policy, approval, state version, execution identity, AWS resource IDs, cluster observation, customer probe, denied unsafe change, environment, timestamp, run, and trace IDs. Still unsolved: Separate AWS account foundations and production Identity and Access Management (IAM) guardrails remain deferred.

Customer outcome and implementation focus

The customer outcome is a reviewable terraform plan, state, modules, and physical effects change, not a collection of requirements. This day starts with the implementation boundary, then uses the command or manifest below to produce positive, denied, and recovery evidence.

Components in focus

Terraform CLI/modules, remote-state backend, and AWS provider APIs; VPC, EKS, nodes, disks, and network hardware; versioned state object storage/lock table; cache: not involved.

This map names the implementation boundary for this day. The service or controller changes only the state it owns; runtime and audit evidence let the operator distinguish a declared change from an effective one.

Trace Terraform declarations into physical resources

Trace HCL to physical reality

Changing a node-group shape is not merely editing text: the provider may replace virtual machines, drain pods, allocate memory, and move network traffic. Review the plan for these effects before execution.

module "environment" {
  source              = "../../modules/environment"
  environment         = "dev"
  expected_account_id = var.account_id
  deployer_role_arn   = var.deployer_role_arn
  monthly_budget_usd  = 250
  region              = var.region
  vpc_cidr            = "10.10.0.0/16"
  kubernetes_version  = var.kubernetes_version
  node_instance_types = ["m7i.large"]
  node_min_size       = 2
  node_max_size       = 5
  deletion_protection = false
}

Repair state only after proving reality

terraform state rm does not delete AWS infrastructure; it only removes Terraform’s mapping and can therefore orphan a live resource. Inspect exact identity first, back up versioned state, and prefer import when the resource exists.

: "${AWS_PROFILE:?set the approved AWS profile}" "${AWS_REGION:?set the intended AWS region}" "${EXPECTED_ACCOUNT_ID:?set the intended 12-digit AWS account}"
actual_account="$(aws --profile "$AWS_PROFILE" --region "$AWS_REGION" sts get-caller-identity --query Account --output text)"
[ "$actual_account" = "$EXPECTED_ACCOUNT_ID" ] || { echo "AWS account mismatch" >&2; exit 1; }
terraform -chdir=infra/stacks/dev state show 'module.environment.aws_eks_cluster.this'
aws --profile "$AWS_PROFILE" --region "$AWS_REGION" eks describe-cluster --name helixworks-forge-dev --region eu-west-2
terraform -chdir=infra/stacks/dev plan -out=verified.tfplan

Do not run a removal command from this lesson. The guarded decision is: if AWS returns the exact expected resource, refresh or import; if independent account-and-region inventory proves it absent, use the approved repair workflow, then re-plan and verify the recreated or adopted identity.

Key takeaways

Terraform connects configuration to physical resources through a reviewed plan, state mapping, provider, and observable AWS effects.

  • State is sensitive durable mapping, not the infrastructure itself.
  • Modules reuse design while separate roots preserve environment isolation.
  • State surgery is last-resort record repair after exact independent inspection.

Checklist

An apply is complete only when its real effects and customer outcome are known.

  • [ ] Plan is fresh, saved, policy-checked, and approved by checksum
  • [ ] Backend is encrypted, locked, versioned, and environment-scoped
  • [ ] Review names replacement, capacity, cost, and availability effects
  • [ ] AWS, Kubernetes, customer, negative, and unaffected evidence are recorded