Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
postgresql_patroni [2023/08/31 19:45] – andonovj | postgresql_patroni [2025/05/13 05:14] (current) – andonovj | ||
---|---|---|---|
Line 100: | Line 100: | ||
cluster is healthy | cluster is healthy | ||
[root@node00 postgresql]# | [root@node00 postgresql]# | ||
+ | </ | ||
+ | |||
+ | If you uses API v3, you have to use the new command: | ||
+ | |||
+ | < | ||
+ | [root@lpara etcd]# etcdctl --cluster=true endpoint health | ||
+ | http:// | ||
+ | http:// | ||
+ | [root@lpara etcd]# | ||
</ | </ | ||
Line 119: | Line 128: | ||
So we have our key-value propagated among the cluster, nice.... | So we have our key-value propagated among the cluster, nice.... | ||
+ | |||
+ | |||
+ | We can also check the health of the cluster endpoints as follow: | ||
+ | |||
+ | < | ||
+ | [root@etcd02 ~]# etcdctl endpoint status --write-out=table --endpoints=http:// | ||
+ | +--------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | ||
+ | | ENDPOINT | ||
+ | +--------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | ||
+ | | http:// | ||
+ | | http:// | ||
+ | | http:// | ||
+ | +--------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+ | ||
+ | [root@etcd02 ~]# | ||
+ | |||
+ | </ | ||
+ | |||
=====Setup Patroni===== | =====Setup Patroni===== | ||
Line 138: | Line 164: | ||
chown -R postgres: | chown -R postgres: | ||
chown postgres: | chown postgres: | ||
- | chmod 600 / | ||
chown postgres: | chown postgres: | ||
chown postgres: | chown postgres: | ||
Line 206: | Line 231: | ||
log_directory: | log_directory: | ||
log_filename: | log_filename: | ||
+ | archive_command: | ||
+ | archive_mode: | ||
EOF | EOF | ||
+ | chown -R postgres: | ||
+ | chown postgres: | ||
+ | chown -R postgres: | ||
+ | chown postgres: | ||
+ | chmod 600 / | ||
+ | chmod 750 /db/pgdata | ||
chown postgres: | chown postgres: | ||
+ | |||
patroni / | patroni / | ||
</ | </ | ||
Line 276: | Line 310: | ||
Well, I had many issues, but one of the most important ones was that Node02 was ahead of the Node00 for some reason, so I had to reinitialize Node02: | Well, I had many issues, but one of the most important ones was that Node02 was ahead of the Node00 for some reason, so I had to reinitialize Node02: | ||
+ | **IT IS IMPORTANT TO NOTE THAT, IF YOU UPDATE THE PATRONI YML FILE, YOU NEED TO RELOAD THE CLUSTER AND RESTART IT!!!** | ||
====Reinitialize a node==== | ====Reinitialize a node==== | ||
Line 295: | Line 330: | ||
</ | </ | ||
- | That was necessary because, even though, node02 was " | ||
+ | |||
+ | ====Restart Cluster==== | ||
+ | < | ||
+ | -bash-4.2$ patronictl -c / | ||
+ | + Cluster: stampede (7337687292879936167) ---+-----------+ | ||
+ | | Member | Host | Role | State | TL | Lag in MB | | ||
+ | +--------+--------+---------+-----------+----+-----------+ | ||
+ | | node00 | node00 | Leader | ||
+ | | node01 | node01 | Replica | streaming | 1 | 0 | | ||
+ | | node02 | node02 | Replica | streaming | 1 | 0 | | ||
+ | +--------+--------+---------+-----------+----+-----------+ | ||
+ | When should the restart take place (e.g. 2024-02-20T20: | ||
+ | Are you sure you want to restart members node01, node02, node00? [y/N]: y | ||
+ | Restart if the PostgreSQL version is less than provided (e.g. 9.5.2) | ||
+ | Success: restart on member node01 | ||
+ | Success: restart on member node02 | ||
+ | Success: restart on member node00 | ||
+ | -bash-4.2$ patronictl -c / | ||
+ | + Cluster: stampede (7337687292879936167) ---+-----------+ | ||
+ | | Member | Host | Role | State | TL | Lag in MB | | ||
+ | +--------+--------+---------+-----------+----+-----------+ | ||
+ | | node00 | node00 | Leader | ||
+ | | node01 | node01 | Replica | streaming | 1 | 0 | | ||
+ | | node02 | node02 | Replica | streaming | 1 | 0 | | ||
+ | +--------+--------+---------+-----------+----+-----------+ | ||
+ | </ | ||
+ | |||
+ | ====Reload cluster==== | ||
+ | The reload is needed if you have changed anything in the configuration file of the resources, EXCEPT the DCS | ||
+ | |||
+ | < | ||
+ | -bash-4.2$ patronictl -c / | ||
+ | + Cluster: stampede (7337687292879936167) ---+-----------+ | ||
+ | | Member | Host | Role | State | TL | Lag in MB | | ||
+ | +--------+--------+---------+-----------+----+-----------+ | ||
+ | | node00 | node00 | Leader | ||
+ | | node01 | node01 | Replica | streaming | 1 | 0 | | ||
+ | | node02 | node02 | Replica | streaming | 1 | 0 | | ||
+ | +--------+--------+---------+-----------+----+-----------+ | ||
+ | Are you sure you want to reload members node01, node02, node00? [y/N]: y | ||
+ | Reload request received for member node01 and will be processed within 10 seconds | ||
+ | Reload request received for member node02 and will be processed within 10 seconds | ||
+ | Reload request received for member node00 and will be processed within 10 seconds | ||
+ | -bash-4.2$ | ||
+ | </ | ||
+ | |||
+ | ====Update DCS==== | ||
+ | If you want to edit the DCS, you have to EITHER re-initialize the server OR use the rest API: | ||
+ | |||
+ | |||
+ | < | ||
+ | $ curl -s -XPATCH -d \ | ||
+ | ' | ||
+ | http:// | ||
+ | </ | ||
+ | =====Appendix===== | ||
+ | The whole code to run you that cluster using vagrant, you can see below. | ||
+ | |||
+ | < | ||
+ | $allow_shell = << | ||
+ | sed -i ' | ||
+ | systemctl restart sshd.service | ||
+ | SCRIPT | ||
+ | |||
+ | $edit_hosts_file = << | ||
+ | cat > /etc/hosts <<EOF | ||
+ | 127.0.0.1 localhost | ||
+ | |||
+ | 10.100.10.200 node00 | ||
+ | 10.100.10.201 node01 | ||
+ | 10.100.10.202 node02 | ||
+ | EOF | ||
+ | SCRIPT | ||
+ | |||
+ | |||
+ | $install_etcd = << | ||
+ | yum -y update | ||
+ | yum -y install python3-psycopg2 python3-pip PyYAML | ||
+ | yum -y install etcd | ||
+ | mkdir -p /db/etcd | ||
+ | |||
+ | # Install PostgreSQL: | ||
+ | sudo yum install -y https:// | ||
+ | sudo yum install -y postgresql15-server | ||
+ | chown postgres: | ||
+ | |||
+ | #Modify etcd | ||
+ | host=`hostname` | ||
+ | cat > / | ||
+ | name: ${host} | ||
+ | data-dir: / | ||
+ | initial-advertise-peer-urls: | ||
+ | listen-peer-urls: | ||
+ | listen-client-urls: | ||
+ | advertise-client-urls: | ||
+ | initial-cluster: | ||
+ | EOF | ||
+ | |||
+ | mkdir -p / | ||
+ | etcd --config-file / | ||
+ | SCRIPT | ||
+ | |||
+ | |||
+ | $install_patroni = << | ||
+ | yum -y install centos-release-scl-rh | ||
+ | yum -y install llvm-toolset-7-clang gcc python3-devel postgresql15-devel.x86_64 | ||
+ | pip3 install patroni | ||
+ | pip3 install python-etcd | ||
+ | mkdir / | ||
+ | mkdir -p / | ||
+ | mkdir -p / | ||
+ | |||
+ | |||
+ | chown -R postgres: | ||
+ | chown postgres: | ||
+ | chmod 600 / | ||
+ | chown postgres: | ||
+ | chown postgres: | ||
+ | |||
+ | host=`hostname` | ||
+ | binexec=`find / -name " | ||
+ | bindir=`${binexec} --bindir` | ||
+ | ipaddr=`cat /etc/hosts | grep " | ||
+ | subnet=`echo ${ipaddr} | cut -d' | ||
+ | |||
+ | cat > / | ||
+ | scope: stampede | ||
+ | name: ${host} | ||
+ | |||
+ | restapi: | ||
+ | listen: ${host}: | ||
+ | connect_address: | ||
+ | |||
+ | etcd: | ||
+ | host: ${host}: | ||
+ | |||
+ | bootstrap: | ||
+ | dcs: | ||
+ | ttl: 30 | ||
+ | loop_wait: 10 | ||
+ | retry_timeout: | ||
+ | maximum_lag_on_failover: | ||
+ | postgresql: | ||
+ | use_pg_rewind: | ||
+ | use_slots: true | ||
+ | parameters: | ||
+ | wal_level: logical | ||
+ | wal_log_hints: | ||
+ | |||
+ | initdb: | ||
+ | - encoding: UTF8 | ||
+ | - data-checksums | ||
+ | |||
+ | pg_hba: | ||
+ | - host replication rep_user ${ipaddr}/ | ||
+ | - host all all ${subnet}.0/ | ||
+ | |||
+ | users: | ||
+ | admin: | ||
+ | password: adminpass | ||
+ | options: | ||
+ | - createrole | ||
+ | - createdb | ||
+ | |||
+ | postgresql: | ||
+ | listen: ${host}: | ||
+ | connect_address: | ||
+ | data_dir: / | ||
+ | bin_dir: ${bindir} | ||
+ | pgpass: / | ||
+ | authentication: | ||
+ | replication: | ||
+ | username: rep_user | ||
+ | password: newpass | ||
+ | superuser: | ||
+ | username: postgres | ||
+ | password: newpass | ||
+ | parameters: | ||
+ | unix_socket_directories: | ||
+ | external_pid_file: | ||
+ | logging_collector: | ||
+ | log_directory: | ||
+ | log_filename: | ||
+ | EOF | ||
+ | |||
+ | |||
+ | chmod 750 /db/pgdata | ||
+ | chown postgres: | ||
+ | patroni / | ||
+ | SCRIPT | ||
+ | |||
+ | $install_ansible = << | ||
+ | sudo yum -y install epel-release | ||
+ | sudo yum -y install ansible | ||
+ | |||
+ | cat > / | ||
+ | [patroni] | ||
+ | 10.100.10.200 | ||
+ | 10.100.10.201 | ||
+ | 10.100.10.202 | ||
+ | |||
+ | [patroni: | ||
+ | ansible_user=root | ||
+ | ansible_password=vagrant | ||
+ | ansible_connection=ssh | ||
+ | EOF | ||
+ | |||
+ | sed -i ' | ||
+ | SCRIPT | ||
+ | |||
+ | $disable_selinux = << | ||
+ | setenforce 0 | ||
+ | SCRIPT | ||
+ | |||
+ | |||
+ | # All Vagrant configuration is done below. The " | ||
+ | # configures the configuration version (we support older styles for | ||
+ | # backwards compatibility). Please don't change it unless you know what | ||
+ | # you're doing. | ||
+ | Vagrant.configure(" | ||
+ | (0..2).each do |i| | ||
+ | config.vm.define " | ||
+ | node.vm.box = " | ||
+ | node.vm.box_check_update = true | ||
+ | node.vm.network : | ||
+ | node.vm.hostname = " | ||
+ | node.vm.provision " | ||
+ | node.vm.provision " | ||
+ | node.vm.provision " | ||
+ | node.vm.provision " | ||
+ | node.vm.provision " | ||
+ | node.vm.provision " | ||
+ | node.vm.provider " | ||
+ | vb.name = " | ||
+ | vb.memory = " | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | </ | ||
+ | |||
+ | That code will create 3 node cluster with everything. | ||
+ | |||
+ | |||
+ | =====Backup===== | ||
+ | Below you can see a method to backup, encrypt and upload a backup to OCI. The backup uses the replica for a backup source: | ||
+ | |||
+ | < | ||
+ | #!/bin/bash | ||
+ | |||
+ | switch_logfiles(){ | ||
+ | v_leader=$1 | ||
+ | |||
+ | while : | ||
+ | do | ||
+ | echo " | ||
+ | psql -Ubarman -h ${v_leader} -c " | ||
+ | sleep 10 | ||
+ | done | ||
+ | } | ||
+ | |||
+ | backup() { | ||
+ | |||
+ | environment=$1 | ||
+ | echo " | ||
+ | |||
+ | echo " | ||
+ | REPLICA_HOST=postgres-${environment} | ||
+ | |||
+ | v_first_replica=$(curl -sk https:// | ||
+ | v_leader=$(curl -sk https:// | ||
+ | |||
+ | echo " | ||
+ | sed -i " | ||
+ | |||
+ | echo " | ||
+ | barman -c / | ||
+ | |||
+ | echo " | ||
+ | barman -c / | ||
+ | |||
+ | echo " | ||
+ | |||
+ | switch_logfiles ${v_leader} & | ||
+ | |||
+ | barman -c / | ||
+ | |||
+ | kill $! | ||
+ | |||
+ | echo " | ||
+ | sed -i " | ||
+ | } | ||
+ | |||
+ | clean_old_backups(){ | ||
+ | find / | ||
+ | } | ||
+ | |||
+ | encrypt_backup(){ | ||
+ | date | ||
+ | environment=$1 | ||
+ | backup_dir=$(ls -rtd / | ||
+ | cd $(dirname ${backup_dir}) | ||
+ | backup_file=$(echo ${backup_dir} | cut -d '/' | ||
+ | enc_key=$(cat / | ||
+ | tar zcvf - ${backup_file}/ | ||
+ | date | ||
+ | } | ||
+ | |||
+ | copy_files_to_os(){ | ||
+ | date | ||
+ | environment=$1 | ||
+ | echo "Set BUCKET_NAME and OCI config file variable" | ||
+ | case ${environment} in | ||
+ | " | ||
+ | BUCKET_NAME=postgres-dev-backup | ||
+ | OCI_CONFIG_FILE=/ | ||
+ | ;; | ||
+ | " | ||
+ | BUCKET_NAME=postgres-stg-backup | ||
+ | OCI_CONFIG_FILE=/ | ||
+ | ;; | ||
+ | " | ||
+ | BUCKET_NAME=postgres-prod-backup | ||
+ | OCI_CONFIG_FILE=/ | ||
+ | ;; | ||
+ | *) | ||
+ | esac | ||
+ | |||
+ | export BUCKET_NAME | ||
+ | export OCI_CONFIG_FILE | ||
+ | |||
+ | encrypted_file=$(ls -rtd / | ||
+ | oci os object put --bucket-name ${BUCKET_NAME} --file ${encrypted_file} | ||
+ | rm -f ${encrypted_file} | ||
+ | date | ||
+ | } | ||
+ | |||
+ | backup $1 | ||
+ | encrypt_backup $1 | ||
+ | copy_files_to_os $1 | ||
+ | |||
+ | </ |