From 0134f914228bd76a6837bc1efe0cc3a37bc55657 Mon Sep 17 00:00:00 2001 From: Jehan-Guillaume de Rorthais Date: Wed, 23 Sep 2020 23:26:54 +0200 Subject: [PATCH] extra: refactor 3nodes-vip vagrant file --- extra/vagrant/3nodes-vip/Makefile | 21 +-- extra/vagrant/3nodes-vip/Vagrantfile | 110 ++++++------ .../3nodes-vip/provision/cluster-common.bash | 92 ----------- .../3nodes-vip/provision/log_sink.bash | 20 --- .../3nodes-vip/provision/pacemaker.bash | 35 ++-- .../3nodes-vip/provision/pgsql-primary.bash | 83 ---------- .../3nodes-vip/provision/pgsql-replicas.bash | 61 ------- extra/vagrant/3nodes-vip/provision/pgsql.bash | 156 ++++++++++++++++++ .../vagrant/3nodes-vip/provision/system.bash | 152 ++++++++++++++--- extra/vagrant/3nodes-vip/vagrant.yml-dist | 2 +- 10 files changed, 375 insertions(+), 357 deletions(-) delete mode 100755 extra/vagrant/3nodes-vip/provision/cluster-common.bash delete mode 100755 extra/vagrant/3nodes-vip/provision/log_sink.bash delete mode 100755 extra/vagrant/3nodes-vip/provision/pgsql-primary.bash delete mode 100755 extra/vagrant/3nodes-vip/provision/pgsql-replicas.bash create mode 100755 extra/vagrant/3nodes-vip/provision/pgsql.bash diff --git a/extra/vagrant/3nodes-vip/Makefile b/extra/vagrant/3nodes-vip/Makefile index 72d410a..5374e43 100644 --- a/extra/vagrant/3nodes-vip/Makefile +++ b/extra/vagrant/3nodes-vip/Makefile @@ -1,25 +1,18 @@ export VAGRANT_BOX_UPDATE_CHECK_DISABLE=1 export VAGRANT_CHECKPOINT_DISABLE=1 -.PHONY: all create_vm pgsql-primary pgsql-replicas pacemaker cts prov clean validate +.PHONY: all up pgsql pacemaker cts clean check validate pcmk-stop +all: up -all: create_vm pgsql-replicas pacemaker - -create_vm: +up: vagrant up -pgsql-replicas: pcmk-stop pgsql-primary - vagrant up --provision-with=pgsql-replicas +pgsql: pcmk-stop + vagrant provision --provision-with=pgsql pacemaker: - vagrant up --provision-with=pacemaker - -pgsql-primary: pcmk-stop - vagrant up --provision-with=pgsql-primary - -prov: - vagrant up --provision + vagrant provision --provision-with=pacemaker clean: vagrant destroy -f @@ -34,7 +27,7 @@ validate: fi cts: - vagrant up --provision-with=cts + vagrant provision --provision-with=cts pcmk-stop: vagrant ssh -c 'if [ -f "/etc/corosync/corosync.conf" ]; then sudo pcs cluster stop --all --wait; fi' diff --git a/extra/vagrant/3nodes-vip/Vagrantfile b/extra/vagrant/3nodes-vip/Vagrantfile index c939b7a..c3ce473 100644 --- a/extra/vagrant/3nodes-vip/Vagrantfile +++ b/extra/vagrant/3nodes-vip/Vagrantfile @@ -2,27 +2,28 @@ require 'ipaddr' require 'yaml' #ENV['VAGRANT_NO_PARALLEL'] = 'yes' # uncomment to forbid parallel execution -ENV["LANG"] = "C" -ENV["LC_ALL"] = "C" - -boxname = 'centos/7' # vagrant box to use -pgver = '11' # pg version to use -hapass = 'hapass' # password for sys user hacluster -ssh_login = 'root' # ssh login to connect to the host when fencing a VM. - # put "./provision/id_rsa.pub" in your "~/.ssh/authorized_keys" -master_ip = '10.20.30.5' # vIP assigned to master -pg_nodes = 'srv1', 'srv2', 'srv3' # first will be primary -log_node = 'log-sink' # name of the node receiving logs -vm_prefix = 'paf_vm' # VM prefix in libvrit -rhel_user = '' # RHEL user account -rhel_pass = '' # RHEL user account password +ENV["LANG"] = "C" +ENV["LC_ALL"] = "C" + +boxname = 'centos/7' # vagrant box to use +pgver = '12' # pg version to use +hapass = 'hapass' # password for sys user hacluster +ssh_login = 'root' # ssh login to connect to the host when fencing a VM. + # put "./provision/id_rsa.pub" in your "~/.ssh/authorized_keys" +base_ip = '10.20.30.50' # vIP assigned to master +vm_prefix = 'paf_3nvIP' # VM prefix in libvrit +rhel_user = '' # RHEL user account +rhel_pass = '' # RHEL user account password +pg_nodes = 'srv1', 'srv2', 'srv3' # first will be primary +log_node = 'log-sink' # name of the node receiving logs + if File.file?('vagrant.yml') and ( custom = YAML.load_file('vagrant.yml') ) boxname = custom['boxname'] if custom.has_key?('boxname') pgver = custom['pgver'] if custom.has_key?('pgver') hapass = custom['hapass'] if custom.has_key?('hapass') ssh_login = custom['ssh_login'] if custom.has_key?('ssh_login') - master_ip = custom['master_ip'] if custom.has_key?('master_ip') + base_ip = custom['base_ip'] if custom.has_key?('base_ip') pg_nodes = custom['pg_nodes'] if custom.has_key?('pg_nodes') log_node = custom['log_node'] if custom.has_key?('log_node') vm_prefix = custom['vm_prefix'] if custom.has_key?('vm_prefix') @@ -32,9 +33,12 @@ end Vagrant.configure(2) do |config| + ############################################################################ + # computes IPs + pgdata = "/var/lib/pgsql/#{pgver}/data" - next_ip = IPAddr.new(master_ip).succ - host_ip = (IPAddr.new(master_ip) & "255.255.255.0").succ.to_s + next_ip = IPAddr.new(base_ip).succ + host_ip = (IPAddr.new(base_ip) & "255.255.255.0").succ.to_s nodes_ips = {} ( pg_nodes + [ log_node ] ).each do |node| @@ -42,6 +46,16 @@ Vagrant.configure(2) do |config| next_ip = next_ip.succ end + ############################################################################ + # general vagrant setup + + # RHEL registration when needed + if Vagrant.has_plugin?('vagrant-registration') + config.registration.unregister_on_halt = false + config.registration.username = rhel_user + config.registration.password = rhel_pass + end + # don't mind about insecure ssh key config.ssh.insert_key = false @@ -57,62 +71,56 @@ Vagrant.configure(2) do |config| lv.qemu_use_session = false end - # disable default share + # sync the root of sources config.vm.synced_folder ".", "/vagrant", disabled: true - config.vm.synced_folder "../../..", "/vagrant", type: "rsync", rsync__exclude: [ ".git/" ] + config.vm.define pg_nodes.first, primary: true + + ############################################################################ # system setup for all nodes + + config.vm.provision 'file', source: 'provision/id_rsa', destination: '/home/vagrant/.ssh/id_rsa' + config.vm.provision 'file', source: 'provision/id_rsa.pub', destination: '/home/vagrant/.ssh/id_rsa.pub' + (pg_nodes + [log_node]).each do |node| config.vm.define node do |conf| conf.vm.network 'private_network', ip: nodes_ips[node] - conf.vm.provision 'system-setup', type: 'shell', path: 'provision/system.bash', - args: [ node, rhel_user, rhel_pass ] + nodes_ips.keys.map {|n| "#{n}=#{nodes_ips[n]}"}, + conf.vm.provision 'system', type: 'shell', + path: 'provision/system.bash', + args: [ node, pgver, base_ip, hapass, log_node ] + + nodes_ips.keys.map {|n| "#{n}=#{nodes_ips[n]}"}, preserve_order: true end end - # setup rsyslog to collect logs from other node on log-sink - config.vm.define log_node do |conf| - conf.vm.provision 'rsyslog-setup', type: 'shell', path: 'provision/log_sink.bash' - end - - # common postgresql+pacemaker installation and setup + ############################################################################ + # build pgsql instances pg_nodes.each do |node| config.vm.define node do |conf| - conf.vm.provision 'cluster-common', type: 'shell', path: 'provision/cluster-common.bash', - args: [ pgver, hapass, master_ip ], + conf.vm.provision 'pgsql', type: 'shell', + path: 'provision/pgsql.bash', + args: [ node, pgver, pgdata, base_ip, pg_nodes.first ], preserve_order: true end end - # build primary pgsql instance - config.vm.define pg_nodes.first, primary:true do |conf| - conf.vm.provision 'pgsql-primary', type: 'shell', - path: 'provision/pgsql-primary.bash', - args: [ pgver, pgdata, master_ip, pg_nodes.first ], - run: 'never' - end - - # replicas setup. Use "vagrant up --provision-with=pgsql-replicas" - pg_nodes[1..-1].each do |node| - config.vm.define node do |conf| - conf.vm.provision 'pgsql-replicas', type: 'shell', path: 'provision/pgsql-replicas.bash', - args: [ pgver, pgdata, master_ip, node ], run: 'never' - end - end - - # cluster setup. Use "vagrant up --provision-with=pacemaker" + ############################################################################ + # cluster setup pg_nodes.each do |node| config.vm.define node do |conf| - conf.vm.provision 'pacemaker', type: 'shell', path:'provision/pacemaker.bash', - args: [ pgver, hapass, master_ip, ssh_login, + conf.vm.provision 'pacemaker', type: 'shell', + path: 'provision/pacemaker.bash', + args: [ pgver, hapass, base_ip, ssh_login, vm_prefix, host_ip, pgdata ] + pg_nodes, - run: 'never' + preserve_order: true end end - # cluster test suite setup. Use "vagrant up --provision-with=cts" - config.vm.provision 'cts', type: 'shell', path: 'provision/cts.bash', run: 'never' + ############################################################################ + # cluster test suite setup. Use "vagrant provision --provision-with=cts" + config.vm.provision 'cts', type: 'shell', + path: 'provision/cts.bash', + run: 'never' end diff --git a/extra/vagrant/3nodes-vip/provision/cluster-common.bash b/extra/vagrant/3nodes-vip/provision/cluster-common.bash deleted file mode 100755 index 1a0436d..0000000 --- a/extra/vagrant/3nodes-vip/provision/cluster-common.bash +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -PGVER="$1" -HAPASS="$2" -MASTER_IP="$3" - -# shellcheck disable=SC1091 -source "/etc/os-release" -OS_ID="$ID" -OS_VER="$VERSION_ID" -YUM_INSTALL="yum install --nogpgcheck --quiet -y -e 0" - -# install required packages -if [ "$OS_ID" = "rhel" ]; then - # use yum instead of dnf for compatibility between EL 7 and 8 - yum-config-manager --enable "*highavailability-rpms" -fi - -if ! rpm --quiet -q "pgdg-redhat-repo"; then - if [ "${OS_VER:0:2}" = "8." ]; then - $YUM_INSTALL "https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm" - else - $YUM_INSTALL "https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm" - fi -fi - -# disable postgresql upstream module conflicting with pgdg packages in RHEL8 -if [ "${OS_VER:0:2}" = "8." ]; then - yum -qy module disable postgresql -fi - -PACKAGES=( - pacemaker pcs resource-agents fence-agents-virsh sbd perl-Module-Build - "postgresql${PGVER}" - "postgresql${PGVER}-server" - "postgresql${PGVER}-contrib" -) - -$YUM_INSTALL "${PACKAGES[@]}" - -# firewall setup -systemctl --quiet --now enable firewalld -firewall-cmd --quiet --permanent --add-service=high-availability -firewall-cmd --quiet --permanent --add-service=postgresql -firewall-cmd --quiet --reload - -# cluster stuffs -systemctl --quiet --now enable pcsd -echo "${HAPASS}"|passwd --stdin hacluster > /dev/null 2>&1 -cp /etc/sysconfig/pacemaker /etc/sysconfig/pacemaker.dist -cat<<'EOF' > /etc/sysconfig/pacemaker -PCMK_debug=yes -PCMK_logpriority=debug -EOF - -# cleanup master ip everywhere -HAS_MASTER_IP=$(ip -o addr show to "${MASTER_IP}"|wc -l) - -if [ "$HAS_MASTER_IP" -gt 0 ]; then - DEV=$(ip route show to "${MASTER_IP}/24"|grep -Eom1 'dev \w+') - ip addr del "${MASTER_IP}/24" dev "${DEV/dev }" -fi - -# send logs to log-sinks -cat <<'EOF' >/etc/rsyslog.d/fwd_log_sink.conf -*.* action(type="omfwd" -queue.type="LinkedList" -queue.filename="log_sink_fwd" -action.resumeRetryCount="-1" -queue.saveonshutdown="on" -target="log-sink" Port="514" Protocol="tcp") -EOF - -systemctl --quiet restart rsyslog - -# cleanup pre-existing IP address -ip -o addr show to "${MASTER_IP}" | if grep -q "${MASTER_IP}" -then - DEV=$(ip route show to "${MASTER_IP}/24"|grep -Eo 'dev \w+') - ip addr del "${MASTER_IP}/24" dev "${DEV/dev }" -fi - -# install PAF -cd /vagrant -[ -f Build ] && perl Build distclean -sudo -u vagrant perl Build.PL --quiet >/dev/null 2>&1 -sudo -u vagrant perl Build --quiet -perl Build --quiet install diff --git a/extra/vagrant/3nodes-vip/provision/log_sink.bash b/extra/vagrant/3nodes-vip/provision/log_sink.bash deleted file mode 100755 index ac45b07..0000000 --- a/extra/vagrant/3nodes-vip/provision/log_sink.bash +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -# setup log sink -cat <<'EOF' > /etc/rsyslog.d/log_sink.conf -$ModLoad imtcp -$InputTCPServerRun 514 - -$template RemoteLogsMerged,"/var/log/%HOSTNAME%/messages.log" -*.* ?RemoteLogsMerged - -$template RemoteLogs,"/var/log/%HOSTNAME%/%PROGRAMNAME%.log" -*.* ?RemoteLogs -#& ~ -EOF - -systemctl --quiet restart rsyslog diff --git a/extra/vagrant/3nodes-vip/provision/pacemaker.bash b/extra/vagrant/3nodes-vip/provision/pacemaker.bash index b920a6e..21f0c34 100755 --- a/extra/vagrant/3nodes-vip/provision/pacemaker.bash +++ b/extra/vagrant/3nodes-vip/provision/pacemaker.bash @@ -4,18 +4,21 @@ set -o errexit set -o nounset set -o pipefail -PGVER="$1" -HAPASS="$2" -MASTER_IP="$3" -SSH_LOGIN="$4" -VM_PREFIX="$5" -HOST_IP="$6" -PGDATA="$7" +declare PCMK_VER +declare -a PGSQLD_RSC_OPTS +declare -r PGVER="$1" +declare -r HAPASS="$2" +declare -r PRIM_IP="$3" +declare -r SSH_LOGIN="$4" +declare -r VM_PREFIX="$5" +declare -r HOST_IP="$6" +declare -r PGDATA="$7" shift 7 -NODES=( "$@" ) +declare -r -a NODES=( "$@" ) -CUSTOMDIR="${PGDATA}/conf.d" +declare -r CUSTOMDIR="${PGDATA}/conf.d" +# extract pacemaker major version PCMK_VER=$(yum info --quiet pacemaker|grep ^Version) PCMK_VER="${PCMK_VER#*: }" # extract x.y.z PCMK_VER="${PCMK_VER:0:1}" # extract x @@ -66,6 +69,7 @@ done PGSQLD_RSC_OPTS=( "ocf:heartbeat:pgsqlms" + "bindir=/usr/pgsql-${PGVER}/bin" "pgdata=${PGDATA}" "recovery_template=${CUSTOMDIR}/recovery.conf.pcmk" @@ -93,13 +97,16 @@ if [ "$PCMK_VER" -eq 1 ]; then pcs -f cluster1.xml resource master pgsqld-clone pgsqld notify=true fi -pcs -f cluster1.xml resource create pgsql-master-ip \ - "ocf:heartbeat:IPaddr2" "ip=${MASTER_IP}" cidr_netmask=24 \ +pcs -f cluster1.xml resource create pgsql-pri-ip \ + "ocf:heartbeat:IPaddr2" "ip=${PRIM_IP}" cidr_netmask=24 \ op monitor interval=10s -pcs -f cluster1.xml constraint colocation add pgsql-master-ip with master pgsqld-clone INFINITY -pcs -f cluster1.xml constraint order promote pgsqld-clone "then" start pgsql-master-ip symmetrical=false -pcs -f cluster1.xml constraint order demote pgsqld-clone "then" stop pgsql-master-ip symmetrical=false +pcs -f cluster1.xml constraint colocation \ + add pgsql-pri-ip with master pgsqld-clone INFINITY +pcs -f cluster1.xml constraint order \ + promote pgsqld-clone "then" start pgsql-pri-ip symmetrical=false +pcs -f cluster1.xml constraint order \ + demote pgsqld-clone "then" stop pgsql-pri-ip symmetrical=false pcs cluster cib-push scope=configuration cluster1.xml --wait diff --git a/extra/vagrant/3nodes-vip/provision/pgsql-primary.bash b/extra/vagrant/3nodes-vip/provision/pgsql-primary.bash deleted file mode 100755 index e7da79c..0000000 --- a/extra/vagrant/3nodes-vip/provision/pgsql-primary.bash +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -PGVER="$1" -PGDATA="$2" -MASTER_IP="$3" -NODENAME="$4" - -CUSTOMDIR="${PGDATA}/conf.d" - -# cleanup -systemctl --quiet --now disable "postgresql-${PGVER}" -rm -rf "${PGDATA}" - -# init instance -"/usr/pgsql-${PGVER}/bin/postgresql-${PGVER}-setup" initdb - -# pg_hba setup -cat< "${PGDATA}/pg_hba.conf" -local all all trust -host all all 0.0.0.0/0 trust - -# forbid self-replication -host replication postgres ${MASTER_IP}/32 reject -host replication postgres ${NODENAME} reject - -# allow any standby connection -host replication postgres 0.0.0.0/0 trust -EOC - -# postgresql.conf setup -mkdir -p "$CUSTOMDIR" -echo "include_dir = 'conf.d'" >> "${PGDATA}/postgresql.conf" - -cat <<'EOC' > "${CUSTOMDIR}/custom.conf" -listen_addresses = '*' -wal_level = replica -max_wal_senders = 10 -hot_standby = on -hot_standby_feedback = on -wal_keep_segments = 256 -log_destination = 'syslog,stderr' -log_checkpoints = on -log_min_duration_statement = 0 -log_autovacuum_min_duration = 0 -log_replication_commands = on -EOC - -if [ "${PGVER%%.*}" -lt 12 ]; then - # recovery.conf setup - cat<<-EOC > "${CUSTOMDIR}/recovery.conf.pcmk" - standby_mode = on - primary_conninfo = 'host=${MASTER_IP} application_name=${NODENAME}' - recovery_target_timeline = 'latest' - EOC -else - cat <<-EOC > "${CUSTOMDIR}/repli.conf" - primary_conninfo = 'host=${MASTER_IP} application_name=${NODENAME}' - EOC - - # standby_mode disappear in v12 - # no need to add recovery_target_timeline as its default is 'latest' since v12 -fi - -# backing up files -cp "${PGDATA}/pg_hba.conf" "${PGDATA}/.." -cp "${PGDATA}/postgresql.conf" "${PGDATA}/.." -cp "${CUSTOMDIR}"/* "${PGDATA}/.." - -chown -R postgres:postgres "$PGDATA" - -# create master ip -ip -o addr show to "${MASTER_IP}" | if ! grep -q "${MASTER_IP}" -then - DEV=$(ip route show to "${MASTER_IP}/24"|grep -Eo 'dev \w+') - ip addr add "${MASTER_IP}/24" dev "${DEV/dev }" -fi - -# restart master pgsql -systemctl --quiet start "postgresql-${PGVER}" diff --git a/extra/vagrant/3nodes-vip/provision/pgsql-replicas.bash b/extra/vagrant/3nodes-vip/provision/pgsql-replicas.bash deleted file mode 100755 index 6b74801..0000000 --- a/extra/vagrant/3nodes-vip/provision/pgsql-replicas.bash +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -PGVER="$1" -PGDATA="$2" -MASTER_IP="$3" -NODENAME="$4" - -CUSTOMDIR="${PGDATA}/conf.d" - -# cleanup -systemctl --quiet --now disable "postgresql-${PGVER}" -rm -rf "${PGDATA}" - -# build standby -"/usr/pgsql-${PGVER}/bin/pg_basebackup" -h "${MASTER_IP}" -U postgres -D "${PGDATA}" -X stream - -# set pg_hba -cat< "${PGDATA}/pg_hba.conf" -local all all trust -host all all 0.0.0.0/0 trust - -# forbid self-replication -host replication postgres ${MASTER_IP}/32 reject -host replication postgres ${NODENAME} reject - -# allow any standby connection -host replication postgres 0.0.0.0/0 trust -EOC -cp "${PGDATA}/pg_hba.conf" "${PGDATA}/.." - -if [ "${PGVER%%.*}" -lt 12 ]; then - # recovery.conf setup - cat<<-EOC > "${CUSTOMDIR}/recovery.conf.pcmk" - standby_mode = on - primary_conninfo = 'host=${MASTER_IP} application_name=${NODENAME}' - recovery_target_timeline = 'latest' - EOC - cp "${CUSTOMDIR}/recovery.conf.pcmk" "${PGDATA}/recovery.conf" -else - cat <<-EOC > "${CUSTOMDIR}/repli.conf" - primary_conninfo = 'host=${MASTER_IP} application_name=${NODENAME}' - EOC - - # standby_mode disappear in v12 - # no need to add recovery_target_timeline as its default is 'latest' since v12 - touch "${PGDATA}/standby.signal" -fi - -# backing up files -cp "${PGDATA}/pg_hba.conf" "${PGDATA}/.." -cp "${PGDATA}/postgresql.conf" "${PGDATA}/.." -cp "${CUSTOMDIR}"/* "${PGDATA}/.." - -chown -R "postgres:postgres" "${PGDATA}/.." - -# start -systemctl --quiet start "postgresql-${PGVER}" diff --git a/extra/vagrant/3nodes-vip/provision/pgsql.bash b/extra/vagrant/3nodes-vip/provision/pgsql.bash new file mode 100755 index 0000000..b4720e9 --- /dev/null +++ b/extra/vagrant/3nodes-vip/provision/pgsql.bash @@ -0,0 +1,156 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +declare -r NODENAME="$1" +declare -r PGVER="$2" +declare -r PGDATA="$3" +declare -r PRIM_IP="$4" +declare -r PRIM_NODE="$5" + +declare -r CUSTOMDIR="${PGDATA}/conf.d" + +# cleanup +systemctl --quiet --now disable "postgresql-${PGVER}" +rm -rf "${PGDATA}" + +if [ "$NODENAME" == "$PRIM_NODE" ]; then + # init instance + "/usr/pgsql-${PGVER}/bin/postgresql-${PGVER}-setup" initdb + + # pg_hba setup + cat<<-EOC > "${PGDATA}/pg_hba.conf" + local all all trust + host all all 0.0.0.0/0 trust + + # forbid self-replication + local replication all reject + host replication all ${NODENAME} reject + host replication all 127.0.0.1/32 reject + host replication all ::1/128 reject + host replication all ${PRIM_IP}/32 reject + + # allow any standby connection + host replication postgres 0.0.0.0/0 trust + EOC + + # postgresql.conf setup + mkdir -p "$CUSTOMDIR" + echo "include_dir = 'conf.d'" >> "${PGDATA}/postgresql.conf" + + cat <<-EOC > "${CUSTOMDIR}/cluster_name.conf" + cluster_name = 'pgsql-$NODENAME' + EOC + + cat <<-'EOC' > "${CUSTOMDIR}/custom.conf" + listen_addresses = '*' + port = 5432 + wal_level = replica + max_wal_senders = 10 + hot_standby = on + hot_standby_feedback = on + wal_keep_segments = 256 + log_destination = 'syslog,stderr' + log_checkpoints = on + log_min_duration_statement = 0 + log_autovacuum_min_duration = 0 + log_replication_commands = on + EOC + + if [ "${PGVER%%.*}" -lt 12 ]; then + # recovery.conf setup + cat<<-EOC > "${CUSTOMDIR}/recovery.conf.pcmk" + standby_mode = on + primary_conninfo = 'host=${PRIM_IP} application_name=${NODENAME}' + recovery_target_timeline = 'latest' + EOC + else + cat <<-EOC > "${CUSTOMDIR}/repli.conf" + primary_conninfo = 'host=${PRIM_IP} application_name=${NODENAME}' + EOC + + # standby_mode disappear in v12 + # no need to add recovery_target_timeline as its default is 'latest' + # since v12 + fi + + # backing up files + cp "${PGDATA}/pg_hba.conf" "${PGDATA}/.." + cp "${PGDATA}/postgresql.conf" "${PGDATA}/.." + cp "${CUSTOMDIR}"/* "${PGDATA}/.." + + chown -R postgres:postgres "$PGDATA" + + # create master ip + ip -o addr show to "${PRIM_IP}" | if ! grep -q "${PRIM_IP}" + then + DEV=$(ip route show to "${PRIM_IP}/24"|grep -Eo 'dev \w+') + ip addr add "${PRIM_IP}/24" dev "${DEV/dev }" + fi + + # restart master pgsql + systemctl --quiet start "postgresql-${PGVER}" + + exit +fi + +# building standby + +# wait for the primary to listen +while ! "/usr/pgsql-${PGVER}/bin/pg_isready" -qh "${PRIM_IP}"; do sleep 1 ; done + + +# build standby +"/usr/pgsql-${PGVER}/bin/pg_basebackup" -h "${PRIM_IP}" -U postgres \ + -D "${PGDATA}" -X stream + +# set pg_hba +cat< "${PGDATA}/pg_hba.conf" +local all all trust +host all all 0.0.0.0/0 trust + +# forbid self-replication +local replication all reject +host replication all ${NODENAME} reject +host replication all 127.0.0.1/32 reject +host replication all ::1/128 reject +host replication all ${PRIM_IP}/32 reject + +# allow any standby connection +host replication postgres 0.0.0.0/0 trust +EOC + +cat < "${CUSTOMDIR}/cluster_name.conf" +cluster_name = 'pgsql-$NODENAME' +EOC + +if [ "${PGVER%%.*}" -lt 12 ]; then + # recovery.conf setup + cat<<-EOC > "${CUSTOMDIR}/recovery.conf.pcmk" + standby_mode = on + primary_conninfo = 'host=${PRIM_IP} application_name=${NODENAME}' + recovery_target_timeline = 'latest' + EOC + + cp "${CUSTOMDIR}/recovery.conf.pcmk" "${PGDATA}/recovery.conf" +else + cat <<-EOC > "${CUSTOMDIR}/repli.conf" + primary_conninfo = 'host=${PRIM_IP} application_name=${NODENAME}' + EOC + + # standby_mode disappear in v12 + # no need to add recovery_target_timeline as its default is 'latest' since v12 + touch "${PGDATA}/standby.signal" +fi + +# backing up files +cp "${PGDATA}/pg_hba.conf" "${PGDATA}/.." +cp "${PGDATA}/postgresql.conf" "${PGDATA}/.." +cp "${CUSTOMDIR}"/* "${PGDATA}/.." + +chown -R "postgres:postgres" "${PGDATA}/.." + +# start +systemctl --quiet start "postgresql-${PGVER}" diff --git a/extra/vagrant/3nodes-vip/provision/system.bash b/extra/vagrant/3nodes-vip/provision/system.bash index 7009a6d..1516cf1 100755 --- a/extra/vagrant/3nodes-vip/provision/system.bash +++ b/extra/vagrant/3nodes-vip/provision/system.bash @@ -4,45 +4,57 @@ set -o errexit set -o nounset set -o pipefail -NODENAME="$1" -RHEL_USER="$2" -RHEL_PASS="$3" -shift -NODES=( "$@" ) +declare -r NODENAME="$1" +declare -r PGVER="$2" +declare -r PRIM_IP="$3" +declare -r HAPASS="$4" +declare -r LOGNODE="$5" -hostnamectl set-hostname "${NODENAME}" +shift 5 +declare -r -a NODES=( "$@" ) -for N in "${NODES[@]}"; do - NG=$(sed -n "/${N%=*}\$/p" /etc/hosts|wc -l) - if [ "$NG" -eq 0 ]; then - echo "${N##*=} ${N%=*}" >> /etc/hosts - fi -done +declare -r YUM_INSTALL="yum install --nogpgcheck --quiet -y -e 0" +# detect operating system provider and version # shellcheck disable=SC1091 source "/etc/os-release" OS_ID="$ID" +OS_VER="$VERSION_ID" + +# set hostname +hostnamectl set-hostname "${NODENAME}" -PACKAGES=( vim bash-completion yum-utils ) +# fill /etc/hosts +for N in "${NODES[@]}"; do + declare HNAME="${N%=*}" + declare HIP="${N##*=}" + if ! grep -Eq "${HNAME}\$" /etc/hosts; then + echo "${HIP} ${HNAME}" >> /etc/hosts + fi +done +# enable required repository if [ "$OS_ID" = "rhel" ]; then - subscription-manager register --force --username "${RHEL_USER:?}" --password "${RHEL_PASS:?}" --auto-attach - PACKAGES+=("tmux") -else - PACKAGES+=("screen") + # use yum instead of dnf for compatibility between EL 7 and 8 + yum-config-manager --enable "*highavailability-rpms" +elif [ "$OS_ID" = "centos" ] && [ "${OS_VER:0:1}" = "8" ]; then + yum-config-manager --enable "HighAvailability" fi -yum install --nogpgcheck --quiet -y -e 0 "${PACKAGES[@]}" +# install essential packages +if [ "${OS_VER:0:1}" = "8" ]; then + $YUM_INSTALL yum-utils tmux vim policycoreutils-python-utils.noarch +else + $YUM_INSTALL yum-utils tmux vim policycoreutils-python +fi +# SSH setup cat <<'EOF' > "/home/vagrant/.ssh/config" Host * CheckHostIP no StrictHostKeyChecking no EOF -cp "/vagrant/extra/vagrant/3nodes-vip/provision/id_rsa" "/home/vagrant/.ssh" -cp "/vagrant/extra/vagrant/3nodes-vip/provision/id_rsa.pub" "/home/vagrant/.ssh" - chown -R "vagrant:" "/home/vagrant/.ssh" chmod 0700 "/home/vagrant/.ssh" chmod 0600 "/home/vagrant/.ssh/id_rsa" @@ -59,3 +71,101 @@ chmod 0600 "/root/.ssh/id_rsa" chmod 0644 "/root/.ssh/id_rsa.pub" chmod 0600 "/root/.ssh/config" chmod 0600 "/root/.ssh/authorized_keys" + +# enable firewall +systemctl --quiet --now enable firewalld + +# setup log sink +if [ "$NODENAME" == "$LOGNODE" ]; then + + cat <<-'EOF' > /etc/rsyslog.d/log_sink.conf + $ModLoad imtcp + $InputTCPServerRun 514 + + $template RemoteLogsMerged,"/var/log/%HOSTNAME%/messages.log" + *.* ?RemoteLogsMerged + + $template RemoteLogs,"/var/log/%HOSTNAME%/%PROGRAMNAME%.log" + *.* ?RemoteLogs + #& ~ + EOF + + if ! firewall-cmd --get-services|grep -q rsyslog-tcp; then + firewall-cmd --quiet --permanent --new-service="rsyslog-tcp" + firewall-cmd --quiet --permanent --service="rsyslog-tcp" --set-description="RSyslog TCP port" + firewall-cmd --quiet --permanent --service="rsyslog-tcp" --add-port="514/tcp" + fi + firewall-cmd --quiet --permanent --add-service="rsyslog-tcp" + firewall-cmd --quiet --reload + + semanage port -m -t syslogd_port_t -p tcp 514 + + systemctl --quiet restart rsyslog + + exit +fi + +# setting up pgsql nodes + +# send logs to log-sinks +cat <<'EOF' >/etc/rsyslog.d/20-fwd_log_sink.conf +*.* action(type="omfwd" +queue.type="LinkedList" +queue.filename="log_sink_fwd" +action.resumeRetryCount="-1" +queue.saveonshutdown="on" +target="log-sink" Port="514" Protocol="tcp") +EOF + +systemctl --quiet restart rsyslog + +# PGDG repo +if ! rpm --quiet -q "pgdg-redhat-repo"; then + if [ "${OS_VER:0:1}" = "8" ]; then + $YUM_INSTALL "https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm" + else + $YUM_INSTALL "https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm" + fi +fi + +# disable postgresql upstream module conflicting with pgdg packages in RHEL8 +if [ "${OS_VER:0:1}" = "8" ]; then + yum -qy module disable postgresql +fi + +$YUM_INSTALL pacemaker pcs \ + resource-agents fence-agents-virsh sbd \ + perl-Module-Build \ + "postgresql${PGVER}" \ + "postgresql${PGVER}-server" \ + "postgresql${PGVER}-contrib" + +# setting up pcs +systemctl --quiet --now enable pcsd.service +echo "$HAPASS"|passwd --stdin hacluster > /dev/null 2>&1 + +# firewall setup +firewall-cmd --quiet --permanent --add-service=high-availability +firewall-cmd --quiet --permanent --add-service=postgresql +firewall-cmd --quiet --reload + +# cleanup pre-existing IP address +ip -o addr show to "${PRIM_IP}" | if grep -q "${PRIM_IP}" +then + DEV=$(ip route show to "${PRIM_IP}/24"|grep -Eo 'dev \w+') + ip addr del "${PRIM_IP}/24" dev "${DEV/dev }" +fi + +# install PAF +cd /vagrant +[ -f Build ] && perl Build distclean +sudo -u vagrant perl Build.PL --quiet >/dev/null 2>&1 +sudo -u vagrant perl Build --quiet +perl Build --quiet install + +# Pcmk setup +cp /etc/sysconfig/pacemaker /etc/sysconfig/pacemaker.dist +cat<<'EOF' > /etc/sysconfig/pacemaker +PCMK_debug=yes +PCMK_logpriority=debug +EOF diff --git a/extra/vagrant/3nodes-vip/vagrant.yml-dist b/extra/vagrant/3nodes-vip/vagrant.yml-dist index 9bfd761..9fcc6a7 100644 --- a/extra/vagrant/3nodes-vip/vagrant.yml-dist +++ b/extra/vagrant/3nodes-vip/vagrant.yml-dist @@ -9,6 +9,6 @@ # - "srv2" # - "srv3" # log_node: "log-sink" -# vm_prefix: "paf_vm" +# vm_prefix: "paf_3nvIP" # rhel_user: "" # RHEL user account # rhel_pass: "" # RHEL user account password