L
Infrastructure as Code (IaC) • Literally Web ID

Automasi Infrastruktur Kubernetes Zero-Downtime dengan Terraform

⏱️ 22 menit baca • 📅 16 Oct 2026 • 👁️ 1 views
Automasi Infrastruktur Kubernetes Zero-Downtime dengan Terraform

1. Konteks Industri & Analisis Akar Masalah

Dalam lanskap arsitektur web modern, kebutuhan akan otomatisasi infrastruktur dan ketersediaan tinggi (high availability) bukan lagi sekadar nilai tambah, melainkan fondasi bisnis yang mutlak. Perusahaan enterprise, SaaS bervolume tinggi, hingga platform e-commerce skala masif sering kali menghadapi bottleneck operasional yang parah akibat pengelolaan infrastruktur secara manual (manual provisioning). Proses tradisional seperti membuat Virtual Private Cloud (VPC), mengonfigurasi rute jaringan, menetapkan kebijakan keamanan IAM, hingga mendesain kluster Kubernetes (K8s) sering kali memakan waktu berhari-hari, rentan terhadap human error, dan hampir mustahil direplikasi dengan akurasi 100% di lingkungan staging dan production.

Masalah utama yang kerap muncul di dunia nyata adalah konfigurasi yang tidak konsisten (drift configuration), waktu downtime yang tidak terduga saat melakukan pembaruan versi kontrol pesawat (control plane) kluster, serta ketidakmampuan untuk melakukan rollback secara instan ketika terjadi kegagalan sistem. Sebelum penerapan otomatisasi penuh berbasis Infrastructure as Code (IaC) menggunakan Terraform dan GitOps, perusahaan umumnya mengandalkan skrip Bash kustom yang rapuh atau konfigurasi manual melalui konsol cloud provider (AWS/GCP). Akibatnya, setiap ada perubahan arsitektur, risiko terjadinya outage sangat tinggi.

Setelah penerapan otomatisasi infrastruktur Kubernetes zero-downtime dengan Terraform, perubahan infrastruktur bertransformasi menjadi kode yang dapat ditinjau (code review), diuji, dan diterapkan secara deterministik. Skala infrastruktur dapat dinaikkan atau diturunkan dalam hitungan menit, dan risiko human error terpangkas hingga mendekati nol. Pendekatan ini memastikan bahwa siklus hidup sistem backend (Node.js, Go, PHP-FPM), lapisan penyimpanan data (MySQL, Redis, S3/MinIO), hingga manajemen DNS dan Edge Caching (Cloudflare) berjalan selaras tanpa gangguan layanan (zero-downtime) bagi pengguna akhir.

2. Konsep Inti & Deep Dive Arsitektur

Arsitektur kluster Kubernetes berbasis cloud yang dikelola melalui Terraform memerlukan pemahaman mendalam mengenai alur eksekusi, manajemen state, dan strategi pembaruan bergulir (rolling update). Terraform bertindak sebagai orkestrator yang mendeklarasikan status akhir (desired state) dari infrastruktur, sementara penyedia cloud (seperti AWS EKS atau Google GKE) bertanggung jawab menyamakan status aktual (actual state) dengan deklarasi tersebut.

Berikut adalah representasi visual alur eksekusi arsitektur dan deployment infrastruktur:

+-----------------------------------------------------------------------+
|                        Developer / GitOps CI/CD                       |
+-----------------------------------------------------------------------+
                                   |
                                   v
+-----------------------------------------------------------------------+
|                       Terraform CLI / Automation                      | 
+-----------------------------------------------------------------------+
           |                                           |
           v (Remote State Lock)                       v (API Calls)
+-------------------------------+           +---------------------------+
|  AWS S3 Bucket & DynamoDB     |           | Cloud Provider (AWS/GCP)  |
|  (State Storage & Locking)    |           | - VPC & Subnets           |
+-------------------------------+           | - EKS/GKE Control Plane   |
                                            | - Managed Node Groups     |
                                            +---------------------------+
                                                       |
                                                       v
                                            +---------------------------+
                                            | Kubernetes Ingress Controller|
                                            | (Nginx / Caddy / ALB)     |
                                            +---------------------------+
                                                       |
                                    +------------------+------------------+
                                    v                                     v
                         +--------------------+                 +--------------------+
                         |  Backend Pods (Go) |                 | Frontend (HTML/JS) |
                         +--------------------+                 +--------------------+

Di balik layar, proses state management memastikan bahwa file terraform.tfstate disimpan secara terpusat dan aman. Mekanisme state locking menggunakan Amazon DynamoDB mencegah terjadinya konflik modifikasi simultan oleh beberapa engineer atau pipeline CI/CD. Ketika perintah terraform apply dijalankan, Terraform melakukan refresh state, menghitung diff antara kode lokal dan infrastruktur nyata, lalu mengeksekusi perubahan secara terstruktur mulai dari lapisan jaringan dasar hingga komponen compute Kubernetes.

3. Perbandingan Komparatif / Analisis Pendekatan

Untuk menentukan strategi manajemen infrastruktur yang optimal, berikut adalah analisis perbandingan mendalam antara tiga pendekatan utama yang sering dievaluasi oleh para Lead Engineer.

Parameter / Aspek Manual Cloud Console / CLI Bash Scripts + Cloud SDK Terraform (Infrastructure as Code)
Reproduksibilitas Buruk (Sangat bergantung pada memori/catatan manusia) Sedang (Sering gagal karena inkonsistensi environment) Sangat Tinggi (Deklaratif & Konsisten)
State Management Tidak ada Tidak ada Ada (Remote State terpusat dengan Locking)
Keamanan & Audit Rendah (Sulit melacak siapa yang mengubah apa) Rendah (Kredensial sering terekspos di skrip) Tinggi (Terintegrasi dengan IAM & Git History)
Rollback Capability Manual & Berisiko tinggi Sangat sulit & Berbahaya Otomatis & Terstruktur (terraform apply versi sebelumnya)
Overhead Sumber Daya Rendah di awal, tinggi saat pemeliharaan Rendah Sedang di awal, sangat efisien dalam jangka panjang
Latency / Performa Bergantung kecepatan manual Cepat tetapi rapuh Optimal (Paralelisasi eksekusi API cloud)

[!IMPORTANT] Hindari penggunaan local state (terraform.tfstate di mesin lokal) untuk lingkungan produksi. Selalu gunakan remote backend terenkripsi yang dilengkapi dengan mekanisme state locking untuk mencegah korupsi data state.

4. Prasyarat Sistem & Persiapan Lingkungan

Sebelum mulai menulis kode Terraform dan membangun kluster Kubernetes, pastikan lingkungan kerja (workstation atau CI/CD runner) memenuhi spesifikasi teknis berikut:

  • Terraform CLI: Versi >= 1.5.0 terpasang.
  • AWS CLI / Google Cloud SDK: Terkonfigurasi dengan hak akses (IAM permissions) yang memadai (Administrator akses penuh atau peran khusus VPC, EKS/GKE, IAM, dan S3).
  • Kubectl: Versi yang kompatibel dengan versi kluster Kubernetes yang akan dibuat (selisih maksimal 1 minor version).
  • Helm CLI: Versi >= 3.10.0 untuk manajemen package aplikasi di dalam kluster.

Verifikasi instalasi dengan menjalankan perintah berikut di terminal:

terraform version
aws --version
kubectl version --client
helm version

Pastikan variabel lingkungan autentikasi cloud telah diatur dengan benar:

export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_REGION="us-east-1"

5. Panduan Implementasi Langkah demi Langkah

Berikut adalah implementasi lengkap kode Terraform modular untuk membangun jaringan VPC, kluster Amazon EKS, dan konfigurasi Node Groups yang siap menangani beban produksi tinggi dengan zero-downtime.

Struktur Direktori Proyek

infra-kubernetes/
├── main.tf
├── variables.tf
├── outputs.tf
├── versions.tf
└── modules/
    ├── vpc/
    │   ├── main.tf
    │   ├── variables.tf
    │   └── outputs.tf
    └── eks/
        ├── main.tf
        ├── variables.tf
        └── outputs.tf

1. versions.tf - Konfigurasi Provider dan Backend S3

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

provider "aws" {
  region = var.aws_region
}

2. modules/vpc/main.tf - Definisi Cloud VPC

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"
    "kubernetes.io/cluster/${var.environment}" = "shared"
  }
}

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-${var.azs[count.index]}"
    "kubernetes.io/cluster/${var.environment}" = "shared"
    "kubernetes.io/role/elb"                    = "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-${var.azs[count.index]}"
    "kubernetes.io/cluster/${var.environment}" = "shared"
    "kubernetes.io/role/internal-elb"           = "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 }

3. modules/eks/main.tf - Definisi Kluster EKS & Node Groups

variable "cluster_name" { type = string }
variable "cluster_version" { type = string }
variable "vpc_id" { type = string }
variable "subnet_ids" { type = list(string) }
variable "instance_types" { type = list(string) }
variable "min_size" { type = number }
variable "max_size" { type = number }
variable "desired_size" { type = number }

resource "aws_iam_role" "cluster" {
  name = "${var.cluster_name}-cluster-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" "cluster_amazon_eks_cluster_policy" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
  role       = aws_iam_role.cluster.name
}

resource "aws_eks_cluster" "main" {
  name     = var.cluster_name
  role_arn = aws_iam_role.cluster.arn
  version  = var.cluster_version

  vpc_config {
    subnet_ids              = var.subnet_ids
    endpoint_private_access = true
    endpoint_public_access  = true
  }

  depends_on = [aws_iam_role_policy_attachment.cluster_amazon_eks_cluster_policy]
}

resource "aws_iam_role" "node" {
  name = "${var.cluster_name}-node-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "ec2.amazonaws.com"
      }
    }]
  })
}

resource "aws_iam_role_policy_attachment" "node_policies" {
  for_each = toset([
    "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy",
    "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy",
    "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
  ])
  policy_arn = each.value
  role       = aws_iam_role.node.name
}

resource "aws_eks_node_group" "main" {
  cluster_name    = aws_eks_cluster.main.name
  node_group_name = "${var.cluster_name}-nodegroup"
  node_role_arn   = aws_iam_role.node.arn
  subnet_ids      = var.subnet_ids
  instance_types  = var.instance_types

  scaling_config {
    desired_size = var.desired_size
    max_size     = var.max_size
    min_size     = var.min_size
  }

  update_config {
    max_unavailable = 1
  }

  depends_on = [aws_iam_role_policy_attachment.node_policies]
}

output "cluster_endpoint" { value = aws_eks_cluster.main.endpoint }
output "cluster_certificate_authority_data" { value = aws_eks_cluster.main.certificate_authority[0].data }

4. main.tf - Root Module Pemanggilan

module "vpc" {
  source          = "./modules/vpc"
  environment     = "production"
  vpc_cidr        = "10.100.0.0/16"
  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.11.0/24"]
}

module "eks" {
  source          = "./modules/eks"
  cluster_name    = "enterprise-prod-cluster"
  cluster_version = "1.28"
  vpc_id          = module.vpc.vpc_id
  subnet_ids      = module.vpc.private_subnets
  instance_types  = ["t3.xlarge"]
  min_size        = 3
  max_size        = 10
  desired_size    = 3
}

6. Bedah Kode & Penjelasan Detail Baris Kunci

Analisis mendalam terhadap parameter-parameter krusial dalam kode di atas sangat menentukan keberhasilan sistem zero-downtime:

  1. update_config { max_unavailable = 1 } pada EKS Node Group: Pengaturan ini menginstruksikan AWS EKS agar ketika dilakukan pembaruan versi worker node atau penggantian instans EC2, hanya maksimal 1 node yang dimatikan dalam satu waktu. Hal ini memastikan beban trafik terdistribusi ke node lain yang masih aktif sehingga tidak terjadi gangguan layanan (zero-downtime rolling update).
  2. enable_dns_hostnames = true & enable_dns_support = true pada VPC: Fitur ini wajib diaktifkan agar pod di dalam kluster Kubernetes dapat melakukan resolusi DNS internal (CoreDNS) dengan lancar, terutama saat menghubungkan backend web (Node.js/Go) ke instance database MySQL atau cache Redis yang berada di subnet privat.
  3. endpoint_private_access = true: Mengamankan control plane EKS dengan menutup akses publik langsung, memaksa semua perintah kubectl dari pengembang melewati bastion host atau CI/CD runner yang berada di dalam jaringan VPC yang sama atau terhubung via VPN aman.

[!TIP] Selalu tetapkan kapasitas cadangan (over-provisioning) pada konfigurasi min_size node group minimal 3 node untuk memastikan toleransi kegagalan (fault tolerance) apabila salah satu zona ketersediaan (availability zone) mengalami gangguan fisik di data center cloud provider.

7. Skenario Produksi & Studi Kasus Dunia Nyata

Dalam sebuah kasus nyata perusahaan Fintech dengan volume transaksi mencapai 50.000 request per detik (RPS), infrastruktur backend berbasis Go dan arsitektur database MySQL master-replica dikelola sepenuhnya melalui Terraform. Ketika terjadi lonjakan trafik masif saat kampanye flash sale, kluster Kubernetes secara otomatis melakukan horizontal pod autoscaling (HPA) berdasarkan metrik penggunaan CPU dan memori.

Namun, lonjakan trafik tersebut juga memerlukan penambahan kapasitas node pada tingkat infrastruktur (AWS EC2). Berkat konfigurasi Terraform yang terintegrasi dengan Cluster Autoscaler dan parameter max_size = 10, kluster secara otomatis menambahkan node baru dalam waktu kurang dari 3 menit tanpa ada satupun dropped connection pada lapisan Nginx Ingress Controller. Seluruh sesi pengguna (yang disimpan di Redis terdistribusi) tetap terjaga aman, dan latensi rata-rata backend API tetap berada di bawah 45 milidetik.

8. Common Pitfalls, Anti-Patterns & Solusi

Beberapa kesalahan fatal yang sering dilakukan oleh praktisi DevOps pemula maupun menengah dalam automasi Terraform Kubernetes meliputi:

  • Anti-Pattern 1: Menggabungkan Stateful Workload dengan Terraform Tanpa Perencanaan Persistensi Disk. Mengandalkan penyimpanan lokal (ephemeral storage) pada node untuk database MySQL. Solusi: Gunakan AWS EBS CSI Driver yang dideklarasikan melalui Terraform atau Helm chart terpisah, dan pisahkan manajemen database ke layanan terkelola seperti AWS RDS.
  • Pitfall 2: Hardcoding Kredensial di dalam File Terraform (.tf). Menyimpan token akses, secret key, atau kata sandi basis data secara langsung di dalam repositori Git. Solusi: Manfaatkan HashiCorp Vault, AWS Secrets Manager, atau variabel sensitif Terraform (sensitive = true) yang dibaca saat runtime melalui environment variables.
  • Pitfall 3: Mengabaikan Locking State. Menjalankan terraform apply secara bersamaan dari laptop dua engineer berbeda, mengakibatkan file terraform.tfstate rusak (state corruption). Solusi: Wajib gunakan backend S3 dengan DynamoDB State Locking.

9. Benchmark, Metrik Kinerja & Tuning Performa

Untuk menguji ketahanan dan performa kluster Kubernetes hasil automasi Terraform, pengujian beban (load testing) dilakukan menggunakan utilitas k6 dengan skenario simulasi 10.000 pengguna virtual bersamaan (virtual users).

Skrip pengujian k6 sederhana (load-test.js):

import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  stages: [
    { duration: '2m', target: 5000 },
    { duration: '5m', target: 10000 },
    { duration: '2m', target: 0 },
  ],
};

export default function () {
  const res = http.get('https://api.production.internal/healthz');
  check(res, { 'status is 200': (r) => r.status === 200 });
  sleep(1);
}

Hasil Analisis Metrik Tuning Lanjutan:

  • TCP Keep-Alive: Pastikan parameter kernel sysctl seperti net.ipv4.tcp_fin_timeout disetel lebih pendek (misal: 15 detik) pada konfigurasi OS Node Group untuk mencegah kehabisan port ephemeral (port exhaustion) pada trafik tinggi.
  • Nginx Ingress Tuning: Sesuaikan parameter worker_connections dan aktifkan penutupan koneksi keepalive yang efisien guna meminimalkan penggunaan RAM pada ingress proxy.

10. Checklist Penerapan Produksi & Kesimpulan

Sebelum meluncurkan infrastruktur kluster Kubernetes produksi ke publik, pastikan seluruh item dalam checklist berikut telah terpenuhi:

  • Remote backend Terraform terenkripsi dan aktif dengan DynamoDB Locking.
  • Konfigurasi VPC menggunakan minimal 2 Availability Zone dengan pemisahan Public dan Private Subnet yang ketat.
  • Akses Control Plane EKS/GKE dibatasi menggunakan IAM dan VPN/Bastion Host.
  • Kebijakan Rolling Update (max_unavailable = 1) terpasang pada semua Node Groups.
  • Pemantauan (Monitoring) dan Logging (seperti Prometheus, Grafana, dan FluentBit) terintegrasi otomatis.
  • Uji pemulihan bencana (Disaster Recovery) dan State Rollback telah disimulasikan di staging.

Dengan menerapkan panduan komprehensif ini, Anda tidak hanya membangun kluster Kubernetes yang stabil dan berkinerja tinggi, tetapi juga menanamkan standar rekayasa infrastruktur tingkat enterprise yang dapat diskalakan secara tak terbatas dan berkelanjutan.

🏷️ Tags: #Devops #Kubernetes #Terraform #Infrastructure As Code #Aws Eks