L
Infrastructure as Code (IaC) ๐Ÿšจ Post-Mortem & Incident Runbook โ€ข Literally Web ID

Automated Infrastructure Provisioning Menggunakan Terraform dan Ansible di AWS

โฑ๏ธ 18 menit baca โ€ข ๐Ÿ“… 21 Oct 2026 โ€ข ๐Ÿ‘๏ธ 2 views
Automated Infrastructure Provisioning Menggunakan Terraform dan Ansible di AWS
๐Ÿ”Š Dengarkan Artikel Ini

1. Alarm Tengah Malam: Saat Layanan Produksi Mulai Tumbang

Pukul 02:14 WIB, PagerDuty berdering nyaring di samping tempat tidur saya. Bukan suara notifikasi WhatsApp biasa, melainkan alarm bernada melengking yang menandakan ada armada EC2 di AWS yang mendadak tidak merespons health check. Sambil mengusap mata dan menyeduh kopi hitam, saya membuka dashboard Grafana. Betapa terkejutnya saya melihat grafik latensi melonjak dari stabil di angka 45 milidetik menjadi lebih dari 8 detik, sementara error rate HTTP 502 Bad Gateway merangkak naik menyentuh 68%.

Di balik layar, infrastruktur web kami yang menopang trafik jutaan pengguna harian sedang sekarat. Frontend berbasis Nginx dan PHP-FPM di balik Application Load Balancer (ALB) mulai berguguran satu per satu karena kehabisan koneksi, sementara database MySQL di RDS mulai mengunci antrean query akibat lonjakan koneksi siluman. Masalah bermula ketika tim staging mencoba melakukan rolling update menggunakan skrip manual heredoc yang diwariskan dari tahun 2018โ€”sebuah metode kuno di mana seorang engineer mengetik perintah SSH manual ke sepuluh server produksi secara bergantian. Kesalahan kecil pada konfigurasi /etc/nginx/nginx.conf membuat Nginx gagal melakukan restart di tengah malam, meninggalkan proses PHP-FPM menggantung dan membebani RAM hingga 98%.

Kejadian ini membuka mata kami bahwa mengandalkan keahlian manual manusia di tengah malam adalah resep bencana yang sempurna. Kami butuh perombakan total menuju otomasi murni berbasis deklaratif, dan di sinilah perjalanan investigasi kami dimulai untuk membongkar akar masalah serta membangun benteng pertahanan infrastruktur yang tak tembus peluru.

[!WARNING] Jangan pernah melakukan hot-fix manual langsung di server produksi menggunakan editor teks tanpa melalui version control dan pipeline CI/CD yang teruji. Tindakan heroik pukul 2 pagi sering kali justru menjadi pemicu utama matinya seluruh kluster.

Transisi dari kepanikan manual ini menuntut kami untuk segera menyelidiki jejak digital yang ditinggalkan oleh sistem yang kolaps, menelusuri log baris demi baris layaknya seorang detektif forensik digital.

2. Jejak Digital: Menelusuri Anomali Log & Lonjakan Metrik

Begitu terhubung ke bastion host menggunakan AWS Systems Manager (SSM) Session Managerโ€”karena SSH port 22 sengaja kami tutup rapat untuk keamananโ€”saya langsung melompat ke direktori log untuk memeriksa apa yang sebenarnya terjadi pada detik-detik kematian server.

# Memeriksa error terakhir pada log Nginx sebelum server tidak merespons
sudo tail -n 100 /var/log/nginx/error.log

# Memeriksa status proses PHP-FPM yang mengalami lonjakan
sudo systemctl status php8.2-fpm

# Menganalisis koneksi jaringan aktif yang macet di status CLOSE_WAIT
netstat -an | grep 443 | awk '{print $6}' | sort | uniq -c | sort -nr

Hasil analisis log sangat mencengangkan. Baris demi baris menunjukkan pesan kesalahan yang berulang: [emerg] 1234#1234: bind() to 0.0.0.0:443 failed (98: Address already in use). Ternyata, ketika skrip deployment manual dijalankan, proses Nginx yang lama tidak ter-terminate dengan sempurna sebelum proses baru mencoba mendengarkan port yang sama. Akibatnya, port 443 terkunci, koneksi HTTPS dari Cloudflare terputus, dan ALB mencatat target sebagai Unhealthy.

Tidak berhenti di situ, pemeriksaan pada konfigurasi sistem operasi menunjukkan bahwa file descriptor limit (ulimit -n) masih menggunakan nilai default sistem operasi sebesar 1024, yang langsung ludes begitu ribuan bot dan pengguna mencoba melakukan reconnect secara bersamaan. Kami juga menemukan bahwa Redis caching mengalami eviction massal karena alokasi memori yang tidak diatur secara deklaratif saat instance pertama kali di-provision.

# Konfigurasi Nginx lama yang rapuh dan menyebabkan port binding conflict
server {
    listen 443 ssl http2;
    server_name example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }
}

Dari temuan ini, jelas bahwa masalah utamanya bukan sekadar kesalahan konfigurasi Nginx, melainkan ketiadaan standardisasi infrastruktur yang dapat direplikasi secara konsisten. Dari sinilah kami mulai membongkar biang kerok yang sebenarnya.

3. Membongkar Biang Kerok: Akar Masalah yang Sebenarnya

Setelah melakukan post-mortem mendalam bersama tim, kami menyimpulkan bahwa akar masalah insiden ini berakar pada tiga dosa besar arsitektur:

  1. Imperative Configuration: Menggunakan skrip bash manual untuk menginstal paket dan menyalin file konfigurasi tanpa jaminan idempotency.
  2. Drift Configuration: Perbedaan kecil antara server staging dan production karena tidak adanya representasi infrastruktur sebagai kode (Infrastructure as Code).
  3. Kurangnya Isolasi State: Manajemen state Terraform yang kala itu masih menggunakan file lokal di laptop salah seorang engineer, alih-alih menggunakan remote backend yang aman dengan penguncian DynamoDB.

Untuk membereskan kekacauan ini secara tuntas, kami memutuskan untuk mengimplementasikan prinsip Declarative Infrastructure menggunakan Terraform untuk provisioning sumber daya AWS (VPC, EC2, Security Groups, IAM Roles) dan melanjutkannya dengan Ansible untuk konfigurasi sistem operasi tingkat lanjut serta deployment aplikasi web.

Berikut adalah struktur direktori modular Terraform yang kami rancang untuk memastikan konsistensi lingkungan:

# terraform/modules/vpc/main.tf
resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true

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

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]

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

Dan untuk modul EC2 yang terintegrasi langsung dengan pemanggilan Ansible dynamic inventory, kami mendefinisikannya seperti ini:

# terraform/modules/ec2/main.tf
resource "aws_instance" "web_server" {
  ami                    = var.ami_id
  instance_type          = var.instance_type
  subnet_id              = var.public_subnet_id
  vpc_security_group_ids = [var.security_group_id]
  key_name               = var.key_name

  root_block_device {
    volume_size           = 50
    volume_type           = "gp3"
    encrypted             = true
    delete_on_termination = false
  }

  tags = {
    Name        = "${var.environment}-web-node"
    Environment = var.environment
    Role        = "webserver"
  }
}

[!TIP] Selalu gunakan tipe EBS volume gp3 untuk beban kerja web modern di AWS. Harganya lebih murah 20% dibanding gp2 dan memberikan performa baseline IOPS serta throughput yang independen dari ukuran disk.

Dengan fondasi Terraform yang kokoh, langkah selanjutnya adalah mengeksekusi provisioning lanjutan menggunakan Ansible Playbooks untuk memastikan sistem operasi siap melayani trafik web.

4. Tindakan Darurat: Menghidupkan Kembali Layanan dalam Hitungan Menit

Ketika insiden terjadi atau saat kami melakukan blue-green deployment, kecepatan pemulihan adalah segalanya. Kami meninggalkan metode SSH manual dan menggantinya dengan eksekusi otomatis satu perintah yang memicu Terraform untuk membangun ulang infrastruktur yang rusak, diikuti oleh Ansible untuk menanamkan konfigurasi web server yang bersih.

Berikut adalah Ansible Playbook utama yang kami gunakan untuk mengonfigurasi ulang Nginx, PHP-FPM, Redis, serta memperkuat sistem keamanan Linux (/etc/security/limits.conf untuk file descriptors) secara otomatis dan idempotent:

---
- name: Provisioning Web Server Cluster
  hosts: webservers
  become: yes
  vars:
    php_version: "8.2"
  
  tasks:
    - name: Update apt cache and install essential web packages
      apt:
        name:
          - nginx
          - php{{ php_version }}-fpm
          - php{{ php_version }}-mysql
          - php{{ php_version }}-redis
          - redis-server
          - certbot
        state: present
        update_cache: yes

    - name: Configure system limits for high concurrency
      pam_limits:
        domain: "www-data"
        limit_type: "-"
        limit_item: "nofile"
        value: "65535"

    - name: Deploy optimized Nginx configuration
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: '0644'
      notify: Restart Nginx

    - name: Ensure PHP-FPM is running and enabled on boot
      systemd:
        name: php{{ php_version }}-fpm
        state: started
        enabled: yes

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

Jika Anda berada dalam situasi darurat di mana instance produksi mengalami korupsi data sistem dan harus diganti total dalam waktu kurang dari 60 detik, berikut adalah emergency one-liner pemulihan infrastruktur yang langsung mengeksekusi Terraform apply dan memanggil Ansible:

cd /infra/terraform/envs/production && terraform apply -auto-approve && ansible-playbook -i inventories/aws_ec2.yml playbooks/site.yml --extra-vars "force_update=true"

Perintah di atas memastikan bahwa setiap node baru langsung mendapatkan patch keamanan, konfigurasi Nginx yang valid tanpa konflik port, serta optimasi connection pooling database sebelum ALB mengarahkan trafik publik kepadanya. Transisi mulus ini membawa kami pada kebijakan retrospektif jangka panjang.

5. Kebijakan Retrospektif: Menambal Celah agar Tak Pernah Terulang

Pengalaman pahit tumbangnya sistem di tengah malam menyadarkan kami bahwa infrastruktur skala besar tidak boleh dikelola berdasarkan ingatan atau kebiasaan manual seorang engineer. Kami merumuskan empat pilar kebijakan baru yang wajib dipatuhi oleh seluruh tim engineering:

  1. Zero Manual SSH Policy: Tidak ada satupun engineer yang diizinkan melakukan perubahan konfigurasi langsung di server produksi. Semua perubahan harus melalui commit ke repositori Git yang memicu pipeline Terraform dan Ansible secara otomatis.
  2. Mandatory Immutable Infrastructure: Alih-alih melakukan in-place update pada instance yang sedang berjalan, setiap pembaruan sistem operasi atau versi PHP kini menggunakan strategi AMI baking menggunakan Packer yang kemudian di-deploy ulang via Terraform replace atau auto-scaling group refresh.
  3. Strict State Locking: Backend Terraform dipindahkan sepenuhnya ke AWS S3 dengan penguncian tabel DynamoDB guna mencegah konflik saat dua pipeline berjalan bersamaan.
  4. Automated Integration Testing: Sebelum merge ke branch main, setiap perubahan konfigurasi Ansible wajib diuji terlebih dahulu di lingkungan ephemeral staging menggunakan Molecule dan Docker.

Dengan aturan main yang ketat ini, infrastruktur kami berubah dari yang tadinya rapuh menjadi sistem yang self-healing dan sangat resilien terhadap human error.

6. Pasang Alarm: Otomasi Deteksi Dini untuk Tim On-Call

Agar kejadian serupa tidak pernah luput dari pantauan, kami memperketat sistem peringatan dini (early warning system) dengan memasang alarm multi-layer yang terintegrasi langsung dengan Slack dan PagerDuty. Berikut adalah konfigurasi Prometheus Alertmanager untuk mendeteksi lonjakan error HTTP 502 dan kegagalan proses Nginx sebelum berdampak luas pada pengguna:

groups:
  - name: WebInfrastructureAlerts
    rules:
      - alert: HighHTTP5xxErrorRate
        expr: sum(rate(nginx_http_requests_total{status=~"5.."}[5m])) / sum(rate(nginx_http_requests_total[5m])) * 100 > 5
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "High HTTP 5xx error rate detected on web cluster"
          description: "Error rate is above 5% for the last 2 minutes. Immediate investigation required via SSM Session Manager."

      - alert: NginxServiceDown
        expr: node_systemd_unit_state{name="nginx.service", state="active"} == 0
        for: 1m
        labels:
          severity: page
        annotations:
          summary: "Nginx service is down on production node"
          description: "The Nginx web server daemon has stopped unexpectedly on {{ $labels.instance }}."

Dengan sistem pemantauan yang proaktif dan fondasi otomasi Terraform-Ansible yang handal, tim on-call kini dapat tidur dengan tenang, mengetahui bahwa infrastruktur kami mampu memulihkan dirinya sendiri bahkan sebelum alarm sempat membangunkan kami di tengah malam.

๐Ÿท๏ธ Tags: #Nginx #Devops #Terraform #Ansible #Aws

Apakah panduan tutorial ini membantu Anda?

Masukan Anda sangat berharga untuk terus memperbarui dan menyempurnakan kualitas materi teknis kami.

๐ŸŽ‰

Terima kasih banyak atas apresiasi Anda!

Tim kami terus menyempurnakan tutorial agar selalu akurat dengan versi teknologi terbaru.

Bantu Kami Menyempurnakan Materi Ini

๐Ÿ—บ๏ธ Jalur Belajar #Infrastructure as Code (IaC) Rangkaian Panduan
← Materi Sebelumnya

Otomasi Infrastruktur Skala Besar Menggunakan Terraform dan Ansible

Akhir Seri → Anda telah mencapai materi terbaru di seri ini.
โšก Literally Tech Digest

Update Tutorial & Developer Tools Terbaru Langsung ke Email Anda

Dapatkan kurasi artikel arsitektur software, tips DevOps, panduan database, serta rilis fitur developer utility gratis setiap minggu. Bebas spam, bisa berhenti kapan saja.

โณ Mencari artikel...
Tutorial & Artikel Terkait
Developer Tools
Tidak ditemukan tutorial atau tool dengan kata kunci "".
Ketik minimal 2 karakter untuk mencari artikel atau nama tools.
Tekan ESC untuk menutup Cari di Semua Artikel →