Import #
Jarang sekali tim memulai dari infrastruktur yang benar-benar kosong. Lebih sering, ada server, database, dan jaringan yang sudah berjalan dan dikelola secara manual jauh sebelum Terraform diperkenalkan. Import adalah mekanisme yang memungkinkan Terraform mengambil alih pengelolaan resource-resource ini tanpa harus menghapus dan membuat ulangnya. Dilakukan dengan benar, import adalah jembatan yang mulus antara infrastruktur manual dan infrastruktur as code.
Apa yang Import Lakukan (dan Tidak Lakukan) #
YANG IMPORT LAKUKAN:
✓ Membaca kondisi aktual resource dari cloud provider
✓ Menambahkan resource ke state Terraform
✓ Memungkinkan Terraform mengelola resource ini ke depannya
YANG IMPORT TIDAK LAKUKAN:
✗ Membuat atau mengubah konfigurasi .tf secara otomatis
(kamu harus tulis sendiri — kecuali pakai -generate-config-out)
✗ Mengubah resource yang ada di cloud sedikitpun
✗ Menjamin konfigurasi .tf yang kamu tulis sudah sesuai
(butuh terraform plan untuk verifikasi)
Menemukan Resource ID untuk Import #
Setiap resource memerlukan ID unik yang dikenali provider untuk proses import. Format ID berbeda-beda per resource type.
# AWS: Cara menemukan resource ID
# EC2 Instance — gunakan instance ID
aws ec2 describe-instances --query 'Reservations[].Instances[].InstanceId'
# Output: ["i-0abcdef1234567890"]
# VPC — gunakan VPC ID
aws ec2 describe-vpcs --query 'Vpcs[].VpcId'
# Output: ["vpc-0abcdef1234567890"]
# S3 Bucket — gunakan nama bucket
aws s3api list-buckets --query 'Buckets[].Name'
# Output: ["my-existing-bucket"]
# RDS Instance — gunakan DB identifier
aws rds describe-db-instances --query 'DBInstances[].DBInstanceIdentifier'
# Output: ["production-database"]
# Security Group — gunakan security group ID
aws ec2 describe-security-groups --query 'SecurityGroups[].GroupId'
# Output: ["sg-0abcdef1234567890"]
FORMAT ID UMUM DI BERBAGAI RESOURCE:
aws_instance → i-0abcdef1234567890
aws_vpc → vpc-0abcdef1234567890
aws_subnet → subnet-0abcdef1234567890
aws_security_group → sg-0abcdef1234567890
aws_s3_bucket → nama-bucket (bukan ARN)
aws_rds_instance → db-identifier (bukan ARN)
aws_iam_role → nama-role
aws_route53_record → ZONE_ID_RECORD-NAME_TYPE
aws_ecs_service → cluster-name/service-name
Metode 1: Import via CLI #
Metode klasik menggunakan perintah terraform import di command line.
# Format: terraform import <resource_address> <resource_id>
# Langkah 1: Tulis blok resource kosong (atau dengan konfigurasi)
# main.tf:
resource "aws_instance" "web" {
# Isi ini setelah import
}
# Langkah 2: Import
terraform import aws_instance.web i-0abcdef1234567890
# Output:
# aws_instance.web: Importing from ID "i-0abcdef1234567890"...
# aws_instance.web: Import prepared!
# Prepared aws_instance for import
# aws_instance.web: Refreshing state... [id=i-0abcdef1234567890]
#
# Import successful!
# Langkah 3: Lihat semua atribut yang tersimpan di state
terraform state show aws_instance.web
# Langkah 4: Lengkapi konfigurasi berdasarkan output state show
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.micro"
subnet_id = "subnet-0abcdef1234"
vpc_security_group_ids = ["sg-0abcdef1234567890"]
tags = {
Name = "web-server"
Environment = "production"
}
}
# Langkah 5: Verifikasi
terraform plan
# Hasil yang diharapkan: "No changes. Your infrastructure matches the configuration."
Metode 2: Import Blok Deklaratif (Terraform 1.5+) #
Blok import dalam konfigurasi lebih deklaratif, bisa di-commit ke version control, dan bisa digunakan bersama -generate-config-out.
# import.tf — file khusus untuk mendefinisikan import
import {
to = aws_instance.web
id = "i-0abcdef1234567890"
}
import {
to = aws_vpc.main
id = "vpc-0abcdef1234567890"
}
import {
to = aws_security_group.web
id = "sg-0abcdef1234567890"
}
# Generate konfigurasi otomatis berdasarkan kondisi aktual di cloud
terraform plan -generate-config-out=generated_resources.tf
# Output: file generated_resources.tf berisi konfigurasi yang di-generate
# Review file ini — mungkin ada atribut yang perlu disesuaikan
# Apply import
terraform apply
# Setelah selesai, hapus blok import (sudah tidak diperlukan)
# dan pindahkan konfigurasi dari generated_resources.tf ke file yang tepat
Import Massal: Strategi untuk Infrastruktur Besar #
Mengimport puluhan atau ratusan resource satu per satu tidak praktis. Ada strategi yang lebih efisien.
# Strategi 1: Script bash untuk import massal
#!/bin/bash
# Dapatkan semua instance ID
INSTANCES=$(aws ec2 describe-instances \
--filters "Name=tag:ManagedBy,Values=manual" \
--query 'Reservations[].Instances[].InstanceId' \
--output text)
# Import setiap instance
for INSTANCE_ID in $INSTANCES; do
# Buat nama resource dari tag Name
NAME=$(aws ec2 describe-instances \
--instance-ids $INSTANCE_ID \
--query 'Reservations[0].Instances[0].Tags[?Key==`Name`].Value' \
--output text | tr '[:upper:]' '[:lower:]' | tr ' ' '_')
echo "Importing $NAME ($INSTANCE_ID)..."
terraform import "aws_instance.$NAME" "$INSTANCE_ID"
done
# Strategi 2: for_each dalam blok import (Terraform 1.7+)
locals {
instances = {
web_1 = "i-0abcdef1234567890"
web_2 = "i-0abcdef2345678901"
worker_1 = "i-0abcdef3456789012"
}
}
import {
for_each = local.instances
to = aws_instance.servers[each.key]
id = each.value
}
resource "aws_instance" "servers" {
for_each = local.instances
ami = var.ami_id
instance_type = "t3.micro"
}
Jebakan Umum Saat Import #
# JEBAKAN 1: Konfigurasi tidak cocok dengan kondisi aktual
# Setelah import, terraform plan menampilkan perubahan
# → konfigurasi .tf berbeda dari kondisi aktual
#
# terraform plan output:
# ~ resource "aws_instance" "web" {
# ~ instance_type = "t3.micro" -> "t3.small"
# }
#
# Ini berarti instance aktualnya t3.small, bukan t3.micro seperti yang kamu tulis
# Sesuaikan konfigurasi .tf dengan kondisi aktual
# JEBAKAN 2: Import resource dengan computed attributes
# Beberapa atribut hanya bisa diketahui setelah resource ada
# Jangan tulis nilai yang bisa berubah atau tidak deterministik di konfigurasi
# JEBAKAN 3: Import resource yang sudah punya dependency
# Jika VPC di-import tapi subnet belum, dependency graph tidak lengkap
# Import selalu dimulai dari resource "pondasi" (VPC, IAM role, dll.)
# sebelum resource yang bergantung padanya
# JEBAKAN 4: Lupa hapus blok import setelah selesai
# Blok import yang dibiarkan tidak menyebabkan error,
# tapi membuang waktu di setiap plan karena Terraform mencoba import ulang
Ringkasan #
- Import tidak mengubah resource di cloud — ia hanya menambahkan resource ke state Terraform.
- Import tidak membuat konfigurasi .tf otomatis (kecuali dengan
-generate-config-out) — kamu harus tulis konfigurasi sendiri lalu verifikasi denganterraform plan.- Tujuan akhir import yang benar:
terraform planmenampilkan “No changes” setelah import selesai.- Blok
importdeklaratif (Terraform 1.5+) lebih clean dari CLI command — bisa di-commit, bisa di-review, bisa digunakan bersama-generate-config-out.- Import dari resource pondasi dulu — VPC sebelum subnet, subnet sebelum instance — agar dependency graph terbentuk dengan benar.
- Hapus blok import setelah selesai — resource sudah di state, blok import tidak diperlukan lagi.