Arsitektur High Availability PostgreSQL dengan Patroni & Etcd
1. Konteks Industri & Analisis Akar Masalah
Dalam lanskap arsitektur web modern, ketersediaan tinggi (High Availability atau HA) pada lapisan basis data adalah fondasi utama yang menentukan apakah sebuah layanan enterprise dapat bertahan menghadapi gangguan infrastruktur. Kegagalan basis data (database downtime) tidak hanya mengakibatkan kerugian finansial yang masif, tetapi juga merusak integritas data jika tidak ditangani dengan mekanisme failover yang tepat. Di era di mana aplikasi backend web dibangun menggunakan tumpukan teknologi modern—seperti Go, Node.js, PHP-FPM di belakang Nginx, serta arsitektur berbasis event-driven dengan WebSocket—bottleneck terbesar sering kali bergeser dari lapisan aplikasi ke lapisan penyimpanan persisten (persistence layer).
Secara historis, administrator sistem mengandalkan replikasi master-slave manual atau skrip bash kustom yang dikombinasikan dengan Pacemaker dan Corosync untuk mengelola kluster PostgreSQL. Pendekatan ini terbukti rapuh, rentan terhadap kondisi split-brain (di mana dua node mengira diri mereka adalah master), dan memerlukan intervensi manual yang memakan waktu pemulihan (Recovery Time Objective / RTO yang tinggi).
Sebelum penerapan kluster berbasis otomatisasi, infrastruktur enterprise sering mengalami:
- Downtime yang lama: Saat node utama mati, proses deteksi kegagalan dilakukan secara manual melalui alert monitoring, memicu eskalasi operasional yang lambat.
- Risiko Kehilangan Data (Data Loss): Tanpa mekanisme konsensus yang kuat, promosi replika cadangan sering kali dilakukan sebelum WAL (Write-Ahead Logging) terakhir tersinkronisasi sepenuhnya, menyebabkan Recovery Point Objective (RPO) yang buruk.
- Konfigurasi Aplikasi yang Kaku: Aplikasi harus diubah konfigurasinya atau memerlukan restarting saat terjadi perubahan alamat IP master.
Setelah menerapkan arsitektur High Availability PostgreSQL menggunakan Patroni, Etcd, dan HAProxy, sistem bertransformasi menjadi:
- Otomatisasi Penuh: Failover terjadi dalam hitungan detik tanpa intervensi manusia.
- Konsensus Terdistribusi: Etcd menjamin bahwa hanya ada satu sumber kebenaran (single source of truth) untuk status master, menghilangkan risiko split-brain.
- Transparansi Aplikasi: HAProxy bertindak sebagai pintu gerbang cerdas yang secara dinamis merutekan lalu lintas baca-tulis (read-write traffic) ke master yang aktif saat ini, sementara lalu lintas baca (read-only) dapat disebar ke node replika.
2. Konsep Inti & Deep Dive Arsitektur
Untuk memahami bagaimana Patroni dan Etcd bekerja sama mengamankan kluster PostgreSQL, kita harus membedah arsitektur internal di balik layar (under the hood).
Komponen Utama Kluster
- Etcd: Sebuah penyimpanan kunci-nilai (key-value store) terdistribusi yang konsisten dan sangat tersedia (highly available), menggunakan algoritma konsensus Raft. Etcd bertindak sebagai penyimpan status kluster (Cluster Configuration Store) dan distributed lock manager.
- Patroni: Sebuah template berbasis Python yang berjalan sebagai daemon di samping setiap instance PostgreSQL. Patroni berinteraksi dengan Etcd untuk melaporkan kesehatan node, berpartisipasi dalam pemilihan pemimpin (leader election), dan mengonfigurasi PostgreSQL secara lokal.
- PostgreSQL: Mesin basis data relasional yang menjalankan replikasi streaming fisik bawaan.
- HAProxy: Lapisan load balancer TCP yang memeriksa kesehatan endpoint Patroni untuk mengarahkan koneksi aplikasi ke master atau replika yang valid.
Alur Kerja Konsensus dan Failover
+-------------------------------------------------------------+
| Client Apps |
+------------------------------id-----------------------------+
|
v
+-------------------------------------------------------------+
| HAProxy (Port 5000 / 5001) |
+-------+---------------------------------------------+-------+
| (Read/Write) | (Read-Only)
v v
+---------------+ +---------------+
| PostgreSQL | | PostgreSQL |
| Node 1 (M) | <--- Streaming Replication - | Node 2 (R) |
+-------+-------+ +-------+-------+
| |
v v
+-------+-------+ +-------+-------+
| Patroni Agent | | Patroni Agent |
+-------+-------+ +-------+-------+
\ /
\-------------------- ----------------------/
v
+-------------------------------------------------------------+
| Etcd Consensus Cluster |
| (Raft Protocol - Leader Election & TTL Keys) |
+-------------------------------------------------------------+
- Pemilihan Pemimpin (Leader Election): Patroni di Node 1 berhasil mengakuisisi leader key di Etcd dengan masa hidup (Time-to-Live / TTL) tertentu. Node 1 bertindak sebagai Master.
- Penyegaran Detak Jantung (Heartbeat): Patroni Node 1 secara berkala memperbarui TTL leader key di Etcd untuk membuktikan bahwa node tersebut masih hidup.
- Deteksi Kegagalan: Jika Node 1 mengalami kegagalan perangkat keras atau terputus dari jaringan, Patroni Node 1 gagal memperbarui TTL di Etcd. Setelah TTL kedaluwarsa, kunci tersebut terhapus.
- Promosi Replikasi: Patroni di Node 2 mendeteksi hilangnya leader key, lalu memulai proses pemilihan. Patroni Node 2 berkomunikasi dengan Etcd untuk mengklaim kepemimpinan. Setelah berhasil, Patroni Node 2 mengeluarkan perintah
pg_ctl promoteuntuk mengubah instance PostgreSQL lokal dari mode recovery (read-only) menjadi master baru. - Pemberitahuan Load Balancer: HAProxy secara rutin melakukan pemeriksaan kesehatan (health check) ke endpoint HTTP Patroni (
/primaryatau/replica). HAProxy segera memperbarui rute lalu lintas aplikasi ke master yang baru.
3. Perbandingan Komparatif / Analisis Pendekatan
Berikut adalah analisis perbandingan mendalam antara pendekatan tradisional vs pendekatan modern berbasis Patroni + Etcd:
| Parameter Perbandingan | Tradisional (Pacemaker / Corosync + Script) | Modern (Patroni + Etcd + HAProxy) | Dampak Sumber Daya / Trade-off |
|---|---|---|---|
| Waktu Pemulihan (RTO) | 30 - 120 Detik | 5 - 15 Detik | Patroni mendeteksi kegagalan lebih cepat via TTL Etcd. |
| Risiko Split-Brain | Tinggi (terutama saat partisi jaringan) | Sangat Rendah (diatasi konsensus Raft) | Etcd menjamin kuorum mayoritas. |
| Kompleksitas Setup | Tinggi & Dokumentasi Terfragmentasi | Sedang (Standar Industri Teruji) | Membutuhkan pemahaman dasar etcd. |
| Overhead CPU & RAM | Rendah | Sangat Rendah (Python ringan + Etcd) | Etcd mengonsumsi RAM kecil (< 100MB per node). |
| Dukungan Cloud/Baremetal | Terbatas pada konfigurasi OS tertentu | Fleksibel (Baremetal, VM, Kubernetes) | Patroni mendukung berbagai dynamic configuration store. |
[!WARNING] Hindari menggunakan kluster Etcd dengan jumlah node genap (misal: 2 atau 4 node). Algoritma konsensus Raft memerlukan kuorum mayoritas ($N/2 + 1$). Kluster 3 node dapat menoleransi kegagalan 1 node, sementara kluster 2 node akan kehilangan kuorum jika 1 node mati.
4. Prasyarat Sistem & Persiapan Lingkungan
Untuk mengimplementasikan panduan ini, kita akan menyiapkan 3 buah node Virtual Machine / Baremetal dengan sistem operasi Ubuntu Server 22.04 LTS.
Spesifikasi Lingkungan:
- Node 1 (DB-01):
192.168.10.11(PostgreSQL, Patroni, Etcd) - Node 2 (DB-02):
192.168.10.12(PostgreSQL, Patroni, Etcd) - Node 3 (DB-03 / Witness):
192.168.10.13(PostgreSQL, Patroni, Etcd, HAProxy)
Prasyarat Awal (Jalankan di Semua Node):
- Konfigurasi Resolusi Host (
/etc/hosts):
192.168.10.11 db-01
192.168.10.12 db-02
192.168.10.13 db-03
- Nonaktifkan Swap untuk performa basis data yang konsisten:
sudo swapoff -a
sudo sed -i '/swap/d' /etc/fstab
- Sinkronkan Waktu Sistem (NTP):
sudo apt update && sudo apt install -y chrony
sudo systemctl enable --now chronyd
5. Panduan Implementasi Langkah demi Langkah
Langkah 1: Instalasi Etcd (Semua Node)
Instal paket Etcd di ketiga node untuk membentuk kluster konsensus.
sudo apt update
sudo apt install -y etcd-server etcd-client
Hentikan layanan bawaan untuk mengonfigurasi parameter kluster:
sudo systemctl stop etcd
Edit file konfigurasi /etc/default/etcd atau buat file sistem unit baru. Berikut adalah konfigurasi valid /etc/etcd/etcd.yml (atau sesuaikan dengan format systemd environment):
name: 'db-01'
data-dir: '/var/lib/etcd/db-01.etcd'
listen-peer-urls: 'http://192.168.10.11:2380'
listen-client-urls: 'http://192.168.10.11:2379,http://127.0.0.1:2379'
initial-advertise-peer-urls: 'http://192.168.10.11:2380'
advertise-client-urls: 'http://192.168.10.11:2379'
initial-cluster: 'db-01=http://192.168.10.11:2380,db-02=http://192.168.10.12:2380,db-03=http://192.168.10.13:2380'
initial-cluster-token: 'etcd-postgres-cluster'
initial-cluster-state: 'new'
(Catatan: Sesuaikan IP dan nama node (db-02 dan db-03) pada masing-masing server).:
Nyalakan dan aktifkan layanan Etcd:
sudo systemctl daemon-reload
sudo systemctl enable --now etcd
Verifikasi kesehatan kluster Etcd:
etcdctl --endpoints=http://192.168.10.11:2379,http://192.168.10.12:2379,http://192.168.10.13:2379 endpoint health
Langkah 2: Instalasi PostgreSQL dan Patroni (Semua Node)
Instal PostgreSQL (versi 15) dan pustaka pendukung Python untuk Patroni:
sudo apt install -y postgresql-15 postgresql-client-15 python3-pip python3-psycopg2
sudo systemctl stop postgresql
sudo systemctl disable postgresql
Instal Patroni melalui pip:
sudo pip3 install patroni[etcd3]
Langkah 3: Konfigurasi Patroni
Buat direktori konfigurasi Patroni:
sudo mkdir -p /etc/patroni
sudo chown postgres:postgres /etc/patroni
Buat file konfigurasi /etc/patroni/patroni.yml (contoh untuk db-01):-
scope: postgres-cluster
namespace: /service
name: db-01
etcd3:
hosts:
- 192.168.10.11:2379
- 192.168.10.12:2379
- 192.168.10.13:2379
restapi:
listen: 192.168.10.11:8008
connect_address: 192.168.10.11:8008
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
synchronous_mode: false
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
max_connections: 200
shared_buffers: 256MB
effective_cache_size: 768MB
maintenance_work_mem: 64MB
work_mem: 4MB
min_wal_size: 1GB
max_wal_size: 4GB
checkpoint_completion_target: 0.9
wal_level: replica
max_wal_senders: 10
max_replication_slots: 10
initdb:
- encoding: UTF8
- data-checksums
pg_hba:
- host replication replicator 192.168.10.0/24 md5
- host all all 0.0.0.0/0 md5
postgresql:
listen: 192.168.10.11:5432
connect_address: 192.168.10.11:5432
data_dir: /var/lib/postgresql/15/patroni
bin_dir: /usr/lib/postgresql/15/bin
admin_user: postgres
admin_password: secure_admin_password
replication:
username: replicator
password: secure_replication_password
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
[!IMPORTANT] Pastikan direktori data PostgreSQL
/var/lib/postgresql/15/patronikosong sebelum menjalankan Patroni untuk pertama kalinya. Patroni akan menjalankan perintahinitdbsecara otomatis pada node pertama.
Langkah 4: Membuat Systemd Service untuk Patroni
Buat file /etc/systemd/system/patroni.service:
[Unit]
Description=Patroni orchestrator for PostgreSQL
After=network.target etcd.service
[Service]
Type=simple
User=postgres
Group=postgres
ExecStart=/usr/local/bin/patroni /etc/patroni/patroni.yml
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
TimeoutSec=30
Restart=no
[Install]
WantedBy=multi-user.target
Aktifkan dan jalankan Patroni di semua node:
sudo systemctl daemon-reload
sudo systemctl enable --now patroni
Verifikasi status kluster:
patronictl -c /etc/patroni/patroni.yml list
Langkah 5: Konfigurasi HAProxy Load Balancer (Node 3)
Instal HAProxy di db-03 untuk merutekan koneksi aplikasi:
sudo apt install -y haproxy
Konfigurasikan /etc/haproxy/haproxy.cfg:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
user haproxy
group haproxy
daemon
defaults
log global
mode tcp
option tcplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
frontend postgres_primary_front
bind *:5000
default_backend postgres_primary_back
backend postgres_primary_back
mode tcp
option httpchk GET /primary
http-check expect status 200
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
server db-01 192.168.10.11:5432 maxconn 200 check port 8008
server db-02 192.168.10.12:5432 maxconn 200 check port 8008
server db-03 192.168.10.13:5432 maxconn 200 check port 8008
frontend postgres_replica_front
bind *:5001
default_backend postgres_replica_back
backend postgres_replica_back
mode tcp
option httpchk GET /replica
http-check expect status 200
default-server inter 3s fall 3 rise 2
server db-01 192.168.10.11:5432 maxconn 200 check port 8008
server db-02 192.168.10.12:5432 maxconn 200 check port 8008
server db-03 192.168.10.13:5432 maxconn 200 check port 8008
Nyalakan layanan HAProxy:
sudo systemctl enable --now haproxy
6. Bedah Kode & Penjelasan Detail Baris Kunci
Mari kita bedah parameter kritis dalam konfigurasi Patroni:
ttl: 30: Menentukan masa hidup kunci pemimpin di Etcd dalam detik. Jika master gagal mengirimkan sinyal heartbeat selama 30 detik, Etcd akan menghapus kunci tersebut dan memicu pemilihan pemimpin baru.loop_wait: 10: Interval waktu (dalam detik) di mana daemon Patroni memeriksa status lokal dan memperbarui status di Etcd. Nilai yang terlalu kecil dapat membebani Etcd, sementara nilai yang terlalu besar memperlambat deteksi kegagalan.maximum_lag_on_failover: 1048576: Batas maksimal jeda byte WAL (1MB) yang diizinkan bagi replika untuk dipromosikan menjadi master. Jika replika tertinggal lebih dari nilai ini, Patroni tidak akan mempromosikannya guna mencegah kehilangan data transaksi penting.use_pg_rewind: true: Memungkinkan node master lama yang telah pulih untuk menyinkronkan ulang dirinya secara otomatis dengan master baru menggunakan utilitaspg_rewindtanpa perlu melakukan pg_basebackup dari awal.
7. Skenario Produksi & Studi Kasus Dunia Nyata
Dalam lingkungan produksi dengan ribuan permintaan per detik dari aplikasi backend (misal: Node.js/Go yang melayani lalu lintas web tinggi), kegagalan koneksi basis data dapat menyebabkan connection storms.
Penanganan Lonjakan Koneksi:
- Pemisahan Beban Kerja (Read/Write Splitting): Aplikasi backend dikonfigurasi untuk mengirim operasi tulis (
INSERT,UPDATE,DELETE) ke port HAProxy5000(mengarah ke Master) dan operasi baca (SELECT) ke port5001(mengarah ke Replikasi). Ini mengurangi beban CPU pada node Master hingga 60%. - Manajemen Sesi HAProxy: Penggunaan parameter
on-marked-down shutdown-sessionspada backend HAProxy memastikan bahwa ketika master gagal dan dialihkan, koneksi TCP lama yang macet langsung diputus, memaksa aplikasi membuat ulang koneksi ke master baru yang telah dipromosikan.
8. Common Pitfalls, Anti-Patterns & Solusi
-
Anti-Pattern: Menggunakan Jumlah Node Etcd Genap
- Masalah: Menyebarkan kluster Etcd pada 2 atau 4 node. Ketika terjadi gangguan jaringan yang memisahkan kluster menjadi dua bagian yang sama besar (skenario split-brain), kuorum tidak tercapai dan kluster menjadi macet (read-only atau gagal melakukan failover).
- Solusi: Selalu gunakan jumlah node ganjil minimum 3 untuk produksi.
-
Kesalahan Konfigurasi
pg_hba.confManual- Masalah: Mengubah file
pg_hba.confsecara langsung di dalam server PostgreSQL. Patroni mengelola konfigurasi ini secara terpusat melalui blokbootstrap.dcs.pg_hbadi dalam filepatroni.yml. - Solusi: Selalu ubah aturan autentikasi melalui file konfigurasi Patroni lalu lakukan reload kluster.
- Masalah: Mengubah file
-
Mengabaikan Pemantauan Disk Ruang WAL
- Masalah: Jika replika tertinggal terlalu jauh dan slot replikasi tidak dibatasi, ruang disk pada master akan habis karena menumpuk file WAL.
- Solusi: Gunakan parameter
max_replication_slotsdan pantau metrik disk secara aktif menggunakan Prometheus dan Grafana.
9. Benchmark, Metrik Kinerja & Tuning Performa
Untuk menguji ketahanan dan performa kluster, jalankan pengujian beban menggunakan perangkat benchmark seperti pgbench yang dikombinasikan dengan simulasi pemutusan jaringan (chaos engineering).
Menjalankan Benchmark dengan pgbench:
- Inisialisasi tabel benchmark melalui HAProxy (Port 5000):
pgbench -i -s 50 -h 192.168.10.13 -p 5000 -U postgres postgres
- Jalankan pengujian konkurensi tinggi selama 5 menit:
pgbench -c 50 -j 4 -T 300 -h 192.168.10.13 -p 5000 -U postgres postgres
- Simulasi Kegagalan (Chaos Test): Selama pengujian
pgbenchberjalan, matikan layanan Patroni pada node Master aktif (sudo systemctl stop patroni). - Analisis Hasil: Amati log HAProxy dan Patroni. Pengujian yang sukses akan menunjukkan jeda koneksi sesaat selama 5 hingga 10 detik, diikuti oleh kelanjutan transaksi setelah master baru dipromosikan secara otomatis.
Parameter Tuning Lanjutan di patroni.yml:
shared_buffers: Atur ke 25% dari total RAM sistem.effective_cache_size: Atur ke 75% dari total RAM sistem.checkpoint_completion_target: Setel ke0.9untuk mendistribusikan penulisan I/O secara merata guna menghindari lonjakan latensi (disk I/O spikes).
10. Checklist Penerapan Produksi & Kesimpulan
Sebelum merilis kluster High Availability PostgreSQL ini ke lingkungan produksi publik, pastikan Anda telah memverifikasi daftar periksa berikut:
- Kluster Etcd berjalan dengan 3 node ganjil dan responsif (< 10ms latency antar node).
- Autentikasi sandi aman dan tidak menggunakan kredensial default.
- Firewall (UFW / iptables) dikonfigurasi hanya mengizinkan port internal (5432, 2379, 2380, 8008, 5000, 5001) antar node yang berhak.
- Skrip pencadangan otomatis (automated backup dengan
pg_backataubarman) dikonfigurasi secara berkala ke penyimpanan eksternal (S3/MinIO). - Pemantauan metrik (Prometheus exporter untuk Patroni dan PostgreSQL) aktif dan terintegrasi dengan sistem alerting (PagerDuty / Telegram / Email).
Dengan menerapkan arsitektur Patroni, Etcd, dan HAProxy ini, infrastruktur basis data enterprise Anda kini memiliki ketahanan militer terhadap kegagalan perangkat keras, memastikan ketersediaan layanan web yang mulus bagi seluruh pengguna.