L
Infrastructure as Code (IaC) β€’ Literally Web ID

Infrastructure as Code (IaC) Menggunakan Terraform untuk Otomasi AWS Cloud Infrastructure

⏱️ 15 menit baca β€’ πŸ“… 15 Oct 2026 β€’ πŸ‘οΈ 1 views
Infrastructure as Code (IaC) Menggunakan Terraform untuk Otomasi AWS Cloud Infrastructure

1. Konteks Industri & Analisis Akar Masalah

Dalam lanskap enterprise modern, kecepatan rilis infrastruktur cloud adalah faktor penentu keunggulan kompetitif. Secara historis, provisioning infrastruktur web stackβ€”yang melibatkan Virtual Private Cloud (VPC), Elastic Container Service (ECS) untuk backend Node.js/Go, Relational Database Service (RDS) untuk MySQL/MariaDB, Cloudflare Edge Caching, hingga konfigurasinya dengan Nginx/PHP-FPMβ€”dilakukan secara manual melalui AWS Management Console atau menggunakan skrip bash ad-hoc yang rapuh.

Pendekatan manual ini menimbulkan apa yang disebut sebagai Configuration Drift (penyimpangan konfigurasi), human error saat mengubah aturan keamanan Security Group, ketidakmampuan mereplikasi environment Staging dan Production secara identik, serta lambatnya pemulihan saat terjadi kegagalan sistem total (Disaster Recovery). Audit keamanan sering kali gagal karena tidak adanya Single Source of Truth dari cetak biru infrastruktur.

Sebelum adopsi Infrastructure as Code (IaC) menggunakan Terraform:

  • Lead Time to Provisioning: Membutuhkan waktu hari atau minggu untuk koordinasi tim networking, security, dan sysadmin.
  • Risk of Drift: Perubahan konfigurasi manual di console AWS tidak tercatat dalam dokumentasi, menyebabkan inkonsistensi antara environment development dan production.
  • Disaster Recovery: Pemulihan infrastruktur dari nol memakan waktu berhari-hari karena ketidakpastian urutan dependensi resource.

Setelah adopsi Terraform:

  • Declarative Provisioning: Seluruh infrastruktur didefinisikan dalam kode HCL (HashiCorp Configuration Language) yang dapat di-versioning menggunakan Git.
  • Predictable Execution: Mekanisme terraform plan memberikan visibilitas penuh terhadap perubahan (add, change, destroy) sebelum diterapkan ke production.
  • Automated CI/CD Pipeline: Integrasi penuh dengan GitHub Actions atau GitLab CI untuk otomatisasi deployment infrastruktur secara aman dan konsisten.

2. Konsep Inti & Deep Dive Arsitektur

Terraform beroperasi dengan memetakan resource dunia nyata ke dalam file state lokal atau remote (terraform.tfstate). State ini bertindak sebagai database bagi Terraform untuk mengetahui resource apa saja yang telah dibuat dan memetakan dependensinya secara otomatis.

Alur Eksekusi & State Management

+-----------------------+
|      Developer        |
+-----------+-----------+
            |
            | 1. terraform apply
            v
+-----------+-----------+        2. Lock State        +-------------------------+
|  Terraform CLI Core   |<-------------------------> | AWS DynamoDB Lock Table |
+-----------+-----------+                            +-------------------------+
            |
            | 3. Read/Write State
            v
+-----------+-----------+                            +-------------------------+
|   Remote Backend S3   |                            |       AWS Cloud         |
+-----------------------+                            | (VPC, ECS, RDS, ALB)    |
            ^                                        +-------------------------+
            |                                                     ^
            +-----------------------------------------------------+
                              4. API Calls (CRUD)
  1. Initialization (terraform init): Mengunduh provider plugins (AWS, Cloudflare, Random) dan mengonfigurasi remote backend.
  2. Planning (terraform plan): Menganalisis konfigurasi lokal dibandingkan dengan remote state dan kondisi aktual di AWS API, menghasilkan execution plan.
  3. Applying (terraform apply): Mengeksekusi plan melalui AWS API secara paralel atau berdasarkan implicit/explicit dependencies (depends_on). State diperbarui dan dikunci menggunakan DynamoDB untuk mencegah race condition.

3. Perbandingan Komparatif / Analisis Pendekatan

Parameter / Aspek Manual AWS Console AWS CloudFormation Terraform by HashiCorp
Sifat Eksekusi Imperative (Klik satu per satu) Declarative (JSON/YAML) Declarative (HCL)
Multi-Cloud Support Tidak (Hanya AWS) Tidak (Hanya AWS) Ya (AWS, GCP, Cloudflare, Kubernetes)
State Management Tidak ada visibilitas terpusat Dikelola internal oleh AWS Stack Remote Backend (S3 + DynamoDB State Locking)
Modularity & Reusability Sangat rendah (Rawan salah klik) Nested Stacks (Kompleks & Verbose) Modules, Registry, Variabel Dinamis
Dry Run Capability Tidak ada aws cloudformation deploy --no-execute-changeset terraform plan (Sangat akurat dan cepat)

4. Prasyarat Sistem & Persiapan Lingkungan

Sebelum mulai menulis kode IaC, pastikan environment lokal atau runner CI/CD memiliki toolchain berikut terinstal:

  • Terraform CLI: Versi >= 1.5.0
  • AWS CLI: Versi >= 2.x dengan konfigurasi kredensial IAM yang memiliki hak akses penuh (AdministratorAccess atau policy yang di-scoped ketat untuk VPC, IAM, ECS, RDS, dan S3).
  • Git: Untuk version control.

Verifikasi instalasi:

terraform version
aws --version

Konfigurasi kredensial AWS CLI:

aws configure
# Masukkan AWS Access Key ID, Secret Access Key, Region default (misal: ap-southeast-1), dan format output (json)

5. Panduan Implementasi Langkah demi Langkah

Berikut adalah struktur direktori proyek enterprise untuk arsitektur web modern:

terraform-aws-enterprise/
β”œβ”€β”€ backend.tf
β”œβ”€β”€ provider.tf
β”œβ”€β”€ variables.tf
β”œβ”€β”€ outputs.tf
β”œβ”€β”€ main.tf
└── modules/
    β”œβ”€β”€ vpc/
    β”‚   β”œβ”€β”€ main.tf
    β”‚   β”œβ”€β”€ variables.tf
    β”‚   └── outputs.tf
    β”œβ”€β”€ rds/
    β”‚   β”œβ”€β”€ main.tf
    β”‚   β”œβ”€β”€ variables.tf
    β”‚   └── outputs.tf
    └── ecs/
        β”œβ”€β”€ main.tf
        β”œβ”€β”€ variables.tf
        └── outputs.tf

1. Konfigurasi Remote Backend (backend.tf)

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

2. Provider Configuration (provider.tf)

provider "aws" {
  region = var.aws_region

  default_tags {
    tags = {
      Environment = var.environment
      ManagedBy   = "Terraform"
      Project     = "EnterpriseWebStack"
    }
  }
}

3. Modul VPC (modules/vpc/main.tf)

variable "vpc_cidr" { type = string }
variable "environment" { type = string }

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

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

data "aws_availability_zones" "available" {
  state = "available"
}

resource "aws_subnet" "public" {
  count                   = 2
  vpc_id                  = aws_vpc.main.id
  cidr_block              = cidrsubnet(var.vpc_cidr, 4, count.index)
  availability_zone       = data.aws_availability_zones.available.names[count.index]
  map_public_ip_on_launch = true

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

resource "aws_subnet" "private" {
  count             = 2
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet(var.vpc_cidr, 4, count.index + 2)
  availability_zone = data.aws_availability_zones.available.names[count.index]

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

resource "aws_internet_gateway" "gw" {
  vpc_id = aws_vpc.main.id

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

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_association" "public" {
  count          = 2
  subnet_id      = aws_subnet.public[count.index].id
  route_table_id = aws_route_table.public.id
}

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

4. Modul RDS MySQL (modules/rds/main.tf)

variable "vpc_id" { type = string }
variable "private_subnet_ids" { type = list(string) }
variable "db_password" { type = string; sensitive = true }
variable "environment" { type = string }

resource "aws_db_subnet_group" "main" {
  name       = "${var.environment}-db-subnet-group"
  subnet_ids = var.private_subnet_ids

  tags = {
    Name = "${var.environment}-db-subnet-group"
  }
}

resource "aws_security_group" "rds" {
  name        = "${var.environment}-rds-sg"
  description = "Allow MySQL inbound traffic from ECS"
  vpc_id      = var.vpc_id

  ingress {
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/16"] # Disesuaikan dengan CIDR VPC
  }

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

resource "aws_db_instance" "mysql" {
  identifier             = "${var.environment}-mysql-db"
  engine                 = "mysql"
  engine_version         = "8.0"
  instance_class         = "db.t4g.medium"
  allocated_storage      = 50
  max_allocated_storage  = 200
  db_name                = "enterprise_db"
  username               = "admin_root"
  password               = var.db_password
  db_subnet_group_name   = aws_db_subnet_group.main.name
  vpc_security_group_ids = [aws_security_group.rds.id]
  skip_final_snapshot    = true
  multi_az               = true

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

output "db_endpoint" { value = aws_db_instance.mysql.endpoint }

5. Modul ECS Fargate (modules/ecs/main.tf)

variable "cluster_name" { type = string }
variable "vpc_id" { type = string }
variable "private_subnet_ids" { type = list(string) }

resource "aws_ecs_cluster" "main" {
  name = var.cluster_name
}

resource "aws_ecs_cluster_capacity_providers" "main" {
  cluster_name = aws_ecs_cluster.main.name

  capacity_providers = ["FARGATE", "FARGATE_SPOT"]

  default_capacity_provider_strategy {
    capacity_provider = "FARGATE"
    weight            = 1
  }
}

output "cluster_id" { value = aws_ecs_cluster.main.id }

6. Root Orchestration (main.tf)

module "vpc" {
  source      = "./modules/vpc"
  vpc_cidr    = "10.0.0.0/16"
  environment = var.environment
}

module "rds" {
  source             = "./modules/rds"
  vpc_id             = module.vpc.vpc_id
  private_subnet_ids = module.vpc.private_subnet_ids
  db_password        = var.db_password
  environment        = var.environment
}

module "ecs" {
  source             = "./modules/ecs"
  cluster_name       = "${var.environment}-ecs-cluster"
  vpc_id             = module.vpc.vpc_id
  private_subnet_ids = module.vpc.private_subnet_ids
}

6. Bedah Kode & Penjelasan Detail Baris Kunci

  • Backend S3 & DynamoDB Locking: Baris backend "s3" memastikan state disimpan secara aman di cloud terpusat. Penggunaan dynamodb_table mencegah dua engineer menjalankan terraform apply secara bersamaan, yang dapat mengakibatkan korupsi file state.
  • Implicit Dependencies: Pada module "rds", Terraform otomatis membaca output module.vpc.vpc_id dan module.vpc.private_subnet_ids. Ini menciptakan dependency graph sehingga VPC dijamin tercipta sebelum RDS di-provisioning.
  • Sensitive Variables: Variabel db_password ditandai dengan sensitive = true untuk mencegah nilai password tercetak di log terminal saat eksekusi terraform plan atau apply.

[!WARNING] Jangan pernah menyimpan file terraform.tfstate atau file .tfvars berisi password/secret ke dalam public Git repository. Gunakan AWS Secrets Manager atau HashiCorp Vault untuk injeksi secret di lingkungan produksi.

7. Skenario Produksi & Studi Kasus Dunia Nyata

Dalam skenario high-traffic e-commerce (menangani 50.000 req/sec), arsitektur Terraform yang kita buat diintegrasikan dengan AWS Application Load Balancer (ALB) dan Auto Scaling Group untuk ECS Fargate tasks. Ketika traffic lonjakan (flash sale), CloudWatch Alarm memicu Auto Scaling untuk menambah jumlah task container Node.js/Go secara horizontal di dalam private subnet, sementara koneksi database dikelola melalui RDS Multi-AZ dengan Read Replica terpisah.

Langkah eksekusi di CI/CD Pipeline:

terraform init
terraform validate
terraform plan -out=tfplan
terraform apply -auto-approve tfplan

8. Common Pitfalls, Anti-Patterns & Solusi

  1. Anti-Pattern: Menggunakan satu file main.tf raksasa untuk seluruh resource production.
    • Solusi: Pecah menjadi modul-modul independen (VPC, Compute, Database, IAM) dengan prinsip Separation of Concerns.
  2. Anti-Pattern: Melakukan modifikasi manual di AWS Console tanpa melakukan import kembali ke Terraform state.
    • Solusi: Gunakan perintah terraform import aws_instance.web i-1234567890abcdef0 untuk menyelaraskan resource manual ke dalam state HCL.
  3. Pitfall: Menghapus resource berstatus state secara paksa menggunakan terraform state rm tanpa membersihkan resource cloud asli, mengakibatkan orphaned resource dan pembengkakan biaya tagihan AWS.

9. Benchmark, Metrik Kinerja & Tuning Performa

Pengujian performa IaC diukur berdasarkan:

  • Execution Time: Waktu yang dibutuhkan untuk menjalankan terraform plan dan apply pada skala 200+ resource (Target: < 3 menit).
  • Parallelism Tuning: Gunakan flag -parallelism=50 pada perintah apply untuk mempercepat provisioning resource yang tidak saling bergantung.

Contoh benchmarking eksekusi:

time terraform plan -parallelism=30

10. Checklist Penerapan Produksi & Kesimpulan

  • Remote backend S3 dikonfigurasi dengan enkripsi KMS dan versioning aktif.
  • DynamoDB State Locking aktif dan teruji.
  • Seluruh secret password dan API key menggunakan variabel sensitif atau terintegrasi dengan AWS Secrets Manager.
  • Uji coba terraform destroy dan apply dilakukan di environment staging untuk memastikan disaster recovery berjalan mulus.
  • Melakukan terraform fmt dan terraform validate secara otomatis pada pre-commit hook.

Dengan menerapkan Terraform secara disiplin dan terstruktur, organisasi Anda tidak hanya mencapai otomatisasi penuh infrastruktur cloud, tetapi juga menjamin keamanan, skalabilitas, dan konsistensi tingkat enterprise.

🏷️ Tags: #Nginx #High Concurrency #Performance #Sysadmin #Web Server