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 1 | Node 2 | Node3 |
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://guncekaya.blogspot.com/2020/01/PostgreSQL-Autofailover.html
https://patroni.readthedocs.io/en/latest/README.html
- AWS nedir? – Cloud 101 - Mayıs 16, 2024
- Vector Databases - Mayıs 15, 2024
- Data Dünyası Nereye Gidiyor? - Mayıs 8, 2024