Manage resources in Terraform state
Terraform stores information about your infrastructure in a state file. This state file keeps track of resources created by your configuration and maps them to real-world resources.
Terraform compares your configuration with the state file and your existing
infrastructure to create plans and make changes to your infrastructure. When you
run terraform apply
or terraform destroy
against your initialized
configuration, Terraform writes metadata about your configuration to the state
file and updates your infrastructure resources accordingly. Occasionally,
you may need to manipulate your projects state outside of the standard
workflow. For example, you may want to remove a resource from your project
without destroying the real-world resource associated with it.
In this tutorial, you will create an AWS instance and security group, examine your project's state file, and use Terraform to remove infrastructure from your project's state.
Prerequisites
This tutorial assumes that you are familiar with the usual Terraform plan/apply workflow. If you are new to Terraform, refer first to the Getting Started tutorial.
For this tutorial, you will need:
- The Terraform CLI 1.7+ installed locally
- An AWS account
- The AWS CLI installed
- Your AWS credentials configured locally with your access keys and a default region.
Note
This tutorial will provision resources that qualify under the AWS free-tier. If your account doesn't qualify under the AWS free-tier, we're not responsible for any charges that you may incur.
Create infrastructure and state
Clone the Learn Terraform State Management repository.
Change into the new directory.
Review the main.tf
file. This configuration deploys an Ubuntu EC2 instance publicly accessible on port 8080.
This configuration uses the AWS provider to create an EC2 instance and a security group that allows public access.
Initialize the directory.
After Terraform initializes, apply the configuration and approve the run by
typing yes
at the prompt.
Examine the state file
Now that you have applied this configuration, you have a local state file that
tracks the resources Terraform created. Check your directory to confirm the
terraform.tfstate
file exists.
You should not manually change information in your state file in a real-world
situation to avoid unnecessary drift between your Terraform configuration,
state, and infrastructure. Any change in state could result in your
infrastructure being destroyed and recreated at your next terraform apply
.
Warning
Do not manually modify state files.
Open the terraform.tfstate
file in your file editor.
This example contains few resources, so your actual state file is relatively small.
This file is the JSON encoded state that Terraform writes and reads at each operation. The first stanza contains information about your Terraform application.
Explore resources
in state
The resources
section of the state file contains the schema for any resources
you create in Terraform. Review the resources
section of this file.
The first key in this schema is the mode
. Mode refers to the type of resource
Terraform creates — either a resource (managed
) or a data source (data
). The
type
key refers to the resource type - in this case, the aws_ami
type is a
resource available in the aws
provider.
##FIXME
The aws_instance
type is a managed
resource with the AMI from the data.aws_ami
source.
The instances
section in this resource contains the attributes
of the resource. The security_groups
attribute, for example, is captured in plain text in state as opposed to the variable interpolated string in the configuration file.
Terraform also marks dependencies between resources in state with the built-in dependency tree logic.
Because your state file has a record of your dependencies, enforced by you with a depends_on
attribute or by Terraform automatically, any changes to the dependencies will force a change to the dependent resource.
Examine State with CLI
The Terraform CLI allows you to review resources in the state file without interacting with the .tfstate
file itself. This is how you should interact with your state.
Run terraform show
to get a human-friendly output of the resources contained in your state.
Run terraform state list
to get the list of resource names and local identifiers in your state file. This command is useful for more complex configurations where you need to find a specific resource without parsing state with terraform show
.
Replace a resource with CLI
Terraform usually only updates your infrastructure if it does not match your configuration. You can use the -replace
flag for terraform plan
and terraform apply
operations to safely recreate resources in your environment even if you have not edited the configuration, which can be useful in cases of system malfunction. Replacing a resource is also useful in cases where a user manually changes a setting on a resource or when you need to update a provisioning script. This allows you to rebuild specific resources and avoid a full terraform destroy
operation on your configuration. The -replace
flag allows you to target specific resources and avoid destroying all the resources in your workspace just to fix one of them.
In older versions of Terraform, you may have used the terraform taint
command
to achieve a similar outcome. That command has now been deprecated in favor of
the -replace
flag, which allows for a simpler, less error-prone workflow. If
you are using an older version of Terraform, consider upgrading or review the
taint
documentation
for more information.
Tip
The -replace
flag was introduced in Terraform 0.15.2. Ensure you are using the correct version of Terraform for this next step.
Run terraform plan -replace="aws_instance.example"
to see the actions Terraform would take if you replaced the instance.
As shown in the output, when you apply this change, Terraform will destroy your running instance and create a new one.
Run terraform apply
with the -replace
flag to force Terraform to destroy and
recreate the resource. Type yes
when prompted to accept this update.
Using the terraform apply
command with the -replace
flag is the
HashiCorp-recommended process for managing resources without manually editing
your state file.
Move a resource to a different state file
Some of the Terraform state subcommands are useful in very specific situations. HashiCorp recommends only performing these advanced operations as the last resort.
The terraform state mv
command moves resources from one state file to another.
You can also rename resources with mv
. The move command will update the
resource in state, but not in your configuration file. Moving resources is
useful when you want to combine modules or resources from other states, but do
not want to destroy and recreate the infrastructure.
The new_state
subdirectory contains a new Terraform configuration. This
configuration creates a new EC2 instance named aws_instance.example_new
and
uses a data resource to use the same security group from your root configuration
file. Change into the subdirectory.
Run terraform init
.
Apply your configuration. Respond to the confirmation prompt with a yes
.
Now, you have a second state file with a managed resource and a data source.
Move the new EC2 instance resource you just created, aws_instance.example_new
, to the old configuration's file in the directory above your current location, as specified with the -state-out
flag. Set the destination name to the same name, since in this case there is no resource with the same name in the target state file.
Note
Resource names must be unique to the intended state file. The terraform state mv
command can also rename resources to make them unique.
Change into your root directory.
Run terraform state list
to confirm that the new EC2 instance, aws_instance.example_new
, is present in the in original configuration's state file.
Without adding the EC2 resource you moved to your configuration files, create a Terraform plan. Because the new EC2 instance is present in state but not in the configuration, Terraform plans to destroy the moved instance, and remove the resource from the state file.
Open the main.tf
file in your root directory. Copy and paste the resource definition below.
Apply your configuration. Your configuration now matches your state file and Terraform will not perform any changes.
Change into your new_state
directory.
Run terraform destroy
and you should have no resources to destroy. Your security_group
resource is a data source and you moved the aws_instance
resource to another state file. Accept the changes by typing yes
when prompted.
Remove a resource from state
Use a removed
block to remove specific resources from your state. This does
not destroy the infrastructure itself, instead it indicates that your Terraform configuration
will no longer manage the resource.
Change into your root directory.
Remove the aws_instance.example_new
from your project's state.
Comment out the entire resource "aws_instance" "example_new"
block from
main.tf
and add a removed
block to instruct Terraform to remove the resource
from state, but not destroy it.
Tip
The removed
block was introduced in Terraform 1.7. Previous versions of
Terraform used the terraform state rm
command to remove resources from state.
Ensure you are using the correct version of Terraform for this step.
Apply your configuration. Before you remove the new instance from your state, make a note of the value of the instance's id field. You will use this value later in this tutorial to re-import the instance.
Respond to the confirmation prompt with a yes
to remove
aws_instance.example_new
from your project's state.
Confirm the change by reviewing the state with terraform state list
.
The aws_instance.example_new
resource does not exist in your project's state,
but the resource still exists in your AWS account.
Import the instance back into your project. First, uncomment the
aws_instance.example_new
block, and comment out the removed
block you added
in the previous step.
Run terraform import
to bring this instance back into your state file. Replace
<INSTANCE_ID>
with the id of the aws_instance.example_new
resource from the
output of the last step.
Tip
This tutorial uses terraform import
to bring infrastructure under Terraform
management. Terraform 1.5+ supports configuration-driven
import, which lets you import multiple resources at
once, review the import in your plan-and-apply workflow, and generate
configuration for imported resources. Review the import
tutorial to learn more.
Refresh modified infrastructure
The terraform refresh
command updates the state file when physical resources change outside of the Terraform workflow.
Delete the original EC2 instance from your AWS account using the AWS CLI or the AWS Console. It may take a few moments for AWS to destroy your instance.
By deleting this instance, you have created a difference between your state and the real-world resources mapped to it. The state file no longer reflects the reality of your environment. It may take up to five minutes for AWS to destroy your instance.
Run the terraform refresh
command to update your state file.
Run terraform state list
to confirm Terraform deleted the original aws_instance.example
resource from state.
Your state file now reflects reality. You deleted the aws_instance.example
and the terraform refresh
command removed it from state.
The terraform refresh
command does not update your configuration file. Run terraform plan
to review the proposed infrastructure updates.
Remove the original aws_instance.example
resource from main.tf
.
Open outputs.tf
and remove the output values that reference the instance.
Apply the configuration, which will confirm that your configuration matches your
state file, and remove their outputs from state. Accept the changes by typing
yes
when prompted.
Notice that Terraform changed the outputs and did not destroy any infrastructure.
Note
Terraform automatically performs a refresh
during the plan
, apply
, and destroy
operations. All of these commands will reconcile state by default, and have the potential to modify your state file.
Destroy your infrastructure
Terraform also updates your state file when you run a terraform destroy
operation.
Destroy your infrastructure. Accept the changes by typing yes
when prompted.
Your terraform.tfstate
file still exists, but does not contain any resources.
Run terraform show
to confirm.
Open the terraform.tfstate
file in your file editor. The empty resources
attribute confirms Terraform destroyed all your previous resources.
Next steps
In this tutorial, you created an EC2 Ubuntu instance and corresponding security group. Then, you examined your local state file and used terraform state
to move, remove, and modify your resources across multiple configurations.
For more information about Terraform state, review the following documentation: