PostgreSQL 17 Cluster Kurulumu (Debian 12)
Bu yazımda sizlere 2 noktadan HAProxy Load Balancer erişimi ile 3 node Patroni PostgreSQL cluster yapısı kurulumunu anlatacağım.
Kuracağımız yapıda 3 adet database sunucusu, 2 adet HAProxy sunucusu bulunacak, sunucularda Debian 12 işletim sistemi mevcut. Ubuntu ve RPM tabanlı diğer dağıtımlar için komutlarda ufak değişiklikler gerekli olabilir.
ETCD
Patroni key value store olarak etcd vb çözümler kullanmakta, biz etcd ile ilerleyeceğiz.
Node 1 üzerinde /etc/default/etcd dosyasının içeriğini değiştiriyoruz;
ETCD_NAME="node-1"
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://<node-1-ip>:2380"
ETCD_LISTEN_PEER_URLS="http://<node-1-ip>:2380"
ETCD_LISTEN_CLIENT_URLS="http://<node-1-ip>:2379,http://127.0.0.1:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://<node-1-ip>:2379"
ETCD_INITIAL_CLUSTER_TOKEN="<token>"
ETCD_INITIAL_CLUSTER="node-1=http://<node-1-ip>:2380,node-2=http://<node-2-ip>:2380,node-3=http://<node-3-ip>:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
Node 2 üzerinde (Node 3'ü de aynı örüntü ile düzenleyebilirsiniz);
ETCD_NAME="node-2"
ETCD_DATA_DIR="/var/lib/etcd"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://<node-2-ip>:2380"
ETCD_LISTEN_PEER_URLS="http://<node-2-ip>:2380"
ETCD_LISTEN_CLIENT_URLS="http://<node-2-ip>:2379,http://127.0.0.1:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://<node-2-ip>:2379"
ETCD_INITIAL_CLUSTER_TOKEN="<token>"
ETCD_INITIAL_CLUSTER="node-1=http://<node-1-ip>:2380,node-2=http://<node-2-ip>:2380,node-3=http://<node-3-ip>:2380"
ETCD_INITIAL_CLUSTER_STATE="new"
Son olarak bütün sunucularda etcd servislerini sisteme kaydedelim.
sudo systemctl enable --now etcd-server
Buraya kadar hatasız geldiysek etcdctl member list
komutu ile şu şekilde bir çıktı almamız gerekiyor;
http://x.x.x.x:2379 is healthy: successfully committed proposal: took = 12.972548ms
http://x.x.x.x:2379 is healthy: successfully committed proposal: took = 13.542307ms
http://x.x.x.x:2379 is healthy: successfully committed proposal: took = 20.649216ms
PostgreSQL
Gerekli yardımcı paketleri kuruyoruz;
sudo apt install gnupg2 curl -y
GPG keyini ve PostgreSQL reposunu ekliyoruz;
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc|sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg
sudo sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
Paket bilgilerini tazeleyip kurulumu sağlıyoruz;
sudo apt update
sudo apt install postgresql-17 -y
Bu aşamada PostgreSQL servisini durdurup data klasörünü siliyoruz.
PostgreSQL process yönetimini ve config ayarlarını Patroni üzerinden yapacağız.
sudo systemctl disable --now postgresql
sudo rm -rf /var/lib/postgresql/*
Patroni
Mevcutta Debian 12 repolarında bulunduğu için patroniyi her üç node'da da direkt kurabiliriz;
sudo apt install patroni -y
Database verilerini /data klasöründe tutmak için klasörü ve izinlerini sağlayalım;
sudo mkdir -p /data
sudo chown -R postgres:postgres /data
sudo chmod -R 700 /data
Patroni için gerekli config dosyasını /etc/patroni/config.yml yolunda Node 1 üzerinde oluşturalım;
PostgreSQL için parameters kısmında yer alan optimizasyon ayarlarını kurduğunuz sunucunun özelliklerini https://pgtune.leopard.in.ua/ adresinde doldurarak kabaca belirleyebilirsiniz.
scope: postgresql-cluster
name: node-1
restapi:
listen: 0.0.0.0:8008
connect_address: <node-1-ip>:8008
etcd3:
host: <node-1-ip>:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
postgresql:
parameters:
max_connections: 300
shared_buffers: 4GB
effective_cache_size: 12GB
maintenance_work_mem: 1GB
checkpoint_completion_target: 0.9
wal_buffers: 16MB
default_statistics_target: 100
random_page_cost: 1.1
effective_io_concurrency: 300
work_mem: 6990kB
huge_pages: off
min_wal_size: 2GB
max_wal_size: 8GB
max_worker_processes: 4
max_parallel_workers_per_gather: 2
max_parallel_workers: 4
max_parallel_maintenance_workers: 2
use_pg_rewind: true
use_slots: true
initdb:
- encoding: UTF8
- locale: en_US.UTF-8
- data-checksums
pg_hba:
- host all all 0.0.0.0/0 md5
- host replication repuser 127.0.0.1/32 md5
- host replication repuser <node-2-ip> md5
- host replication repuser <node-3-ip> md5
users:
postgres:
password: "<super-user-pass>"
options:
- superuser
- createdb
repuser:
password: "<repuser-pass>"
options:
- replication
postgresql:
listen: 0.0.0.0:5432
connect_address: <node-1-ip>:5432
data_dir: /data
bin_dir: /usr/lib/postgresql/17/bin
authentication:
superuser:
username: postgres
password: "<super-user-pass>"
replication:
username: repuser
password: "<repuser-pass>"
parameters:
wal_level: replica
hot_standby: "on"
max_wal_senders: 10
wal_keep_size: 512MB
synchronous_commit: "off"
tags:
nofailover: false
noloadbalance: false
clonefrom: false
Node 2 üzerinde de aynı yol üzerinde dosyayı oluşturalım;
scope: postgresql-cluster
name: node-2
restapi:
listen: 0.0.0.0:8008
connect_address: <node-2-ip>:8008
etcd3:
host: <node-2-ip>:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
postgresql:
parameters:
max_connections: 300
shared_buffers: 4GB
effective_cache_size: 12GB
maintenance_work_mem: 1GB
checkpoint_completion_target: 0.9
wal_buffers: 16MB
default_statistics_target: 100
random_page_cost: 1.1
effective_io_concurrency: 300
work_mem: 6990kB
huge_pages: off
min_wal_size: 2GB
max_wal_size: 8GB
max_worker_processes: 4
max_parallel_workers_per_gather: 2
max_parallel_workers: 4
max_parallel_maintenance_workers: 2
use_pg_rewind: true
use_slots: true
initdb:
- encoding: UTF8
- locale: en_US.UTF-8
- data-checksums
pg_hba:
- host all all 0.0.0.0/0 md5
- host replication repuser 127.0.0.1/32 md5
- host replication repuser <node-1-ip> md5
- host replication repuser <node-3-ip> md5
users:
postgres:
password: "<super-user-pass>"
options:
- superuser
- createdb
repuser:
password: "<repuser-pass>"
options:
- replication
postgresql:
listen: 0.0.0.0:5432
connect_address: <node-2-ip>:5432
data_dir: /data
bin_dir: /usr/lib/postgresql/17/bin
authentication:
superuser:
username: postgres
password: "<super-user-pass>"
replication:
username: repuser
password: "<repuser-pass>"
parameters:
wal_level: replica
hot_standby: "on"
max_wal_senders: 10
wal_keep_size: 512MB
synchronous_commit: "off"
tags:
nofailover: false
noloadbalance: false
clonefrom: false
Node 3 için de aynı örüntüyle dosya oluşturduktan sonra sırasıyla sunucularda Patroni servislerini başlatalım;
sudo systemctl enable --now patroni
sudo systemctl restart patroni
Node 1 üzerinde patronictl -c /etc/patroni/config.yml list
komutuyla cluster durumunu kontrol ettiğimizde şöyle bir sonuç almalısınız;
+ Cluster: postgresql-cluster ----+---------+----+-----------+
| Member | Host | Role | State | TL | Lag in MB |
+--------+--------------+---------+---------+----+-----------+
| node-1 | x.x.x.x | Leader | running | 1 | |
| node-2 | x.x.x.x | Replica | running | 1 | 0 |
| node-3 | x.x.x.x | Replica | running | 1 | 0 |
+--------+--------------+---------+---------+----+-----------+
Bu aşamada replikasyon kurulumu tamamlandı, psql ile ilk sunucuya bağlanıp bir database oluşturduğunuzda diğer node'lar üzerinde de beliriyor olmalı.
HAProxy
Repolarda HAProxy de mevcut;
sudo apt install haproxy -y
İki node üzerinde de /etc/haproxy/haproxy.cfg dosyasını güncelliyoruz;
global
maxconn 1000
defaults
log global
mode tcp
retries 2
timeout client 30m
timeout connect 4s
timeout server 30m
timeout check 5s
listen stats
mode http
bind *:7000
stats enable
stats uri /
listen postgres
bind *:5432
option httpchk
http-check expect status 200
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
server psql-node-1 <node-1-ip>:5432 maxconn 200 check port 8008
server psql-node-2 <node-2-ip>:5432 maxconn 200 check port 8008
server psql-node-3 <node-3-ip>:5432 maxconn 200 check port 8008
İki sunucuyu da aktif ediyoruz;
sudo systemctl enable --now haproxy
sudo systemctl restart haproxy
Bu iki sunucunun ip adreslerini connection string'e birlikte eklediğimizde yedekli olarak çalışacaklar. HAProxy servisleri primary sunucuya yönlendirme sağlayacaklar. Örneğin;
jdbc:postgresql://<ha-node-1>:5432,<ha-node-2>:5432/test