L
Infrastructure as Code (IaC) • Literally Web ID

Deklarasi Infrastruktur Skala Enterprise Menggunakan Terraform dan AWS

⏱️ 18 menit baca • 📅 15 Oct 2026 • 👁️ 1 views
Deklarasi Infrastruktur Skala Enterprise Menggunakan Terraform dan AWS

1. Konteks Industri & Analisis Akar Masalah

Dalam lanskap pengembangan infrastruktur web modern, pengelolaan server secara manual melalui konsol AWS Management Console (sering disebut ClickOps) telah menjadi titik kegagalan utama (single point of failure) bagi organisasi skala enterprise. Ketika sistem berkembang dari satu instans monolitik menjadi klaster multi-tier yang mendistribusikan beban antara Nginx, PHP-FPM, Go microservices, MySQL, Redis, hingga edge caching Cloudflare, kompleksitas konfigurasi meningkat secara eksponensial.

Bottle-neck utama dalam manajemen infrastruktur manual meliputi:

  • Drift Konfigurasi: Ketidaksesuaian antara dokumentasi arsitektur dan kondisi aktual di cloud, yang memicu kerentanan keamanan dan error tak terduga saat deployment.
  • Human Error: Kesalahan saat mengatur Security Groups, subnet routing, atau parameter IAM roles yang sering berujung pada eksploitasi data atau outage layanan.
  • Waktu Provisioning yang Lambat: Proses inisialisasi lingkungan staging, uat, dan production yang memakan waktu berhari-hari karena harus dilakukan konfigurasi ulang satu per satu.

Perbandingan pendekatan tradisional (ClickOps) versus pendekatan modern Infrastructure as Code (IaC) dengan Terraform menunjukkan transformasi yang signifikan:

Aspek ClickOps (Manual AWS Console) Terraform (IaC Enterprise)
Reproduksibilitas Rendah; sangat bergantung pada ingatan administrator. Tinggi; seluruh arsitektur dideklarasikan dalam kode versi.
Kecepatan Deployment Berjam-jam hingga berhari-hari; rentan kesalahan manusia. Menit; otomatisasi penuh melalui apply plan yang teruji.
Auditabilitas Sangat sulit melacak siapa yang mengubah parameter server. Transparan melalui Git commit history dan Terraform state/plan.
Manajemen State Tidak ada dokumentasi terpusat; berisiko dangling resources. Terpusat menggunakan remote backend dengan locking dinamis.

Melalui panduan ini, kita akan mengimplementasikan otomatisasi penuh infrastruktur web enterprise multi-tier yang aman, repeatable, dan scalable.

2. Konsep Inti & Deep Dive Arsitektur

Terraform bekerja dengan membangun Desired State berdasarkan file konfigurasi deklaratif berbahasa HCL (HashiCorp Configuration Language). Ia berkomunikasi dengan AWS API melalui Terraform AWS Provider untuk memetakan Current State dan mengeksekusi Diff (Plan) yang diperlukan.

+-----------------------------------------------------------------------+
|                        AWS Cloud Environment                          | 
|                                                                       | 
|  +--------------------------+     +-------------------------------+   | 
|  |     Public Subnet 1      |     |     Public Subnet 2           |   | 
|  |  [ Cloudflare CDN WAF ]  |     |  [ Application Load Balancer] |   | 
|  +-------------+------------+     +---------------+---------------+   | 
|                |                                  |                   | 
|  +-------------v----------------------------------v---------------+   | 
|  |                       Private Subnets                          |   | 
|  |  +--------------------+  +--------------------+  +----------+  |   | 
|  |  | Nginx / Go Backend |  | PHP-FPM / Node.js  |  |  Redis   |  |   | 
|  |  +---------+----------+  +---------+----------+  +----+-----+  |   | 
|  +------------|-----------------------|----------------|----------+   | 
|               |                       |                |              | 
|  +------------v-----------------------v----------------v----------+   | 
|  |                    Isolated Database Subnet                    |   | 
|  |                 [ Amazon Aurora MySQL Multi-AZ ]               |   | 
|  +----------------------------------------------------------------+   | 
+-----------------------------------------------------------------------+

Alur eksekusi data dimulai dari klien global yang mengakses domain, melewati Cloudflare CDN dan WAF untuk mitigasi DDoS, menuju Application Load Balancer (ALB) di public subnet AWS. Permintaan diteruskan ke instance backend web (Nginx/Go/PHP-FPM) di private subnet, yang kemudian berinteraksi dengan Redis caching layer dan Amazon Aurora MySQL berarsitektur Multi-AZ.

3. Perbandingan Komparatif / Analisis Pendekatan

Dalam membangun modul Terraform untuk enterprise, terdapat dua pendekatan utama dalam struktur repositori: Monolithic State vs Modular Composable State.

Parameter Monolithic Terraform Modular Composable Terraform
Skalabilitas Tim Buruk; sering terjadi state lock collision antar engineer. Sangat baik; pemisahan state per domain (Networking, Compute, Database).
Blast Radius Sangat luas; satu kesalahan merusak seluruh infrastruktur. Terisolasi; kegagalan pada modul komputasi tidak memengaruhi database.
Reusabilitas Rendah; kode sulit digunakan ulang di proyek lain. Tinggi; modul dapat dipublikasikan ke private registry.
Kompleksitas State File terraform.tfstate berukuran masif dan lambat. State file terdistribusi secara logis dan teringan.

[!TIP] Gunakan pendekatan Modular Composable dengan memisahkan state jaringan dasar (vpc), basis data (rds), dan layanan komputasi (compute) untuk menjaga blast radius sekecil mungkin.

4. Prasyarat Sistem & Persiapan Lingkungan

Sebelum menjalankan provisioning, pastikan lingkungan kerja Anda memenuhi spesifikasi teknis berikut:

  • Terraform CLI: Versi >= 1.5.0 terinstal di mesin lokal atau CI/CD runner.
  • AWS CLI: Versi >= 2.13.0 terkonfigurasi dengan kredensial IAM yang memiliki hak akses administratif penuh atau melalui AWS SSO.
  • Backend Storage: S3 Bucket untuk remote state dan DynamoDB Table untuk state locking.

Verifikasi instalasi dengan perintah berikut di terminal:

terraform -version
aws --version
aws sts get-caller-identity

Pastikan variabel environment AWS telah diexport:

export AWS_REGION="us-east-1"
export AWS_PROFILE="enterprise-admin"

5. Panduan Implementasi Langkah demi Langkah

Berikut adalah implementasi kode lengkap untuk arsitektur modular enterprise. Buat struktur direktori proyek Anda seperti di bawah ini:

infra-root/
├── main.tf
├── variables.tf
├── outputs.tf
├── backend.tf
└── modules/
    ├── vpc/
    │   ├── main.tf
    │   ├── variables.tf
    │   └── outputs.tf
    └── compute/
        ├── main.tf
        ├── variables.tf
        └── outputs.tf

File 1: backend.tf (Manajemen State Terpusat)

terraform {
  required_version = ">= 1.5.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
  backend "s3" {
    bucket         = "enterprise-terraform-state-prod-xyz"
    key            = "core-infrastructure/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "enterprise-terraform-locks"
    encrypt        = true
  }
}

provider "aws" {
  region = var.aws_region
  default_tags {
    tags = {
      Environment = var.environment
      ManagedBy   = "Terraform"
      Owner       = "Platform-Engineering"
    }
  }
}

File 2: modules/vpc/main.tf

variable "vpc_cidr" { type = string }
variable "environment" { type = string }
variable "azs" { type = list(string) }
variable "public_subnets" { type = list(string) }
variable "private_subnets" { type = list(string) }

resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "${var.environment}-vpc"
  }
}

resource "aws_internet_gateway" "gw" {
  vpc_id = aws_vpc.main.id
  tags = {
    Name = "${var.environment}-igw"
  }
}

resource "aws_subnet" "public" {
  count                   = length(var.public_subnets)
  vpc_id                  = aws_vpc.main.id
  cidr_block              = var.public_subnets[count.index]
  availability_zone       = var.azs[count.index]
  map_public_ip_on_launch = true

  tags = {
    Name = "${var.environment}-public-subnet-${count.index + 1}"
  }
}

resource "aws_subnet" "private" {
  count             = length(var.private_subnets)
  vpc_id            = aws_vpc.main.id
  cidr_block        = var.private_subnets[count.index]
  availability_zone = var.azs[count.index]

  tags = {
    Name = "${var.environment}-private-subnet-${count.index + 1}"
  }
}

resource "aws_eip" "nat" {
  domain     = "vpc"
  depends_on = [aws_internet_gateway.gw]
}

resource "aws_nat_gateway" "nat" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public[0].id
  tags = {
    Name = "${var.environment}-nat-gw"
  }
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.gw.id
  }
  tags = {
    Name = "${var.environment}-public-rt"
  }
}

resource "aws_route_table" "private" {
  vpc_id = aws_vpc.main.id
  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.nat.id
  }
  tags = {
    Name = "${var.environment}-private-rt"
  }
}

resource "aws_route_table_association" "public" {
  count          = length(var.public_subnets)
  subnet_id      = aws_subnet.public[count.index].id
  route_table_id = aws_route_table.public.id
}

resource "aws_route_table_association" "private" {
  count          = length(var.private_subnets)
  subnet_id      = aws_subnet.private[count.index].id
  route_table_id = aws_route_table.private.id
}

output "vpc_id" { value = aws_vpc.main.id }
output "private_subnets" { value = aws_subnet.private[*].id }
output "public_subnets" { value = aws_subnet.public[*].id }

File 3: main.tf (Root Module)

module "vpc" {
  source          = "./modules/vpc"
  vpc_cidr        = "10.100.0.0/16"
  environment     = "production"
  azs             = ["us-east-1a", "us-east-1b"]
  public_subnets  = ["10.100.1.0/24", "10.100.2.0/24"]
  private_subnets = ["10.100.10.0/24", "10.100.20.0/24"]
}

resource "aws_security_group" "web_sg" {
  name        = "production-web-sg"
  description = "Security group for enterprise web servers"
  vpc_id      = module.vpc.vpc_id

  ingress {
    description = "Allow HTTP from Cloudflare/ALB"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    description = "Allow HTTPS"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Jalankan perintah inisialisasi dan penerapan di terminal:

terraform init
terraform plan -out=tfplan
terraform apply tfplan

6. Bedah Kode & Penjelasan Detail Baris Kunci

  • backend "s3": Baris ini mengonfigurasi Terraform agar tidak menyimpan state secara lokal (terraform.tfstate), melainkan di S3 bucket yang terenkripsi. Penggunaan properti dynamodb_table mengaktifkan mekanisme state locking atomik menggunakan kunci hash untuk mencegah dua engineer melakukan apply secara bersamaan dan merusak integritas state.
  • default_tags dalam Provider AWS: Memastikan seluruh resource AWS yang diciptakan melalui kode ini secara otomatis membawa tag kepemilikan (Owner, Environment, ManagedBy), memudahkan audit keuangan perusahaan dan manajemen cost center.
  • enable_dns_hostnames = true: Parameter esensial pada aws_vpc agar EC2 instans yang berada di dalam subnet privat maupun publik mendapatkan resolusi DNS internal yang valid untuk komunikasi mikrolayanan (misalnya dengan Redis dan database MySQL).

7. Skenario Produksi & Studi Kasus Dunia Nyata

Pada lingkungan enterprise dengan trafik tinggi (contoh: flash sale e-commerce mencapai 50.000 request per detik), arsitektur Terraform yang kita buat digabungkan dengan Auto Scaling Groups (ASG) dan Application Load Balancer (ALB).

resource "aws_autoscaling_group" "web_asg" {
  name_prefix         = "enterprise-web-asg-"
  max_size            = 20
  min_size            = 4
  desired_capacity    = 6
  vpc_zone_identifier = module.vpc.private_subnets

  launch_template {
    id      = aws_launch_template.web.id
    version = "$Latest"
  }

  target_group_arns = [aws_lb_target_group.web_tg.arn]

  instance_refresh {
    strategy = "Rolling"
    preferences {
      min_healthy_percentage = 50
    }
  }
}

Konfigurasi instance_refresh di atas memastikan bahwa pembaruan kode aplikasi (Go/PHP) atau patch sistem operasi pada AMI baru dapat diluncurkan secara otomatis tanpa downtime (zero-downtime rolling deployment).

8. Common Pitfalls, Anti-Patterns & Solusi

  1. Hardcoding Rahasia di dalam File Terraform (variables.tf atau main.tf)
    • Anti-Pattern: Menyimpan password database atau API key secara plaintext.
    • Solusi: Selalu gunakan AWS Secrets Manager atau HashiCorp Vault, lalu ambil nilai rahasia menggunakan data sources Terraform (data.aws_secretsmanager_secret_version).
  2. Mengubah ID Resource Secara Manual di AWS Console
    • Anti-Pattern: Mengubah konfigurasi Security Group langsung lewat console AWS.
    • Solusi: Terapkan prevent_destroy lifecycle meta-argument dan jalankan pemeriksaan rutin dengan terraform plan untuk mendeteksi drift.
lifecycle {
  prevent_destroy = true
}

9. Benchmark, Metrik Kinerja & Tuning Performa

Untuk memvalidasi kesiapan performa infrastruktur web yang diprovisioning oleh Terraform, lakukan pengujian beban menggunakan perangkat k6 atau wrk terhadap ALB URL.

wk -t12 -c400 -d30s https://your-enterprise-alb-dns.amazonaws.com/

Metrik kunci yang harus dipantau melalui CloudWatch:

  • Latency Target Response Time: Harus konsisten di bawah 50ms untuk operasi cache Redis dan di bawah 200ms untuk query kompleks database MySQL.
  • CPU Utilization pada ASG Instance: Jaga rata-rata penggunaan di bawah 70% dengan scaling policy berbasis CPU tracking.
  • State Execution Time: Pastikan ukuran state file tetap optimal dengan memecah modul jika eksekusi terraform plan memakan waktu lebih dari 30 detik.

10. Checklist Penerapan Produksi & Kesimpulan

Sebelum merilis infrastruktur ke production, pastikan seluruh item dalam checklist berikut telah terpenuhi:

  • Remote S3 state telah dienkripsi dengan KMS Key milik perusahaan.
  • DynamoDB table state locking aktif dan dapat diakses oleh CI/CD pipeline.
  • Tidak ada hardcode secret di dalam repositori Git.
  • Seluruh Security Group menerapkan prinsip Least Privilege (port terbuka hanya dari Cloudflare/ALB).
  • Mekanisme backup otomatis dan snapshot Aurora MySQL telah dideklarasikan melalui Terraform.

Dengan mendeklarasikan infrastruktur secara utuh menggunakan Terraform, organisasi Anda mencapai level kematangan operasional tingkat tinggi, menjamin keandalan sistem, serta menghilangkan risiko inkonsistensi lingkungan cloud secara permanen.

🏷️ Tags: #Devops #Terraform #Aws #Infrastructure As Code #Cloud Architecture