State #
State adalah konsep yang paling krusial — sekaligus paling sering disalahpahami — di Terraform. Semua hal yang berjalan baik atau buruk dalam workflow Terraform bermuara pada state. Tanpa pemahaman yang tepat tentang state, kamu akan kesulitan men-debug masalah, takut menjalankan apply, dan tidak tahu harus mulai dari mana saat ada yang salah. Bagian ini akan membongkar apa sebenarnya state itu, bagaimana Terraform menggunakannya, dan bagaimana cara mengelolanya dengan aman.
Apa itu State #
State adalah file JSON yang menyimpan pemetaan antara resource yang kamu definisikan di konfigurasi Terraform dan resource yang benar-benar ada di cloud provider. File ini bernama terraform.tfstate dan secara default disimpan di direktori yang sama dengan konfigurasimu.
// terraform.tfstate — contoh potongan isinya
{
"version": 4,
"terraform_version": "1.6.0",
"serial": 5,
"resources": [
{
"type": "aws_instance",
"name": "web",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"mode": "managed",
"instances": [
{
"attributes": {
"id": "i-0abcdef1234567890",
"ami": "ami-0abcdef1234567890",
"instance_type": "t3.micro",
"public_ip": "54.123.45.67",
"private_ip": "10.0.1.42",
"tags": {
"Name": "web-server"
}
}
}
]
}
]
}
State menyimpan semua atribut resource — termasuk atribut yang baru tersedia setelah resource dibuat (seperti public_ip dan id yang digenerate AWS). Ini berarti state bukan hanya sekadar catatan — ia adalah representasi lengkap dari apa yang Terraform kelola.
Informasi yang Disimpan di State #
| Informasi | Contoh | Fungsi |
|---|---|---|
| Resource identity | aws_instance.web → i-0abcdef1234567890 | Pemetaan config ↔ real resource |
| Atribut lengkap | public_ip, arn, id | Referensi antar resource |
| Dependency | aws_subnet.public bergantung aws_vpc.main | Dependency graph |
| Provider config | hashicorp/aws versi 5.31.0 | Menentukan provider yang mengelola |
| Serial number | 5 | Optimistic locking untuk concurrency |
Mengapa State Dibutuhkan #
Tanpa state, Terraform tidak punya cara untuk mengetahui resource mana yang sudah ada, apa konfigurasinya saat ini, dan apa yang perlu diubah. State memecahkan tiga masalah fundamental.
flowchart TD
A["Tiga masalah tanpa state"] --> B["1. Tahu resource apa yang ada"]
A --> C["2. Tahu atribut apa yang dimiliki"]
A --> D["3. Performa plan yang cepat"]
B --> E["State menyimpan mapping\nantara config dan real resource\n→ Terraform tahu resource mana\nyang harus di-manage"]
C --> F["State menyimpan atribut\ndari resource yang ada\n→ Referensi antar resource\nbisa bekerja"]
D --> G["State menyimpan cache\natribut terakhir\n→ Tidak perlu query API\nuntuk setiap plan"]
style A fill:#ffebee,stroke:#c62828
style E fill:#e8f5e9,stroke:#2e7d32
style F fill:#e8f5e9,stroke:#2e7d32
style G fill:#e8f5e9,stroke:#2e7d32Tanpa state — Terraform harus me-query semua resource ke API cloud provider setiap kali plan. Untuk infrastruktur dengan ratusan resource, ini bisa memakan waktu berpuluh-puluh menit. Dan Terraform masih tidak tahu resource mana yang sengaja dibuat oleh Terraform vs yang dibuat manual.
Dengan state — Terraform tahu persis: aws_instance.web ada dengan ID i-0abcdef1234567890, instance_type t3.micro, public_ip 54.123.45.67. Plan bisa dihitung dalam detik karena hanya perlu membandingkan state dengan konfigurasi.
# Tidak punya state → Terraform tidak bisa menjawab:
# "Apakah aws_instance.web sudah ada?"
# → Harus query AWS untuk semua resource
# → Lambat untuk infrastruktur besar
# → Tidak tahu atribut mana yang kamu set vs yang AWS set
# Punya state → Terraform tahu:
# "aws_instance.web ada dengan ID i-0abcdef1234567890"
# → Plan cepat
# → Tahu persis apa yang berubah
# → Bisa hitung dependency graph dengan akurat
Local State vs Remote State #
Secara default, state disimpan secara lokal di terraform.tfstate. Ini cukup untuk eksperimen dan belajar, tapi tidak aman dan tidak bisa untuk kolaborasi tim.
Local State #
# Tidak perlu konfigurasi apapun — ini default
# File terraform.tfstate ada di direktori yang sama dengan .tf files
# MASALAH:
# 1. File bisa mengandung secret (password, API key) → tidak boleh di-commit ke Git
# 2. Tidak bisa diakses oleh anggota tim lain
# 3. Tidak ada locking — dua orang apply sekaligus = state corrupt
# 4. Tidak ada backup — hard disk rusak = state hilang
Remote State #
Remote state menyimpan file state di backend terpusat yang bisa diakses oleh semua anggota tim. Semua anggota tim membaca dan menulis state yang sama.
# Contoh: AWS S3 sebagai remote backend
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "production/terraform.tfstate"
region = "ap-southeast-1"
encrypt = true # Enkripsi at-rest
dynamodb_table = "terraform-lock" # Untuk state locking
}
}
# Contoh: Google Cloud Storage
terraform {
backend "gcs" {
bucket = "my-terraform-state"
prefix = "production"
}
}
# Contoh: Terraform Cloud (managed backend)
terraform {
cloud {
organization = "my-company"
workspaces {
name = "production"
}
}
}
flowchart TD
A["Pilih backend"] --> B{"Environment?"}
B -->|"Belajar / eksperimen"| C["Local state\n(default)"]
B -->|"Tim kecil"| D["S3 + DynamoDB\natau GCS"]
B -->|"Tim besar / enterprise"| E["Terraform Cloud\natau Spacelift"]
C --> F["Tidak perlu config\nbackup manual"]
D --> G["Versioning + locking\nbutuh maintenance"]
E --> H["Managed + RBAC + UI\nberbayar"]
style C fill:#fff3e0,stroke:#e65100
style D fill:#e3f2fd,stroke:#1565c0
style E fill:#e8f5e9,stroke:#2e7d32Perbandingan Backend #
| Backend | Locking | Versioning | Enkripsi | Cocok untuk |
|---|---|---|---|---|
| Local | Tidak | Tidak | Tidak | Belajar, eksperimen |
| S3 | DynamoDB | S3 versioning | AES-256 | AWS production |
| GCS | Built-in | GCS versioning | Built-in | GCP production |
| Terraform Cloud | Built-in | Built-in | Built-in | Enterprise, managed |
| Consul | Built-in | KV store | TLS | On-premise |
State Locking #
State locking mencegah dua proses Terraform mengubah state secara bersamaan. Tanpa locking, dua orang yang menjalankan terraform apply di waktu yang sama bisa menghasilkan state corrupt.
sequenceDiagram
participant A as Developer A
participant S3 as S3 Backend
participant B as Developer B
A->>S3: terraform apply → acquire lock
S3-->>A: Lock acquired ✓
B->>S3: terraform apply → try acquire lock
S3-->>B: Lock denied ✗ (already locked)
Note over B: Error: state is locked
A->>S3: Apply complete → release lock
S3-->>A: Lock released ✓
B->>S3: terraform apply → acquire lock
S3-->>B: Lock acquired ✓ (sekarang bisa)# Normal operation — locking terjadi otomatis
$ terraform apply
# Lock acquired automatically...
# ... apply ...
# Lock released automatically.
# Force unlock — HANYA jika lock tidak terlepas karena crash
$ terraform force-unlock LOCK_ID
# Dapatkan LOCK_ID dari error message
# GUNAKAN DENGAN HATI-HATI — pastikan tidak ada proses lain yang berjalan
Jangan pernah menjalankan terraform force-unlock kecuali kamu yakin tidak ada proses Terraform lain yang sedang berjalan. Force unlock pada lock yang masih aktif bisa menyebabkan state corrupt jika dua proses menulis state secara bersamaan.State Bukan untuk Diedit Manual #
State adalah file yang dikelola sepenuhnya oleh Terraform. Mengeditnya secara manual — bahkan untuk “perbaikan kecil” — hampir selalu berakhir buruk karena state memiliki format internal yang spesifik, checksum yang harus konsisten, dan serial number yang harus berurutan.
# ANTI-PATTERN: Edit terraform.tfstate langsung dengan text editor
# Ini bisa menyebabkan:
# - State corrupt yang tidak bisa di-recover
# - Resource orphan (ada di cloud, tidak ada di state)
# - Dependency yang rusak
# - Serial number conflict
# BENAR: Gunakan perintah Terraform untuk manipulasi state
terraform state list # Lihat semua resource di state
terraform state show aws_instance.web # Lihat detail satu resource
terraform state rm aws_instance.web # Hapus resource dari state (tanpa destroy infra)
terraform state mv \ # Rename / pindah resource di state
aws_instance.web \
aws_instance.app_server
terraform state pull # Download state dari remote backend
terraform state push backup.tfstate # Upload state ke remote backend
Mengapa Harus Pakai terraform state Command
#
Setiap perintah terraform state memastikan:
- Serial number di-increment dengan benar
- Checksum di-update
- Dependency graph tetap valid
- Perubahan di-propagate ke remote backend (jika ada)
Editing manual melanggar semua validasi ini — mirip dengan mengedit database langsung tanpa melalui ORM.
Risiko Kehilangan State #
Kehilangan state file adalah salah satu skenario paling berbahaya di Terraform. Tanpa state, Terraform kehilangan peta yang menghubungkan konfigurasi dengan resource nyata.
flowchart TD
A["State hilang!"] --> B["terraform plan"]
B --> C["Terraform tidak tahu\nresource mana yang ada"]
C --> D["Plan menunjukkan:\n+47 resource to create"]
D --> E{"terraform apply?"}
E -->|"Ya"| F["ERROR: resource sudah ada\ndi cloud, tidak bisa duplikat"]
E -->|"Tidak"| G["Harus import ulang\nsemua resource manual"]
F --> H["State baru berisi\nresource yang gagal"]
G --> I["terraform import aws_instance.web i-0abc...\n(untuk SETIAP resource)"]
style A fill:#ffebee,stroke:#c62828
style F fill:#ffebee,stroke:#c62828
style G fill:#fff3e0,stroke:#e65100
style I fill:#fff3e0,stroke:#e65100Pencegahan #
# 1. Gunakan remote backend dengan versioning
# S3 versioning bisa di-restore ke versi sebelumnya
# 2. Backup state sebelum operasi berisiko
$ terraform state pull > backup-$(date +%Y%m%d).tfstate
# 3. Enable S3 versioning
# (pastikan bucket policy mengizinkan restore)
# 4. Monitor state file — jangan sampai terhapus
# 5. Jangan hapus state kecuali kamu tahu persis apa akibatnya
Recovery dari State Hilang #
# Opsi 1: Restore dari S3 versioning
$ aws s3api list-object-versions \
--bucket my-terraform-state \
--prefix production/terraform.tfstate
# Lalu restore versi terakhir yang valid
# Opsi 2: Import ulang semua resource
# (hanya jika backup tidak tersedia)
$ terraform import aws_vpc.main vpc-0abc1234
$ terraform import aws_subnet.public subnet-0def5678
$ terraform import aws_instance.web i-0abcdef1234567890
# ... untuk setiap resource — sangat melelahkan
# Opsi 3: Terraform Cloud (jika menggunakan)
# Terraform Cloud punya built-in state history dan rollback
terraform state Subcommands
#
Berikut daftar lengkap perintah terraform state yang perlu kamu ketahui.
| Perintah | Fungsi | Kapan digunakan |
|---|---|---|
state list | Lihat daftar resource di state | Audit, debugging |
state show <addr> | Lihat detail atribut satu resource | Debugging, cek nilai |
state mv <src> <dst> | Pindah/rename resource di state | Refactoring, pindah module |
state rm <addr> | Hapus resource dari state | Unmanage resource tanpa destroy |
state pull | Download state dari remote backend | Backup, debugging |
state push <file> | Upload state ke remote backend | Restore dari backup |
import <addr> <id> | Tambah resource existing ke state | Manage resource yang sudah ada |
# Contoh penggunaan umum:
# Lihat semua resource yang dikelola Terraform
$ terraform state list
aws_vpc.main
aws_subnet.public[0]
aws_subnet.public[1]
aws_instance.web
aws_s3_bucket.data
# Lihat detail satu resource
$ terraform state show aws_instance.web
# resource "aws_instance" "web" {
# ami = "ami-0abcdef1234567890"
# instance_type = "t3.micro"
# public_ip = "54.123.45.67"
# ...
# }
# Hapus resource dari state tanpa menghapus dari cloud
# Berguna saat ingin "berhenti mengelola" resource tertentu
$ terraform state rm aws_instance.legacy_server
# Resource masih ada di AWS, tapi Terraform tidak lagi mengelolanya
Ringkasan #
- State adalah peta antara konfigurasi dan realita — Terraform membandingkan state dengan konfigurasi untuk menentukan apa yang perlu berubah.
- State menyimpan semua atribut resource termasuk yang digenerate oleh cloud provider — ini memungkinkan referensi antar resource bekerja.
- Tanpa state, Terraform buta — ia tidak bisa tahu resource apa yang sudah ada tanpa query ke semua API provider, yang sangat lambat.
- Local state cukup untuk belajar — tapi remote state (S3, GCS, Terraform Cloud) adalah keharusan untuk tim dan production.
- State locking mencegah dua proses menulis state secara bersamaan — pastikan backend mendukung locking (DynamoDB untuk S3, built-in untuk GCS/Terraform Cloud).
- Jangan edit state manual — gunakan
terraform statesubcommand untuk semua manipulasi state agar checksum dan serial number tetap valid.- Kehilangan state adalah darurat — lindungi dengan remote backend yang ter-versioning, backup rutin, dan jangan pernah hapus state tanpa tahu akibatnya.