Manage resource drift
The Terraform state file is a record of all resources Terraform manages. You should not make manual changes to resources controlled by Terraform, because the state file will be out of sync, or "drift," from the real infrastructure. If your state and configuration do not match your infrastructure, Terraform will attempt to reconcile your infrastructure, which may unintentionally destroy or recreate resources.
In this tutorial, you will detect and fix differences between your state file and real infrastructure. First, you will create an EC2 instance and security group with Terraform. Then, you will manually edit them via the AWS CLI. Next, you will identify and resolve the discrepancies between Terraform state and your infrastructure.
Note
Drift detection is available in HCP Terraform Plus Edition. Refer to HCP Terraform pricing for details.
Prerequisites
This tutorial assumes you are familiar with the standard Terraform workflow. If you are unfamiliar with Terraform, complete the Get Started tutorials first.
For this tutorial, you will need:
- The Terraform CLI, version 0.15.4 or later.
- AWS Credentials configured for use with Terraform.
- The
awscli
configured
Create infrastructure
Start by cloning the example repository. This configuration builds an EC2 instance, an SSH key pair, and a security group rule to allow SSH access to the instance.
Change into the repository directory.
Create an SSH key pair in your current directory, replacing your_email@example.com
with your email address. Use an empty passphrase.
Confirm your AWS CLI region.
Open the terraform.tfvars
file and edit the region to match your AWS CLI configuration.
Open the main.tf
file and review your configuration. The main resources are your EC2 instance, your key pair, and the SSH security group.
Initialize your configuration.
Apply your configuration. Enter yes
when prompted to accept your changes.
When your apply operation completes, run terraform state list
to review the resources managed by Terraform in your state file.
Introduce drift
To introduce a change to your configuration outside the Terraform workflow, create a new security group with the AWS CLI and export that value as an environment variable.
Confirm you created the environment variable. This will return the security group you just created.
Next, create a new rule for your group to provide TCP access to the instance on port 8080.
Associate the security group you created manually with the EC2 instance provisioned by Terraform.
Now, you have replaced your instance's SSH security group with a new security group that is not tracked in the Terraform state file.
Run a refresh-only plan
By default, Terraform compares your state file to real infrastructure whenever
you invoke terraform plan
or terraform apply
. The refresh updates your
state file in-memory to reflect the actual configuration of your infrastructure. This
ensures that Terraform determines the correct changes to make to your
resources.
If you suspect that your infrastructure configuration changed outside of the
Terraform workflow, you can use a -refresh-only
flag to inspect what the
changes to your state file would be. This is safer
than the refresh
subcommand, which
automatically overwrites your state file without displaying the updates.
Tip
The -refresh-only
flag was introduced in Terraform 0.15.4, and is preferred over the terraform refresh
subcommand.
Run terraform plan -refresh-only
to determine the drift between your current state file and actual configuration.
As shown in the output, Terraform has detected differences between the infrastructure and the current state, and sees that your original security group allowing access on port 22 is no longer attached to your EC2 instance. The refresh-only plan output indicates that Terraform will update your state file to modify the configuration of your EC2 instance to reflect the new security group with access on port 8080.
Apply these changes to make your
state file match your real infrastructure, but not your Terraform configuration.
Respond to the prompt with a yes
.
A refresh-only operation does not attempt to modify your infrastructure to match your Terraform configuration -- it only gives you the option to review and track the drift in your state file.
If you ran terraform plan
or terraform apply
without the
-refresh-only
flag now, Terraform would attempt to revert your manual
changes. Instead, you will update your configuration to associate your EC2 instance with
both security groups.
Add the security group to configuration
Import the sg_web
security group resource to your state file to bring it under Terraform management.
First, add the resource definition to your configuration by adding a new security group resource and rule resource to your main.tf
file.
Add the security group ID to your instance resource.
Import the security group
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.
Run terraform import
to associate your resource definition with the security group created in the AWS CLI.
Import your security group rule.
Run terraform state list
to return the list of resources Terraform is managing, which now includes the imported resources.
Terraform successfully associated both security groups with the instance in state. However, your instance still only allows port 8080 access because the modify-instance-attribute
AWS CLI command detached the SSH security group.
Update your resources
Now that the sg_web
security group is represented in state, re-run terraform apply
to associate the SSH security group with your EC2 instance.
Notice how this updates your EC2 instance's security group to include both the security groups allowing SSH and 8080
. Enter yes
when prompted to confirm your changes.
Access the instance
Confirm your instance allows SSH. Enter yes
when prompted to connect to the instance.
Exit the SSH connection by typing exit
in the SSH prompt.
Confirm your instance allows port 8080 access.
Clean up your resources
When you are finished with this tutorial, destroy the resources you created. Enter yes
when prompted to confirm your changes.
Next steps
In this tutorial, you created an EC2 instance and security group deployment with Terraform. Then, you introduced drift by editing your security groups outside the Terraform workflow. Finally, you learned how to detect your drifted configuration with -refresh-only
operations and how to reconcile your state file and configuration with the Terraform CLI refresh and import commands.
For more information about Terraform state and drift management, review the resources below:
- The Terraform
refresh
documentation - The
refresh-only
planning mode documentation - The State of Infrastructure Drift Presentation from Stephane Jourdan on the HashiCorp Blog
- Learn how to use configuration-driven import
- Manipulate Terraform State documentation