はじめに
Hiveについて、独立したホストでクラスタ化(pgpool利用)してみました。
前提として、以下手順に従いHadoopクラスタを構築してること。
動作確認用にzeppelinも構築していること。
構成概要
Hadoop クラスタ
master1 : ZooKeeper / JournalNode / NameNode(nn1) / ZKFC
JobHistoryServer / ATSv2 / Hive / PostgreSQL
master2 : ZooKeeper / JournalNode / NameNode(nn2) / ZKFC
ResourceManager(rm1)
master3 : ZooKeeper / JournalNode
ResourceManager(rm2)
worker1 : DataNode / NodeManager
worker2 : DataNode / NodeManager
zeppelin1 : zeppelin
上記ZookeeeperをHiveServer2クラスタで利用。
master1のHive&PostgreSQLは下記ホスト、Hive稼働できたらサービス停止してよい。
追加ホスト
hive1 : HiveServer2 + Hive Metastore
hive2 : HiveServer2 + Hive Metastore
pg1 : PostgreSQL Primary + pgpool
pg2 : PostgreSQL Standby + pgpool
pg3 : PostgreSQL Standby + pgpool
pg-vip : PostgreSQL 仮想IP(pgpool制御)
pg1/pg2/pg3について、AlmaLinux9を使用する。
それ以外は、Ubuntu24.04を使用する。
HA 方針
| コンポーネント | HA方式 |
|---|---|
| HiveServer2 | ZooKeeper Service Discovery |
| Hive Metastore | Active-Active |
| PostgreSQL | Streaming Replication |
| Primary 切替 | pgpool |
| postgresql接続先 | VIP (pgpool) |
| ZooKeeper | Hadoop 既存を流用 |
前提 IP(例)
192.168.11.54 hive1
192.168.11.55 hive2
192.168.11.37 pg1
192.168.11.38 pg2
192.168.11.39 pg3
192.168.11.40 pg-vip
※適宜読み替えてください
1. 全ノード共通設定(新規ホスト)
全ホストの名前解決を行えるようにする。
以下のコマンドでBigTop APT リポジトリ追加すること。
こちらについてはpg1/pg2/pg3では実施しなくてよい。
sudo tee /etc/apt/sources.list.d/bigtop.list << 'EOF'
deb [trusted=yes] http://repos.bigtop.apache.org/releases/3.3.0/ubuntu/22.04/amd64 bigtop contrib
EOF
sudo apt update
2. PostgreSQL HA 構築
2.1. 全台共通(pg1 / pg2 / pg3)
2.1.1. 基本設定
sudo dnf -y update
sudo dnf -y install chrony vim wget
sudo systemctl enable --now chronyd
2.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
2.1.3. PostgreSQL + Pgpool インストール(全台)
sudo dnf -y install pgpool-II pgpool-II-pcp
sudo dnf -y install postgresql16-server
2.2 PostgreSQL:Streaming Replication 構築
2.2.1. 3台共通:初期化・起動
sudo /usr/pgsql-16/bin/postgresql-16-setup initdb
sudo systemctl enable --now postgresql-16
2.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
2.2.2. 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パスワードを定め、パスワードを控える
2.2.3. 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
2.3. pg2/pg3 を Standby にする(basebackup)
2.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
2.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入力が出ます
2.3.3. pg2/pg3: 起動
sudo systemctl start postgresql-16
2.3.4. pg1: 確認
sudo -u postgres psql -c "select client_addr,state,sync_state from pg_stat_replication;"
→sync_stateが全てasyncとなること。
2.4 Pgpool-II:3台 Watchdog + VIP 構築
2.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
2.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
2.4.3. pg1: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
2.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
2.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
2.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
2.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
2.5 pgpool.conf/pool_hba.conf
2.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
2.6. サンプルスクリプト有効化(PG16向けに修正)
2.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
'
2.7. pgpool 起動(全台)
2.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
2.7.2. 起動
sudo systemctl enable --now pgpool-II
sudo systemctl status pgpool-II
2.8. 確認(VIP / watchdog / pool_nodes)
2.8.1. VIPがどこにいるか(3台どれかで)
ip -br addr | grep 192.168.11.40 || true
→3台のどれかでVIPが出ればよい。
2.8.2. Pgpool経由で backend 状態(どこからでも)
psql -h 192.168.11.40 -p 9999 -U pgpool -d postgres -c "SHOW pool_nodes;"
→backendのステータスが見れること。
2.8.3. watchdog 状態
pcp_watchdog_info -h 127.0.0.1 -p 9898 -U pgpool
→pgpoolのパスワードを入れる。
3台のステータスが見れること。
2.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
2.10. pgpool認証ファイルコピー
2.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
2.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/
2.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
2.10.4. Pgpool 反映(全ノード)
sudo systemctl restart pgpool-II
2.10.5.【後始末】pg1 の /tmp を掃除
sudo rm -f /tmp/pool_passwd /tmp/.pgpoolkey
2.11 postgresql自動起動停止
pgpoolにてpostgresqlの制御を実施させるため、postgresqlの自動起動を停止する。
sudo systemctl disable postgresql-16
3. Hive(hive1 / hive2)
3.1. インストール
sudo apt install -y hive hive-metastore hive-server2
sudo apt install -y openjdk-8-jdk
3.2. hadoop ユーザー作成
sudo useradd -m -g hadoop -s /bin/bash hadoop
3.3. Hadoop 設定作成
sudo tee /etc/hadoop/conf/core-site.xml << 'EOF'
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://cluster1</value>
</property>
<property>
<name>ha.zookeeper.quorum</name>
<value>master1:2181,master2:2181,master3:2181</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/var/lib/hadoop/tmp</value>
</property>
</configuration>
EOF
sudo tee /etc/hadoop/conf/hdfs-site.xml << 'EOF'
<configuration>
<property>
<name>dfs.nameservices</name>
<value>cluster1</value>
</property>
<property>
<name>dfs.ha.namenodes.cluster1</name>
<value>nn1,nn2</value>
</property>
<property>
<name>dfs.namenode.rpc-address.cluster1.nn1</name>
<value>master1:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.cluster1.nn2</name>
<value>master2:8020</value>
</property>
<property>
<name>dfs.namenode.http-address.cluster1.nn1</name>
<value>master1:9870</value>
</property>
<property>
<name>dfs.namenode.http-address.cluster1.nn2</name>
<value>master2:9870</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///var/lib/hadoop-hdfs/namenode</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///var/lib/hadoop-hdfs/datanode</value>
</property>
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://master1:8485;master2:8485;master3:8485/cluster1</value>
</property>
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/var/lib/hadoop-hdfs/journalnode</value>
</property>
<property>
<name>dfs.client.failover.proxy.provider.cluster1</name>
<value>
org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider
</value>
</property>
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hadoop/.ssh/id_rsa</value>
</property>
</configuration>
EOF
sudo tee /etc/hadoop/conf/yarn-site.xml << 'EOF'
<configuration>
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>ycluster</value>
</property>
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>master2</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>master3</value>
</property>
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>master1:2181,master2:2181,master3:2181</value>
</property>
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>512</value>
</property>
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>128</value>
</property>
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>256</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.timeline-service.enabled</name>
<value>true</value>
</property>
<property>
<name>yarn.timeline-service.version</name>
<value>2.0</value>
</property>
<property>
<name>yarn.timeline-service.fs-writer.root-dir</name>
<value>/atsv2</value>
</property>
<property>
<name>yarn.timeline-service.reader.webapp.address</name>
<value>master1:8188</value>
</property>
<property>
<name>yarn.webapp.ui2.enable</name>
<value>true</value>
</property>
<property>
<name>yarn.log.server.url</name>
<value>http://master1:19888/jobhistory/logs</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address.rm1</name>
<value>master2:8088</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address.rm2</name>
<value>master3:8088</value>
</property>
</configuration>
EOF
sudo tee /etc/hadoop/conf/mapred-site.xml << 'EOF'
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>yarn.app.mapreduce.am.env</name>
<value>HADOOP_COMMON_HOME=/usr/lib/hadoop,HADOOP_HDFS_HOME=/usr/lib/hadoop-hdfs,HADOOP_MAPRED_HOME=/usr/lib/hadoop-mapreduce</value>
</property>
<property>
<name>mapreduce.map.env</name>
<value>HADOOP_COMMON_HOME=/usr/lib/hadoop,HADOOP_HDFS_HOME=/usr/lib/hadoop-hdfs,HADOOP_MAPRED_HOME=/usr/lib/hadoop-mapreduce</value>
</property>
<property>
<name>mapreduce.reduce.env</name>
<value>HADOOP_COMMON_HOME=/usr/lib/hadoop,HADOOP_HDFS_HOME=/usr/lib/hadoop-hdfs,HADOOP_MAPRED_HOME=/usr/lib/hadoop-mapreduce</value>
</property>
<property>
<name>mapreduce.application.classpath</name>
<value>/etc/hadoop/conf,/etc/hadoop/conf/*,/usr/lib/hadoop/*,/usr/lib/hadoop/lib/*,/usr/lib/hadoop-hdfs/*,/usr/lib/hadoop-hdfs/lib/*,/usr/lib/hadoop-mapreduce/*,/usr/lib/hadoop-mapreduce/lib/*,/usr/lib/hadoop-yarn/*,/usr/lib/hadoop-yarn/lib/*</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>master1:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>master1:19888</value>
</property>
<property>
<name>mapreduce.jobhistory.done-dir</name>
<value>/mr-history/done</value>
</property>
<property>
<name>mapreduce.jobhistory.intermediate-done-dir</name>
<value>/mr-history/tmp</value>
</property>
<property>
<name>yarn.app.mapreduce.am.command-opts</name>
<value>-Dlog4j.configuration=file:/etc/hadoop/conf/log4j.properties</value>
</property>
<property>
<name>mapreduce.map.java.opts</name>
<value>-Dlog4j.configuration=file:/etc/hadoop/conf/log4j.properties</value>
</property>
<property>
<name>mapreduce.reduce.java.opts</name>
<value>-Dlog4j.configuration=file:/etc/hadoop/conf/log4j.properties</value>
</property>
<property>
<name>mapreduce.job.am.webapp.address</name>
<value>0.0.0.0:0</value>
</property>
<property>
<name>mapreduce.job.am.webapp.https.address</name>
<value>0.0.0.0:0</value>
</property>
<property>
<name>mapreduce.shuffle.port</name>
<value>13562</value>
</property>
</configuration>
EOF
3.4. hive-site.xml(両ノード共通)
sudo tee /etc/hive/conf/hive-site.xml << 'EOF'
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:postgresql://pg-vip:9999/hive_metastore</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>org.postgresql.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hive</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>HivePasswordHere</value>
</property>
<property>
<name>hive.metastore.uris</name>
<value>thrift://hive1:9083,thrift://hive2:9083</value>
</property>
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
<property>
<name>hive.server2.support.dynamic.service.discovery</name>
<value>true</value>
</property>
<property>
<name>hive.zookeeper.quorum</name>
<value>master1:2181,master2:2181,master3:2181</value>
</property>
<property>
<name>hive.server2.zookeeper.namespace</name>
<value>hiveserver2</value>
</property>
<property>
<name>hive.metastore.client.notification.event.poll.interval</name>
<value>0s</value>
</property>
<property>
<name>hive.metastore.event.db.notification.api.auth</name>
<value>false</value>
</property>
<property>
<name>hive.server2.enable.doAs</name>
<value>false</value>
</property>
</configuration>
EOF
3.5. PostgreSQL JDBC ドライバを Hive に追加
sudo apt install -y libpostgresql-jdbc-java
dpkg -L libpostgresql-jdbc-java | grep -E 'postgresql.*\.jar$'
sudo ln -sf /usr/share/java/postgresql.jar /usr/lib/hive/lib/postgresql.jar
sudo rm -rf /usr/lib/hive/lib/postgresql-9.4.1208.jre7.jar
3.6. hive DB設定
3.6.1. HiveDB作成
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
3.6.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
3.6.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.7. Metastore スキーマ初期化(hive1で1 回のみ)
sudo -u hadoop /usr/lib/hive/bin/schematool -dbType postgres -initSchema
3.8. サービス作成
sudo tee /etc/default/hive <<'EOF'
HIVE_HOME=/usr/lib/hive
HIVE_CONF_DIR=/etc/hive/conf
HADOOP_CONF_DIR=/etc/hadoop/conf
YARN_CONF_DIR=/etc/hadoop/conf
MAPRED_CONF_DIR=/etc/hadoop/conf
JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
TERM=dumb
EOF
sudo tee /etc/systemd/system/hive-metastore.service <<'EOF'
[Unit]
Description=Apache Hive Metastore Service
After=network.target
Wants=network.target
After=hadoop-hdfs-namenode.service hadoop-hdfs-datanode.service hadoop-yarn-resourcemanager.service hadoop-yarn-nodemanager.service
Wants=hadoop-hdfs-namenode.service hadoop-hdfs-datanode.service hadoop-yarn-resourcemanager.service hadoop-yarn-nodemanager.service
[Service]
Type=simple
User=hive
Group=hive
EnvironmentFile=-/etc/default/hive
Environment="HIVE_CONF_DIR=/etc/hive/conf"
ExecStart=/usr/lib/hive/bin/hive --service metastore
Restart=on-failure
RestartSec=5
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
EOF
sudo tee /etc/systemd/system/hiveserver2.service <<'EOF'
[Unit]
Description=Apache HiveServer2 Service
After=network.target hive-metastore.service
Wants=network.target hive-metastore.service
[Service]
Type=simple
User=hive
Group=hive
EnvironmentFile=-/etc/default/hive
Environment="HADOOP_CLIENT_OPTS=-Dlog4j2.debug=false"
Environment="HIVE_OPTS=--hiveconf hive.root.logger=INFO,console --hiveconf hive.server2.logging.operation.enabled=true"
Environment="HADOOP_HEAPSIZE=1024"
ExecStartPre=/bin/bash -lc 'for i in {1..30}; do nc -z localhost 9083 && exit 0; sleep 1; done; exit 1'
ExecStart=/usr/lib/hive/bin/hive --service hiveserver2
Restart=on-failure
RestartSec=5
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
EOF
3.9. HDFS 上に Hive warehouse 作成(master1で実施)
既存のHadoopクラスタに対し、以下の設定を実施すること。
sudo su - hadoop
hdfs dfs -mkdir -p /user/hive/warehouse
hdfs dfs -chown -R hive:hive /user/hive
hdfs dfs -chmod 771 /user/hive
hdfs dfs -chmod 771 /user/hive/warehouse
hdfs dfs -chmod -R 1777 /tmp
exit
3.10. 起動(hive1/hive2)
sudo systemctl enable --now hive-metastore hiveserver2
4. 動作確認(Hive)
4.1. beeline/zeppelin利用確認
それぞれのHive接続で使用するJDBC設定を以下のように変更して、
それぞれ利用できることを確認する。
変更前
'jdbc:hive2://master1:10000/default'
変更後
'jdbc:hive2://master1:2181,master2:2181,master3:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2'
5. 動作確認(PostgreSQL)
5.1 準備
5.1.1 確認用端末
psqlコマンドを使用できるホストを用意する。
psqlコマンドを使用できるようにする。
sudo apt install postgresql-client-16
5.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
5.1.3 動作確認
ope1にて以下のコマンドを入力して応答が返ることを確認する。
psql -h 192.168.11.40 -p 9999 -U pgpool -d postgres -c "SHOW pool_nodes;"
5.2. 事前確認(共通)
5.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
5.3. フェールオーバー(postgresqlサービス停止)
5.3.1. 概要
目的:primary を pg1 → pg2 に自動的にフェールオーバーさせる。
障害注入方法:
pg1のpostgresqlサービスを停止する。
期待する結果:
自動的にpg2へDBプライマリが自動的に切り替わり、外からの接続も実施できること。
pg1/pg3について、自動的にpg2のstandbyとなること。
合わせて、pgpoolのattachも自動的に実施される。
5.3.2. primary(pg1) の PostgreSQL を停止(障害注入)
pg1
sudo systemctl stop postgresql-16
sudo systemctl is-active postgresql-16 || true
期待結果
inactive
数十秒待って再度2つめのコマンドを実施して、activeとなること。
5.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
5.3.4. 新primary(pg2) 側で “本当にprimaryか” を確認
pg2
sudo -u postgres psql -c "select pg_is_in_recovery();"
期待結果
f(= primary)
5.3.5. レプリケーション確認
pg2
sudo -u postgres psql -c "select client_addr,state,sync_state,application_name from pg_stat_replication;"
期待結果
pg1/pg3 が並ぶ(2行)
5.4. フェールオーバー(primaryホスト停止)
5.4.1. 概要
目的:primary を pg2 → pg1 に自動的にフェールオーバーさせる。
障害注入方法:
pg2ホストを停止する。
期待する結果:
自動的にpg1へDBプライマリが自動的に切り替わり、外からの接続も実施できること。
pg3について、自動的にpg1のstandbyとなること。
合わせて、pgpoolのattachも自動的に実施される。
pg2復旧後、手動操作を行いstandbyとして復旧すること。
5.4.2. primary(pg2) の ノードを停止(障害注入)
pg2
sudo shutdown -h now
5.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
5.4.4. 新primary(pg1) 側で “本当にprimaryか” を確認
pg1
sudo -u postgres psql -c "select pg_is_in_recovery();"
期待結果
f(= primary)
5.4.5. レプリケーション確認
pg1
sudo -u postgres psql -c "select client_addr,state,sync_state,application_name from pg_stat_replication;"
期待結果
pg3 が並ぶ(1行)
5.4.6. pg2ホスト立ち上げ
落とした元primaryホストを立ち上げる
5.4.7. pg2ホストの再加入
pg2
sudo -u postgres /etc/pgpool-II/follow_primary.sh 1 pg2 0 pg1
5.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
5.4.9. pg2で “本当にstandbyか” を確認
pg2
sudo -u postgres psql -c "select pg_is_in_recovery();"
期待結果
t(= standby)
5.4.10. レプリケーション確認
pg1
sudo -u postgres psql -c "select client_addr,state,sync_state,application_name from pg_stat_replication;"
期待結果
pg2/pg3 が並ぶ(1行)
5.5. フェイルバック
5.5.1. 概要
目的:
primary を pg1 → pg2 に戻す
リスク:
pgpool稼働中にpg1を止めると、自動判定が走る可能性(pg2に確実に戻したい。)
pg2のスタンバイとしてpg1/pg3が立ち上がらなくなり、クラスタ状態が壊れる
対策:
フェイルバック作業中だけ pgpoolを全台止める
follow_primaryシェルを利用し、pg1/pg3のstanby化を確実に実施する。
5.5.2. pgpool を全台停止(pg1/pg2/pg3)
各ノードで:
sudo systemctl stop pgpool-II
sudo systemctl is-active pgpool-II || true
期待結果
3台とも pgpool-II inactive
5.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();"
上記の結果が全台で一致すること。
5.5.4. 現primary(pg1) を停止
pg1
sudo systemctl stop postgresql-16
sudo systemctl is-active postgresql-16 || true
期待結果
pg2 postgresql-16 inactive
5.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)
5.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)
5.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)
5.5.8. pg2でレプリケーション確認
pg2
sudo -u postgres psql -c "select client_addr,state,sync_state,application_name from pg_stat_replication;"
期待結果
pg1/pg3 が並ぶ(2行)
5.5.9. pgpool を全台起動
sudo systemctl start pgpool-II
sudo systemctl is-active pgpool-II
5.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
5.6. 全台落としたあとの復帰
5.6.1. 概要
目的:
全台落として復帰させる
作業概要:
pg1をプライマリとしてpostgresqlを立ち上げ、
その後standby(pg2/pg3)のDB同期、立ち上げを実施する。
5.6.2. ノードを全台停止(pg1/pg2/pg3)
各ノードで:
sudo shutdown -h now
5.6.3 pg1/pg2/pg3立ち上げ
正常に立ち上がり、SSHでログインできること。
5.6.4. pg1/pg2/pg3 のpgpool-IIを停止する
pg1/pg2/pg3
sudo systemctl stop pgpool-II
sudo systemctl is-active pgpool-II || true
期待結果
5.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)
5.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)
5.6.7. pg1でレプリケーション確認
pg1
sudo -u postgres psql -c "select client_addr,state,sync_state,application_name from pg_stat_replication;"
期待結果
pg2/pg3 が並ぶ(2行)
5.6.8. pgpool を全台起動
sudo systemctl start pgpool-II
sudo systemctl is-active pgpool-II
5.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