Lifecycle Management #
Membuat resource dengan Terraform itu mudah. Yang lebih menantang adalah mengelolanya setelah dibuat — terutama ketika perlu diubah, dipindahkan, atau dihapus tanpa menyebabkan gangguan pada infrastruktur yang sedang berjalan. Terraform menyediakan beberapa mekanisme untuk ini: lifecycle block yang mengontrol perilaku resource, moved block untuk refactoring tanpa destroy, dan removed block untuk decommission yang terkontrol. Memahami alat-alat ini membuat kamu bisa melakukan perubahan besar pada konfigurasi dengan aman.
Lifecycle Block: Kontrol Perilaku Resource #
# Empat opsi lifecycle yang paling berguna
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
lifecycle {
# 1. create_before_destroy
# Buat resource baru SEBELUM menghapus yang lama
# Berguna untuk resource yang tidak boleh ada jedanya
create_before_destroy = true
# 2. prevent_destroy
# Terraform error jika ada yang mencoba destroy resource ini
# Perlindungan untuk resource kritikal (database production, dll.)
prevent_destroy = true
# 3. ignore_changes
# Abaikan perubahan pada atribut tertentu
# Berguna jika atribut diubah di luar Terraform
ignore_changes = [
tags["LastModified"],
user_data,
]
# 4. replace_triggered_by (Terraform 1.2+)
# Trigger replacement saat resource lain berubah
replace_triggered_by = [
aws_launch_template.web.id
]
}
}
create_before_destroy: Zero-Downtime Replacement #
# Tanpa create_before_destroy (default):
# 1. Hapus resource lama
# 2. Buat resource baru
# → Ada jeda di mana tidak ada resource yang jalan (downtime)
# ANTI-PATTERN: Resource yang butuh high availability tanpa create_before_destroy
resource "aws_lb_target_group" "app" {
name = "production-tg"
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id
# Jika nama TG perlu diubah → destroy dulu, baru create → downtime
}
# BENAR: Dengan create_before_destroy dan name_prefix
resource "aws_lb_target_group" "app" {
name_prefix = "app-" # AWS generate suffix unik
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id
lifecycle {
create_before_destroy = true
# 1. Buat TG baru dengan nama baru
# 2. Pindahkan listener ke TG baru
# 3. Hapus TG lama
# → Tidak ada downtime
}
}
moved Block: Refactoring Tanpa Destroy #
moved block adalah cara yang tepat untuk mengubah address resource di state tanpa menghapus dan membuat ulang resource di cloud. Berguna saat refactoring konfigurasi — rename resource, pindah ke module, atau reorganisasi struktur.
# Skenario 1: Rename resource
# Sebelum: resource "aws_instance" "server"
# Sesudah: resource "aws_instance" "web_server"
moved {
from = aws_instance.server
to = aws_instance.web_server
}
# Terraform akan memperbarui state (rename address)
# tanpa menghapus dan membuat ulang instance di AWS
# Skenario 2: Pindah resource ke dalam module
# Sebelum: resource "aws_vpc" "main" di root module
# Sesudah: dipindah ke module "networking"
moved {
from = aws_vpc.main
to = module.networking.aws_vpc.main
}
# terraform plan akan menampilkan:
# # aws_vpc.main has moved to module.networking.aws_vpc.main
# → Tidak ada resource yang dihapus atau dibuat ulang
# Skenario 3: Pindah dari count ke for_each
# Sebelum: resource "aws_subnet" "public" count = 3
# Sesudah: resource "aws_subnet" "public" for_each
moved {
from = aws_subnet.public[0]
to = aws_subnet.public["ap-southeast-1a"]
}
moved {
from = aws_subnet.public[1]
to = aws_subnet.public["ap-southeast-1b"]
}
moved {
from = aws_subnet.public[2]
to = aws_subnet.public["ap-southeast-1c"]
}
moved block bisa dihapus setelah semua environment sudah di-apply dan state sudah diperbarui. Tapi sebaiknya biarkan beberapa sprint sebelum dihapus agar environment yang jarang di-apply juga kebagian.removed Block: Decommission yang Terkontrol #
removed block (Terraform 1.7+) memungkinkan kamu menghapus resource dari konfigurasi dan state tanpa menghapus resource aktual di cloud — berguna untuk “melepaskan” resource dari kontrol Terraform tanpa menghancurkannya.
# Skenario: Database lama tidak lagi dikelola Terraform
# tapi tidak mau dihapus dari cloud (masih ada data)
removed {
from = aws_db_instance.legacy
lifecycle {
destroy = false # Jangan hapus dari cloud, hanya hapus dari state
}
}
# Setelah apply:
# - Resource dihapus dari state Terraform
# - Resource TETAP ada di AWS
# - Terraform tidak lagi mengelola resource ini
# Berbeda dengan destroy = true (untuk resource yang memang perlu dihapus):
removed {
from = aws_instance.deprecated_worker
lifecycle {
destroy = true # Hapus dari state DAN dari cloud
}
}
Mengelola Breaking Change di Module #
Ketika modul yang digunakan banyak tempat perlu perubahan breaking, ada cara yang lebih aman dari “langsung ubah dan semua pemanggilnya pecah”.
# Strategi: Backward compatibility dengan deprecation period
# modules/networking/main.tf — tambahkan alias untuk input yang berubah nama
variable "vpc_cidr_block" {
description = "CIDR block untuk VPC"
type = string
}
# Variable lama yang sudah deprecated — masih ada untuk backward compatibility
variable "cidr_block" {
description = "DEPRECATED: Gunakan vpc_cidr_block. Akan dihapus di v3.0"
type = string
default = null
}
locals {
# Gunakan yang baru jika ada, fallback ke yang lama
vpc_cidr = coalesce(var.vpc_cidr_block, var.cidr_block)
}
resource "aws_vpc" "main" {
cidr_block = local.vpc_cidr
}
TIMELINE DEPRECATION YANG AMAN:
v2.0 — Variable baru ditambahkan, variable lama masih ada
v2.1 — Warning ditampilkan jika masih menggunakan variable lama
v3.0 — Variable lama dihapus (di CHANGELOG dan README disebutkan)
Pemanggilnya punya waktu untuk migrasi di antara versi major.
Kapan State Surgery Dibutuhkan #
Ada situasi di mana manipulasi state manual diperlukan — ini harus jadi pilihan terakhir, bukan default.
# State surgery — gunakan dengan sangat hati-hati
# Pindahkan resource antar state (jika moved block tidak cukup)
terraform state mv \
-state=old/terraform.tfstate \
-state-out=new/terraform.tfstate \
aws_vpc.main \
aws_vpc.main
# Hapus resource dari state tanpa menghapus dari cloud
terraform state rm aws_instance.orphaned
# Import resource yang sudah ada ke state
terraform import aws_instance.existing i-0abcdef1234567890
# SELALU backup sebelum state surgery
terraform state pull > backup-$(date +%Y%m%d-%H%M%S).tfstate
# Verifikasi setelah state surgery
terraform plan # Harusnya "No changes" jika state sudah benar
Ringkasan #
create_before_destroypenting untuk resource high-availability — pastikan terpasang pada load balancer, target group, dan resource yang tidak boleh ada jedanya saat diganti.prevent_destroysebagai perlindungan terakhir untuk resource kritikal — Terraform error jika ada plan yang akan menghapus resource ini.movedblock adalah cara yang tepat untuk refactoring konfigurasi — rename resource, pindah ke module, atau ganti daricountkefor_eachtanpa destroy.removedblock untuk decommission yang terkontrol — bisa memilih apakah resource dihapus dari cloud atau hanya dilepaskan dari kontrol Terraform.- Breaking change di module butuh deprecation period — tambahkan variable baru sambil jaga yang lama, beri waktu pemanggilnya untuk migrasi sebelum variable lama dihapus.
- State surgery (
terraform state mv/rm) adalah pilihan terakhir — selalu backup state sebelum, verifikasi denganterraform plansesudah.
← Sebelumnya: Monorepo vs Multirepo Berikutnya: Scale Terraform →