L
Infrastructure as Code (IaC) • Literally Web ID

Automasi Infrastruktur Enterprise Menggunakan Terraform dan Ansible di AWS

⏱️ 18 menit baca • 📅 14 Oct 2026 • 👁️ 1 views
Automasi Infrastruktur Enterprise Menggunakan Terraform dan Ansible di AWS

Automasi Infrastruktur Enterprise Menggunakan Terraform dan Ansible di AWS

1. Konteks Industri & Analisis Akar Masalah

Dalam lanskap enterprise modern, kecepatan rilis fitur dan stabilitas sistem adalah dua pilar penentu daya saing bisnis. Namun, banyak organisasi masih terjebak dalam model operasional lama yang mengandalkan manajemen infrastruktur manual (manual provisioning). Pendekatan ini tidak hanya lambat, tetapi juga membuka celah lebar terhadap inkonsistensi lingkungan (environment drift), kesalahan manusia (human error), dan kerentanan keamanan yang sulit dilacak.

Di dunia nyata, infrastruktur web enterprise tidak berdiri sendiri. Ia adalah ekosistem kompleks yang melibatkan orkestrasi Virtual Private Cloud (VPC), klaster Kubernetes (EKS), layanan basis data terdistribusi (MySQL/MariaDB), sistem caching berperforma tinggi (Redis), mekanisme queue & scheduler (Supervisor, Cron), hingga lapisan pengamanan tepi seperti Cloudflare WAF, SSL/TLS, dan manajemen DNS tingkat lanjut. Jika proses provisioning dan konfigurasi layanan-layanan ini dilakukan melalui konsol AWS atau SSH manual, proses disaster recovery dapat memakan waktu berhari-hari.

Perbandingan Kondisi: Sebelum vs Sesudah Automasi

Parameter Sebelum Automasi (Manual / Ad-hoc) Sesudah Automasi (Terraform + Ansible) Dampak Bisnis
Waktu Provisioning 3 - 5 Hari Kerja 10 - 15 Menit Time-to-market meningkat drastis
Inkonsistensi Environment Tinggi (dev vs staging vs prod berbeda) Nol (Infrastruktur sebagai Kode) Mengurangi bug yang hanya muncul di prod
Auditabilitas Lemah (bergantung pada memori tim) Kuat (Git History sebagai source of truth) Kepatuhan (Compliance) mudah dicapai
Disaster Recovery Berjam-jam hingga berhari-hari Hitungan menit (Infrastructure Recreation) High Availability dan Business Continuity

Dengan memadukan Terraform untuk orkestrasi infrastruktur imajinatif (IaaS) dan Ansible untuk manajemen konfigurasi sistem operasi serta aplikasi (Configuration Management), organisasi dapat mencapai siklus hidup infrastruktur yang sepenuhnya deklaratif, dapat diulang (repeatable), dan aman secara default.


2. Konsep Inti & Deep Dive Arsitektur

Arsitektur enterprise modern menuntut pemisahan tugas yang jelas antara pembuatan fondasi infrastruktur dan konfigurasi di dalam instans. Terraform bertindak sebagai declarative provisioner yang berinteraksi langsung dengan AWS API untuk membangun sumber daya fisik, sementara Ansible mengambil alih setelah instans siap untuk menginstal paket, mengatur konfigurasi Nginx/PHP-FPM, mengamankan daemon SSH, dan menjalankan layanan latar belakang.

Berikut adalah representasi visual alur eksekusi dari kode hingga infrastruktur hidup:

+--------------------------------------------------------------------------+
|                            Developer / Git                               | 
+--------------------------------------------------------------------------+
                                     |
                                     v
+--------------------------------------------------------------------------+
|                   Terraform (Declarative IaaS)                           | 
|  - AWS VPC (Public/Private Subnets, NAT Gateway, Internet Gateway)       | 
|  - AWS EKS Cluster (Control Plane, Worker Nodes, IAM Roles)              | 
|  - RDS MySQL & ElastiCache Redis                                         | 
+--------------------------------------------------------------------------+
                                     |
                                     v
+--------------------------------------------------------------------------+
|                   Ansible (Configuration Management)                     | 
|  - OS Hardening & Fail2ban Setup                                         | 
|  - Web Server (Nginx / Caddy) & PHP-FPM Pool Configuration               | 
|  - Supervisor Queue Workers & Cron Jobs                                  | 
+--------------------------------------------------------------------------+
                                     |
                                     v
+--------------------------------------------------------------------------+
|                    Production Web Ecosystem Ready                        | 
+--------------------------------------------------------------------------+

Alur Data & Eksekusi Under the Hood

  1. Inisialisasi Terraform: Terraform membaca file .tf, melakukan parsing grafik ketergantungan (dependency graph), dan mencocokkan status lokal/remote dengan state aktual di AWS.
  2. Eksekusi AWS API: Terraform memicu pembuatan VPC, subnet multi-AZ, route tables, internet gateway, NAT gateway, dan meluncurkan klaster EKS.
  3. Dinamis Ekstraksi IP/DNS: Output Terraform (seperti IP instans atau endpoint RDS) diekspor secara otomatis atau disimpan ke dalam file inventaris Ansible.
  4. Eksekusi Playbook Ansible: Ansible melakukan koneksi SSH berbasis kunci ke instans target, mengeksekusi peran (roles) secara berurutan, menerapkan hardening keamanan, dan menyalakan service web server.

3. Perbandingan Komparatif / Analisis Pendekatan

Dalam membangun pipeline otomatisasi, arsitek sering dihadapkan pada pilihan alat. Berikut adalah analisis mendalam mengenai trade-off pendekatan yang digunakan:

Aspek Penilaian Terraform Ansible CloudFormation / AWS SSM
Paradigma Deklaratif (IaaS) Prosedural/Deklaratif (Config Mgmt) Deklaratif (Native AWS)
Cakupan Multi-Cloud Sangat Luas (AWS, GCP, Azure, Cloudflare) Luas (OS, Network Devices, Cloud) Terbatas hanya pada ekosistem AWS
State Management Menggunakan State File (Local/Remote S3) Stateless (Berbasis SSH & Inventaris) Dikelola penuh oleh AWS Control Plane
Konsumsi CPU & RAM Ringan (Go Binary) Sangat Ringan (Python/SSH Agentless) Dikelola oleh AWS Backend
Kurva Pembelajaran Menengah (HCL syntax) Rendah (YAML syntax) Menengah-Tinggi (YAML/JSON Verbose)

[!TIP] Gunakan Terraform untuk membuat wadah dan infrastruktur dasarnya (infrastructure provisioning), lalu gunakan Ansible untuk mengisi isi dalam instans tersebut (configuration management). Jangan mencoba menggunakan Terraform untuk manajemen file konfigurasi aplikasi yang kompleks, karena hal tersebut adalah ranah utama Ansible.


4. Prasyarat Sistem & Persiapan Lingkungan

Sebelum melangkah ke implementasi kode, pastikan workstation atau CI/CD runner Anda memiliki spesifikasi dan perangkat lunak berikut terinstal dengan benar:

Spesifikasi & Dependensi

  • OS: Linux (Ubuntu 22.04 LTS / Amazon Linux 2023) atau macOS Sonoma/Ventura.
  • Terraform: Versi >= 1.5.0
  • Ansible: Versi >= 2.15.0
  • AWS CLI: Versi 2.x dengan kredensial IAM yang memiliki hak akses administrator penuh (AdministratorAccess atau PowerUserAccess).
  • Git: Untuk manajemen versi modul.

Verifikasi instalasi dengan menjalankan perintah berikut di terminal:

terraform version
ansible --version
aws --version

Pastikan variabel lingkungan AWS telah dikonfigurasi dengan benar:

export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_DEFAULT_REGION="ap-southeast-1"

5. Panduan Implementasi Langkah demi Langkah

Bagian ini menyajikan kode implementasi lengkap siap produksi. Kita akan memecahnya menjadi modul Terraform untuk VPC dan EKS, manajemen state menggunakan S3 + DynamoDB, serta konfigurasi server menggunakan Ansible.

5.1 Desain Modul Terraform untuk VPC

Buat direktori proyek dengan struktur berikut:

infra-enterprise/
├── modules/
│   ├── vpc/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   └── eks/
│       ├── main.tf
│       ├── variables.tf
│       └── outputs.tf
├── backend.tf
├── main.tf
├── variables.tf
└── outputs.tf

Isi file modules/vpc/main.tf:

variable "vpc_cidr" {
  type    = string
  default = "10.0.0.0/16"
}

variable "environment" {
  type    = string
  default = "production"
}

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

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

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

  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, 8, count.index + 10)
  availability_zone = data.aws_availability_zones.available.names[count.index]

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

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

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

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

resource "aws_eip" "nat" {
  domain = "vpc"
}

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

resource "aws_route_table_association" "private" {
  count          = 2
  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
}

5.2 Desain Modul Terraform untuk EKS

Isi file modules/eks/main.tf:

variable "cluster_name" {
  type    = string
  default = "enterprise-eks-cluster"
}

variable "subnet_ids" {
  type = list(string)
}

resource "aws_iam_role" "eks_cluster" {
  name = "${var.cluster_name}-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "eks.amazonaws.com"
      }
    }]
  })
}

resource "aws_iam_role_policy_attachment" "eks_cluster_policy" {
  role       = aws_iam_role.eks_cluster.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
}

resource "aws_eks_cluster" "main" {
  name     = var.cluster_name
  role_arn = aws_iam_role.eks_cluster.arn

  vpc_config {
    subnet_ids = var.subnet_ids
  }

  depends_on = [aws_iam_role_policy_attachment.eks_cluster_policy]
}

output "cluster_endpoint" {
  value = aws_eks_cluster.main.endpoint
}

output "cluster_name" {
  value = aws_eks_cluster.main.name
}

5.3 Manajemen State Berkelanjutan

Isi file backend.tf untuk menyimpan state di AWS S3 dengan penguncian DynamoDB guna mencegah konflik konkurensi:

terraform {
  backend "s3" {
    bucket         = "enterprise-terraform-state-bucket-xyz"
    key            = "production/terraform.tfstate"
    region         = "ap-southeast-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

5.4 Konfigurasi OS dan Service Provisioning dengan Ansible

Buat struktur direktori Ansible:

ansible/
├── inventory/
│   └── hosts.ini
├── roles/
│   └── webserver/
│       ├── tasks/
│       │   └── main.yml
│       └── templates/
│           └── nginx.conf.j2
└── playbook.yml

Isi file ansible/inventory/hosts.ini:

[webservers]
server-prod-01 ansible_host=54.169.10.20 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/prod-key.pem

[webservers:vars]
ansible_python_interpreter=/usr/bin/python3

Isi file ansible/roles/webserver/tasks/main.yml:

---
- name: Update apt cache and install Nginx & PHP-FPM
  apt:
    name:
      - nginx
      - php8.2-fpm
      - php8.2-mysql
      - redis
      - fail2ban
    state: present
    update_cache: yes

- name: Configure Nginx virtual host from template
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/sites-available/default
    owner: root
    group: root
    mode: '0644'
  notify: Restart Nginx

- name: Ensure Fail2ban service is running and enabled
  service:
    name: fail2ban
    state: started
    enabled: yes

- name: Ensure Nginx service is running and enabled
  service:
    name: nginx
    state: started
    enabled: yes

- name: Ensure PHP-FPM service is running and enabled
  service:
    name: php8.2-fpm
    state: started
    enabled: yes

Handler untuk Ansible di ansible/roles/webserver/handlers/main.yml:

---
- name: Restart Nginx
  service:
    name: nginx
    state: restarted

File ansible/playbook.yml:

---
- hosts: webservers
  become: yes
  roles:
    - webserver

Jalankan Ansible dengan perintah:

ansible-playbook -i ansible/inventory/hosts.ini ansible/playbook.yml

6. Bedah Kode & Penjelasan Detail Baris Kunci

  • cidrsubnet(var.vpc_cidr, 8, count.index): Fungsi internal Terraform ini memecah blok CIDR utama (misal /16) menjadi sub-blok (/24) secara dinamis berdasarkan indeks iterasi. Ini mencegah hardcode IP dan memastikan kalkulasi jaringan matematis tanpa tumpang tindih (overlap).
  • backend "s3": Konfigurasi kunci enterprise. Menyimpan state di local rentan terhadap korupsi file saat dikerjakan oleh tim. S3 mengenkripsi state secara at-rest, sementara DynamoDB memberikan mekanisme state locking atomik.
  • become: yes pada Ansible: Menjalankan tugas-tugas konfigurasi di bawah hak akses sudo (root), mutlak diperlukan untuk instalasi paket OS, modifikasi konfigurasi Nginx di /etc/nginx, dan pengelolaan systemd services.

7. Skenario Produksi & Studi Kasus Dunia Nyata

Dalam menghadapi flash sale atau lonjakan trafik e-commerce tiba-tiba (misal 50.000 requests per second), arsitektur yang dibangun harus siap melakukan auto-scaling.

  1. Infrastruktur Dasar: Terraform menyediakan Auto Scaling Group (ASG) di belakang Application Load Balancer (ALB) dengan zona ketersediaan ganda (Multi-AZ).
  2. Manajemen Konfigurasi Cepat: Saat instans baru diputar (spawned) oleh ASG, skrip cloud-init memanggil Ansible pull mode atau menarik konfigurasi yang telah di-bake ke dalam Amazon Machine Image (AMI) menggunakan Packer.
  3. Kinerja Web & Database: Nginx dikonfigurasi dengan worker_processes auto dan keepalive_timeout 65, sementara Redis bertindak sebagai session store dan query cache untuk mengurangi beban basis data MySQL Aurora.

8. Common Pitfalls, Anti-Patterns & Solusi

[!WARNING] Kesalahan Fatal #1: Menyimpan AWS Secret Access Key atau SSH Private Key secara plainteks di dalam repositori Git publik maupun privat. Solusi: Gunakan AWS Secrets Manager, HashiCorp Vault, atau variabel lingkungan terenkripsi. Manfaatkan file .gitignore secara ketat.

[!WARNING] Kesalahan Fatal #2: Menghapus atau mengubah struktur resource block di Terraform tanpa melakukan migrasi state (terraform state mv), yang menyebabkan sumber daya produksi terhapus tidak sengaja (destroy/recreate). Solusi: Selalu jalankan terraform plan dan periksa bendanya dengan teliti. Gunakan lifecycle { prevent_destroy = true } pada database kritis.


9. Benchmark, Metrik Kinerja & Tuning Performa

Untuk memverifikasi kesiapan performa server web yang dikonfigurasi melalui Ansible, jalankan pengujian beban menggunakan k6 atau wrk:

wrk -t12 -c400 -d30s http://enterprise-alb-123456789.ap-southeast-1.elb.amazonaws.com/

Parameter Tuning Kernel Linux (/etc/sysctl.conf):

Terapkan parameter berikut melalui peran Ansible untuk menangani koneksi TCP konkurensi tinggi:

# Meningkatkan batas maksimal file descriptor
fs.file-max = 2097152

# Optimasi ukuran buffer TCP socket
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.ip_local_port_range = 1024 65535

Terapkan perubahan dengan perintah sysctl -p.


10. Checklist Penerapan Produksi & Kesimpulan

Sebelum merilis infrastruktur ini ke lingkungan live, pastikan Anda telah melewati checklist berikut:

  • State Terraform diamankan di S3 dengan enkripsi KMS dan dikunci via DynamoDB.
  • Seluruh port keamanan Security Groups AWS dibatasi secara ketat (prinsip least privilege).
  • Ansible Playbook telah diuji pada staging environment tanpa error (Idempotensi terbukti).
  • Fail2ban dan pembaruan keamanan otomatis OS telah aktif.
  • Pemantauan (Monitoring) dan Logging (CloudWatch / Prometheus) telah terpasang pada klaster EKS dan instans.

Dengan memadukan Terraform dan Ansible secara disiplin, tim infrastruktur enterprise Anda memiliki fondasi yang tangguh, dapat diskalakan secara masif, dan tahan terhadap bencana operasional.

🏷️ Tags: #Devops #Terraform #Ansible #Aws #Infrastructure As Code