This document outlines the steps to move existing terraform resources to different remote states.
Reference: https://medium.com/@lynnlin827/moving-terraform-resources-states-from-one-remote-state-to-another-c76f8b76a996
Steps
1. Move Terraform files to the new folder
2. Run make plan to get a list of resources that would be deleted
sample to generate desired commands used for next step
1 | terraform plan | grep '\s-\s' | sed -e 's/\s-\s//g' | awk '{print "terraform state mv -state-out=monitoring/.terraform/terraform.tfstate "$1,$1}' |
3. Ran commands bellow to move
1 | cd infrastructure |
4. Push remote state in new folder
1 | cd monitoring |
As in the company we use Makefile
to chain several steps together, so remember to push the remote state before run make plan
(otherwise the tfstate will be deleted):
1 | clean: |
5. Check by make plan
Example of a terraform plan
from infrastructure/monitoring
folder to confirm that nothing has changed
1 | If you ever set or change modules or backend configuration for Terraform, |
terraform plan
from main folder
1 | aws_alb_listener.main: Refreshing state... (ID: arn:aws:elasticloadbalancing:us-west-2:...tion/22124b66b571c93f/1553846d70106854) |
6. Recovery in case ruin the remote state
For Step 4, if ran make plan
before pushing the remote state in new folder, the dedicated remote state file will be deleted, and the make plan output will show that the new resources would be created.
So for recovery, there’re two places that can give some hints.
Local terraform backup
Terraform usually creates a backup file under .terraform/
(after run terraform state mv
command in Step 3)
1 | -rw-r--r-- 1 davidlu 329622 May 5 10:46 terraform.tfstate.1588632389.backup |
S3 bucket (recommend)
We can still restore an older remote state version from S3
Steps:
Download original older remote state file from S3 (e.g.
production-terraform/datastores/production
)Extract the related resources (e.g. blaze)
- Search the keyword and copy & paste
- The above process can be tedious and error-prone: introduce gron here - would be helpful for double-check (can make JSON greppable and turn filtered data back into JSON)
1 | e.g. |
- Tweak config to match
- Base the previous steps, we’ve got the remote state file in new folder, something like this:
1 | { |
- Download remote state file for new folder (e.g.
production-terraform/datastores/services/blaze
)
1 | { |
- Make sure has the same lineage, and higher version of serial (compared with destination in S3)
Differing lineage: The “lineage” is a unique ID assigned to a state when it is created. If a lineage is different, then it means the states were created at different times and its very likely you’re modifying a different state. Terraform will not allow this.
Higher serial: Every state has a monotonically increasing “serial” number. If the destination state has a higher serial, Terraform will not allow you to write it since it means that changes have occurred since the state you’re attempting to write.
Ref: https://www.terraform.io/docs/backends/state.html
- Upload new tfstate file to S3
1 | e.g. |
- Run
terraform plan
in new folder (no changes expected)