Scale Terraform #
Konfigurasi Terraform yang dimulai kecil — satu main.tf, satu terraform.tfstate — bisa tumbuh hingga mengelola ratusan resource dalam satu konfigurasi. Di titik ini, masalah mulai muncul: terraform plan butuh waktu lama karena harus refresh semua resource, satu kesalahan bisa mempengaruhi infrastruktur yang tidak berhubungan, dan blast radius dari setiap apply menjadi terlalu besar. Scaling Terraform bukan soal menambah spesifikasi mesin yang menjalankan pipeline, tapi soal memecah konfigurasi berdasarkan prinsip yang tepat.
Tanda Konfigurasi Perlu Dipecah #
SINYAL BAHWA KONFIGURASI SUDAH TERLALU BESAR:
✗ terraform plan butuh lebih dari 5 menit (terlalu banyak API refresh)
✗ Satu apply mempengaruhi puluhan resource yang tidak berhubungan
✗ Tim berbeda sering konflik karena mengubah file yang sama
✗ Ada resource yang "tidak boleh disentuh" campur dengan yang rutin berubah
✗ Test perubahan kecil butuh menunggu plan seluruh infrastruktur
✗ State file lebih dari beberapa MB (ribuan resource)
✗ Tim tidak tahu lagi resource apa yang ada di konfigurasi ini
Prinsip Pemisahan: Lifecycle dan Blast Radius #
Cara paling efektif memecah konfigurasi bukan berdasarkan tipe resource, tapi berdasarkan dua pertanyaan: seberapa sering berubah, dan apa dampak jika ada yang salah?
PRINSIP LIFECYCLE:
Resource yang berubah dengan frekuensi berbeda sebaiknya dipisah.
Jarang berubah (bulan/tahun):
VPC, subnets, routing, peering
IAM roles, SCPs, organizations
DNS zones (bukan records)
→ Satu konfigurasi, apply sangat jarang
Sesekali berubah (minggu/bulan):
Cluster Kubernetes, RDS instances
Load balancers, security groups
S3 buckets, KMS keys
→ Konfigurasi terpisah per domain
Sering berubah (hari/minggu):
Kubernetes deployments
Task definitions ECS
Lambda functions
DNS records
→ Konfigurasi terpisah, bisa auto-apply
PRINSIP BLAST RADIUS:
Resource yang kritis (downtime mahal) dipisah dari yang tidak kritis.
Jika ada bug saat apply database konfigurasi,
jangan sampai mempengaruhi networking.
Pola Layering: Dependency Antar Konfigurasi #
ARSITEKTUR LAYERED:
Layer 1: Foundation (paling jarang berubah)
├── VPC, subnets, internet gateway
├── Route53 zones
├── IAM roles dasar
└── S3 bucket untuk state
Output: vpc_id, subnet_ids, route53_zone_id
Layer 2: Platform (berubah saat ada upgrade infrastruktur)
├── EKS cluster / ECS cluster
├── RDS instances
├── ElastiCache
└── Load balancers
Input: vpc_id, subnet_ids (dari layer 1)
Output: cluster_endpoint, db_endpoint, lb_dns_name
Layer 3: Application (paling sering berubah)
├── Kubernetes deployments
├── Task definitions ECS
├── DNS records (pointing ke LB dari layer 2)
└── Lambda functions
Input: cluster_endpoint, db_endpoint (dari layer 2)
Setiap layer hanya bergantung ke layer di bawahnya.
Perubahan di layer atas tidak mempengaruhi layer bawah.
# Layer 3 membaca output dari Layer 2 via remote state
data "terraform_remote_state" "platform" {
backend = "s3"
config = {
bucket = "my-terraform-state"
key = "platform/terraform.tfstate"
region = "ap-southeast-1"
}
}
resource "aws_route53_record" "app" {
zone_id = data.terraform_remote_state.platform.outputs.route53_zone_id
name = "api.example.com"
type = "CNAME"
ttl = 300
records = [data.terraform_remote_state.platform.outputs.lb_dns_name]
}
Struktur Direktori untuk Infrastruktur Besar #
infra-repo/
├── modules/ ← Shared, versioned modules
│ ├── networking/
│ ├── eks-cluster/
│ └── rds/
│
├── foundation/ ← Layer 1
│ ├── networking/
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── backend.tf
│ └── iam/
│
├── platform/ ← Layer 2
│ ├── eks/
│ ├── databases/
│ └── load-balancers/
│
├── applications/ ← Layer 3
│ ├── api-service/
│ ├── worker-service/
│ └── frontend/
│
└── scripts/
├── plan-all.sh ← Plan semua layer secara berurutan
└── apply-all.sh
# plan-all.sh — plan semua layer dengan order yang benar
#!/bin/bash
set -e
ENVIRONMENT=${1:-staging}
echo "=== Layer 1: Foundation ==="
cd foundation/networking
terraform plan -var="environment=$ENVIRONMENT"
echo "=== Layer 2: Platform ==="
cd ../../platform/eks
terraform plan -var="environment=$ENVIRONMENT"
echo "=== Layer 3: Applications ==="
cd ../../applications/api-service
terraform plan -var="environment=$ENVIRONMENT"
Paralel vs Serial Execution #
SERIAL (default untuk dependency):
Layer 1 selesai → Layer 2 mulai → Layer 3 mulai
Cocok untuk dependency yang ketat antar layer
PARALEL (untuk konfigurasi yang independen):
Layer 2: eks, databases, load-balancers bisa diapply bersamaan
Masing-masing hanya bergantung ke Layer 1 (sudah selesai)
Dalam CI/CD matrix:
jobs:
apply-platform:
strategy:
matrix:
component: [eks, databases, load-balancers]
max-parallel: 3
steps:
- run: terraform apply platform/${{ matrix.component }}/tfplan
PERHATIAN: Paralel hanya aman jika tidak ada dependency antar komponen
yang dirun paralel. Jika EKS butuh output dari databases, harus serial.
Mengelola Banyak Environment dengan Satu Konfigurasi #
# Pola: Satu konfigurasi, tiga environment, backend berbeda
# environments/dev/backend.tf
terraform {
backend "s3" {
bucket = "terraform-state-dev"
key = "platform/eks/terraform.tfstate"
region = "ap-southeast-1"
}
}
# environments/production/backend.tf
terraform {
backend "s3" {
bucket = "terraform-state-production"
key = "platform/eks/terraform.tfstate"
region = "ap-southeast-1"
}
}
# Konfigurasi utama (symlink atau shared) menggunakan variable
variable "environment" {
type = string
}
module "eks" {
source = "../../modules/eks"
cluster_name = "myapp-${var.environment}"
node_count = var.environment == "production" ? 5 : 2
instance_type = var.environment == "production" ? "m5.xlarge" : "t3.medium"
}
Ringkasan #
- Tanda konfigurasi perlu dipecah: plan butuh lebih dari 5 menit, tim sering konflik di file yang sama, ada resource “tidak boleh disentuh” campur dengan yang rutin berubah.
- Pecah berdasarkan lifecycle dan blast radius, bukan berdasarkan tipe resource — resource yang jarang berubah dan kritis dipisah dari yang sering berubah dan tidak terlalu kritis.
- Pola layering (foundation → platform → application) memberikan dependency yang jelas: setiap layer hanya bergantung ke layer di bawahnya, perubahan di atas tidak mempengaruhi bawah.
- Gunakan
terraform_remote_stateuntuk membaca output antar konfigurasi yang terpisah — tapi ingat ini menciptakan coupling antar konfigurasi.- Komponen di layer yang sama (EKS, database, load balancer) bisa diapply secara paralel jika tidak ada dependency antar sesama.
- Mulai sederhana — jangan premature decompose konfigurasi sebelum ada masalah nyata. Pecah hanya ketika sinyal sudah jelas muncul.
← Sebelumnya: Lifecycle Management Berikutnya: Performance Optimization →