Terraform Import
Introduction
When adopting Infrastructure as Code (IaC) with Terraform, you'll likely encounter situations where you need to bring existing infrastructure under Terraform's management. This is where the terraform import
command becomes invaluable.
Terraform Import allows you to take resources that were created outside of Terraform (manually through a console, via other tools, or inherited from previous teams) and bring them under Terraform's management without having to recreate them.
In this guide, we'll explore:
- Why and when to use Terraform Import
- The import process step by step
- Practical examples with different resource types
- Best practices and common challenges
Why Use Terraform Import?
Before diving into the how, let's understand why importing existing resources is beneficial:
-
Avoid Recreating Resources: Importing allows you to manage existing resources without tearing them down and rebuilding them.
-
Consistent Management: After importing, you can manage all your infrastructure through the same Terraform workflow.
-
Documentation as Code: Your infrastructure becomes documented in your Terraform configuration files.
-
Easier Collaboration: Team members can understand and modify infrastructure through version-controlled code.
-
Gradual Migration: You can incrementally move from manual management to IaC.
The Import Process
Importing resources into Terraform involves three main steps:
Step 1: Write Resource Configuration
Before importing, you need to create a Terraform configuration file (.tf
) that describes the resource you want to import. You don't need to know all the attributes, but you must define the resource type and name.
resource "aws_instance" "web_server" {
# Minimal configuration - we'll fill in details after import
# You must specify the resource type and a name
}
Step 2: Run terraform import
The basic syntax for the import command is:
terraform import [options] ADDRESS ID
Where:
ADDRESS
is the Terraform resource address (e.g.,aws_instance.web_server
)ID
is the ID of the existing infrastructure resource as recognized by the provider
For example:
terraform import aws_instance.web_server i-1234567890abcdef0
Step 3: Verify and Adjust
After importing, you should:
- Run
terraform plan
to see what changes Terraform would make - Update your configuration to match the imported resource's actual attributes
- Run
terraform plan
again to confirm there are no differences
Step 4: Apply Changes
Once your configuration matches the imported state, you can run terraform apply
to apply any changes you've made to your configuration.
Practical Examples
Let's walk through some common scenarios where Terraform Import proves useful.
Example 1: Importing an AWS EC2 Instance
Imagine you have an EC2 instance that was created manually through the AWS console.
Step 1: Create a configuration file (main.tf
):
provider "aws" {
region = "us-west-2"
}
resource "aws_instance" "web_server" {
# Minimal configuration to start with
}
Step 2: Run the import command:
terraform import aws_instance.web_server i-1234567890abcdef0
Output:
aws_instance.web_server: Importing from ID "i-1234567890abcdef0"...
aws_instance.web_server: Import prepared!
Prepared aws_instance for import
aws_instance.web_server: Refreshing state... [id=i-1234567890abcdef0]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
Step 3: After import, run terraform state show
to see the resource details:
terraform state show aws_instance.web_server
Output:
# aws_instance.web_server:
resource "aws_instance" "web_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
key_name = "my-key"
subnet_id = "subnet-1234567890abcdef0"
vpc_security_group_ids = ["sg-1234567890abcdef0"]
# ... other attributes ...
}
Step 4: Update your configuration to match the actual resource:
resource "aws_instance" "web_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
key_name = "my-key"
subnet_id = "subnet-1234567890abcdef0"
vpc_security_group_ids = ["sg-1234567890abcdef0"]
tags = {
Name = "Web Server"
}
}
Step 5: Run terraform plan
to verify there are no differences between your configuration and the imported state:
terraform plan
Output:
No changes. Your infrastructure matches the configuration.
Example 2: Importing an Azure Resource Group
For Azure resources, the process is similar but with provider-specific IDs.
Step 1: Create your configuration:
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "example" {
# Minimal configuration
}
Step 2: Run the import command:
terraform import azurerm_resource_group.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-resources
Step 3: Update your configuration based on the imported state:
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "East US"
tags = {
environment = "production"
}
}
Example 3: Importing Multiple Resources
For more complex scenarios, you might need to import multiple related resources.
Let's say you have an AWS VPC with subnets and route tables:
# First, import the VPC
terraform import aws_vpc.main vpc-1234567890abcdef0
# Then import the subnets
terraform import aws_subnet.public subnet-public1234567890
terraform import aws_subnet.private subnet-private1234567890
# Finally, import the route tables
terraform import aws_route_table.public rtb-public1234567890
terraform import aws_route_table.private rtb-private1234567890
You would then update your Terraform configuration to accurately reflect all these resources.
Advanced Import Techniques
Using Import Block (Terraform 1.5+)
Starting with Terraform 1.5, you can use the import
block in your configuration to declaratively specify imports:
import {
to = aws_instance.web_server
id = "i-1234567890abcdef0"
}
resource "aws_instance" "web_server" {
# Configuration will be filled in during import
}
Then run:
terraform plan -generate-config -out=import.tfplan
This will generate the configuration for the imported resource.
Importing Modules
When your infrastructure is organized into modules, you can import resources into a module:
terraform import module.vpc.aws_vpc.this vpc-1234567890abcdef0
Common Challenges and Solutions
1. Missing Required Attributes
Challenge: After importing, Terraform might complain about missing required attributes.
Solution: Use terraform state show
to see all attributes of the imported resource and add them to your configuration.
2. Dependent Resources
Challenge: Some resources depend on others, and importing them in the wrong order can cause issues.
Solution: Import resources in the correct dependency order, typically starting with foundational resources (like VPCs) before more specific ones (like EC2 instances).
3. Generated Names and IDs
Challenge: Some resources have provider-generated names or IDs that Terraform expects to manage.
Solution: Use the lifecycle
block with ignore_changes
for attributes that should not be managed by Terraform:
resource "aws_instance" "example" {
# ... configuration ...
lifecycle {
ignore_changes = [
# Ignore changes to tags that are managed externally
tags["AutoScalingGroupName"],
]
}
}
Best Practices
-
Import One Resource at a Time: This makes troubleshooting easier.
-
Version Control: Commit your Terraform files to version control before and after imports.
-
Backup State: Always back up your Terraform state before importing resources.
-
Validate Before Apply: Always run
terraform plan
after importing to check for any unexpected changes. -
Documentation: Document the import process and reasons for any special configurations.
-
Use Modules: For repeated imports of similar resources, consider creating a module.
Summary
Terraform Import is a powerful tool that bridges the gap between existing infrastructure and Infrastructure as Code. By following the steps outlined in this guide, you can gradually bring your infrastructure under Terraform management without disruption.
Remember:
- Write resource configurations before importing
- Use
terraform import
to bring resources into state - Adjust configurations to match the actual resources
- Validate with
terraform plan
before applying changes
With proper use of Terraform Import, you can achieve a fully managed, version-controlled infrastructure even when starting with existing resources.
Additional Resources
- Terraform Import Official Documentation
- Terraform Import Block Documentation
- Terraform State Commands
Exercises
- Import an existing cloud storage bucket (S3 on AWS or Cloud Storage on GCP) into Terraform.
- Import a network security group with multiple rules.
- Create a small module that imports and manages a set of related resources (e.g., a VPC with subnets).
- Practice using the
terraform plan -generate-config
workflow with an imported resource. - Import a resource and then modify one of its attributes through Terraform.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)