Integrating existing infrastructure into Terraform can feel like trying to fit a square peg in a round hole. You’ve spent time crafting resources, and now you need to manage them with code. But there’s a way to bring your current setup into the fold without starting over: the terraform import
command. This article walks you through how to use terraform import
to manage your existing infrastructure, step by step. We’ll cover everything from the basic syntax to complex scenarios, giving you the knowledge to bring your legacy resources into the Terraform world.
Understanding Terraform Import
The core of integrating your existing infrastructure into Terraform is using the terraform import
command. This command lets you take a resource that you’ve created manually (or with other tools) and bring it under Terraform management. It doesn’t magically create all the code for you, but it does connect your real-world resource to a corresponding resource block in your Terraform configuration. In this way, Terraform becomes aware of the existence of your resource, and it can then apply plans and changes as needed.
How it Works
Here’s a simple overview of the terraform import
process:
- Identify Resource: First, you need to know the type of resource you want to import (e.g., an AWS EC2 instance, an Azure virtual machine) and the unique identifier that the cloud provider uses to manage it (e.g., its ID or name).
- Write Terraform Configuration: Next, craft the resource block in your Terraform file to mirror the properties of the resource you wish to import.
- Run
terraform import
: Use the command to link the real-world resource and the resource block in your configuration. - Plan and Apply: After the import, use
terraform plan
to check for any discrepancies. And then useterraform apply
to bring the state of your Terraform config in sync with your real-world resource.
Why Use terraform import
?
Why use terraform import
when you could try to recreate all of your resources from scratch? Here are a few good reasons:
- Avoid Downtime: Recreating resources from scratch might cause service disruptions. Import lets you avoid that, because it integrates current resources.
- Save Time: Writing Terraform code for every resource you already have can be time consuming. Import provides a good way to speed this up.
- Reduce Errors: If you try to create the resources by hand in your Terraform config, you might end up misconfigured or with resources that are not quite the same as the real ones. Import does not create any new resources, instead it ties in your real resources to the code, avoiding this mistake.
- Centralized Management: Once your infrastructure is under Terraform management, you can handle all changes, version control, and collaboration with the rest of your team in one place.
Preparing for Import
Before diving into the command, you need to lay some groundwork. Proper setup before importing your resources will smooth the process, and reduce mistakes.
Setting Up Your Terraform Environment
First, make sure your Terraform setup is in good working order. This means:
- Install Terraform: Ensure you have Terraform installed on your machine. If not, download it from the official website.
- Choose a Backend: Select a suitable backend to store your Terraform state. Cloud options like AWS S3, Azure Storage Account, or Google Cloud Storage are good choices for team setups. Or, you can stick to local state for practice.
- Configure Your Provider: Configure your chosen cloud provider to work with Terraform. For instance, for AWS, set up your credentials using environment variables or an AWS profile.
Understanding the Resource Identifier
The most critical piece of info for terraform import
is the resource identifier. This is a unique ID or name that the cloud provider gives to each resource. It is different for each provider, here are some examples:
- AWS: Resource IDs (e.g.,
i-0abcdef1234567890
,subnet-0abcdef1234567890
) or resource names, depending on the provider. - Azure: Resource IDs (e.g.,
/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-resource-group/providers/Microsoft.Compute/virtualMachines/example-vm
) - Google Cloud: Fully qualified resource names (e.g.,
projects/example-project/zones/us-central1-a/instances/example-instance
).
You’ll find these identifiers in your cloud provider’s console, CLI, or API. Always double-check you have the correct ID before importing.
Writing the Terraform Configuration
Before importing, you need the resource code ready in Terraform. Here’s a simple example for an AWS EC2 instance:
resource "aws_instance" "example" {
ami = "ami-0c55b23422d01c15a"
instance_type = "t2.micro"
tags = {
Name = "example-instance"
}
}
This resource block defines the characteristics of the resource. Notice that this block doesn’t create a new instance, it only describes it. You’ll have to replace placeholders such as ami
with real values, if they are different.
Your configuration doesn’t have to match your real-world resource exactly. The import process will update the Terraform state and allow Terraform to track it. But, starting with a correct config helps avoid extra changes later.
Using the terraform import
Command
With prep done, it’s time to use the terraform import
command. Let’s look at the basic syntax and how it applies in common scenarios.
Basic Syntax
The terraform import
command structure is straightforward:
terraform import <ADDRESS> <ID>
ADDRESS
: This points to the Terraform resource you want to import. It matches the name you’ve set in the configuration file (e.g.,aws_instance.example
).ID
: This is the unique identifier of the real-world resource that you got from your cloud provider.
Let’s look at a real-world example of importing an AWS EC2 instance, with these identifiers:
- ADDRESS:
aws_instance.example
- ID:
i-0abcdef1234567890
The command would be:
terraform import aws_instance.example i-0abcdef1234567890
When executed, this will bring the real AWS EC2 instance under the umbrella of your Terraform configuration.
Common Import Scenarios
Let’s explore some common use cases for terraform import
:
Importing an AWS EC2 Instance
Using the example config above, you would run this command to import an EC2 instance that has an identifier as i-0abcdef1234567890
:
terraform import aws_instance.example i-0abcdef1234567890
After running, you can use terraform plan
to check if everything matches, and then use terraform apply
.
Importing an Azure Virtual Machine
Here is an example configuration for an Azure Virtual Machine:
resource "azurerm_virtual_machine" "example" {
name = "example-vm"
resource_group_name = "example-resource-group"
location = "eastus"
vm_size = "Standard_DS1_v2"
storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}
os_profile {
computer_name = "example-vm"
admin_username = "adminuser"
}
os_profile_linux_config {
disable_password_authentication = true
}
network_interface_ids = [
azurerm_network_interface.example.id,
]
}
And assuming the resource ID is /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-resource-group/providers/Microsoft.Compute/virtualMachines/example-vm
, your import command would be:
terraform import azurerm_virtual_machine.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-resource-group/providers/Microsoft.Compute/virtualMachines/example-vm
Importing a Google Cloud Instance
And here’s a configuration for a Google Cloud instance:
resource "google_compute_instance" "example" {
project = "example-project"
zone = "us-central1-a"
name = "example-instance"
machine_type = "e2-medium"
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
network_interface {
network = "default"
}
}
With the identifier projects/example-project/zones/us-central1-a/instances/example-instance
, the import command would be:
terraform import google_compute_instance.example projects/example-project/zones/us-central1-a/instances/example-instance
Handling Errors and Troubleshooting
Importing resources doesn’t always go off without a hitch. Here are some common issues you might encounter and how to handle them:
- Incorrect Address: If the address doesn’t match the resource in your Terraform configuration, you’ll get an error. Check that the
ADDRESS
parameter in the import command corresponds with your resource name in the code. - Incorrect ID: An incorrect ID will lead to an error. Double-check the identifier you copy and paste.
- Resource Already Managed: If Terraform already manages the resource, you can’t import it again. In this case, make sure you are importing the correct resource, or try
terraform refresh
to see if you already have the resource in your state. - Missing Configuration: If you’re missing a key attribute in your config, you may get errors when running
terraform plan
. Make sure to define all the necessary configurations in your code. - Drift Detection: If your configuration does not exactly match the real-world resource, you might detect a drift. In this case, you have two options: adjust your configuration code, or accept the change the plan is trying to make.
After the Import
Importing is only the first step in the journey of moving your resources into Terraform. Let’s discuss what comes next.
Planning and Applying
After the import, it is important to always use terraform plan
. The plan
command will show you all the differences between the real-world resource and your Terraform configuration. This helps you to find any mistakes. Once you review the plan, if there are no errors, you can then use terraform apply
to apply the configuration in the plan, bringing the Terraform state file in sync with the resources you just imported.
Managing State
Terraform state keeps track of the resources managed by your config. After the import, your state file now has information about your resources, so it can track changes. You may need to store this file in a secure, shared backend for teams.
Updating and Modifying Resources
Once imported, you can modify your resources by changing the corresponding attributes in your Terraform code. For instance, change instance types, update tags, or adjust other parameters. After making these changes, run terraform plan
to confirm the changes you’re about to apply, and use terraform apply
to update your resources.
Deleting Imported Resources
To delete a resource that you imported, you will first need to use the terraform destroy
command. This command removes resources from your provider, not from your state. This operation destroys the real-world resource, and removes it from the state file.
Advanced Import Techniques
Now that you know the basics, let’s look at some more advanced techniques to handle complex situations.
Importing Multiple Resources
You can import multiple resources at once, one after another. It is a good idea to do them in the correct order, for example, import a VPC first, and then the subnets and instances in that VPC. Use terraform plan
after every import to catch potential errors early on.
Using For Loops for Multiple Imports
If you need to import many of the same kind of resource, you can use a for loop with the terraform import
command. Create a list of identifiers and use a for_each
loop:
resource "aws_instance" "example" {
for_each = toset(["i-0abcdef1234567890", "i-0fedcba9876543210"])
ami = "ami-0c55b23422d01c15a"
instance_type = "t2.micro"
tags = {
Name = "example-instance-${each.key}"
}
}
And in your import command, you need to use the correct addresses:
terraform import aws_instance.example["i-0abcdef1234567890"] i-0abcdef1234567890
terraform import aws_instance.example["i-0fedcba9876543210"] i-0fedcba9876543210
This method automates the import process, saving time and effort.
Importing Resources with Dependencies
When importing resources with dependencies, such as a virtual machine that depends on a network interface, be sure to import them in the correct order. Start with the lowest-level resources and move up.
Dealing with Complex Resource Configurations
Complex resource configurations might require breaking down your import process. Sometimes you might need to import the resources one by one, and test after each import. After you import all resources, always run terraform plan
to detect and fix errors.
Best Practices for Terraform Import
To avoid problems, here are some best practices for using terraform import
:
- Always Plan: After each import, run
terraform plan
to check for discrepancies. This is a key step for a successful import. - Test in a Non-Prod Environment: Try import on test resources before applying them to production. This helps you become familiar with the process.
- Version Control Your Configuration: Put your Terraform files under version control so you can track changes and rollback if needed.
- Use a Remote Backend: Store state files remotely to ensure that multiple team members can collaborate without problems.
- Document Your Process: Document your import process and the challenges you faced. This serves as a guide for future imports.
- Clean up Old Configurations: Once your real resources are tied to Terraform, it is a good idea to delete or archive any old resource files or configs that are no longer being used.
- Use descriptive names: Use names that will help you find your resources quickly. A good name can make the import process easier.
- Stay Updated: Keep up with updates to Terraform and its providers. That will help you avoid surprises.
- Read the provider documentation: Each provider has unique characteristics and specifics for its import command. Read the documentation to avoid common errors.
- Start small: Don’t try to import everything at once. Start with a few simple resources, and then move to more complex ones.
- Double-check IDs: Always double-check the ID before running the import command. A mistake in the ID will result in problems and errors.
- Use proper formatting: Follow the correct formatting for the configuration file. This helps prevent syntax errors and makes your config easier to read.
The Benefits of Terraform Import
Using terraform import
is more than a way to move your old resources to Terraform. Here are a few benefits that make it important for the modern infrastructure engineer:
- Improved Resource Management: By bringing your entire infrastructure under Terraform, you have more control, better auditing, and a more unified way to handle changes.
- Increased Efficiency: The import feature speeds up the process of managing your infrastructure, reducing the time it takes to set up.
- Better Collaboration: The import option lets you bring legacy infrastructure into a shared system that works well with teams.
- Less Risk of Human Error: By using the import process, you avoid manually making changes to the infrastructure. And all changes are logged and easy to track.
- Faster Adoption of IaC: If you work on an environment that already exists, using
terraform import
is the best way to adopt Infrastructure as Code.
A Well-Managed Infrastructure
terraform import
helps you keep pace with infrastructure changes without starting from scratch. By using this command with the correct planning, your real-world resources can be tracked by your Terraform configurations. This makes it easier to keep a well-managed infrastructure. This tool enables you to bridge the gap between what you already have and the world of infrastructure as code.