L
High Availability & Scaling • Literally Web ID

Designing Zero-Downtime High Availability Clusters with Kubernetes and MySQL

⏱️ 15 menit baca • 📅 15 Oct 2026 • 👁️ 1 views
Designing Zero-Downtime High Availability Clusters with Kubernetes and MySQL

1. Konteks Industri & Analisis Akar Masalah

Dalam lanskap arsitektur web modern yang menuntut ketersediaan 99.999% (five nines), kegagalan infrastruktur bukanlah sebuah kemungkinan, melainkan kepastian waktu. Sistem web backend tradisional yang mengandalkan satu node database tunggal (Single Point of Failure atau SPOF) dan server aplikasi tanpa manajemen status otomatis sudah usang. Ketika terjadi lonjakan traffic, kegagalan disk, atau peremajaan kernel (kernel upgrade), sistem tersebut akan mengalami downtime yang merugikan secara finansial dan merusak reputasi merek.

Secara historis, administrator sistem sering mengandalkan skrip bash sederhana, pengaturan Master-Slave replikasi manual, dan penyeimbang beban konvensional berbasis HAProxy atau Nginx lokal yang rapuh. Masalah utama dari pendekatan ini adalah lambatnya proses deteksi kegagalan (failover detection), ketidakkonsistenan data akibat split-brain syndrome, serta tidak adanya orkestrasi otomatis ketika pod aplikasi kehilangan koneksi ke database mereka.

Sebelum vs Sesudah Penerapan Arsitektur Zero-Downtime

Parameter Arsitektur Tradisional (SPOF) Arsitektur Kluster K8s & MySQL GR
Waktu Pemulihan (RTO) Menghitung jam hingga intervensi manual Detik (Otomatis melalui Kubernetes liveness/readiness probes)
Kehilangan Data (RPO) Tinggi jika terjadi crash sebelum sync Nol (Strong consistency via MySQL Group Replication Multi-Master/Single-Master)
Strategi Deployment Rolling update manual yang menyebabkan terputusnya koneksi aktif Rolling deployment tanpa drop packet dengan graceful termination
Skalabilitas Terikat pada batas kapasitas satu server fisik/VM Dinamis, dapat diskalakan secara horizontal via Kubernetes HPA & StatefulSets

2. Konsep Inti & Deep Dive Arsitektur

Membangun kluster yang tahan banting memerlukan integrasi erat antara lapisan orkestrasi kontainer (Kubernetes) dan mesin basis data transaksional (MySQL). Mari kita bedah bagaimana komponen-komponen ini saling berinteraksi under the hood.

Alur Kerja Komunikasi Antar Komponen

+-------------------------------------------------------------------------+
|                        Kubernetes Cluster (Control Plane)               |
|                                                                         |
|  +----------------------+      +-------------------------------------+  |
|  |   Ingress Controller | ---> | Headless Service (mysql-h)          |  |
|  +----------------------+      +-------------------------------------+  |
|                                            |         |         |        |
|                                            v         v         v        |
|                                       +--------+ +--------+ +--------+ |
|                                       | Pod-0  | | Pod-1  | | Pod-2  | |
|                                       | (SQL)  | | (SQL)  | | (SQL)  | |
|                                       +--------+ +--------+ +--------+ |
|                                            ^         ^         ^        |
|                                            +----+----+----+----+        |
|                                                 Group Replication       |
+-------------------------------------------------------------------------+
  1. StatefulSets: Berbeda dengan Deployment biasa, StatefulSet memastikan penamaan pod yang deterministik (mysql-0, mysql-1, mysql-2) dan keterikatan volume penyimpanan persisten yang stabil (PersistentVolumeClaim) meskipun pod tersebut mengalami penjadwalan ulang (rescheduling) di node Kubernetes yang berbeda.
  2. MySQL Group Replication (MGR): Menyediakan replikasi tingkat lanjut berbasis Paxos consensus algorithm. Transaksi divalidasi di tingkat grup sebelum di-commit. Jika node primer (mysql-0) gagal, node sekunder secara otomatis memilih pemimpin baru tanpa kehilangan urutan transaksi (GTID - Global Transaction Identifier).
  3. Headless Service: Memungkinkan klien (seperti aplikasi backend berbasis Go, Node.js, atau PHP) untuk melakukan resolusi DNS langsung ke IP masing-masing pod di dalam kluster, memfasilitasi koneksi langsung ke node primer untuk operasi tulis dan node sekunder untuk operasi baca (Read/Write Splitting).

3. Perbandingan Komparatif / Analisis Pendekatan

Sebelum memutuskan desain akhir, kita harus mengevaluasi beberapa pendekatan arsitektur basis data di dalam Kubernetes.

Pendekatan Latency Konsistensi Data Kompleksitas Operasional Konsumsi Sumber Daya Rekomendasi Kasus Penggunaan
Operator Pihak Ketiga (Percona / Oracle) Sedang Kuat (Strong) Tinggi Tinggi (Operator overhead) Perusahaan besar dengan tim DBA khusus
Native StatefulSet + MySQL Group Replication Rendah Kuat (Strong) Menengah-Tinggi Sedang Enterprise production workloads dengan kontrol penuh
External Managed DB (AWS RDS / Google Cloud SQL) Tinggi Kuat (Strong) Rendah Rendah (Offloaded) Tim kecil, anggaran besar, minim pengelolaan infrastruktur

[!IMPORTANT] Penggunaan Operator pihak ketiga memang menyederhanakan day-2 operations seperti backup dan scaling, namun konfigurasi native StatefulSet memberikan fleksibilitas penuh terhadap parameter konfigurasi MySQL (my.cnf) dan kontrol jaringan (network policies).


4. Prasyarat Sistem & Persiapan Lingkungan

Sebelum mengeksekusi manifes Kubernetes, pastikan lingkungan Anda memenuhi standar spesifikasi berikut:

  • Kubernetes Cluster: Versi 1.25+ dengan Container Network Interface (CNI) yang mendukung NetworkPolicies (misal: Calico atau Cilium).
  • Storage Class: Penyedia Dynamic Provisioning yang mendukung ReadWriteOnce dengan performa IOPS tinggi (misal: AWS EBS gp3, Ceph RBD, atau Local Storage untuk edge).
  • Resource Node Minimum:
    • CPU: 4 vCPU per node
    • RAM: 8 GB per node
    • Disk: 50 GB SSD NVMe
  • Tooling: kubectl, helm, dan kubectx terpasang di mesin lokal administrator.

Verifikasi bahwa kluster Anda aktif dan berjalan normal:

kubectl cluster-info
kubectl get nodes -o wide

5. Panduan Implementasi Langkah demi Langkah

Kita akan membangun kluster menggunakan manifes YAML tunggal yang mencakup ConfigMap, Headless Service, StatefulSet, dan PersistentVolumeClaim.

1. Membuat Namespace Khusus

Simpan skrip ini ke dalam file 00-namespace.yaml:

apiVersion: v1
kind: Namespace
metadata:
  name: production-db

Terapkan ke kluster:

kubectl apply -f 00-namespace.yaml

2. Konfigurasi MySQL (my.cnf) via ConfigMap

Buat file 01-configmap.yaml untuk mendefinisikan parameter replikasi grup:

apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config
  namespace: production-db
data:
  my.cnf: |
    [mysqld]
    default_authentication_plugin=mysql_native_password
    skip-name-resolve
    server-id=1
    gtid_mode=ON
    enforce_gtid_consistency=ON
    binlog_checksum=NONE
    log_slave_updates=ON
    master_info_repository=TABLE
    relay_log_info_repository=TABLE
    read_only=ON
    transaction_write_set_extraction=XXHASH64
    group_replication=ON
    group_replication_start_on_boot=OFF
    group_replication_ssl_mode=REQUIRED
    group_replication_recovery_use_ssl=1

3. Layanan Jaringan Headless dan ClusterIP

Buat file 02-service.yaml untuk mengelola lalu lintas internal dan eksternal pod:

apiVersion: v1
kind: Service
metadata:
  name: mysql-headless
  namespace: production-db
  labels:
    app: mysql
spec:
  clusterIP: None
  selector:
    app: mysql
  ports:
    - name: mysql
      port: 3306
    - name: mysql-replication
      port: 33061
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-read
  namespace: production-db
  labels:
    app: mysql
spec:
  type: ClusterIP
  selector:
    app: mysql
  ports:
    - name: mysql
      port: 3306

4. StatefulSet Manifes Utama

Buat file 03-statefulset.yaml:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  namespace: production-db
spec:
  selector:
    matchLabels:
      app: mysql
  serviceName: mysql-headless
  replicas: 3
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: mysql
    spec:
      initContainers:
        - name: init-mysql
          image: mysql:8.0.33
          command:
            - bash
            - "-c"
            - |
              set -ex
              # Generate server-id from pod ordinal index
              [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
              ordinal='${BASH_REMATCH[1]}'
              echo "[mysqld]" > /mnt/conf.d/server-id.cnf
              echo "server-id=$((100 + ordinal))" >> /mnt/conf.d/server-id.cnf
              if [[ $ordinal -eq 0 ]]; then
                echo "group_replication_single_primary_mode=ON" >> /mnt/conf.d/server-id.cnf
              else
                echo "group_replication_single_primary_mode=OFF" >> /mnt/conf.d/server-id.cnf
              fi
          volumeMounts:
            - name: conf-dir
              mountPath: /mnt/conf.d
      containers:
        - name: mysql
          image: mysql:8.0.33
          ports:
            - containerPort: 3306
              name: mysql
            - containerPort: 33061
              name: replication
          resources:
            requests:
              cpu: "1"
              memory: "2Gi"
            limits:
              cpu: "2"
              memory: "4Gi"
          readinessProbe:
            exec:
              command: ["mysql
🏷️ Tags: #Nginx #High Concurrency #Performance #Sysadmin #Web Server