Skip to main content

Migrating to Terraform

1. Discovering Existing Infrastructure

Command Description Notes
terraform import Imports existing resources into Terraform state Must manually update configuration after import
terraform state list Lists all resources in the current state Useful for discovering what's managed
terraform state show Shows details of a specific resource Can be used to inspect imported resources

Example: Importing an AWS EC2 instance

terraform import aws_instance.example i-1234567890abcdef0
Note: After importing, you must manually create the corresponding Terraform configuration to ensure future state consistency.

Workflow: Discovering and Importing Infrastructure

  1. Identify existing resources in your cloud provider console or CLI
  2. Run terraform state list to see what's already managed
  3. Use terraform import to bring resources into Terraform state
  4. Create corresponding HCL configuration files for each imported resource
  5. Verify that the state matches actual infrastructure with terraform plan

2. Importing Resources

Importing existing infrastructure into Terraform state allows you to manage pre-existing resources with Terraform.

Command Description Example
terraform import Imports a resource into Terraform state terraform import aws_instance.web i-1234567890abcdef0

Example: Importing an AWS EC2 Instance

terraform import aws_instance.web i-1234567890abcdef0
Note: After importing, you must manually create the corresponding resource block in your configuration file.
Warning: Importing does not automatically generate the HCL configuration. You must define the resource in your Terraform files.
Option Description Notes
-config Path to the configuration directory Defaults to current directory
-state Path to the state file Defaults to terraform.tfstate
-lock Lock the state file during import Defaults to true

3. Generating Configuration

Property Description Example
terraform.required_version Specifies the minimum version of Terraform required to run the configuration. ">= 1.0"
provider Defines the provider to use for managing resources (e.g., AWS, Azure).
provider "aws" {
  region = "us-west-2"
}
resource Defines a resource to be managed by Terraform.
resource "aws_instance" "web" {
  ami           = "ami-12345678"
  instance_type = "t2.micro"
}
data Retrieves external data or information from a provider.
data "aws_ami" "latest" {
  most_recent = true
  owners      = ["self"]
}
output Exports values from the Terraform configuration for use elsewhere.
output "instance_ip" {
  value = aws_instance.web.private_ip
}

Example: Basic Terraform Configuration

terraform {
  required_version = ">= 1.0"
}

provider "aws" {
  region = "us-west-2"
}

resource "aws_instance" "web" {
  ami           = "ami-12345678"
  instance_type = "t2.micro"
}

output "instance_ip" {
  value = aws_instance.web.private_ip
}

4. Using Import Blocks

Property Description Example
import Defines how to import existing infrastructure into Terraform state
import {
  to = aws_instance.example
  id = "i-1234567890abcdef0"
}

Example: Importing an AWS EC2 Instance

import {
  to = aws_instance.example
  id = "i-1234567890abcdef0"
}
Note: The to attribute specifies the resource address in your configuration, and id is the identifier of the existing resource in the cloud provider.
Warning: Importing resources does not automatically generate the configuration code. You must manually create the resource block in your Terraform files.

5. Validating Imported State

Example: Validate imported state

terraform state list
terraform state show <resource_address>
Command Description Notes
terraform state list Lists all resources in the state Useful for verifying imported resources
terraform state show <resource_address> Shows details of a specific resource Validate attributes match expected values
Note: Ensure all imported resources are correctly mapped to their respective configurations in your Terraform files.
Warning: Modifying state directly can lead to inconsistencies. Always backup before manual changes.

6. Handling Import Conflicts

Note: Import conflicts occur when Terraform cannot uniquely identify a resource in the state file after an import operation.
Conflict Type Description Solution
Duplicate Resource IDs Multiple resources with the same ID in state Manually edit state file to rename or remove duplicates
Missing Resource References Imported resource not found in configuration Recreate resource block with correct attributes
Attribute Mismatch Imported resource has different attributes than config Update configuration to match imported resource

Example: Resolving Duplicate Resource IDs

terraform state list
terraform state show <resource_address>
terraform state rm <resource_address>

Workflow: Resolving Import Conflicts

  1. Run terraform plan to identify conflicts
  2. Review state file for duplicate or missing resources
  3. Manually edit terraform.tfstate if needed
  4. Re-run terraform apply to resolve state inconsistencies

Comparison: Import vs. Refresh

  • Import: Adds existing resources to state without config
  • Refresh: Updates state from real infrastructure

7. Migrating from CloudFormation

Aspect Terraform Approach CloudFormation Approach
Resource Definition resource "aws_instance" "example" { ... } Resources: Example: Type: AWS::EC2::Instance
State Management Uses terraform.tfstate or remote backends Stores state in S3 with DynamoDB locking
Configuration Language HCL (HashiCorp Configuration Language) YAML or JSON
Modularity Modular with module blocks Stacks and nested templates
Versioning Versioned via Git or VCS Versioned via S3 or CodePipeline

Example: Migrating a Simple EC2 Instance

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1d0"
  instance_type = "t2.micro"

  tags = {
    Name = "example-instance"
  }
}

Migration Steps Overview

  • Export existing CloudFormation stack resources to HCL format
  • Use terraform import to bring existing resources under Terraform control
  • Refactor CloudFormation templates into reusable Terraform modules
  • Validate and test the new configuration before full migration
Note: Ensure all dependencies and resource relationships are correctly mapped during migration.
Warning: Always backup your CloudFormation stack and state before starting migration.

8. Migrating from ARM Templates

ARM Template Element Terraform Equivalent Notes
Resource Group azurerm_resource_group Represents a logical container for Azure resources
Virtual Machine azurerm_linux_virtual_machine or azurerm_windows_virtual_machine Creates a VM instance in Azure
Storage Account azurerm_storage_account Creates a storage account for data storage
Virtual Network azurerm_virtual_network Defines a network in Azure with subnets
Public IP Address azurerm_public_ip Assigns a public IP to a resource

Example: Migrating a Resource Group

{
  "parameters": {
    "rgName": {
      "type": "string"
    }
  },
  "resources": [
    {
      "type": "Microsoft.Resources/resourceGroups",
      "apiVersion": "2021-04-01",
      "name": "[parameters('rgName')]",
      "location": "East US"
    }
  ]
}
resource "azurerm_resource_group" "main" {
  name     = "example-resource-group"
  location = "East US"
}

Example: Migrating a Virtual Machine

{
  "parameters": {
    "vmName": {
      "type": "string"
    }
  },
  "resources": [
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2021-03-01",
      "name": "[parameters('vmName')]",
      "location": "East US",
      "properties": {
        "hardwareProfile": {
          "vmSize": "Standard_B1s"
        },
        "osProfile": {
          "computerName": "myVM",
          "adminUsername": "adminuser"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "Canonical",
            "offer": "UbuntuServer",
            "sku": "18.04-LTS",
            "version": "latest"
          }
        }
      }
    }
  ]
}
resource "azurerm_linux_virtual_machine" "main" {
  name                = "example-vm"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  size                = "Standard_B1s"
  admin_username      = "adminuser"
  admin_password      = "Password123!"

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = "18.04-LTS"
    version   = "latest"
  }
}
Note: ARM templates use JSON syntax, while Terraform uses HCL. Ensure all resource dependencies and references are properly translated.

9. Using Third-Party Import Tools

Terraform provides several third-party tools to help with importing existing infrastructure into state. These tools can simplify the process of migrating from other IaC solutions or manually provisioned resources.

Tool Description Supported Providers Notes
terraform-importer A community-driven tool that automates importing resources from various sources into Terraform state. AWS, GCP, Azure, Kubernetes Supports multiple cloud providers and can be extended via plugins.
tfimport CLI tool to generate Terraform configuration from existing infrastructure. AWS, GCP, Azure Can generate HCL code from existing resources and manage state.
terraform-inventory Generates inventory of Terraform-managed resources from state files. All Helps in analyzing and auditing existing Terraform configurations.

Example: Using tfimport to import AWS resources

tfimport aws_instance.my_instance \
  --region us-west-2 \
  --id i-1234567890abcdef0
Note: Third-party tools may not support all Terraform features or providers. Always validate the generated configuration before applying changes.

10. Documenting Migration Process

Example: Migration Documentation Structure

# Terraform Migration Documentation

## 1. Current State
- Infrastructure as code: No
- Version control: None
- Configuration management: Manual

## 2. Target State
- Infrastructure as code: Terraform
- Version control: Git
- Configuration management: Terraform

## 3. Migration Steps
1. Identify existing resources
2. Create Terraform configuration
3. Import resources into state
4. Validate and test
5. Update documentation

## 4. Risks & Mitigations
- Risk: Data loss during migration
  - Mitigation: Backup all resources before import

## 5. Rollback Plan
- Revert to previous infrastructure state if needed
Documentation Section Description Status
Current State Details of existing infrastructure and configuration practices Required
Target State Planned infrastructure as code setup with Terraform Required
Migration Steps Sequential steps to migrate from current to target state Required
Risks & Mitigations Identified risks and their mitigation strategies Recommended
Rollback Plan Procedure to revert to previous state if migration fails Recommended
Note: Documentation should be version-controlled and reviewed by stakeholders before migration begins.
Warning: Incomplete or inaccurate documentation can lead to failed migrations and data loss.

Was this article helpful?