PostgreSQL High Availability - Patroni 2


Patroni kurulumuyla ilgili oldukça fazla kaynak bulunmakta fakat kurulum ve yönetimini beraber barındıran kaynağa denk gelmedim. Bu yazıda hem Patroni kurulumu hem de kurulum sonrası yönetimiyle alakalı detaylara ulaşabilirsiniz.

PostgreSQL cluster'larının yönetimi için kullanılan Patroni ile ilgili temel bilgilerin yer aldığı Autofailover üzerine hazırladığım yazı serisine aşağıdaki linklerden erişebilirsiniz.

PostgreSQL ve Autofailover
PostgreSQL'de Autofailover ve Patroni 1 (Giriş)
PostgreSQL'de Autofailover ve Patroni 2 (Kurulum, Konfigürasyon ve Yönetim)
PostgreSQL'de Autofailover ve Patroni 3 (Mevcut PostgreSQL Cluster'inin Patroni'ye Geçirilmesi)

Patroni, PostgreSQL veritabanlarının kurulumundan ve konfigürasyonundan sorumludur. Yani Patroni'yi kurduğumuz sunucular aynı zamanda Patroni ile kurulmuş PostgreSQL'leri barındıracak. Üç node'lu PostgreSQL ve üç node'lu ETCD cluster'larını oluşturacağım.

Kuruluma önce üç node'lu ETCD cluster yapısını kurarak başlayacağım. Tüm sunucularda aşağıdaki paketler kurulur.

yum install -y gcc python-devel epel-release

ETCD Kurulumu
ETCD, GO dili ile yazılmış, CoreOS tarafından geliştirilen, dağıtık sistemlerin konfigürasyonları için kullanılan distributed High Available key-value store’u olarak tanımlanır.

Üç ETCD sunucusunun her birinde aşağıdaki paket kurulur.

yum install etcd -y

Paketin kurulmasıyla /etc/etcd/etcd.conf dosyası oluşur içinde ETCD cluster yapısının kurulması için MEMBER ve CLUSTERING altındaki parametrelerin bazıları düzenlenir. ETCD_INITIAL_CLUSTER_STATE değişkeninin değeri “new” olmasına dikkat edelim.

Primary etcd - /etc/etcd/etcd.conf

[root@guncek01 ~]# cat /etc/etcd/etcd.conf #[Member] ETCD_DATA_DIR="/var/lib/etcd/default.etcd" ETCD_LISTEN_PEER_URLS="http://ETCD_IP1:2380,http://127.0.0.1:7001" ETCD_LISTEN_CLIENT_URLS="http://ETCD_IP1:2379,http://127.0.0.1:2379" ETCD_NAME="cluster1" #[Clustering] ETCD_INITIAL_ADVERTISE_PEER_URLS="http://:2380" ETCD_ADVERTISE_CLIENT_URLS="http://ETCD_IP1:2379" ETCD_INITIAL_CLUSTER="cluster1=http://ETCD_IP1:2380,cluster2=http://ETCD_IP2:2380,cluster3=http://ETCD_IP3:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-01" ETCD_INITIAL_CLUSTER_STATE="new"

ETCD paketinin kurulumu ve etcd.conf dosyasındaki düzenleme tüm ETCD node’larında yapılmalı. Etcd.conf dosyası içinde yapılacak düzenlemeler node’ların IP’siyle beraber yeniden düzenlenmeli.

Etcd.conf içinde yapılan değişikliğin yansıması için node’lar üzerindeki etcd servisleri sırayla başlatılır ve sunucunun başlamasıyla etcd servisinin de başlaması için servis enable edilir.


systemctl start etcd systemctl enable etcd

Her node üzerinde aynı düzenlemeler yapıldıktan sonda ETCD Health-Check yapılır.

[root@guncek01 ~]# etcdctl cluster-health member 147c3c754f89f96f is healthy: got healthy result from http://ETCD_IP1:2379 member 58b8f74d65899ae4 is healthy: got healthy result from http://ETCD_IP2:2379 member ea2bd704a356529e is healthy: got healthy result from http://ETCD_IP3:2379 cluster is healthy

Oluşturduğumuz bu ETCD cluster'i altındaki tüm member'ları ayrıca listeleyebilirsiniz. "member list" komutunu herhangi bir ETCD node'u üzerinde çalıştırabilirsiniz.

[root@guncek01 pgsql]# etcdctl member list 147c3c754f89f96f: name=cluster3 peerURLs=http://ETCD_IP3:2380 clientURLs=http://ETCD_IP3:2379 isLeader=false 58b8f74d65899ae4: name=cluster2 peerURLs=http://ETCD_IP2:2380 clientURLs=http://ETCD_IP2:2379 isLeader=true d5233d20be500cbc: name=cluster1 peerURLs=http://ETCD_IP1:2380 clientURLs=http://ETCD_IP1:2379 isLeader=false

ETCD Cluster'a yeni node eklemek
Ayakta olan ETCD cluster'larının birinde eklemek istediğimiz yeni node'un IP'sini kullanarak yeni node ekleyebiliriz.
etcdctl member add cluster1 http://NEW_ETCD_NODE_IP:2380

ETCD Cluster'dan node çıkarmak
ETCD clsuter'i üzerinden bir node'u çıkarmak için member id’yi kullanarak o node’u cluster’dan çıkarırız.
etcdctl member remove 41cc095a288b712a

Patroni Kurulumu
Kuruluma başlamadan önce tüm Postgres node'ları arasında root kullanıcısı için karşılıklı olarak parolasız ssh yapılması için gerekli düzenleme yapılması gerekir. Bu düzenlemeyi yaptıysanız, Patroni kurulumuna devam edebilirsiniz.

Patroni kurulumu öncesinde Postgres rpm paketlerini kurmak gerekir. Patroni ile Postgres node'ları bootstrap(başlatılması) yapılsa da en nihayetinde replikasyonun kurulması gibi işlemleri Postgres'in tool'larını kullanarak yapacak. Dolayısıyla Postgres kurulumu için gereken tüm paketleri kurmak gerekecek.

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

Tüm Postgres node'ları üzerinde RPM'leri kurduktan sonra aynı node'lar üzerinde Patroni kurulumu yapacağız.

cd /usr/src/ wget https://github.com/cybertec-postgresql/patroni-packaging/releases/download/1.6.0-1/patroni-1.6.0-1.rhel7.x86_64.rpm yum install patroni

Patroni’nin bootstrap sırasında oluşturacağı veritabanına ait cluster dizini olmalı. Patroni için yeni cluster dizini oluşturulur.

mkdir /var/lib/pgsql/patroni -p chown postgres:postgres /var/lib/pgsql/patroni chmod 700 /var/lib/pgsql/patroni

Patroni’nin log dizini tüm sunucular üzerinde oluşturulur. Patroni servisinin başlamasıyla log dosyası, bizim oluşturduğumuz dizin altında oluşturulacaktır.

mkdir /var/log/patroni chown postgres:postgres /var/log/patroni chmod 755 /var/log/patroni

Patroni paketinin kurulmasıyla /usr/src/app/patroni/etc dizini altında postgresql.yml.sample dosyası oluşturulmuştur. Bu dosyanın yedeğini alarak yeni postgresql.yml konfigürayon dosyası üzerinden çalışmaya devam edilir. Bu dosya tüm PostgreSQL sunucuları üzerinde oluşturulmalıdır.
cp /usr/src/app/patroni/etc/postgresql.yml.sample /usr/src/app/patroni/etc/postgresql.yml

IP adresi, name, restapi, etcd, listen, connected address alanları her veritabanı sunucusu için unique alanlar olduğundan bu alanları sunucu bazlı doldurmak gerekir.
Primary patroni - /usr/src/app/patroni/etc/postgresql.yml
[root@guncek02 ~]# cat /usr/src/app/patroni/etc/postgresql.yml scope: batman2 namespace: /db/ name: postgresql0 log: dir: /var/log/patroni restapi: listen: 127.0.0.1:8008 connect_address: 127.0.0.1:8008 # certfile: /etc/ssl/certs/ssl-cert-snakeoil.pem # keyfile: /etc/ssl/private/ssl-cert-snakeoil.key # authentication: # username: username # password: password etcd: host: ETCD_IP1:2379 protocol: http bootstrap: # this section will be written into Etcd:///config after initializing new cluster # and all other cluster members will use it as a `global configuration` dcs: ttl: 30 loop_wait: 30 retry_timeout: 30 maximum_lag_on_failover: 1048576 # master_start_timeout: 300 # synchronous_mode: false postgresql: use_pg_rewind: true use_slots: true parameters: log_line_prefix: " time:%m pid=%p host=%h db=%d app=%a " wal_level: hot_standby hot_standby: "on" wal_keep_segments: 8 max_wal_senders: 5 max_replication_slots: 5 wal_log_hints: "on" archive_mode: "off" archive_timeout: 1800s # archive_command: mkdir -p ../wal_archive && test ! -f ../wal_archive/%f && cp %p ../wal_archive/%f # recovery_conf: # restore_command: cp ../wal_archive/%f %p # some desired options for 'initdb' initdb: # Note: It needs to be a list (some options need values, others are switches) - encoding: UTF8 - data-checksums pg_hba: # Add following lines to pg_hba.conf after running 'initdb' - host all all DB_IP1/32 md5 - host all all DB_IP2/32 md5 - host all all DB_IP3/32 md5 - host replication replicator DB_IP1/32 md5 - host replication replicator DB_IP2/32 md5 - host replication replicator DB_IP3/32 md5 - host all all 0.0.0.0/0 md5 # - hostssl all all 0.0.0.0/0 md5 # Additional script to be launched after initial cluster creation (will be passed the connection URL as parameter) # post_init: /usr/local/bin/setup_cluster.sh # Some additional users users which needs to be created after initializing new cluster users: admin: password: admin options: - createrole - createdb postgresql: listen: DB_IP1:5432 connect_address: DB_IP1:5432 data_dir: /var/lib/pgsql/patroni bin_dir: /usr/pgsql-11/bin # pgpass: /tmp/pgpass0 authentication: replication: username: replicator password: 'replicator' superuser: username: postgres password: 'postgres' #watchdog: # mode: automatic # Allowed values: off, automatic, required # device: /dev/watchdog # safety_margin: 5 tags: nofailover: false noloadbalance: false clonefrom: false nosync: false

Önce primary olmak üzere Patroni servisleri node’lar üzerinde sırasıyla çalıştırılır. Sırayla çalıştırılmasının sebebi primary sunucunun ayağa kalkmasından sonra diğer Postgres node’larının replika olarak ayağa kaldırılmasıdır. Bunu da pg_basebackup ile yapacaktır. Patroni servisini önce primary sunucuda sonra standby sunucuda başlattım.
systemctl start patroni systemctl enable patroni

Primary patroni log -
2019-12-25 16:22:39,406 INFO: Lock owner: postgresql0; I am postgresql0 2019-12-25 16:22:39,411 INFO: no action. i am the leader with the lock

Standby patroni log -
2019-12-25 16:21:39,411 INFO: Lock owner: postgresql0; I am postgresql1 2019-12-25 16:21:39,411 INFO: does not have lock 2019-12-25 16:21:39,415 INFO: no action. i am a secondary and i am following a leader


Patroni cluster listesine bakalım.
[root@guncek02 ~]# patronictl -d etcd://localhost:2379 -c /usr/src/app/patroni/etc/postgresql.yml list +---------+-------------+---------------+--------+---------+----+-----------+ | Cluster | Member | Host | Role | State | TL | Lag in MB | +---------+-------------+---------------+--------+---------+----+-----------+ | batman2 | postgresql0 | DB_IP1 | Leader | running | 1 | 0 | | batman2 | postgresql1 | DB_IP2 | | running | 1 | 0 | +---------+-------------+---------------+--------+---------+----+-----------+

Patroni cluster içine tüm Postgres node'larını ekledik. Primary Postgres servisini kapatalım ve testlere başlayalım.
service patroni stop
Standby sunuculardan birin primary olarak devam eder.
[root@guncek03 ~]# patronictl -d etcd://localhost:2379 -c /usr/src/app/patroni/etc/postgresql.yml list +----------+-------------+---------------+--------+---------+----+-----------+ | Cluster | Member | Host | Role | State | TL | Lag in MB | +----------+-------------+---------------+--------+---------+----+-----------+ | batman_3 | postgresql0 | DB_IP1 | | running | 11 | 0 | | batman_3 | postgresql1 | DB_IP2 | Leader | running | 11 | 0 | | batman_3 | postgresql2 | DB_IP3 | | stopped | | unknown | +----------+-------------+---------------+--------+---------+----+-----------+
Yeni primary(eski standby) sunucunun log dosyasında artık yeni primary olduğuna dair log yazılır.
2019-12-25 16:28:27,396 INFO: Lock owner: postgresql1; I am postgresql1 2019-12-25 16:28:27,402 WARNING: Watchdog not supported because leader TTL 30 is less than 2x loop_wait 30 2019-12-25 16:28:27,407 INFO: no action. i am the leader with the lock

Eski primary sunucuyu yeniden başlatalım. Bir süre sonra eski primary artık standby sunuculardan biri olarak cluster’a katılacak.
[root@guncek02 ~]# service patroni start Redirecting to /bin/systemctl start patroni.service [root@guncek02 ~]# patronictl -c /usr/src/app/patroni/etc/postgresql.yml list +----------+-------------+---------------+--------+---------+----+-----------+ | Cluster | Member | Host | Role | State | TL | Lag in MB | +----------+-------------+---------------+--------+---------+----+-----------+ | batman_3 | postgresql0 | DB_IP1 | | running | 11 | 0 | | batman_3 | postgresql1 | DB_IP2 | Leader | running | 11 | 0 | | batman_3 | postgresql2 | DB_IP3 | | running | 11 | 0 | +----------+-------------+---------------+--------+---------+----+-----------+

Patroni Cluster’indan Node Silmek
/usr/src/app/patroni/bin/patronictl -d etcd://localhost:2379 -c /usr/src/app/patroni/etc/postgresql.yml remove batman_3

PostgreSQL konfgürasyon parametrelerinin güncellenmesi
Patroni ile PostgreSQL'i entegre ettikten sonra PostgreSQL konfigürasyon parametrelerini ALTER SYSTEM komutunu kullanarak veya postgresql.conf içinde düzenleme yaparak değiştirilmemelidir. Replikalardan birinde patronictl komutu edit-config seçeneği ile çalıştırılır. Örneğin wal_keep_segments değerinin değiştirilmek istersek, patronictl komutunu çalıştırdıktan sonra değişikliği kaydedelim. Yapılan değişiklik DCS sayesinde tüm sunucular üzerinde aynı değişiklikler uygulanacak.
[root@guncek02 ~]# patronictl -c /usr/src/app/patroni/etc/postgresql.yml edit-config --- +++ @@ -8,7 +8,7 @@ log_line_prefix: ' time:%m pid=%p host=%h db=%d app=%a ' max_replication_slots: 5 max_wal_senders: 5 - wal_keep_segments: 10 + wal_keep_segments: 8 wal_level: hot_standby wal_log_hints: 'on' use_pg_rewind: true Apply these changes? [y/N]: y Configuration changed

Patroni log dosyasında yapılan değişiklik aşağıdaki gibi yansıyacaktır.
grep -i changed /var/log/patroni/patroni.log 2019-12-30 10:02:58,878 INFO: Changed wal_keep_segments from 10 to 8 2019-12-30 10:02:58,879 INFO: PostgreSQL configuration items changed, reloading configuration. 2019-12-30 10:03:28,865 INFO: Lock owner: postgresql1; I am postgresql1

Mevcut bir Postgres veritabanının Patroni'ye taşınmasını anlatan serinin son yazısına buradan ulaşabilirsiniz.

Comments

Popular posts from this blog

PostgreSQL Foreign Data Wrappers

PostgreSQL High Availability - Patroni 1