Patroni ile Postgresql HA Cluster

Patroni, High availability çözümü sunan failover ve failback işlemlerini destekleyen bir replication yazılımıdır. Patroni ile high available postgresql kurulum, yönetim ve monitoring işlemleri geçekleştirilir. Patroni streaming replication yöntemini kullanır. MIT lisansı ile dağıtımı yapılmakta olup PIP ile yüklenebilir. Python ile geliştirilmiş ve açık kaynak kodludur.

Klasik postgresql replication methotlarının uygulanmasındaki zorluk ve dezavantajlar şu şekilde sıralanabilir.

  • Default replication mekanizmaları Failover işlemini desteklememesi.
  • Disk bazında yapılan replication işlemleri bazı durumlarda data corruption sebebi ile sorunlara sebep olması.
  • Failover için external tool kullanıldığı zaman ortaya çıkan ekstra efor gereksinimi.
  • Fail olan node’un tekrar Cluster’a eklenme işleminin zorluğu.

Patroni;

Cluster konfigürasyonu ve streaming replication işleminin başlatımlasını sağlar. Primary and replica rolündeki sunucuların durumlarını izler. Clusterdaki bütün üyelerin konfigürasyonlarında değişiklik yapabilir. Seçilen cluster üyelerinin restart ve reload edilmesi işlemlerini gerçekleştirir. Planlı ve plansız failover işlemlerini yapar. Fail eden master sunucuların tekrar cluster’a dahil edilmesi işlemini yapar.

Patroni’nin hatalara karşı dayanıklı ve stabil bir yapısı vardır. Patroni mimarisinde her postgresql instance’ı kendisin monitor ve kontrol eden bir patroni instance’ı bulunur. Patroni’nin topladığı tüm veriler dağıtık bir key-value store’da tutulur(Örneğin etcd,consul vb.). Ve patroni instance bu bilgi araclığı ile primary’de yaşanacak bir sorunda hangi replica’nın primary rolüne atanacağına karar verir. Patroni ile DCS(Distributed Configuration Store) araçlarından bir tanesi (Etcd, Consul, ZooKeeper, Kubernetes) auto-failover özelliği için kullanılmalıdır. DCS Konfigürasyon dosyalarının cluster içindeki node’lar arasında güncel kalmasını sağlar.

ETCD : Distributed Configuration Store araçlarından bir tanesidir. ETCD, patroni ile postgresql cluster’ın health, node state ve cluster hakkındaki diğer bilgilerin tutulması için kullanılır. Tek ETCD’li mimaride sistemin en zayıf noktası ETCD’nin crash olması olacağı için ETCD aracı da High available modda konfigüre edilmelidir.

HA Proxy : Patroni kurulumu için en az 3 node’a ihtiyaç vardır. Failover durumunda Virtual IP üzerinden application’ın veri tabanına erişiminin devam etmesi gerekir. HA proxy sürekli master node ile konuşur.HA proxy master bilgisini almak için Patroni’nin default rest API protu olan 8008’e bir GET request’I gönderir. Cluster’daki node’lar arasından bir tek master node’un 8008 portu bu requeste 200 OK cevabını verir. Master dışındaki node’lar ise 503 Server Unavilable cevabını döndürür.

Keepalived : HA proxy servisi’ne virtual IP üzerinden erişebilmek için kullanılan servistir.

Patroni kurulum testi Centos7 üzerinde 3Node ile yapılmıştır. Bu 3Node’un her birinde Patroni,Postgresql,Etcd servisleri çalışırken; 1 ve 2.nodelar üzerinde Haproxy ve Keepalived servisleri de kurulmuştur. Kurulan patroni cluster’a client erişimi bir virtual IP üzerinden gerçekleştirilmektedir.

Etcd Kurulum

Kurulum işlemlerine başlamadan önce bütün node’lar üzerine aşağıdaki paketler kurulmalıdır.

yum install -y gcc python-devel epel-release

Bu paketler kurulduktan sonra 3 sunucu üzerinde de etcd servisi kurulumu için aşağıdaki komut çalıştırılır.

yum install etcd -y

etcd cluster kurulumu için /etc/etcd dizini altında bulunan etcd.conf konfigürasyon dosyası aşağıdaki gibi düzenlenir. INITIAL_CLUSTER parametresi new olarak set edilmelidir. ETCD_INITIAL_CLUSTER parametresi 3 node için de aynı set edilir. DATA_DIR parametresi key-value verilerini tutan dosyaların tutulacağı dizini belirtir.

192.168.1.10 – ptest1.test.com sunucusu
ETCD_INITIAL_CLUSTER=”etcd1=http://192.168.1.10:2380,etcd2=http://192.168.1.11:2380,etcd3=http://192.168.1.12:2380″ ETCD_INITIAL_CLUSTER_STATE=”new” ETCD_INITIAL_CLUSTER_TOKEN=”etcd-cluster-01″ ETCD_INITIAL_ADVERTISE_PEER_URLS=”http://192.168.1.10:2380″ ETCD_DATA_DIR=”/var/lib/etcd/default.etcd” ETCD_LISTEN_PEER_URLS=”http://192.168.1.10:2380″ ETCD_LISTEN_CLIENT_URLS=”http://192.168.1.10:2379,http://127.0.0.1:2379″ ETCD_ADVERTISE_CLIENT_URLS=”http://192.168.1.10:2379″ ETCD_NAME=”etcd1″  
192.168.1.11 – ptest2.test.com sunucusu
ETCD_INITIAL_CLUSTER=”etcd1=http://192.168.1.10:2380,etcd2=http://192.168.1.11:2380,etcd3=http://192.168.1.12:2380″ ETCD_INITIAL_CLUSTER_STATE=”new” ETCD_INITIAL_CLUSTER_TOKEN=”etcd-cluster-01″ ETCD_INITIAL_ADVERTISE_PEER_URLS=”http://192.168.1.11:2380″ ETCD_DATA_DIR=”/var/lib/etcd/default.etcd” ETCD_LISTEN_PEER_URLS=”http://192.168.1.11:2380″ ETCD_LISTEN_CLIENT_URLS=”http://192.168.1.11:2379,http://127.0.0.1:2379″ ETCD_ADVERTISE_CLIENT_URLS=”http://192.168.1.11:2379″ ETCD_NAME=”etcd2″  
192.168.1.12 – ptest3.test.com sunucusu
ETCD_INITIAL_CLUSTER=”etcd1=http://192.168.1.10:2380,etcd2=http://192.168.1.11:2380,etcd3=http://192.168.1.12:2380″ ETCD_INITIAL_CLUSTER_STATE=”new” ETCD_INITIAL_CLUSTER_TOKEN=”etcd-cluster-01″ ETCD_INITIAL_ADVERTISE_PEER_URLS=”http://192.168.1.12:2380″ ETCD_DATA_DIR=”/var/lib/etcd/default.etcd” ETCD_LISTEN_PEER_URLS=”http://192.168.1.12:2380″ ETCD_LISTEN_CLIENT_URLS=”http://192.168.1.12:2379,http://127.0.0.1:2379″ ETCD_ADVERTISE_CLIENT_URLS=”http://192.168.1.12:2379″ ETCD_NAME=”etcd3″

Konfigürasyon dosyalarında bu değişiklikler yapıldıktan sonra her sunucuda etcd servisleri enable edilir ve başlatılır.

systemctl enable etcd

systemctl enable etcd

Serivslerin durumu systemctl status etcd komutu ile gözlenebilir.

3 sunucuda da servisler ayağa kaldırıldıktan sonra etcd cluster’ın yönetim ve monitor işlemi etcdctl komutu ile yapılır.

etcdctl cluster-health komutu ile cluster servislerinin durumu izlenir.

Etcdctl komutu ile cluster üyeleri hakkında ayrıntılı bilgi almak için aşağıdaki komut çalıştırılır.

Etcdctl komutu ile cluster’a node ekleme(member add) ve çıkarma(member remove) işlemleri de gerçekleştirilebilir.

Not: Etcd servislerinin kurulumu ayrı sunuculara yapılabilir. Test senaryosu gereği kurulum patroni sunucularına yapılmıştır.

Patroni ve Postgresql Kurulumu

Etcd cluster kurulumu tamamlandıktan sonra herbir node üzerine patroni ve postgresql kurulumu yapılır. Kuruluma başlamadan önce 3 sunucunun da root userları arasında passwordless SSH özelliği aktif hale getirilmelidir. Aşağıdaki repo file ve paketler sunucular üzerine indirilir. Daha sonra patroni ve postgresql’in kullanacağı dizinler oluşturulur.

yum install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

yum install postgresql12 postgresql12-server -y

yum install -y python3-pip-9.0.3-5.el7.noarch gcc python3-devel python-psycopg2

pip install –upgrade setuptools

pip install python-etcd

pip install psycopg2-binary

pip install patroni

mkdir /etc/patroni/

chown postgres:postgres /etc/patroni/

mkdir /postgres/

chown postgres:postgres /postgres/

3 sunucu için de /etc/patroni dizini altında patroni.yml dosyası oluşturulur ve içerikler her bir sunucuda aşağıdaki gibi düzenlenir.

Node 1Node 2Node3
scope: pgdb-patroni
name: postgres1
restapi:
listen: 192.168.1.10:8008
connect_address: 192.168.1.10:8008
etcd:
hosts: 192.168.1.10:2379,192.168.1.11:2379,192.168.1.12:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
work_mem: 5242kB
min_wal_size: 1GB
max_wal_size: 4GB
max_worker_processes: 2
max_parallel_workers_per_gather: 1
max_parallel_workers: 2
max_parallel_maintenance_workers: 1
initdb:
encoding: UTF8
data-checksums
pg_hba:
host replication replicator 192.168.1.0/24 md5
host replication replicator 127.0.0.1/32 md5
host replication replicator 192.168.1.10/0 md5
host replication replicator 192.168.1.11/0 md5
host replication replicator 192.168.1.12/0 md5
host all all 0.0.0.0/0 md5
host all all 0.0.0.0/0 md5
users:
admin:
password: admin
options:
– createrole
– createdb
postgresql:
listen: 192.168.1.10:5432
connect_address: 192.168.1.10:5432
data_dir: /postgres/data/
bin_dir: /usr/pgsql-12/bin
pgpass: /tmp/pgpass0
authentication:
replication:
username: replicator
password: replicator
superuser:
username: postgres
password: postgres
rewind:
username: rewind_user
password: rewind_password
parameters:
unix_socket_directories: ‘/var/run/postgresql/’
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
scope: pgdb-patroni
name: postgres2
restapi:
listen: 192.168.1.11:8008
connect_address: 192.168.1.11:8008
etcd:
hosts: 192.168.1.10:2379,192.168.1.11:2379,192.168.1.12:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
work_mem: 5242kB
min_wal_size: 1GB
max_wal_size: 4GB
max_worker_processes: 2
max_parallel_workers_per_gather: 1
max_parallel_workers: 2
max_parallel_maintenance_workers: 1
initdb:
encoding: UTF8
data-checksums
pg_hba:
host replication replicator 192.168.1.0/24 md5
host replication replicator 127.0.0.1/32 md5
host replication replicator 192.168.1.10/0 md5
host replication replicator 192.168.1.11/0 md5
host replication replicator 192.168.1.12/0 md5
host all all 0.0.0.0/0 md5
host all all 0.0.0.0/0 md5
users:
admin:
password: admin
options:
– createrole
– createdb
postgresql:
listen: 192.168.1.11:5432
connect_address: 192.168.1.11:5432
data_dir: /postgres/data/
bin_dir: /usr/pgsql-12/bin
pgpass: /tmp/pgpass0
authentication:
replication:
username: replicator
password: replicator
superuser:
username: postgres
password: postgres
rewind:
username: rewind_user
password: rewind_password
parameters:
unix_socket_directories: ‘/var/run/postgresql/’
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false
scope: pgdb-patroni
name: postgres3
restapi:
listen: 192.168.1.12:8008
connect_address: 192.168.1.12:8008
etcd:
hosts: 192.168.1.10:2379,192.168.1.11:2379,192.168.1.12:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
use_slots: true
parameters:
work_mem: 5242kB
min_wal_size: 1GB
max_wal_size: 4GB
max_worker_processes: 2
max_parallel_workers_per_gather: 1
max_parallel_workers: 2
max_parallel_maintenance_workers: 1
initdb:
encoding: UTF8
data-checksums
pg_hba:
host replication replicator 192.168.1.0/24 md5
host replication replicator 127.0.0.1/32 md5
host replication replicator 192.168.1.10/0 md5
host replication replicator 192.168.1.11/0 md5
host replication replicator 192.168.1.12/0 md5
host all all 0.0.0.0/0 md5
host all all 0.0.0.0/0 md5
users:
admin:
password: admin
options:
– createrole
– createdb
postgresql:
listen: 192.168.1.12:5432
connect_address: 192.168.1.12:5432
data_dir: /postgres/data/
bin_dir: /usr/pgsql-12/bin
pgpass: /tmp/pgpass0
authentication:
replication:
username: replicator
password: replicator
superuser:
username: postgres
password: postgres
rewind:
username: rewind_user
password: rewind_password
parameters:
unix_socket_directories: ‘/var/run/postgresql/’
tags:
nofailover: false
noloadbalance: false
clonefrom: false
nosync: false

Patroni.yml dosyasında patroni instance’lar için bilgilerin yanı sıra postgresql veri tabanı parametreleri ve hba.conf dosyasının içeriği ile ilgili parametreler bulunmaktadır.

Patroni service dosyası /etc/systemd/system/patroni.service oluşturulur ve içeriği aşağıdaki gibi düzenlenir.

[Unit]

Description=Runners to orchestrate a high-availability PostgreSQL

After=syslog.target network.target

[Service]

Type=simple

User=postgres

Group=postgres

ExecStart=/usr/local/bin/patroni /etc/patroni/patroni.yml

KillMode=process

TimeoutSec=30

Restart=no

[Install]

WantedBy=multi-user.target

Servis oluşturulduktan sonra patroni servisi aşağıdaki gibi enable edilir ve start edilir.

systemctl start patroni

systemctl enable patroni

patronictl komutu ile patroni instanceların yönetimi yapılır. List komutu ve cluster adı ile aşağıdaki gibi veri tabanlarının durumu, rolleri incelenebilir.

Bu adımla patroni servisleri ve postgresql veri tabanları HA mimaride kurulmuş olur. Clusterda yer alan 192.168.1.11 IP’li sunucu üzerindeki veri tabanı primary veri tabanı durumundadır.

Haproxy ve Keepalived kurulumu

Haproxy ve Keepalived patroni cluster yapısına dışardan bağlanma noktasında Tek bir IP üzerinden (switchower durumunda dahi) bağlanılmasını sağlar gelen bağlantı isteklerini primary veri tabanına yönlendirir. Haproxy ve keepalived paketleri aşağıdaki gibi kurulur. Test ortamında Node1 ve Node2 üzerinde bu servislerin kurulumu(yedekli yapıda) yapılmıştır. Postgres user’ı ile passwordless ssh özelliği aktifleştirilmelidir.

yum install haproxy keepalived -y

haproxy servis dosyasının içerisinde belirtilen haproxy.cf dosyasının dizini kontrol edilir (/etc/haproxy/haproxy.cfg) ve bu dosyanın içeriği düzenlenir.

Node1
global
maxconn 100
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 /
Connections to port 5002
listen Master_Server
bind 192.168.1.20:500
mode tcp
option tcpka
option httpchk OPTIONS /master
http-check expect status 200
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
server 192.168.1.10 192.168.1.10:5432 maxconn 100 check port 8008
server 192.168.1.11 192.168.1.11:5432 maxconn 100 check port 8008
server 192.168.1.12 192.168.1.12:5432 maxconn 100 check port 8008
Connections to port 5003
listen Standby_Servers
bind 192.168.1.20:5001
mode tcp
option tcpka
option httpchk OPTIONS /replica
http-check expect status 200
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
server 192.168.1.10 192.168.1.10:5432 maxconn 100 check port 8008
server 192.168.1.11 192.168.1.11:5432 maxconn 100 check port 8008
server 192.168.1.12 192.168.1.12:5432 maxconn 100 check port 8008
Node2
global
maxconn 100
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 /
Connections to port 5002
listen Master_Server
bind 192.168.1.20:5000
mode tcp
option tcpka
option httpchk OPTIONS /master
http-check expect status 200
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
server 192.168.1.10 192.168.1.10:5432 maxconn 100 check port 8008
server 192.168.1.11 192.168.1.11:5432 maxconn 100 check port 8008
server 192.168.1.12 192.168.1.12:5432 maxconn 100 check port 8008
Connections to port 5003
listen Standby_Servers
bind 192.168.1.20:5001
mode tcp
option tcpka
option httpchk OPTIONS /replica
http-check expect status 200
default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
server 192.168.1.10 192.168.1.10:5432 maxconn 100 check port 8008
server 192.168.1.11 192.168.1.11:5432 maxconn 100 check port 8008
server 192.168.1.12 192.168.1.12:5432 maxconn 100 check port 8008

Bu dosyalar düzenlendikten sonra systemctl start haproxy komutu ile servisler başlatılır. Daha sonra /etc/keepalived/keepalived.conf dosyasının içeriği aşağıdaki gibi düzenlenir.

Node1
global_defs {
}
vrrp_script chk_haproxy { # Requires keepalived-1.1.13
script “killall -0 haproxy” # widely used idiom
interval 2 # check every 2 seconds
weight 2 # add 2 points of prio if OK
}
vrrp_instance VI_1 {
interface enp0s3
state MASTER # or “BACKUP” on backup
priority 101 # 101 on master, 100 on backup
virtual_router_id 51
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.168.1.20
}
track_script {
chk_haproxy
}
}
Node 2
global_defs {
}
vrrp_script chk_haproxy { # Requires keepalived-1.1.13
script “killall -0 haproxy” # widely used idiom
interval 2 # check every 2 seconds
weight 2 # add 2 points of prio if OK
}
vrrp_instance VI_1 {
interface enp0s3
state BACKUP # or “BACKUP” on backup
priority 100 # 101 on master, 100 on backup
virtual_router_id 51
authentication { auth_type PASS auth_pass 1234 } virtual_ipaddress { 192.168.1.20 } track_script { chk_haproxy }
}

Systemctl start keepalived komutu ile keepalived servisleri başlatılır ve Bu işlemler yapıldıktan sonra postgresql veri tabanına bağlantı işlemi artık Virtual IP üzerinden yapılmaktadır. 5000 portundan bağlanıldığında master, 5001 portundan bağlanıldığında ise standby veri tabanına bağlanılır.

Ref:

https://www.cybertec-postgresql.com/en/postgresql-high-availability-and-patroni-an-introduction/?gclid=CjwKCAiAsaOBBhA4EiwAo0_AnC5JgZVQIf1-YGFkYmrz5T26XA077mPypRxfXWJyweF32e6iinoiwBoCFi0QAvD_BwE

https://medium.com/searce/design-a-highly-available-postgresql-cluster-with-patroni-in-gcp-part-2-9df6ab4de741

https://guncekaya.blogspot.com/2020/01/PostgreSQL-Autofailover.html

https://patroni.readthedocs.io/en/latest/README.html

Veysel YUKSEL
Latest posts by Veysel YUKSEL (see all)

Veysel YUKSEL

RDBMS ve NoSQL veri tabanı yönetimi ve Big Data teknolojileri.

You may also like...

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir