Skip to main content

Import Existing Resources

นำ resource ที่สร้างใน console (หรือ tool อื่น) มาให้ Terraform manage — โดยไม่ต้องสร้างใหม่

ทำไมต้อง Import?

Real world scenarios:

  • มี infrastructure ที่สร้างใน console ก่อนที่จะใช้ Terraform
  • ทีมเก่าสร้างไว้ ทีมใหม่อยากเปลี่ยนมาใช้ IaC
  • Resource ที่ Terraform ลืม manage (ลบจาก state แล้วลืม config)

วิธี Import — 2 แบบ

แบบเก่า: terraform import CLI (ต้องเขียน config เอง)

แบบใหม่: import block (Terraform 1.5+) ⭐

imports.tf
import {
to = aws_s3_bucket.existing
id = "my-existing-bucket"
}

resource "aws_s3_bucket" "existing" {
bucket = "my-existing-bucket"
}

Workflow

  1. Generate config (Terraform 1.5+)
terraform plan -generate-config-out=generated.tf

→ Terraform สร้าง config ให้อัตโนมัติจาก existing resource

  1. Review generated config

  2. Apply

terraform apply

→ Resource เข้า state, ไม่สร้างใหม่

ตัวอย่าง Generate Config

imports.tf
import {
to = aws_s3_bucket.legacy
id = "company-legacy-bucket-2020"
}
$ terraform plan -generate-config-out=generated.tf

Terraform planned the following actions, but then encountered a problem:

Terraform generated configuration for these resources:
+ aws_s3_bucket.legacy

Generated configuration was written to "generated.tf".
generated.tf
# __generated__ by Terraform from "company-legacy-bucket-2020"
resource "aws_s3_bucket" "legacy" {
bucket = "company-legacy-bucket-2020"
force_destroy = false
object_lock_enabled = false

tags = {
"ManagedBy" = "manual"
"Owner" = "data-team"
}
}

→ คัดลอก content ไปใส่ใน main config, ลบ import block

แบบเก่า: terraform import Command

terraform import aws_s3_bucket.existing my-existing-bucket

ต้องเขียน config ก่อน:

resource "aws_s3_bucket" "existing" {
bucket = "my-existing-bucket"
# config ที่ตรงกับ resource จริง
}

แล้วรัน import:

terraform import <RESOURCE_ADDRESS> <RESOURCE_ID>

Resource IDs

แต่ละ resource มี ID format ต่างกัน — อ่านจาก Terraform Registry docs

ตัวอย่าง:

ResourceID Formatตัวอย่าง
aws_s3_bucketbucket namemy-bucket
aws_instanceinstance IDi-1234567890abcdef0
aws_vpcVPC IDvpc-12345678
aws_iam_rolerole nameMyRole
aws_route53_zonezone IDZ1234567890ABC
aws_security_groupsg IDsg-12345678

ตัวอย่าง: Import VPC

imports.tf
import {
to = aws_vpc.main
id = "vpc-0a1b2c3d"
}
terraform plan -generate-config-out=generated.tf
generated.tf (output)
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
instance_tenancy = "default"
tags = {
"Name" = "production-vpc"
}
}

ตัวอย่าง: Import Multiple Resources

imports.tf
import {
to = aws_vpc.main
id = "vpc-0a1b2c3d"
}

import {
to = aws_subnet.public[0]
id = "subnet-aaa"
}

import {
to = aws_subnet.public[1]
id = "subnet-bbb"
}

import {
to = aws_security_group.web
id = "sg-xyz"
}
terraform plan -generate-config-out=generated.tf

→ Generate config สำหรับทุก resource ที่ list ไว้

Import เข้า Module

import {
to = module.network.aws_vpc.main
id = "vpc-0a1b2c3d"
}

Import กับ count / for_each

count

import {
to = aws_subnet.public[0]
id = "subnet-aaa"
}

import {
to = aws_subnet.public[1]
id = "subnet-bbb"
}

for_each

import {
to = aws_iam_user.team["alice"]
id = "alice"
}

Import Workflow ทำเป็นขั้นตอน

Common Pitfalls

1. Config ไม่ตรง Reality

หลัง import → terraform plan แสดง diff → แก้ config ให้ตรง

2. Computed Attributes

บาง attribute = Terraform คำนวณเอง — ไม่ต้องใส่ใน config:

  • id, arn, *_id
  • created_date, last_modified

3. Default Values

บาง argument มี default ของ provider — ไม่ใส่ก็ได้

4. Tag Drift

ถ้ามี default_tags ใน provider — resource อาจมี tag ที่ไม่ตรง

Bulk Import Tools

มี tool ช่วย import infrastructure ทั้งบ้าน:

Terraformer (by Google)

brew install terraformer
terraformer import aws --resources=vpc,subnet,sg --regions=ap-southeast-1

→ Generate ทั้ง config + state

former2 (web-based)

former2.com — UI ดึง AWS resource → generate Terraform config

CDKTF

CDK for Terraform — เขียน Terraform ด้วย Python/TypeScript + import

Best Practices

✅ DO:
- ใช้ import block (Terraform 1.5+) แทน terraform import CLI
- Review generated.tf อย่างละเอียด
- Plan ก่อน apply เพื่อดู diff
- Import ทีละ component (network ก่อน → compute → app)

❌ DON'T:
- ห้าม import แล้วใช้ทันที (ต้อง verify config ก่อน)
- ห้าม import resource ที่จะ destroy ทันที
- ห้าม import resource ที่ provider ไม่รองรับ (เช็คก่อน)

ตัวอย่าง: Migration Real-World

step1-imports.tf
# Phase 1: Import network
import {
to = aws_vpc.main
id = "vpc-0a1b2c3d"
}

import {
for_each = toset(["subnet-aaa", "subnet-bbb"])
to = aws_subnet.public[index]
id = each.value
}
terraform plan -generate-config-out=network.tf
# Review network.tf
terraform apply
step2-imports.tf
# Phase 2: Import compute
import {
to = aws_instance.web
id = "i-1234567890abcdef0"
}

ทำทีละขั้นตอน — ไม่ import ทุกอย่างพร้อมกัน

สรุป

  • Import = นำ existing resource เข้า Terraform state
  • import block (1.5+) — แนะนำ
  • -generate-config-out สร้าง config ให้อัตโนมัติ
  • Resource ID format ต่างกัน — เช็คใน docs
  • Tools เช่น Terraformer / former2 / CDKTF ช่วย bulk import
  • Plan ก่อน apply เพื่อ verify

ต่อไป → Splitting State Files