1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

postgresクラスターを構築してみた。(pgpool)

1
Last updated at Posted at 2026-01-16

はじめに

以前、以下の記事で手順を出していましたが、表題について
汎用的に利用できると思い、切り出しました。

構成概要

構築ホスト

pg1 : PostgreSQL Primary + pgpool
pg2 : PostgreSQL Standby + pgpool
pg3 : PostgreSQL Standby + pgpool
pg-vip : PostgreSQL 仮想IP(pgpool制御)

AlmaLinux9を使用する。

HA 方針

コンポーネント HA方式
PostgreSQL Streaming Replication
Primary 切替 pgpool
postgresql接続先 VIP (pgpool)

前提 IP(例)

192.168.11.37 pg1
192.168.11.38 pg2
192.168.11.39 pg3
192.168.11.40 pg-vip

※適宜読み替えてください

1. PostgreSQL HA 構築

1.1. 全台共通(pg1 / pg2 / pg3)

1.1.1. 基本設定

sudo dnf -y update
sudo dnf -y install chrony vim wget
sudo systemctl enable --now chronyd

1.1.2. PostgreSQL PGDG リポジトリ

sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --set-enabled crb
sudo dnf -qy module disable postgresql
sudo dnf -y install \
  https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

1.1.3. PostgreSQL + Pgpool インストール(全台)

sudo dnf -y install pgpool-II pgpool-II-pcp
sudo dnf -y install postgresql16-server

1.2 PostgreSQL:Streaming Replication 構築

1.2.1. 3台共通:初期化・起動

sudo /usr/pgsql-16/bin/postgresql-16-setup initdb
sudo systemctl enable --now postgresql-16

1.2.2. pg1: postgresql.conf

sudo -u postgres sed -i \
  -e "s/^#listen_addresses.*/listen_addresses = '*'/" \
  /var/lib/pgsql/16/data/postgresql.conf
sudo -u postgres tee -a /var/lib/pgsql/16/data/postgresql.conf >/dev/null <<'EOF'
wal_level = replica
max_wal_senders = 10
max_replication_slots = 10
hot_standby = on
wal_log_hints = on
EOF

1.2.3. pg1: DBユーザー作成(pgpool / repl)

sudo -u postgres psql <<'SQL'
SET password_encryption = 'scram-sha-256';

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname='pgpool') THEN
    CREATE ROLE pgpool LOGIN;
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname='repl') THEN
    CREATE ROLE repl REPLICATION LOGIN;
  END IF;
END $$;

GRANT pg_monitor TO pgpool;
SQL
sudo -u postgres psql -c "\password pgpool"

sudo -u postgres psql -c "\password repl"

sudo -u postgres psql -c "\password postgres"

→それぞれのDBパスワードを定め、パスワードを控える

1.2.4. pg1: pg_hba.conf

sudo -u postgres tee -a /var/lib/pgsql/16/data/pg_hba.conf >/dev/null <<'EOF'
host    all             all             192.168.11.0/24         scram-sha-256
host    replication     all             192.168.11.0/24         scram-sha-256
EOF
sudo systemctl restart postgresql-16

1.3. pg2/pg3 を Standby にする(basebackup)

1.3.1. pg2 / pg3: データ作り直し

sudo systemctl stop postgresql-16
sudo mv /var/lib/pgsql/16/data /var/lib/pgsql/16/data.old.$(date +%F-%H%M%S)
sudo install -d -o postgres -g postgres -m 700 /var/lib/pgsql/16/data
sudo restorecon -RFv /var/lib/pgsql/16/data || true

1.3.2. pg2/pg3: pg_basebackup(pg1から)

sudo -u postgres /usr/pgsql-16/bin/pg_basebackup \
  -h pg1 -p 5432 -U repl \
  -D /var/lib/pgsql/16/data \
  -R -X stream -C -S "$(hostname)" \
  --write-recovery-conf

→replのPW入力が出ます

1.3.3. pg2/pg3: 起動

sudo systemctl start postgresql-16

1.3.4. pg1: 確認

sudo -u postgres psql -c "select client_addr,state,sync_state from pg_stat_replication;"

→sync_stateが全てasyncとなること。

1.4 Pgpool-II:3台 Watchdog + VIP 構築

1.4.1. 3台共通:pgpool_node_id

pg1

echo 0 | sudo tee /etc/pgpool-II/pgpool_node_id

pg2

echo 1 | sudo tee /etc/pgpool-II/pgpool_node_id

pg3

echo 2 | sudo tee /etc/pgpool-II/pgpool_node_id

1.4.2. pg1:pgpool.conf(仮置き)

sudo cp -p /etc/pgpool-II/pgpool.conf.sample /etc/pgpool-II/pgpool.conf
sudo chown root:root /etc/pgpool-II/pgpool.conf
sudo chmod 644 /etc/pgpool-II/pgpool.conf
sudo tee -a /etc/pgpool-II/pgpool.conf >/dev/null <<'EOF'

# ===== minimal settings for pg_enc / SR mode =====
listen_addresses = '*'
port = 9999
pcp_port = 9898

backend_clustering_mode = 'streaming_replication'

backend_hostname0 = 'pg1'
backend_port0 = 5432
backend_data_directory0 = '/var/lib/pgsql/16/data'
backend_flag0 = 'ALLOW_TO_FAILOVER'

backend_hostname1 = 'pg2'
backend_port1 = 5432
backend_data_directory1 = '/var/lib/pgsql/16/data'
backend_flag1 = 'ALLOW_TO_FAILOVER'

backend_hostname2 = 'pg3'
backend_port2 = 5432
backend_data_directory2 = '/var/lib/pgsql/16/data'
backend_flag2 = 'ALLOW_TO_FAILOVER'

# pool_passwd を使う前提
health_check_user = 'pgpool'
health_check_password = ''
sr_check_user = 'pgpool'
sr_check_password = ''
EOF

1.4.3. 全台:pool_passwd

sudo -u postgres bash -lc '
set -e
umask 077
openssl rand -base64 32 | tr -d "\n" > ~/.pgpoolkey
chmod 600 ~/.pgpoolkey
ls -l ~/.pgpoolkey
wc -c ~/.pgpoolkey
'
sudo install -o postgres -g postgres -m 600 /dev/null /etc/pgpool-II/pool_passwd
sudo restorecon -v /etc/pgpool-II/pool_passwd 2>/dev/null || true
sudo -u postgres bash -lc 'pg_enc -m -k ~/.pgpoolkey -u pgpool -p'

→pgpoolのPW入力をすること。

sudo cat /etc/pgpool-II/pool_passwd

1.4.4. 3台共通:PCPユーザー(pgpool)

sudo chown -R postgres:postgres /etc/pgpool-II
sudo -u postgres touch /etc/pgpool-II/pcp.conf
sudo pg_md5 -u pgpool -p

→pgpoolパスワードをここで新しく設定し、帰ってきた値を控える

sudo -u postgres vi /etc/pgpool-II/pcp.conf

→以下の記載を入れる。

pgpool:<先ほど控えた値>

sudo chmod 600 /etc/pgpool-II/pcp.conf

1.4.5. 3台共通:sudoers(VIP操作)

sudo visudo -f /etc/sudoers.d/pgpool_vip

中身:

postgres ALL=NOPASSWD: /usr/sbin/ip
postgres ALL=NOPASSWD: /usr/sbin/arping
Defaults:postgres !requiretty

1.4.6. 3台共通:postgres SSH鍵(フェールオーバースクリプト用)

SSHフルメッシュ交換(postgresSSH鍵)

sudo -u postgres bash -lc 'test -f ~/.ssh/id_rsa_pgpool || ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_rsa_pgpool'
sudo -u postgres cat /var/lib/pgsql/.ssh/id_rsa_pgpool.pub

それぞれの公開鍵を控える。

sudo -u postgres touch /var/lib/pgsql/.ssh/authorized_keys
sudo -u postgres chmod 600 /var/lib/pgsql/.ssh/authorized_keys
sudo -u postgres vi /var/lib/pgsql/.ssh/authorized_keys

控えた3台の公開鍵を書き込む。

sudo -u postgres ssh -i /var/lib/pgsql/.ssh/id_rsa_pgpool postgres@pg1 'hostname'
sudo -u postgres ssh -i /var/lib/pgsql/.ssh/id_rsa_pgpool postgres@pg2 'hostname'
sudo -u postgres ssh -i /var/lib/pgsql/.ssh/id_rsa_pgpool postgres@pg3 'hostname'

→yesを入力し、以下の回答が出てくること。(2回やったほうが結果はわかりやすい)

pg1
pg2
pg3

1.4.7. 3台共通:.pgpass(repl / postgres)

REPL_PASSWORDとPOSTGRES_PASSWORDとPGPOOL_PASSWORDは実値に置換する。

sudo -u postgres tee /var/lib/pgsql/.pgpass >/dev/null <<'EOF'
pg1:5432:replication:repl:REPL_PASSWORD
pg2:5432:replication:repl:REPL_PASSWORD
pg3:5432:replication:repl:REPL_PASSWORD
pg1:5432:postgres:postgres:POSTGRES_PASSWORD
pg2:5432:postgres:postgres:POSTGRES_PASSWORD
pg3:5432:postgres:postgres:POSTGRES_PASSWORD
pg1:5432:postgres:pgpool:PGPOOL_PASSWORD
pg2:5432:postgres:pgpool:PGPOOL_PASSWORD
pg3:5432:postgres:pgpool:PGPOOL_PASSWORD
EOF
sudo -u postgres chmod 600 /var/lib/pgsql/.pgpass

1.5 pgpool.conf/pool_hba.conf

1.5.1. pg1/pg2/pg3共通で設定

sudo tee /etc/pgpool-II/pgpool.conf >/dev/null <<'EOF'
########## 基本 ##########
listen_addresses = '*'
port = 9999
pcp_port = 9898

backend_clustering_mode = 'streaming_replication'

########## Backend ##########
backend_hostname0 = 'pg1'
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = '/var/lib/pgsql/16/data'
backend_flag0 = 'ALLOW_TO_FAILOVER'

backend_hostname1 = 'pg2'
backend_port1 = 5432
backend_weight1 = 1
backend_data_directory1 = '/var/lib/pgsql/16/data'
backend_flag1 = 'ALLOW_TO_FAILOVER'

backend_hostname2 = 'pg3'
backend_port2 = 5432
backend_weight2 = 1
backend_data_directory2 = '/var/lib/pgsql/16/data'
backend_flag2 = 'ALLOW_TO_FAILOVER'

########## health / sr check ##########
health_check_period = 5
health_check_timeout = 30
health_check_max_retries = 3
health_check_user = 'pgpool'
health_check_password = 'pgpoolpass'   # pgpool_passwdを使う
health_check_database = 'postgres'

sr_check_period = 5
sr_check_user = 'pgpool'
sr_check_password = 'pgpoolpass'       # pgpool_passwdを使う

########## フェイルオーバ / 追従 ##########
failover_command = '/etc/pgpool-II/failover.sh %d %h %p %D %m %H %M %P %r %R %N %S'
follow_primary_command = '/etc/pgpool-II/follow_primary.sh %d %h %m %H'

########## watchdog + VIP ##########
use_watchdog = on
delegate_ip = '192.168.11.40'

# VIP scripts(ip/arping は実パスに統一)
if_up_cmd   = '/usr/bin/sudo /usr/sbin/ip addr add $_IP_$/24 dev eth0 label eth0:0'
if_down_cmd = '/usr/bin/sudo /usr/sbin/ip addr del $_IP_$/24 dev eth0'
arping_cmd  = '/usr/bin/sudo /usr/sbin/arping -U $_IP_$ -w 1 -I eth0'

# lifcheck: heartbeat(※定義がないと起動時に FATAL になります)
wd_lifecheck_method = 'heartbeat'
wd_interval = 10

heartbeat_hostname0 = 'pg1'
heartbeat_port0 = 9694

heartbeat_hostname1 = 'pg2'
heartbeat_port1 = 9694

heartbeat_hostname2 = 'pg3'
heartbeat_port2 = 9694

# watchdog peers
hostname0 = 'pg1'
wd_port0 = 9000
pgpool_port0 = 9999

hostname1 = 'pg2'
wd_port1 = 9000
pgpool_port1 = 9999

hostname2 = 'pg3'
wd_port2 = 9000
pgpool_port2 = 9999

wd_escalation_command = '/etc/pgpool-II/escalation.sh'

########## pool_hba ##########
enable_pool_hba = on
pool_passwd = '/etc/pgpool-II/pool_passwd'
pool_key = '/var/lib/pgsql/.pgpoolkey'

########## ファイル出力先(Permission denied 回避のため必須) ##########
logdir = '/var/log/pgpool-II'
backend_status_file = '/var/log/pgpool-II/pgpool_status'
wd_ipc_socket_dir = '/var/run/pgpool'
pid_file_name = '/var/run/pgpool/pgpool.pid'

# ---- auto failback ----
auto_failback = on
EOF
sudo tee /etc/pgpool-II/pool_hba.conf <<EOF
# ローカル運用
local   all         all                             trust
host    all         all         127.0.0.1/32         scram-sha-256
host    all         all         ::1/128              scram-sha-256

host    all         all         192.168.11.0/24      scram-sha-256

EOF

1.6. サンプルスクリプト有効化(PG16向けに修正)

1.6.1. 3台共通:配置

  • failover.sh(フェイルオーバーシェル)

以下の動作を行います。

スタンバイ障害なら「レプリケーションスロットを落として終わり」
プライマリ障害なら「新しいメイン(=昇格対象)を promote して終わり」

sudo tee /etc/pgpool-II/failover.sh >/dev/null <<'EOF'
#!/bin/bash
# This script is run by failover_command.
set -o xtrace

FAILED_NODE_ID="$1"
FAILED_NODE_HOST="$2"
FAILED_NODE_PORT="$3"
FAILED_NODE_PGDATA="$4"
NEW_MAIN_NODE_ID="$5"
NEW_MAIN_NODE_HOST="$6"
OLD_MAIN_NODE_ID="$7"
OLD_PRIMARY_NODE_ID="$8"
NEW_MAIN_NODE_PORT="$9"
NEW_MAIN_NODE_PGDATA="${10}"
OLD_PRIMARY_NODE_HOST="${11}"
OLD_PRIMARY_NODE_PORT="${12}"

PGHOME=/usr/pgsql-16
REPL_SLOT_NAME=$(echo "${FAILED_NODE_HOST,,}" | tr -- -. _)
POSTGRESQL_STARTUP_USER=postgres
SSH_KEY_FILE=id_rsa_pgpool
SSH_OPTIONS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/${SSH_KEY_FILE}"

echo failover.sh: start: failed_node_id=$FAILED_NODE_ID failed_host=$FAILED_NODE_HOST \
    old_primary_node_id=$OLD_PRIMARY_NODE_ID new_main_node_id=$NEW_MAIN_NODE_ID new_main_host=$NEW_MAIN_NODE_HOST

# If there's no main node anymore, skip failover.
if [ "$NEW_MAIN_NODE_ID" -lt 0 ]; then
    echo failover.sh: All nodes are down. Skipping failover.
    exit 0
fi

# Test passwordless SSH
ssh -T ${SSH_OPTIONS} ${POSTGRESQL_STARTUP_USER}@${NEW_MAIN_NODE_HOST} ls /tmp > /dev/null
if [ $? -ne 0 ]; then
    echo failover.sh: passwordless SSH to ${POSTGRESQL_STARTUP_USER}@${NEW_MAIN_NODE_HOST} failed.
    exit 1
fi

# If Standby node is down (not old primary), drop replication slot and exit.
if [ "$OLD_PRIMARY_NODE_ID" != "-1" -a "$FAILED_NODE_ID" != "$OLD_PRIMARY_NODE_ID" ]; then
    ${PGHOME}/bin/psql -h ${OLD_PRIMARY_NODE_HOST} -p ${OLD_PRIMARY_NODE_PORT} postgres \
        -c "SELECT pg_drop_replication_slot('${REPL_SLOT_NAME}');"  >/dev/null 2>&1 || true
    echo failover.sh: end: standby node is down. Skipping failover.
    exit 0
fi

# Promote Standby node.
echo failover.sh: primary node is down, promote new_main_node_id=$NEW_MAIN_NODE_ID on ${NEW_MAIN_NODE_HOST}.
ssh -T ${SSH_OPTIONS} ${POSTGRESQL_STARTUP_USER}@${NEW_MAIN_NODE_HOST} \
  ${PGHOME}/bin/pg_ctl -D ${NEW_MAIN_NODE_PGDATA} -w promote

if [ $? -ne 0 ]; then
    echo ERROR: failover.sh: promote failed
    exit 1
fi

echo failover.sh: end: new_main_node_id=$NEW_MAIN_NODE_ID on ${NEW_MAIN_NODE_HOST} was successfully promoted to primary
exit 0
EOF
sudo chown postgres:postgres /etc/pgpool-II/failover.sh
sudo chmod 700 /etc/pgpool-II/failover.sh
  • escalation.sh(VIP取り扱いシェル)

自身がリーダーになった(VIP付与対象になった)際、他のホストのVIPの取り外しを実施します。

sudo tee /etc/pgpool-II/escalation.sh >/dev/null <<'EOF'
#!/bin/bash
# Bring down the virtual IP on other pgpool nodes before bringing it up on this node.
set -o xtrace

POSTGRESQL_STARTUP_USER=postgres
SSH_KEY_FILE=id_rsa_pgpool
SSH_OPTIONS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/${SSH_KEY_FILE}"
SSH_TIMEOUT=5

PGPOOLS=(pg1 pg2 pg3)

VIP=192.168.11.40
DEVICE=eth0
CIDR_NETMASK=24
IP=/usr/sbin/ip

for pgpool in "${PGPOOLS[@]}"; do
  [ "$HOSTNAME" = "${pgpool}" ] && continue

  timeout ${SSH_TIMEOUT} ssh -T ${SSH_OPTIONS} ${POSTGRESQL_STARTUP_USER}@${pgpool} "
    ${IP} addr show dev ${DEVICE} | grep -F ${VIP} > /dev/null 2>&1
  "

  if [ $? -eq 0 ]; then
    timeout ${SSH_TIMEOUT} ssh -T ${SSH_OPTIONS} ${POSTGRESQL_STARTUP_USER}@${pgpool} "
      /usr/bin/sudo ${IP} addr del ${VIP}/${CIDR_NETMASK} dev ${DEVICE}
    " || echo "ERROR: escalation.sh: failed to release VIP on ${pgpool}."
  fi
done
exit 0
EOF
sudo chown postgres:postgres /etc/pgpool-II/escalation.sh
sudo chmod 700 /etc/pgpool-II/escalation.sh
  • follow_primary.sh(スタンバイ追従シェル)

スタンバイとするノードに対し、以下の操作を実施します。

postgresql停止
pg_rewind/basebackupによるスタンバイ化
postgresql開始
pgpoolへのアタッチ

sudo tee /etc/pgpool-II/follow_primary.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
set -o xtrace

NODE_ID="${1:?}"
NODE_HOST="${2:?}"
NEW_PRIMARY_NODE_ID="${3:?}"
NEW_PRIMARY_HOST="${4:?}"

PGDATA="/var/lib/pgsql/16/data"
PRIMARY_PORT="5432"
REPLUSER="repl"

PGHOME="/usr/pgsql-16"
PGBASEBACKUP="${PGHOME}/bin/pg_basebackup"
PGREWIND="${PGHOME}/bin/pg_rewind"
PSQL="${PGHOME}/bin/psql"

# pg_rewind 用(確実に行くなら postgres。必要に応じて変更)
REWIND_USER="postgres"
REWIND_DB="postgres"

POSTGRESQL_STARTUP_USER="postgres"

SSH_KEY_FILE="id_rsa_pgpool"
SSH_BASE_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/${SSH_KEY_FILE} \
-o ConnectTimeout=5 -o ServerAliveInterval=5 -o ServerAliveCountMax=3 -o BatchMode=yes"

SSH_CMD_TIMEOUT="60"
BASEBACKUP_TIMEOUT="1800"
REWIND_TIMEOUT="600"
START_WAIT="60"

REPL_SLOT_NAME="$(echo "${NODE_HOST,,}" | tr -- -. _)"
BACKUP_TS="$(date +%F_%H%M%S)"
BACKUP_DIR="${PGDATA}.bak_${BACKUP_TS}"

log(){ echo "follow_primary.sh: $*"; }

run_ssh() {
  local host="$1"; shift
  timeout "${SSH_CMD_TIMEOUT}" ssh -T ${SSH_BASE_OPTS} "${POSTGRESQL_STARTUP_USER}@${host}" "$@"
}

run_ssh_long() {
  local host="$1"; shift
  timeout "${BASEBACKUP_TIMEOUT}" ssh -T ${SSH_BASE_OPTS} "${POSTGRESQL_STARTUP_USER}@${host}" "$@"
}

run_ssh_rewind() {
  local host="$1"; shift
  timeout "${REWIND_TIMEOUT}" ssh -T ${SSH_BASE_OPTS} "${POSTGRESQL_STARTUP_USER}@${host}" "$@"
}

die_remote() {
  local host="$1"; shift
  log "ERROR: $*"
  run_ssh "${host}" "sudo systemctl --no-pager -l status postgresql-16 || true; sudo journalctl -u postgresql-16 -n 80 --no-pager || true" || true
  exit 1
}

# --- PCP attach (best-effort) ---
PCP_HOST="127.0.0.1"
PCP_PORT="9898"
PCP_ATTACH_NODE="$(command -v pcp_attach_node || true)"
PCP_NODE_INFO="$(command -v pcp_node_info || true)"
PCP_TIMEOUT="3"

pcp_attach_best_effort() {
  local nid="$1"
  [ -n "$PCP_ATTACH_NODE" ] || { log "pcp_attach_node not found, skip"; return 0; }
  if [ -n "$PCP_NODE_INFO" ]; then
    timeout "$PCP_TIMEOUT" "$PCP_NODE_INFO" -h "$PCP_HOST" -p "$PCP_PORT" -U pgpool -n "$nid" >/dev/null 2>&1 || {
      log "PCP not reachable on ${PCP_HOST}:${PCP_PORT}, skip attach"
      return 0
    }
  fi
  log "try pcp_attach_node nid=${nid} (best-effort)"
  timeout "$PCP_TIMEOUT" "$PCP_ATTACH_NODE" -h "$PCP_HOST" -p "$PCP_PORT" -U pgpool -n "$nid" >/dev/null 2>&1 || true
}

# --- standby config helper (pg_basebackup -R 相当を自前で) ---
configure_as_standby() {
  local host="$1"
  log "configure standby.signal + primary_conninfo on ${host}"

  run_ssh "${host}" "
    set -euo pipefail
    sudo -u postgres bash -ceu '
      : \"\${PGDATA:=${PGDATA}}\"

      # standby.signal(PG16はこれでstandby)
      touch \"${PGDATA}/standby.signal\"
      chown postgres:postgres \"${PGDATA}/standby.signal\"

      # primary_conninfo / primary_slot_name を postgresql.auto.conf に入れる
      # 既存行がある場合は置換(無ければ追記)
      AUTO=\"${PGDATA}/postgresql.auto.conf\"
      touch \"\$AUTO\"
      chown postgres:postgres \"\$AUTO\"

      # primary_conninfo を整形(必要に応じて sslmode など追記)
      PC=\"host=${NEW_PRIMARY_HOST} port=${PRIMARY_PORT} user=${REPLUSER} application_name=${NODE_HOST}\"

      # 行置換 or 追記
      grep -q \"^primary_conninfo\" \"\$AUTO\" && sed -i \"s|^primary_conninfo.*|primary_conninfo = '\\''\${PC}'\\''|\" \"\$AUTO\" || echo \"primary_conninfo = '\\''\${PC}'\\''\" >> \"\$AUTO\"
      grep -q \"^primary_slot_name\" \"\$AUTO\" && sed -i \"s|^primary_slot_name.*|primary_slot_name = '\\''${REPL_SLOT_NAME}'\\''|\" \"\$AUTO\" || echo \"primary_slot_name = '\\''${REPL_SLOT_NAME}'\\''\" >> \"\$AUTO\"
    '
  " || die_remote "${host}" "failed to write standby settings"
}

# --- optional: create replication slot on new primary (best-effort) ---
create_slot_best_effort() {
  local host="$1"
  log "best-effort create slot on new primary: ${REPL_SLOT_NAME}"
  # ここは「新プライマリ側」に対して実行する(postgresで実行できる前提)
  run_ssh "${host}" "
    set -euo pipefail
    sudo -u postgres ${PSQL} -h '${NEW_PRIMARY_HOST}' -p '${PRIMARY_PORT}' -d '${REWIND_DB}' -Atc \"
      DO \\\$\\\$BEGIN
        IF NOT EXISTS (SELECT 1 FROM pg_replication_slots WHERE slot_name='${REPL_SLOT_NAME}') THEN
          PERFORM pg_create_physical_replication_slot('${REPL_SLOT_NAME}');
        END IF;
      END\\\$\\\$;
    \" >/dev/null 2>&1 || true
  " || true
}

# --- try pg_rewind. return 0 if success, 1 if not ---
try_pg_rewind() {
  local host="$1"

  log "try pg_rewind on ${host} (if prerequisites ok)"
  # PGDATA が無い/空なら無理なので即失敗扱い
  run_ssh "${host}" "test -d '${PGDATA}' -a -f '${PGDATA}/PG_VERSION'" || {
    log "pg_rewind skipped: PGDATA missing or not initialized on ${host}"
    return 1
  }

  # pg_rewind 実行(失敗してもここでは die しない)
  set +e
  run_ssh_rewind "${host}" "
    set -euo pipefail
    sudo -u postgres '${PGREWIND}' -D '${PGDATA}' \
      --source-server=\"host=${NEW_PRIMARY_HOST} port=${PRIMARY_PORT} user=${REWIND_USER} dbname=${REWIND_DB}\" \
      --progress
  "
  local rc=$?
  set -e

  if [ $rc -eq 0 ]; then
    log "pg_rewind SUCCESS on ${host}"
    return 0
  fi

  log "pg_rewind FAILED on ${host} (rc=${rc}) -> fallback to basebackup"
  return 1
}

log "start node=${NODE_ID} host=${NODE_HOST} new_primary=${NEW_PRIMARY_NODE_ID}(${NEW_PRIMARY_HOST}:${PRIMARY_PORT})"

if [ "${NODE_ID}" = "${NEW_PRIMARY_NODE_ID}" ]; then
  log "this node is new primary -> skip"
  exit 0
fi

run_ssh "${NODE_HOST}" "hostname; id" || { log "ssh failed to ${NODE_HOST}"; exit 1; }
run_ssh "${NODE_HOST}" "sudo -n true" || die_remote "${NODE_HOST}" "sudo requires password (NOPASSWD missing)"

# 1) 停止
log "stop postgresql-16 on ${NODE_HOST}"
run_ssh "${NODE_HOST}" "
  set -euo pipefail
  sudo systemctl stop postgresql-16 || true

  if [ -f '${PGDATA}/postmaster.pid' ]; then
    PID=\$(head -n 1 '${PGDATA}/postmaster.pid' 2>/dev/null || true)
    if [ -n \"\${PID}\" ] && kill -0 \"\${PID}\" 2>/dev/null; then
      echo \"[remote] postgres still running pid=\${PID}, killing...\"
      sudo kill -TERM \"\${PID}\" || true
      sleep 1
      sudo kill -KILL \"\${PID}\" || true
    fi
  fi
  ss -lntp | grep ':5432' || true
" || die_remote "${NODE_HOST}" "failed to stop postgres"

# 2) まず pg_rewind を試す(成功なら basebackup スキップ)
if try_pg_rewind "${NODE_HOST}"; then
  # standby 設定(-R 相当)
  create_slot_best_effort "${NODE_HOST}"
  configure_as_standby "${NODE_HOST}"

  # 起動
  log "start postgresql-16 on ${NODE_HOST} (after pg_rewind)"
  run_ssh "${NODE_HOST}" "
    set -euo pipefail
    sudo systemctl start postgresql-16
  " || die_remote "${NODE_HOST}" "systemctl start failed after pg_rewind"

else
  # 3) rewind失敗時は従来通り:PGDATA退避&空作成 → basebackup
  log "rotate PGDATA on ${NODE_HOST} (for basebackup)"
  run_ssh "${NODE_HOST}" "
    set -euo pipefail
    if [ -d '${PGDATA}' ]; then
      sudo mv '${PGDATA}' '${BACKUP_DIR}'
    fi
    sudo -u postgres mkdir -p '${PGDATA}'
    sudo chown -R postgres:postgres '${PGDATA}'
    sudo chmod 700 '${PGDATA}'
  " || die_remote "${NODE_HOST}" "failed to rotate PGDATA"

  log "pg_basebackup to ${NODE_HOST} from ${NEW_PRIMARY_HOST} slot=${REPL_SLOT_NAME}"
  run_ssh_long "${NODE_HOST}" "
    set -euo pipefail
    '${PGBASEBACKUP}' -h '${NEW_PRIMARY_HOST}' -p '${PRIMARY_PORT}' -U '${REPLUSER}' \
      -D '${PGDATA}' -R -X stream -C -S '${REPL_SLOT_NAME}' --no-password
  " || die_remote "${NODE_HOST}" "pg_basebackup failed (auth/pg_hba/network/slot?)"

  log "start postgresql-16 on ${NODE_HOST} (after basebackup)"
  run_ssh "${NODE_HOST}" "
    set -euo pipefail
    sudo systemctl start postgresql-16
  " || die_remote "${NODE_HOST}" "systemctl start failed after basebackup"
fi

# 4) 起動待ち&standby確認
log "wait up to ${START_WAIT}s for postgres and check recovery on ${NODE_HOST}"
run_ssh "${NODE_HOST}" "
  set -euo pipefail
  for i in \$(seq 1 ${START_WAIT}); do
    if sudo systemctl is-active --quiet postgresql-16; then
      break
    fi
    sleep 1
  done
  sudo systemctl --no-pager -l status postgresql-16 | sed -n '1,25p' || true
  psql -U postgres -d postgres -tAc 'select pg_is_in_recovery();'
" | tail -n 1 | grep -qx 't' || die_remote "${NODE_HOST}" "postgres is not standby after recovery"

pcp_attach_best_effort "${NODE_ID}"

log "done node=${NODE_ID} host=${NODE_HOST}"
exit 0
EOF
sudo chmod 755 /etc/pgpool-II/follow_primary.sh
sudo chown postgres:postgres /etc/pgpool-II/follow_primary.sh
sudo restorecon -v /etc/pgpool-II/follow_primary.sh 2>/dev/null || true
  • postgresユーザーでのsudo操作許可(follow_primary.shで必要)
sudo tee /etc/sudoers.d/postgres_tmp_all >/dev/null <<'EOF'
Defaults:postgres !requiretty
postgres ALL=(ALL) NOPASSWD: ALL
EOF

sudo chmod 440 /etc/sudoers.d/postgres_tmp_all
sudo visudo -cf /etc/sudoers.d/postgres_tmp_all
  • postgres ユーザー用に pgpool-II の PCP コマンドのパスワードファイル作成(follow_primary.shで必要)
sudo -u postgres bash -lc 'umask 077; cat > ~/.pcppass <<EOF
127.0.0.1:9898:pgpool:pgpoolpass
EOF
chmod 600 ~/.pcppass
ls -l ~/.pcppass
'

1.7. pgpool 起動(全台)

1.7.1. pid/書き込み先置き場所作成

sudo install -d -m 755 -o postgres -g postgres /var/run/pgpool /var/log/pgpool-II
sudo restorecon -RFv /var/run/pgpool /var/log/pgpool-II 2>/dev/null || true

sudo tee /etc/tmpfiles.d/pgpool.conf >/dev/null <<'EOF'
d /var/run/pgpool 0755 postgres postgres -
EOF

sudo systemd-tmpfiles --create /etc/tmpfiles.d/pgpool.conf

1.7.2. 起動

sudo systemctl enable --now pgpool-II
sudo systemctl status pgpool-II

1.8. 確認(VIP / watchdog / pool_nodes)

1.8.1. VIPがどこにいるか(3台どれかで)

ip -br addr | grep 192.168.11.40 || true

→3台のどれかでVIPが出ればよい。

1.8.2. Pgpool経由で backend 状態(どこからでも)

psql -h 192.168.11.40 -p 9999 -U pgpool -d postgres -c "SHOW pool_nodes;"

→backendのステータスが見れること。

1.8.3. watchdog 状態

pcp_watchdog_info -h 127.0.0.1 -p 9898 -U pgpool

→pgpoolのパスワードを入れる。
3台のステータスが見れること。

1.9. アクセス制限更新(pg_hba.conf,pool_hba.conf)

pg1/pg2/pg3で実施

sudo tee /var/lib/pgsql/16/data/pg_hba.conf >/dev/null <<'EOF'
# ===== local =====
local   all             all                                     peer
host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             ::1/128                 scram-sha-256

# ===== Pgpool health/sr_check user (pgpool) =====
# pgpool は同居でも別ノード経由でも backend に接続し得るので、3台のIPを明示許可
host    all             pgpool           192.168.11.37/32       scram-sha-256
host    all             pgpool           192.168.11.38/32       scram-sha-256
host    all             pgpool           192.168.11.39/32       scram-sha-256

# ===== Streaming Replication (repl) =====
# standby が primary に replication 接続するため
host    replication     repl             192.168.11.37/32       scram-sha-256
host    replication     repl             192.168.11.38/32       scram-sha-256
host    replication     repl             192.168.11.39/32       scram-sha-256

# follow_primary動作のため
host    all     postgres   192.168.11.37/32   scram-sha-256
host    all     postgres   192.168.11.38/32   scram-sha-256
host    all     postgres   192.168.11.39/32   scram-sha-256

EOF
sudo tee /etc/pgpool-II/pool_hba.conf <<EOF
# ローカル運用
local   all         all                              scram-sha-256
host    all         all         127.0.0.1/32         scram-sha-256
host    all         all         ::1/128              scram-sha-256

# pg1/pg2/pg3からのアクセス許可
host    all         all         192.168.11.37/32      scram-sha-256
host    all         all         192.168.11.38/32      scram-sha-256
host    all         all         192.168.11.39/32      scram-sha-256

EOF
sudo systemctl reload postgresql-16
sudo systemctl reload pgpool-II

1.10. pgpool認証ファイルコピー

1.10.1.【pg1】/tmp に一時コピーを作る(root)

sudo cp /etc/pgpool-II/pool_passwd /tmp/pool_passwd
sudo cp /var/lib/pgsql/.pgpoolkey /tmp/.pgpoolkey

sudo chown postgres:postgres /tmp/pool_passwd /tmp/.pgpoolkey
sudo chmod 600 /tmp/pool_passwd /tmp/.pgpoolkey

1.10.2.【pg1】postgres SSH で配布

sudo -u postgres scp -i /var/lib/pgsql/.ssh/id_rsa_pgpool \
  /tmp/pool_passwd /tmp/.pgpoolkey \
  postgres@pg2:/tmp/

sudo -u postgres scp -i /var/lib/pgsql/.ssh/id_rsa_pgpool \
  /tmp/pool_passwd /tmp/.pgpoolkey \
  postgres@pg3:/tmp/

1.10.3.【pg2 / pg3】正規配置(root)

sudo mv /tmp/pool_passwd /etc/pgpool-II/pool_passwd
sudo chown postgres:postgres /etc/pgpool-II/pool_passwd
sudo chmod 600 /etc/pgpool-II/pool_passwd
sudo mv /tmp/.pgpoolkey /var/lib/pgsql/.pgpoolkey
sudo chown postgres:postgres /var/lib/pgsql/.pgpoolkey
sudo chmod 600 /var/lib/pgsql/.pgpoolkey

1.10.4. Pgpool 反映(全ノード)

sudo systemctl restart pgpool-II

1.10.5.【後始末】pg1 の /tmp を掃除

sudo rm -f /tmp/pool_passwd /tmp/.pgpoolkey

1.11 postgresql自動起動停止

pgpoolにてpostgresqlの制御を実施させるため、postgresqlの自動起動を停止する。

sudo systemctl disable postgresql-16

2. ユーザーDB構築

2.1. ユーザーDB作成

下記のDB名、DBユーザ名、パスワード、クライアントIPを環境に合わせ作成してください。

例:
DB名:hive_metastore
DBユーザー名:hive
パスワード:HivePasswordHere
クライアントIP:192.168.11.54,192.168.11.55

pg1で実施。

psql -h pg1 -U postgres -d postgres <<'SQL'

DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'hive') THEN
    CREATE ROLE hive LOGIN PASSWORD 'HivePasswordHere';
  END IF;
END $$;

CREATE DATABASE hive_metastore OWNER postgres;

\connect hive_metastore

GRANT CONNECT, TEMP ON DATABASE hive_metastore TO hive;

ALTER SCHEMA public OWNER TO hive;
GRANT USAGE, CREATE ON SCHEMA public TO hive;

GRANT ALL PRIVILEGES ON ALL TABLES    IN SCHEMA public TO hive;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO hive;
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO hive;

ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES    TO hive;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO hive;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON FUNCTIONS TO hive;

SQL

2.2. HiveDBアクセス設定

pg1/pg2/pg3で実施

sudo tee -a /var/lib/pgsql/16/data/pg_hba.conf >/dev/null <<'EOF'
# ------------------------------------------------------------
# 3) Hive Metastore
# ------------------------------------------------------------
host    hive_metastore  hive        192.168.11.37/32            scram-sha-256
host    hive_metastore  hive        192.168.11.38/32            scram-sha-256
host    hive_metastore  hive        192.168.11.39/32            scram-sha-256

EOF
sudo tee -a /etc/pgpool-II/pool_hba.conf <<EOF
# ------------------------------------------------------------
# Hive Metastore -> Pgpool VIP
# ------------------------------------------------------------
host    hive_metastore  hive    192.168.11.54/32    scram-sha-256
host    hive_metastore  hive    192.168.11.55/32    scram-sha-256

EOF
sudo systemctl reload postgresql-16
sudo systemctl reload pgpool-II

2.3. HiveDBアクセス認証情報配布

  • 【pg1】認証情報作成
sudo -u postgres bash -lc 'pg_enc -m -k ~/.pgpoolkey -u hive -p'
→HivePasswordHereを入れる
  • 【pg1】/tmp に一時コピーを作る(root)
sudo cp /etc/pgpool-II/pool_passwd /tmp/pool_passwd
sudo cp /var/lib/pgsql/.pgpoolkey /tmp/.pgpoolkey

sudo chown postgres:postgres /tmp/pool_passwd /tmp/.pgpoolkey
sudo chmod 600 /tmp/pool_passwd /tmp/.pgpoolkey
  • 【pg1】postgres SSH で配布
sudo -u postgres scp -i /var/lib/pgsql/.ssh/id_rsa_pgpool \
  /tmp/pool_passwd /tmp/.pgpoolkey \
  postgres@pg2:/tmp/

sudo -u postgres scp -i /var/lib/pgsql/.ssh/id_rsa_pgpool \
  /tmp/pool_passwd /tmp/.pgpoolkey \
  postgres@pg3:/tmp/
  • 【pg2 / pg3】正規配置(root)
sudo mv /tmp/pool_passwd /etc/pgpool-II/pool_passwd
sudo chown postgres:postgres /etc/pgpool-II/pool_passwd
sudo chmod 600 /etc/pgpool-II/pool_passwd
sudo mv /tmp/.pgpoolkey /var/lib/pgsql/.pgpoolkey
sudo chown postgres:postgres /var/lib/pgsql/.pgpoolkey
sudo chmod 600 /var/lib/pgsql/.pgpoolkey
  • Pgpool 反映(全ノード)
sudo systemctl restart pgpool-II
  • 【後始末】pg1 の /tmp を掃除
sudo rm -f /tmp/pool_passwd /tmp/.pgpoolkey

3. 動作確認(PostgreSQL)

3.1 準備

3.1.1 確認用端末

psqlコマンドを使用できるホストを用意する。

psqlコマンドを使用できるようにする。

sudo apt install postgresql-client-16

3.1.2 pg1/pg2/pg3設定

例として以下のIP(192.168.11.71)で登録する。

sudo tee -a /etc/pgpool-II/pool_hba.conf <<EOF
# ope1からのアクセス許可(オプション)
host    all         all         192.168.11.71/32    scram-sha-256 

EOF
sudo systemctl reload pgpool-II

3.1.3 動作確認

ope1にて以下のコマンドを入力して応答が返ることを確認する。

psql -h 192.168.11.40 -p 9999 -U pgpool -d postgres -c "SHOW pool_nodes;"

3.2. 事前確認(共通)

3.2.1. 現在状態(VIP経由で確認)

ope1

psql -h 192.168.11.40 -p 9999 -U pgpool -d postgres -c "SHOW pool_nodes;"

期待結果

pg1 primary
pg2 standby
pg3 standby
status/pg_status: up

3.3. フェールオーバー(postgresqlサービス停止)

3.3.1. 概要

目的:primary を pg1 → pg2 に自動的にフェールオーバーさせる。
障害注入方法:
pg1のpostgresqlサービスを停止する。

期待する結果:
自動的にpg2へDBプライマリが自動的に切り替わり、外からの接続も実施できること。
pg1/pg3について、自動的にpg2のstandbyとなること。
合わせて、pgpoolのattachも自動的に実施される。

3.3.2. primary(pg1) の PostgreSQL を停止(障害注入)

pg1

sudo systemctl stop postgresql-16
sudo systemctl is-active postgresql-16 || true

期待結果

inactive

数十秒待って再度2つめのコマンドを実施して、activeとなること。

3.3.3. フェールオーバー成立確認(VIP経由)

ope1

psql -h 192.168.11.40 -p 9999 -U pgpool -d postgres -c "SHOW pool_nodes;"

期待結果(数十秒〜で変化)

pg1 standby
pg2 primary
pg3 standby
status/pg_status: up

3.3.4. 新primary(pg2) 側で “本当にprimaryか” を確認

pg2

sudo -u postgres psql -c "select pg_is_in_recovery();"

期待結果

f(= primary)

3.3.5. レプリケーション確認

pg2

sudo -u postgres psql -c "select client_addr,state,sync_state,application_name from pg_stat_replication;"

期待結果

pg1/pg3 が並ぶ(2行)

3.4. フェールオーバー(primaryホスト停止)

3.4.1. 概要

目的:primary を pg2 → pg1 に自動的にフェールオーバーさせる。
障害注入方法:
pg2ホストを停止する。

期待する結果:
自動的にpg1へDBプライマリが自動的に切り替わり、外からの接続も実施できること。
pg3について、自動的にpg1のstandbyとなること。
合わせて、pgpoolのattachも自動的に実施される。
pg2復旧後、手動操作を行いstandbyとして復旧すること。

3.4.2. primary(pg2) の ノードを停止(障害注入)

pg2

sudo shutdown -h now

3.4.3. フェールオーバー成立確認(VIP経由)

ope1

psql -h 192.168.11.40 -p 9999 -U pgpool -d postgres -c "SHOW pool_nodes;"

期待結果(数十秒〜で変化)

pg1 primary
pg2 standby,status/pg_status: down
pg3 standby
status/pg_status: up

3.4.4. 新primary(pg1) 側で “本当にprimaryか” を確認

pg1

sudo -u postgres psql -c "select pg_is_in_recovery();"

期待結果

f(= primary)

3.4.5. レプリケーション確認

pg1

sudo -u postgres psql -c "select client_addr,state,sync_state,application_name from pg_stat_replication;"

期待結果

pg3 が並ぶ(1行)

3.4.6. pg2ホスト立ち上げ

落とした元primaryホストを立ち上げる

3.4.7. pg2ホストの再加入

pg2

sudo -u postgres /etc/pgpool-II/follow_primary.sh 1 pg2 0 pg1

3.4.8. フェールオーバー成立確認(VIP経由)

ope1

psql -h 192.168.11.40 -p 9999 -U pgpool -d postgres -c "SHOW pool_nodes;"

期待結果(数十秒〜で変化)

pg1 primary
pg2 standby
pg3 standby
status/pg_status: up

3.4.9. pg2で “本当にstandbyか” を確認

pg2

sudo -u postgres psql -c "select pg_is_in_recovery();"

期待結果

t(= standby)

3.4.10. レプリケーション確認

pg1

sudo -u postgres psql -c "select client_addr,state,sync_state,application_name from pg_stat_replication;"

期待結果

pg2/pg3 が並ぶ(1行)

3.5. フェイルバック

3.5.1. 概要

目的:
primary を pg1 → pg2 に戻す

リスク:
pgpool稼働中にpg1を止めると、自動判定が走る可能性(pg2に確実に戻したい。)
pg2のスタンバイとしてpg1/pg3が立ち上がらなくなり、クラスタ状態が壊れる

対策:
フェイルバック作業中だけ pgpoolを全台止める
follow_primaryシェルを利用し、pg1/pg3のstanby化を確実に実施する。

3.5.2. pgpool を全台停止(pg1/pg2/pg3)

各ノードで:

sudo systemctl stop pgpool-II
sudo systemctl is-active pgpool-II || true

期待結果

3台とも pgpool-II inactive

3.5.3 primary-standby追いつき確認

pg1:

sudo -u postgres psql -Atc "select pg_current_wal_lsn();"

pg2/pg3:

sudo -u postgres psql -Atc "select pg_last_wal_replay_lsn();"

上記の結果が全台で一致すること。

3.5.4. 現primary(pg1) を停止

pg1

sudo systemctl stop postgresql-16
sudo systemctl is-active postgresql-16 || true

期待結果

pg2 postgresql-16 inactive

3.5.5. pg2 を primary に昇格

pg2

sudo -u postgres /usr/pgsql-16/bin/pg_ctl -D /var/lib/pgsql/16/data -w promote
sudo -u postgres psql -c "select pg_is_in_recovery();"

期待結果

f(pg2 primary)

3.5.6. pg3 を pg2 の standby として作り直し

  • pg3:follow_primaryシェルで作り直す
sudo systemctl stop postgresql-16
sudo -u postgres /etc/pgpool-II/follow_primary.sh 2 pg3 1 pg2
sudo -u postgres psql -c "select pg_is_in_recovery();"

期待結果

t(pg3 standby)

3.5.7. pg1 を pg2 の standby として作り直す

  • pg1:follow_primaryシェルで作り直す
sudo -u postgres /etc/pgpool-II/follow_primary.sh 0 pg1 1 pg2
sudo -u postgres psql -c "select pg_is_in_recovery();"

期待結果

t(pg1 standby)

3.5.8. pg2でレプリケーション確認

pg2

sudo -u postgres psql -c "select client_addr,state,sync_state,application_name from pg_stat_replication;"

期待結果

pg1/pg3 が並ぶ(2行)

3.5.9. pgpool を全台起動

sudo systemctl start pgpool-II
sudo systemctl is-active pgpool-II

3.5.10. VIP経由で最終確認

ope1

psql -h 192.168.11.40 -p 9999 -U pgpool -d postgres -c "SHOW pool_nodes;"

期待結果

pg1 standby
pg2 primary
pg3 standby
status/pg_status: up

3.6. 全台落としたあとの復帰

3.6.1. 概要

目的:
全台落として復帰させる

作業概要:
pg1をプライマリとしてpostgresqlを立ち上げ、
その後standby(pg2/pg3)のDB同期、立ち上げを実施する。

3.6.2. ノードを全台停止(pg1/pg2/pg3)

各ノードで:

sudo shutdown -h now

3.6.3 pg1/pg2/pg3立ち上げ

正常に立ち上がり、SSHでログインできること。

3.6.4. pg1/pg2/pg3 のpgpool-IIを停止する

pg1/pg2/pg3

sudo systemctl stop pgpool-II
sudo systemctl is-active pgpool-II || true

期待結果

3台ともinactiveと出てくること。

3.6.5. pg1 のpostgresqlを立ち上げて、primaryとする

pg1

sudo systemctl start postgresql-16
sudo -u postgres /usr/pgsql-16/bin/pg_ctl -D /var/lib/pgsql/16/data -w promote
sudo -u postgres psql -c "select pg_is_in_recovery();"

"pg_ctl: cannot promote server; server is not in standby mode"と出る場合は無視してよい。

期待結果

f(pg1 primary)

3.6.6. pg2/pg3 を pg1 の standby として作り直し

pg2/pg3

sudo systemctl stop postgresql-16
sudo mv /var/lib/pgsql/16/data /var/lib/pgsql/16/data.old.$(date +%F-%H%M%S)
sudo install -d -o postgres -g postgres -m 700 /var/lib/pgsql/16/data
sudo restorecon -RFv /var/lib/pgsql/16/data || true
sudo -u postgres /usr/pgsql-16/bin/pg_basebackup \
  -h pg1 -p 5432 -U repl \
  -D /var/lib/pgsql/16/data \
  -R -X stream -S "$(hostname)" \
  --write-recovery-conf
sudo systemctl start postgresql-16
sudo -u postgres psql -c "select pg_is_in_recovery();"

期待結果

t(pg2/pg3 standby)

3.6.7. pg1でレプリケーション確認

pg1

sudo -u postgres psql -c "select client_addr,state,sync_state,application_name from pg_stat_replication;"

期待結果

pg2/pg3 が並ぶ(2行)

3.6.8. pgpool を全台起動

sudo systemctl start pgpool-II
sudo systemctl is-active pgpool-II

3.6.9. VIP経由で最終確認

ope1

psql -h 192.168.11.40 -p 9999 -U pgpool -d postgres -c "SHOW pool_nodes;"

期待結果

pg1 primary
pg2 standby
pg3 standby
status/pg_status: up

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?