Migration #

Seiring bertumbuhnya infrastruktur dan tim, kebutuhan untuk memindahkan state sering muncul. Migrasi dari local ke remote backend saat onboarding anggota tim baru, memecah state monolitik yang terlalu besar, atau pindah dari satu cloud provider ke yang lain — semuanya melibatkan migrasi state. Migrasi yang tidak hati-hati bisa menyebabkan resource orphan atau state yang tidak sinkron. Artikel ini memandu prosesnya secara step-by-step.

flowchart TD
    A["🔄 Perlu Migrasi State?"] --> B{"Jenis Migrasi?"}
    B --> C["Local → Remote"]
    B --> D["Remote → Remote"]
    B --> E["Monolitik → Split"]
    C --> F["terraform init\n-migrate-state"]
    D --> G["Pull backup →\nUpdate backend →\nInit migrate-state"]
    E --> H["terraform state mv\n-state-out"]

    style A fill:#3b82f6,stroke:#1e40af,color:#fff
    style B fill:#f59e0b,stroke:#d97706,color:#fff
    style C fill:#3b82f6,stroke:#1e40af,color:#fff
    style D fill:#3b82f6,stroke:#1e40af,color:#fff
    style E fill:#3b82f6,stroke:#1e40af,color:#fff
    style F fill:#10b981,stroke:#059669,color:#fff
    style G fill:#10b981,stroke:#059669,color:#fff
    style H fill:#10b981,stroke:#059669,color:#fff

Migrasi dari Local ke Remote Backend #

Ini adalah migrasi paling umum — proyek yang dimulai dengan local state perlu dipindahkan ke S3 atau backend lain saat tim mulai bertambah.

LANGKAH MIGRASI LOCAL → S3:

1. Buat S3 bucket dan DynamoDB table (jika belum ada)
2. Tambahkan konfigurasi backend ke konfigurasi Terraform
3. Jalankan terraform init -migrate-state
4. Verifikasi state berhasil dipindahkan
5. Commit perubahan konfigurasi backend ke Git
6. Hapus terraform.tfstate lokal (sudah tidak diperlukan)
# Langkah 2: Tambahkan backend configuration ke providers.tf atau backend.tf

# SEBELUM (tidak ada backend block — menggunakan local):
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

# SESUDAH (dengan remote backend):
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "production/terraform.tfstate"
    region         = "ap-southeast-1"
    dynamodb_table = "terraform-state-lock"
    encrypt        = true
  }
}
# Langkah 3: Jalankan init dengan flag migrate-state
terraform init -migrate-state

# Output:
# Initializing the backend...
# Do you want to copy existing state to the new backend?
#   Pre-existing state was found while migrating the previous "local" backend to
#   the newly configured "s3" backend. An existing non-empty state already exists
#   in the new backend. The two states have been merged. Please check the output
#   above to ensure this is correct before continuing.
#
#   Enter a value: yes

# Verifikasi state berhasil dipindahkan
terraform state list  # Harus menampilkan resource yang sama seperti sebelumnya

# Langkah 6: Hapus state lokal (setelah yakin remote state berhasil)
rm terraform.tfstate terraform.tfstate.backup

Migrasi Antar Remote Backend #

Terkadang perlu berpindah dari satu remote backend ke backend lain — misalnya dari Terraform Cloud ke S3, atau dari S3 ke GCS.

# Langkah 1: Pull state saat ini ke lokal sebagai backup
terraform state pull > state-backup-$(date +%Y%m%d-%H%M%S).tfstate

# Langkah 2: Update konfigurasi backend ke backend baru
# (edit backend.tf)

# Langkah 3: Jalankan init dengan migrate-state
terraform init -migrate-state

# Langkah 4: Verifikasi
terraform plan  # Seharusnya "No changes"

# Langkah 5: Simpan backup state di tempat yang aman
# Jangan hapus backup sampai yakin migrasi berhasil

Memecah State Monolitik #

State yang terlalu besar — ratusan resource dalam satu state file — menjadi masalah karena setiap apply harus memproses semua resource sekaligus, plan menjadi lambat, dan risiko apply yang gagal di tengah jalan semakin besar.

SKENARIO: Memecah state monolitik production menjadi networking + compute

State SEBELUM (satu file, semua resource):
  aws_vpc.main
  aws_subnet.public[0]
  aws_subnet.public[1]
  aws_subnet.private[0]
  aws_subnet.private[1]
  aws_internet_gateway.main
  aws_instance.web[0]
  aws_instance.web[1]
  aws_instance.worker[0]
  aws_rds_instance.main
  ...

State SESUDAH (dua file terpisah):
  networking/terraform.tfstate:
    aws_vpc.main
    aws_subnet.public[0..1]
    aws_subnet.private[0..1]
    aws_internet_gateway.main

  compute/terraform.tfstate:
    aws_instance.web[0..1]
    aws_instance.worker[0]
    aws_rds_instance.main
flowchart TD
    subgraph MONO["❌ State Monolitik"]
        direction TB
        M1["🗂️ Semua Resource\nsatu state file"]
        M2["aws_vpc.main"]
        M3["aws_subnet.public"]
        M4["aws_instance.web"]
        M5["aws_rds_instance.main"]
        M1 --- M2
        M1 --- M3
        M1 --- M4
        M1 --- M5
    end

    subgraph SPLIT["✅ State Terpisah"]
        direction LR
        subgraph NET["Networking State"]
            N1["aws_vpc.main"]
            N2["aws_subnet.public"]
            N3["aws_internet_gateway"]
        end
        subgraph COMP["Compute State"]
            C1["aws_instance.web"]
            C2["aws_rds_instance.main"]
        end
    end

    MONO -->|"terraform state mv\n-state-out"| SPLIT

    style MONO fill:#ffebee,stroke:#c62828
    style SPLIT fill:#e8f5e9,stroke:#2e7d32
    style NET fill:#e3f2fd,stroke:#1565c0
    style COMP fill:#fff3e0,stroke:#e65100
# CARA MEMECAH STATE — menggunakan terraform state mv

# 1. Siapkan direktori baru untuk workspace compute
mkdir -p environments/production/compute
cd environments/production/compute

# Buat konfigurasi Terraform untuk compute resources
# (pindahkan resource yang relevan dari konfigurasi monolitik)

# 2. Inisialisasi workspace baru dengan remote backend yang berbeda
terraform init

# 3. Pindahkan resource dari state lama ke state baru
# (jalankan dari direktori monolitik)
cd ../  # kembali ke direktori monolitik

terraform state mv \
  -state-out=compute/terraform.tfstate \
  aws_instance.web[0] \
  aws_instance.web[0]

# Untuk banyak resource, gunakan script:
for i in 0 1; do
  terraform state mv \
    -state-out="../compute/terraform.tfstate" \
    "aws_instance.web[$i]" \
    "aws_instance.web[$i]"
done

# 4. Push state yang sudah dimodifikasi ke remote backend
cd ../compute
terraform state push terraform.tfstate

# 5. Verifikasi kedua workspace
terraform state list  # compute
cd ../networking
terraform state list  # networking

Backup Sebelum Migrasi #

# SELALU backup state sebelum migrasi apapun

# Pull state terkini
terraform state pull > pre-migration-backup.tfstate

# Verifikasi backup bisa dibaca
cat pre-migration-backup.tfstate | python3 -m json.tool > /dev/null
echo "Backup valid: $?"

# Simpan di tempat aman (bukan hanya lokal)
aws s3 cp pre-migration-backup.tfstate \
  s3://my-backup-bucket/terraform-state-backups/$(date +%Y%m%d-%H%M%S).tfstate

Rollback Jika Migrasi Bermasalah #

# Jika migrasi menghasilkan state yang tidak benar:

# Opsi 1: Restore dari backup
terraform state push pre-migration-backup.tfstate
# PERHATIAN: Ini menimpa state saat ini dengan backup

# Opsi 2: Revert backend configuration
# - Hapus atau comment blok backend dari konfigurasi
# - Jalankan terraform init -reconfigure
# - Terraform kembali ke local state atau backend sebelumnya

# Opsi 3: Jika pakai S3 dengan versioning aktif
# Restore versi sebelumnya dari S3 console atau CLI
aws s3api list-object-versions \
  --bucket my-terraform-state \
  --prefix production/terraform.tfstate

aws s3api get-object \
  --bucket my-terraform-state \
  --key production/terraform.tfstate \
  --version-id VERSION_ID \
  restored-state.tfstate


Pre-Migration Checklist #

Sebelum migrasi state, persiapkan dengan matang untuk menghindari kehilangan data.

# CHECKLIST SEBELUM MIGRASI STATE:

# 1. Backup state saat ini
terraform state pull > backup-$(date +%Y%m%d-%H%M%S).tfstate
ls -la backup-*.tfstate  # Verifikasi file ada dan ukurannya wajar

# 2. Pastikan tidak ada perubahan tertunda
terraform plan
# Harusnya "No changes" — jika ada, apply dulu atau resolve

# 3. Pastikan tidak ada lock aktif
terraform state pull  # Jika berhasil, tidak ada lock

# 4. Verifikasi tidak ada yang sedang bekerja
# Cek CI/CD pipeline, komunikasi dengan tim

# 5. Siapkan rollback plan
cp backup-*.tfstate emergency-rollback.tfstate
flowchart TD
    A["Pre-Migration
Checklist"] --> B["Backup state"]
    B --> C["Verify plan
= No changes"]
    C --> D["Check no
active locks"]
    D --> E["Coordinate
with team"]
    E --> F["Execute
migration"]
    F --> G{"Success?"}
    G -->|"Ya"| H["Verify:
terraform plan = No changes"]
    G -->|"Tidak"| I["Rollback:
terraform state push backup"]

    style A fill:#e3f2fd,stroke:#1565c0
    style H fill:#e8f5e9,stroke:#2e7d32
    style I fill:#ffebee,stroke:#c62828

Backend Migration #

Memindahkan state dari satu backend ke backend lain adalah operasi berisiko.

# Scenario: Pindah dari local ke S3

# 1. Konfigurasi backend baru (belum di-init)
terraform {
  backend "s3" {
    bucket = "my-terraform-state"
    key    = "prod/terraform.tfstate"
    region = "ap-southeast-1"
  }
}

# 2. Jalankan init — Terraform akan mendeteksi backend berubah
terraform init
# Output: "Backend configuration changed. Do you want to copy existing state?"
# Answer: yes

# 3. Terraform otomatis copy state dari local ke S3
# 4. Verifikasi: terraform plan harus "No changes"

# ROLLBACK jika ada masalah:
# 1. Ubah backend config kembali ke local
# 2. Jalankan terraform init
# 3. Copy state backup ke direktori lokal
flowchart TD
    A["State di
Local"] --> B["terraform init"]
    B --> C{"Copy state
ke backend baru?"}
    C -->|"Yes"| D["State copied
to S3"]
    C -->|"No"| E["State tetap
di local"]
    D --> F["Verify:
terraform plan
= No changes"]
    F --> G{"OK?"}
    G -->|"Ya"| H["Selesai ✅"]
    G -->|"Tidak"| I["Rollback ❌"]

    style A fill:#fff3e0,stroke:#e65100
    style D fill:#e8f5e9,stroke:#2e7d32
    style H fill:#e8f5e9,stroke:#2e7d32
    style I fill:#ffebee,stroke:#c62828

State File Security #

# State file mengandung SEMUA informasi resource:
# - ID, ARN, IP address
# - Password, API keys (jika didefinisikan di Terraform)
# - Semua attribute dari semua managed resource

# JANGAN:
# - Commit state ke Git
# - Simpan di local filesystem untuk production
# - Share state file tanpa enkripsi

# HARUS:
# - Simpan di encrypted backend (S3+KMS, GCS, TFC)
# - Enable access logging
# - Restrict IAM access (hanya CI/CD role)

Ringkasan #

  • Backup sebelum migrasi apapunterraform state pull > backup.tfstate adalah langkah pertama yang tidak boleh dilewati.
  • terraform init -migrate-state untuk pindah antar backend — Terraform akan menawarkan untuk menyalin state lama ke backend baru.
  • State monolitik yang besar harus dipecah menjadi beberapa workspace untuk efisiensi — gunakan terraform state mv -state-out untuk memindahkan resource antar state.
  • S3 versioning yang aktif adalah safety net terbaik — memungkinkan restore state ke versi manapun jika terjadi kesalahan.
  • Verifikasi setelah migrasi dengan terraform plan — jika output “No changes”, migrasi berhasil dan tidak ada resource yang hilang.
  • Jangan hapus state lama sampai yakin state baru berfungsi dengan benar di semua operasi.

← Sebelumnya: Locking   Berikutnya: Import →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact