← Recipes

阅读中文版本

Version Terraform Modules Properly

Tag module releases, pin module sources to exact versions, keep inputs documented, and use a lock file so plans are reproducible.

~35 minterraformiacreliability

Task

Adopt versioned Terraform modules with pinned sources and a committed lock file.

When to use this

Modules are referenced by a moving branch, so a change upstream silently alters an environment on the next apply and plans are not reproducible.

Prerequisites

  • Terraform 0.14+ for dependency lock files
  • A registry or Git repo for modules

Steps

1. Tag module releases semantically and reference exact tags.

Expected output: A given config always uses the same module code.

2. Commit the dependency lock file.

Expected output: Providers and modules resolve reproducibly.

3. Document inputs and outputs and validate with terraform-docs or validate.

Expected output: Consumers know the contract.

4. Test plans in a staging workspace before applying to production.

terraform init -upgrade && terraform providers lock

Expected output: Changes are seen before they land.

Troubleshooting

Problem

Upgrade unexpectedly changes resources

Solution

Pin to an exact tag and upgrade deliberately with a reviewed plan, not by tracking a branch.

Problem

Lock file not committed

Solution

Commit .terraform.lock.hcl; without it each machine may pick different provider versions.

Limitations

  • Pinning modules means upgrades are manual and can lag behind security fixes if not scheduled.
  • Lock files are platform-sensitive; teams on mixed OSes should use the providers lock command.

Context

Adopt versioned Terraform modules with pinned sources and a committed lock file. Modules are referenced by a moving branch, so a change upstream silently alters an environment on the next apply and plans are not reproducible.

Steps

  1. Tag module releases semantically and reference exact tags. Expected: A given config always uses the same module code.
  2. Commit the dependency lock file. Expected: Providers and modules resolve reproducibly.
  3. Document inputs and outputs and validate with terraform-docs or validate. Expected: Consumers know the contract.
  4. Test plans in a staging workspace before applying to production. Expected: Changes are seen before they land.
module "network" {
  source  = "git::https://github.com/acme/network.git?ref=v2.3.1"
  cidr    = var.cidr
}
# commit .terraform.lock.hcl
terraform providers lock -platform=linux_amd64 -platform=darwin_arm64

Verify

  • A given config always uses the same module code.
  • Providers and modules resolve reproducibly.
  • Consumers know the contract.
  • Changes are seen before they land.

Limits

  • Pinning modules means upgrades are manual and can lag behind security fixes if not scheduled.
  • Lock files are platform-sensitive; teams on mixed OSes should use the providers lock command.