lesson ── terraform-beginner ── ~10 мин ── 4 шагов
In real work HCL changes all the time: you add a tag, fix a name, switch the class on a database. Terraform has to figure out what changed and send exactly the API calls the change needs, without deleting and recreating everything along the way.
In this lesson you create a bucket, change its tags, and watch how plan shows the diff. You learn the difference between an update (update-in-place) and a recreate (-/+ replacement).
интерактивный sandbox
Поднимется пара контейнеров: terraform 1.9 и localstack 3.8 в одной сети. В браузере откроется терминал, можно сразу terraform init. Каждый шаг проверяется автоматически. TTL 45 минут, без регистрации.
stack ── terraform · localstack · 1 GB RAM · самоуничтожается через 45 мин простоя
Create the file main.tf:
resource "aws_s3_bucket" "demo" { bucket = "linuxlab-update-${random_id.suffix.hex}" tags = {Owner = "student"
}
}
resource "random_id" "suffix" {byte_length = 4
}
Run:
cd /home/student/tf-update
terraform init -input=false
terraform apply -auto-approve -input=false
After apply, state knows the bucket with one tag, Owner.
If something fails: check init. And that LocalStack is alive.
✓ Bucket created with the tag Owner=student. Now add a second tag.
Open main.tf and change the tags block:
tags = {Owner = "student"
Environment = "learning"
}
Now run plan without apply, and you will see the diff:
terraform plan
The output will contain a block like this:
~ resource "aws_s3_bucket" "demo" { ~ tags = {"Owner" = "student"
+ "Environment" = "learning"
}
}
Plan: 0 to add, 1 to change, 0 to destroy.
The ~ next to resource means update in place. No recreation.
Inside: + "Environment" means the new tag will be added. Owner
has no sign, so it does not change.
See tf-plan on what the signs mean.
If plan shows `-/+ resource ...`: you changed something that cannot be updated without replacement. Revert and change only tags.
✓ Plan showed a ~ change. Apply it: it will update without recreation.
terraform apply -auto-approve
Apply will show:
aws_s3_bucket.demo: Modifying...
aws_s3_bucket.demo: Modifications complete after Xs
Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
The key part: 0 destroyed, 1 changed. The bucket was not recreated. The AWS provider simply sent a PutBucketTagging API request.
The objects inside (if there had been any) stayed where they were.
This is update-in-place. Your job is to structure HCL so that most changes follow this path.
If you get a destroy: something besides tags changed. Check the main fields (bucket, etc): they should not be changing.
✓ Tag updated in place, same bucket.
OpenTofu keeps the CLI and state compatible with Terraform for the
commands in this step: migration usually goes through mv .terraform .terraform.bak; tofu init -upgrade. On a first switch, though, make
a backup of the state and do a run on a feature branch. The
differences cluster in the newer features (variables in backend,
state encryption, OCI registry-backed modules). See
tf-opentofu-parity for the full matrix.
The main Terraform invariant: after apply, a repeated plan = No changes. If it shows changes, something is off (drift, or
ignore_changes skipped something).
Check it:
terraform plan -detailed-exitcode
echo "exit: $?"
It should be exit: 0. If it were 2, that means there is an
inconsistency.
-detailed-exitcode matters for CI: you can alert automatically
on drift.
If plan prints `No changes` in the human-readable text: everything is OK, the exit code will be 0.
✓ Plan is clean. Invariant holds: state == HCL.
Some resource attributes cannot be changed without recreation.
For example, availability_zone on an EC2 instance, instance_class
on some RDS instances, bucket on an S3 bucket. If you change the
bucket name, AWS cannot rename it, only create a new one and
tear down the old one. Terraform shows this in the plan as -/+.
Be careful: the data of a recreated resource is lost.
You saw four kinds of change in a plan: + create, ~ update
in place, -/+ recreate, and the final No changes after apply.
This is the basic grammar of reading plans.
команды
terraform planshow the diff between HCL and stateterraform apply -auto-approveapply the planterraform plan -detailed-exitcodeexit 0 = clean, 2 = there are changesконцепции