Day 25 - Terraform Import for Existing AWS Resources
Today I worked on Terraform import as part of Day 25 of my AWS Terraform learning series.
In real projects, not every AWS resource starts from Terraform. Some resources are created manually from the AWS Console. Some are created by older scripts. Some are created by different teams before Infrastructure as Code is adopted.
Terraform import helps bring those existing resources into Terraform state so they can be managed going forward.
For this project, I created a few AWS resources manually first, then imported them into Terraform.
What I Built
I used three existing AWS resources:
S3 bucket
EC2 instance
Security group
These resources were created outside Terraform first. Then I wrote Terraform configuration blocks for them and used terraform import to connect those real AWS resources to Terraform state.
Architecture
The workflow is simple:
Existing AWS resources already exist in the AWS account.
Terraform configuration defines matching resource blocks.
terraform import maps those resources into Terraform state.
terraform plan checks whether the code and real infrastructure match.
Terraform manages the resources going forward.
Why Terraform Import Matters
Terraform normally manages resources from the time it creates them. But in real environments, we often inherit existing infrastructure.
Terraform import is useful when:
A company is adopting Infrastructure as Code.
Resources were created manually before Terraform was introduced.
A production resource should not be recreated.
A resource was created during troubleshooting and now needs to be managed properly.
Teams want better drift detection and consistent change control.
The important point is this: import does not create infrastructure. It only updates Terraform state so Terraform knows about the existing resource.
Terraform Configuration
I started with a normal Terraform provider and backend configuration.
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "jay-terraformstate-bucket"
key = "day-25/dev/terraform.tfstate"
region = "us-east-1"
encrypt = true
use_lockfile = true
}
}
provider "aws" {
region = var.aws_region
}
Then I defined the existing resources in Terraform.
resource "aws_s3_bucket" "imported_bucket" {
bucket = var.existing_bucket_name
tags = {
Name = var.existing_bucket_name
Project = "Day25TerraformImport"
ManagedBy = "Terraform"
Environment = "dev"
}
}
I also added resource blocks for the existing security group and EC2 instance.
This screenshot should show the Terraform files before running the import commands.
Import Commands
After initializing Terraform, I ran the import commands.
terraform init
terraform validate
Then I imported the existing S3 bucket.
terraform import aws_s3_bucket.imported_bucket day25-import-demo-xxxx
Next, I imported the security group.
terraform import aws_security_group.imported_sg sg-xxxxxxxxxxxxxxxxx
Then I imported the EC2 instance.
terraform import aws_instance.imported_ec2 i-xxxxxxxxxxxxxxxxx
State Verification
After importing, I checked the Terraform state.
terraform state list
Expected output:
aws_instance.imported_ec2
aws_s3_bucket.imported_bucket
aws_security_group.imported_sg
Before import, terraform state list returned no resources because Terraform had configuration files but no state mapping to existing AWS resources. After running import commands, the resources appeared in Terraform state, confirming that Terraform now tracks and manages them.
I also checked detailed state information.
terraform state show aws_instance.imported_ec2
This helps verify that Terraform has stored the correct resource attributes.
Drift Check
The most important step after import is running:
terraform plan
This step shows whether the Terraform configuration matches the real AWS resources.
If the plan shows changes, it means the Terraform code does not fully match the existing resource. In that case, I need to update the Terraform configuration carefully until the plan becomes clean.
A good final result is:
No changes. Your infrastructure matches the configuration.
One observation was, there's 1 resource that is destroyed as per above.I noticed that changing the security group description forced replacement.This showed me why terraform plan is critical after import.Imported resources should first match the real AWS configurationbefore making changes.
Test Scenario
To test that Terraform can now manage the imported resources, I added a new tag:
Owner = "Jay"
Then I ran:
terraform plan
terraform apply
This proves Terraform is not just tracking the resource, but can also manage changes going forward.
Key Learnings
Terraform import is useful for bringing existing AWS resources under Infrastructure as Code.
Import does not create resources. It connects existing resources to Terraform state.
A matching Terraform resource block is required before import.
terraform state list and terraform state show help verify the import.
terraform plan is the most important validation step because it shows drift between code and real infrastructure.
Cleanup
For this project, cleanup should be handled carefully.
If these are demo resources, they can be destroyed using:
But in real environments, imported resources may already be production resources. In that case, do not destroy them unless the resource owner approves it.
Conclusion
Day 25 helped me understand how Terraform can adopt existing AWS resources. This is an important real world skill because cloud environments often already have resources before Terraform is introduced.
The main lesson is to import carefully, validate state, review the plan, and only then allow Terraform to manage future changes.
Comments
Post a Comment