I have the unenviable task of getting our current Terraform codebase upgraded from 0.12 to 1.x and I’m struggling to find a workable strategy for the project.
The problem I have is that the original code is split by resource type so there’s terraform for EC2, terraform for Fargate, terraform for IAM, etc. instead of code per project.
This means that any single project might use multiple terraform ‘pieces’ to make the whole product.
As a result, there are many state files being used as data sources in each piece and we have lots of coupling between each piece
This makes upgrading Terraform a nightmare as upgrading a single piece will change the state file and I don’t think the pieces still using 0.12 will be able to read a 1.x state file as a data source.
Does anyone have any ideas on how I can approach this? It’s making my brain melt!
I think the most significant “hazard” on the path from v0.12 to v1.x is the v0.13 change to how Terraform records which resources belong to which providers: v0.13 introduced a heirarchical namespace for providers which means that e.g. what Terraform v0.12 calls just
aws is now called
registry.terraform.io/hashicorp/aws when recorded in the state, to differentiate it from possible other “aws” providers that might exist in other namespaces.
Terraform v0.13 knows how to parse a state snapshot containing the old v0.12 provider address format, and will initially load it into memory as a special “legacy provider address” which the UI tends to present using a special placeholder syntax like
- here is representing “unknown namespace”.
The first time you apply a plan with Terraform v0.13 it will use information from the configuration to determine which namespace each of your providers is supposed to belong to and then the new state snapshot will use the modern address syntax, which is incompatible with Terraform v0.12’s state snapshot parser. Terraform v0.14 and later cannot consume a Terraform v0.12 state snapshot, so applying at least once with Terraform v0.13 is a crucial upgrade step.
With all of that said then, I have the following recommendations for your case:
Focus on getting from Terraform v0.12 to v0.13 first. This is likely to be the most annoying step because of the significant state format change, so better to deal with that in isolation without bringing any other changes into the mix.
Try to avoid upgrading any providers at the same time as you upgrade to Terraform v0.13, because that will minimize the risk of provider schema changes causing extra churn in your state snapshots at the same time as you are trying to update to the v0.13 state snapshot format.
Take a “leaf-inwards” approach to upgrading: start by upgrading the configurations which only consume remote state, where no other configuration depends on their state, because creating new state snapshots for those will not affect anything outside of their scope, and the leaf ones should keep working because Terraform v0.13 can parse a Terraform v0.12 state snapshot.
Once you’ve dealt with that first layer, identify the next set where all of the dependents are already using Terraform v0.13 and upgrade those. Continue in this way until you’ve worked your way up to the root of the dependency graph, where the last to be upgraded will be the ones that don’t contain any
data "terraform_remote_state" blocks at all.
While you work on the upgrading you will probably need to make some changes to your configurations to configure explicit provider source locations. The
terraform 0.13upgrade command in Terraform v0.13 knows how to generate these for any providers that Terraform v0.12 was able to install automatically, so you can rely on that unless you have some local providers that you installed manually. If you do have locally-installed providers, you can see more information on how to deal with those in the upgrade guide.
Once you’ve got everything on v0.13, the rest of the upgrade path is typically relatively straightforward:
As mentioned in the v1.0 upgrade guide, I recommend that you first try to at least run
terraform init and
terraform plan across all of your configurations with Terraform v0.14 before proceeding further, just because that will catch anything you missed during the v0.13 upgrade process and confirm that all of your state snapshots are ready to be consumed by Terraform v0.14.
Once you’ve seen at least planning work with
v0.14 you can probably skip directly to the latest v1.x release, which is v1.3 at the time I’m writing this. You don’t need to coordinate the ordering of these so tightly because the state snapshot format didn’t change so significantly in subsequent versions, but I would still try for the “leaf-inwards” ordering if possible just because that’s the least risky option.
I still recommend reading through all of the intervening upgrade guides because there are some caveats that apply in a few rare situations, but if none of that content seems to apply to you then it’s reasonable to just try skipping directly from v0.14 to v1.3 without any other pit stops.
I hope that helps! I’m happy to try to answer follow-up questions if you have them.
This is amazingly detailed. Thank you so much
Really appreciate your earlier reply. We actually have similar requirements. There are about 2000 terraform configs in my org which need to be upgraded from TF v0.12 to TF v1.x. We have following questions:
Based on terraform upgrade guide, we are aware that it’s recommended to make sure terraform plan shows no proposed changes during upgrade. However, it’s really difficult for us to guarantee that considering the number of configs we have. What are the potential errors/unknowns if we have proposed changes in terraform plan?
We are planning to do this: having 2 terraform plans, one with old version terraform CLI, second with new version terraform CLI. If those 2 plans show same changes, then we know it should be ok to upgrade. Do you think this make sense? Any concerns on that?