← Recipes

阅读中文版本

Reconcile State Drift with terraform import

Detect resources that exist in the cloud but not in state, import them with terraform import, and run a plan that shows zero diff before adopting the resources.

~25 minterraformdriftimport

Task

Bring resources that were created out of band into Terraform state so a plan shows no changes and they are managed going forward.

When to use this

An S3 bucket was created by hand during an incident and is not in Terraform. A plan wants to destroy it. The team wants to adopt it without recreating it.

Prerequisites

  • Terraform 1.6 or later with the provider configured
  • The address of the resource in the configuration and its cloud id
  • Read access to the resource so import can read its attributes

Steps

1. Write the resource block in the configuration with the same attributes you expect the cloud resource to have.

resource "aws_s3_bucket" "logs" {
  bucket = "incident-logs-2026"
}

Expected output: A resource block that matches the cloud resource, so the import can align state with config.

2. Import the cloud resource into state at the address of the new block.

terraform import aws_s3_bucket.logs incident-logs-2026

Expected output: The state file now contains the resource, and terraform plan shows a diff only for attributes that differ.

3. Run a plan and reconcile any non-zero diff by updating the config to match the cloud.

terraform plan -out=adopt.tfplan

Expected output: A second plan shows zero changes, meaning the config, the state, and the cloud all agree.

Troubleshooting

Problem

The plan still shows a diff after import

Solution

The config attributes do not match the cloud; read the resource with terraform show and update the config to match, then plan again.

Problem

The import fails because the resource is gone

Solution

The resource was deleted out of band; remove the block from config and state, and let Terraform recreate it on the next apply.

Limitations

  • Import reads the cloud resource but does not change it; a subsequent apply is what makes changes.
  • A resource with attributes the provider cannot read must be imported with -ignore-remote-version, which is a last resort.

Import, then reconcile

Write the resource block first, then import the cloud resource into state at that address. The import reads the cloud and writes state; it does not change the cloud. Run a plan and update the config until the diff is zero.

terraform import aws_s3_bucket.logs incident-logs-2026
terraform plan -out=adopt.tfplan

Match the config to the cloud

If the plan shows a diff, the config does not match the cloud. Read the imported state with terraform show, update the config to match, and plan again. The goal is a zero diff, which means the resource is safely adopted.

resource "aws_s3_bucket" "logs" {
  bucket = "incident-logs-2026"
}

Expected outcome

The state file contains the resource, a plan shows zero changes, and the next apply is a no-op. The resource is now managed by Terraform, so a future plan will not try to destroy it. Import reads but does not change the cloud; only apply changes it.