L
High Availability & Scaling • Literally Web ID

High Availability Microservices Scaling dengan Docker Swarm dan Node.js

⏱️ 18 menit baca • 📅 16 Oct 2026 • 👁️ 1 views
High Availability Microservices Scaling dengan Docker Swarm dan Node.js

1. Konteks Industri & Analisis Akar Masalah

Dalam lanskap arsitektur web modern, kebutuhan akan High Availability (HA) dan skalabilitas horizontal bukan lagi sebuah kemewahan, melainkan syarat mutlak untuk menjamin kelangsungan bisnis digital. Bayangkan sebuah aplikasi e-commerce berskala enterprise yang dibangun di atas platform Node.js. Node.js terkenal dengan model single-threaded event loop-nya yang sangat efisien untuk menangani operasi I/O asinkron (non-blocking). Namun, karakteristik ini juga menjadi pedang bermata dua: ketika terjadi lonjakan traffic mendadak (flash sale atau serangan DDoS), satu instans aplikasi Node.js akan kehabisan kapasitas CPU core tunggal, menyebabkan latensi melonjak drastis, dan berujung pada Application Downtime.

Secara historis, banyak tim infrastruktur mencoba mengatasi masalah ini dengan menggunakan process manager seperti PM2 pada satu server berkapasitas besar (vertical scaling). Pendekatan ini memiliki batas fisik (hardware ceiling). Ketika server tersebut mengalami kegagalan perangkat keras (hardware failure), seluruh layanan akan lumpuh total. Di sinilah Horizontal Scaling berbasis kluster kontainer masuk sebagai solusi standar industri.

Namun, mengelola orkestrasi kontainer sering kali diasosiasikan dengan kompleksitas tinggi. Kubernetes (K8s), meskipun sangat powerful, memiliki kurva pembelajaran yang curam (steep learning curve) dan membutuhkan overhead manajemen operasional yang masif (etcd, kube-apiserver, kube-scheduler, ingress controller yang rumit) untuk sekadar menjalankan kluster mikroservis menengah.

Sebelum vs Sesudah Penerapan Docker Swarm & Node.js HA

Parameter Sebelum (Monolitik / Single Server PM2) Sesudah (Docker Swarm Cluster + Node.js)
Arsitektur Monolitik / Single Instance Mikroservis Terdistribusi Multi-Node
Sistem Pemulihan Manual restart via cron / SSH Auto-healing otomatis oleh Swarm Manager
Distribusi Beban Single point of failure (Nginx ke 1 port) Built-in Routing Mesh & Ingress Load Balancer
Zero-Downtime Update Terjadi downtime saat restart aplikasi Rolling updates bertahap tanpa menjatuhkan koneksi
Skalabilitas Terbatas pada kapasitas RAM/CPU satu mesin Dinamis, dapat menambah worker node kapan saja

[!WARNING] Jangan pernah menjalankan database transaksional (seperti MySQL/MariaDB) di dalam ephemeral container tanpa konfigurasi Persistent Volume yang terisolasi ke penyimpanan eksternal (seperti AWS EBS, MinIO, atau NFS terpusat) untuk mencegah kehilangan data saat kontainer direlokasi oleh Swarm.


2. Konsep Inti & Deep Dive Arsitektur

Docker Swarm mengubah sekumpulan mesin fisik atau virtual Docker menjadi satu kluster virtual yang kohesif. Di balik layar, Swarm menggunakan arsitektur Manager-Worker.

  • Manager Node: Bertanggung jawab atas cluster state management, penjadwalan tugas (scheduling tasks), dan pemeliharaan Raft Consensus Algorithm untuk memastikan konsistensi status kluster.
  • Worker Node: Menerima dan menjalankan tugas (containers) yang diinstruksikan oleh Manager.

Alur Kerja Routing Mesh & Ingress

Salah satu fitur tercanggih Docker Swarm adalah Ingress Routing Mesh. Ketika sebuah port dipublikasikan pada layanan Swarm (misalnya port 80 atau 443), setiap node di dalam kluster akan mendengarkan port tersebut, terlepas dari apakah node itu menjalankan kontainer aplikasi yang bersangkutan atau tidak.

[ Client / Browser ]
         │
         ▼
┌─────────────────────────────────────────┐
│         Nginx Edge / Load Balancer      │
└────────────────────┬────────────────────┘
                     │
         ┌───────────┴───────────┐
         ▼                       ▼
   [ Worker Node 1 ]      [ Worker Node 2 ] (No App Container here)
   Port 80 (Routing Mesh) Port 80 (Routing Mesh)
         │                       │
         └───────────┬───────────┘
                     ▼
         ┌───────────────────────┐
         │ Node.js App Container │
         │       (Task 1)        │
         └───────────────────────┘

Ketika request masuk ke Node 2 (yang sedang tidak memiliki kontainer aplikasi), Swarm secara otomatis melakukan packet routing internal menggunakan protokol IPVS (IP Virtual Server) ke node yang benar-benar menjalankan kontainer Node.js (Worker Node 1).


3. Perbandingan Komparatif / Analisis Pendekatan

Sebelum memilih Docker Swarm untuk ekosistem Node.js enterprise Anda, mari kita bandingkan dengan alternatif orkestrasi populer lainnya:

Fitur / Metrik Docker Swarm Kubernetes (K8s) Nomad (HashiCorp)
Kompleksitas Setup Sangat Rendah (Bawaan Docker) Tinggi (Butuh Helm, CNI, dll) Sedang
Kurva Pembelajaran Cepat (1-2 hari) Lambat (Minggu/Bulan) Sedang
Overhead Sumber Daya Sangat Minimal (~50MB RAM) Tinggi (~500MB-1GB RAM) Rendah
Service Discovery Built-in (DNS internal Docker) Built-in (CoreDNS) Integrasi Consul
Skalabilitas Maksimal Optimal s/d 1000 node Tak terbatas (Puluhan ribu node) Sangat Tinggi
Cocok Untuk Tim kecil-menengah, MVP, Enterprise mid Enterprise skala masif, multi-cloud Sistem heterogen & batch job

Trade-off Analisis:

  • Menggunakan Docker Swarm memberikan efisiensi operasional yang luar biasa. Tim infrastruktur tidak perlu mendeploy komponen tambahan untuk networking karena overlay network sudah terintegrasi natively di dalam mesin Docker daemon.

4. Prasyarat Sistem & Persiapan Lingkungan

Untuk membangun kluster High Availability, kita membutuhkan minimal 3 Node (untuk menjaga kuorum Raft Consensus):

  • 1 Manager Node (swarm-mgr-01, IP: 192.168.1.10)
  • 2 Worker Node (swarm-wrk-01, IP: 192.168.1.11 dan swarm-wrk-02, IP: 192.168.1.12)

Persiapan Sistem Operasi (Ubuntu 22.04 LTS pada setiap Node)

Jalankan perintah berikut pada semua node untuk memastikan instalasi bersih dan dependensi terpenuhi:

# Update sistem dan instal prasyarat
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release

# Tambahkan GPG key resmi Docker
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Tambahkan repositori Docker
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Instal Docker Engine & Docker CLI
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io

# Validasi instalasi Docker
sudo docker --version

[!TIP] Pastikan port jaringan berikut terbuka pada firewall (UFW / Cloud Security Group) antar node:

  • TCP 2377 untuk komunikasi kluster manajemen Swarm.
  • TCP & UDP 7946 untuk komunikasi antar node (container network discovery).
  • UDP 4789 untuk trafik overlay network (VXLAN).

5. Panduan Implementasi Langkah demi Langkah

Langkah 1: Inisialisasi Docker Swarm pada Manager Node

Masuk ke swarm-mgr-01 dan jalankan perintah inisialisasi Swarm:

sudo docker swarm init --advertise-addr 192.168.1.10

Simpan token worker yang dihasilkan oleh terminal (contoh: docker swarm join --token SWMTKN-1-xxxxx 192.168.1.10:2377). Jalankan token tersebut di swarm-wrk-01 dan swarm-wrk-02 untuk menggabungkannya ke dalam kluster.

Verifikasi bahwa kluster telah terbentuk dengan sukses:

sudo docker node ls

Langkah 2: Membuat Struktur Aplikasi Node.js High Availability

Buat direktori proyek baru di manager node. Kita akan membuat aplikasi Node.js sederhana menggunakan Express yang mendukung graceful shutdown agar zero-downtime deployment berjalan mulus.

Buat file package.json:

{
  "name": "node-swarm-app",
  "version": "1.0.0",
  "description": "High Availability Node.js on Docker Swarm",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "4.18.2"
  }
}

Buat file implementasi server server.js:

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

// Health check endpoint wajib untuk sistem auto-healing
app.get('/health', (req, res) => {
  res.status(200).json({
    status: 'UP',
    timestamp: new Date(),
    node: process.env.HOSTNAME
  });
});

app.get('/', (req, res) => {
  res.status(200).send(`Hello from High Availability Node.js instance running on host: ${process.env.HOSTNAME}\n`);
});

const server = app.listen(PORT, () => {
  console.log(`Server started on port ${PORT}, assigned to host ${process.env.HOSTNAME}`);
});

// Menangani sinyal SIGTERM untuk Zero-Downtime Graceful Shutdown
process.on('SIGTERM', () => {
  console.log('SIGTERM signal received: closing HTTP server gracefully');
  server.close(() => {
    console.log('HTTP server closed. Exiting process.');
    process.exit(0);
  });

  // Force close jika koneksi macet setelah 10 detik
  setTimeout(() => {
    console.error('Could not close connections in time, forcefully shutting down');
    process.exit(1);
  }, 10000);
});

Langkah 3: Menulis Dockerfile yang Dioptimalkan untuk Produksi

# Gunakan base image LTS resmi berbasis Alpine untuk ukuran image yang kecil dan aman
FROM node:18-alpine AS builder

WORKDIR /usr/src/app

COPY package*.json ./

# Instal dependensi produksi saja
RUN npm ci --only=production

FROM node:18-alpine AS runner

WORKDIR /usr/src/app

# Jalankan sebagai non-root user untuk keamanan tingkat lanjut
USER node

COPY --chown=node:node --from=builder /usr/src/app/node_modules ./node_modules
COPY --chown=node:node package*.json server.js ./

ENV NODE_ENV=production
ENV PORT=3000

EXPOSE 3000

CMD ["node", "server.js"]

Langkah 4: Konfigurasi docker-stack.yml untuk Orkestrasi Swarm

Buat file manifest infrastruktur stack kita. File ini mengatur jumlah replika, strategi update, dan batasan sumber daya (resource limits).

version: '3.8'

services:
  web_app:
    image: registry.local/node-swarm-app:latest
    ports:
      - "80:3000"
    deploy:
      mode: replicated
      replicas: 4
      endpoint_mode: vip
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
      update_config:
        parallelism: 2
        delay: 10s
        order: start-first
        failure_action: rollback
      resources:
        limits:
          cpus: '0.50'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M
    healthcheck:
      test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1); }).on('error', () => { process.exit(1); });"]
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 15s

networks:
  default:
    driver: overlay

Langkah 5: Mendeploy Stack ke Docker Swarm

Build image docker Anda (pastikan tag sesuai dengan registri lokal atau Docker Hub), lalu deploy menggunakan perintah Stack:

# Build image
docker build -t registry.local/node-swarm-app:latest .

# Deploy stack
docker stack deploy -c docker-stack.yml node_stack

# Verifikasi status servis
docker stack services node_stack
docker stack ps node_stack

6. Bedah Kode & Penjelasan Detail Baris Kunci

  1. order: start-first pada update_config: Baris ini adalah kunci utama Zero-Downtime Deployment. Docker Swarm akan menjalankan kontainer versi baru terlebih dahulu, menunggu hingga kontainer tersebut lolos health check, baru kemudian mematikan kontainer versi lama secara bertahap (parallelism: 2).
  2. SIGTERM Graceful Shutdown pada Node.js: Tanpa penanganan sinyal SIGTERM, ketika kontainer dihentikan oleh Swarm, request aktif yang sedang diproses akan langsung terputus di tengah jalan (connection reset). Dengan menangani SIGTERM, server menutup pintu masuk koneksi baru sambil tetap menyelesaikan request yang sedang berjalan.
  3. healthcheck JavaScript Inline: Menggunakan perintah node -e tanpa mengandalkan utilitas eksternal seperti curl atau wget di dalam image Alpine membuat image tetap bersih dan meminimalkan celah keamanan (attack surface).

7. Skenario Produksi & Studi Kasus Dunia Nyata

Studi Kasus: Penanganan Flash Sale Marketplace dengan 50.000 Request per Detik (RPS).

Ketika menghadapi traffic ekstrem, arsitektur yang kita buat bekerja secara sinkron:

  • Nginx Edge Layer mendistribusikan trafik masuk ke IP dari node-node Swarm.
  • Routing Mesh memecah beban secara merata ke 4 replika kontainer Node.js yang tersebar di seluruh worker node.
  • Jika salah satu worker node mengalami lonjakan penggunaan CPU hingga 90% dan kontainer mengalami crash, Swarm Manager secara otomatis mendeteksi kegagalan tersebut dalam kurun waktu kurang dari 10 detik dan segera memijat kontainer pengganti di worker node lain yang kapasitasnya masih longgar.

8. Common Pitfalls, Anti-Patterns & Solusi

[!IMPORTANT] Anti-Pattern Terbesar: Menyimpan data sesi (session state) secara lokal di dalam memori kontainer Node.js (express-session dengan MemoryStore). Solusi: Karena kontainer bersifat ephemeral (bisa mati dan dibuat ulang kapan saja), seluruh session state dan cache aplikasi wajib dipindahkan ke Redis terpusat yang berjalan di luar kontainer aplikasi atau dikelola sebagai servis terpisah di dalam kluster Swarm.

  • Kesalahan Penggunaan localhost pada Koneksi Database: Sering kali developer menulis localhost:3306 pada konfigurasi koneksi database. Di dalam arsitektur mikroservis Docker Swarm, kontainer aplikasi berada di dalam jaringan overlay yang terisolasi. Gunakan nama servis atau alamat IP jaringan internal Docker untuk berkomunikasi antar kontainer.

9. Benchmark, Metrik Kinerja & Tuning Performa

Untuk menguji ketahanan kluster, kita dapat menggunakan tool pengujian beban modern seperti k6.

Buat file skrip pengujian load-test.js:

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

export const options = {
  stages: [
    { duration: '30s', target: 200 }, // Ramp up ke 200 virtual users
    { duration: '1m', target: 500 },  // Beban puncak 500 virtual users
    { duration: '30s', target: 0 },   // Cool down
  ],
};

export default function () {
  const res = http.get('http://192.168.1.10/');
  check(res, {
    'status was 200': (r) => r.status === 200,
    'response time < 50ms': (r) => r.timings.duration < 50,
  });
  sleep(1);
}

Jalankan benchmark di terminal:

k6 run load-test.js

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

# Tingkatkan jumlah maksimum koneksi jaringan tertunda
net.core.somaxconn = 65535
# Perluas rentang port lokal untuk koneksi keluar
net.ipv4.ip_local_port_range = 1024 65535
# Optimalkan reuse port TIME_WAIT
net.ipv4.tcp_tw_reuse = 1

Terapkan perubahan dengan perintah sudo sysctl -p.


10. Checklist Penerapan Produksi & Kesimpulan

Sebelum merilis sistem ini ke lingkungan produksi publik, pastikan Anda memvalidasi poin-poin dalam checklist berikut:

  • Semua kontainer Node.js berjalan dengan user non-root (USER node).
  • Variabel lingkungan sensitif (Database Password, API Keys) dikelola menggunakan Docker Secrets, bukan hardcode di file stack.
  • Health check endpoint (/health) berfungsi dengan benar dan mengembalikan status code HTTP 200.
  • Mekanisme Graceful Shutdown telah diuji secara lokal menggunakan SIGTERM.
  • Log kontainer dikirimkan ke sistem agregasi terpusat (seperti ELK Stack, Fluentd, atau Grafana Loki).

Dengan memadukan ketangguhan Node.js dalam menangani I/O asinkron dan keandalan manajemen kontainer Docker Swarm, Anda kini memiliki fondasi infrastruktur web enterprise yang tidak hanya cepat, tetapi juga tahan banting terhadap berbagai skenario kegagalan sistem.

🏷️ Tags: #Microservices #High Availability #Devops #Node.js #Docker Swarm