PostgreSQL環境構築

## この記事について
[pgpool-IIの使い方を考える](https://qiita.com/sankaku/items/94f2b6421f100e5f48f7)のサブページです。

## 前提
[【前提】CentOS検証環境初期設定](https://qiita.com/sankaku/items/073683cfe674cb73d5de)

上記で作成した環境のクローン（クローン時にMACアドレスは初期化）を１ノード作成して、以下IPアドレスを設定しておきます。

※スタンバイノードはマスターノードの構築が完了してからマスターノードをクローンして作成するほうが効率的です。当ページ「スタンバイ設定」の項でクローン作製のタイミングを指定していますので、参照してください。
さらに言えばスタンバイノードを1台作成して他のスタンバイサーバはそのクローンとすればIP変更だけで済みますが、そもそもスタンバイノードの作成はそんなに面倒ではないので～というかpgpool-IIを入れるとフェイルオーバーの度に自動構築します～ので、そこまで効率化しなくても良いかと思います。

- 192.168.56.121/24 マスターノード向け

※IPアドレス変更操作例（設定済み固定IPを削除してから追加します。そのまま追加した場合は複数のIPが設定されます。）

```:command
# nmcli connection edit bond0
```

```:result
（省略）
```

```:command
nmcli> remove ipv4.addresses
nmcli> set ipv4.addresses 192.168.56.121/24
'ipv4.method' を 'manual' に設定しますか? [yes]: yes
nmcli> save
```

```:result
接続 'bond0' (da47bbce-f15c-4c12-bd2d-09f68129ae41) が正常に更新されました。
```

```:command
nmcli> print
```

```:result
（省略）
```

```:command
nmcli> quit
```

ネットワークを再起動します。

```:command
# systemctl restart network
```

## マスター/スタンバイ共通

### PostgreSQLインストール

- CentOS同梱版PostgreSQLがインストールされていないことを確認します。

OSインストール時にあえて選択していなければPostgreSQLはインストールされていないと思いますが、存在する場合は削除します。また、クラスタディレクトリはyum removeで削除しきれませんので、手動で削除する必要があります。さらに、設定をカスタマイズしている場合に削除されないファイルが出てくる可能性がありますので、それらは別途削除する必要があります。（起動設定/etc/systemd/system/postgresql.service等）

```:command
# yum list installed|grep -i postgres
```

```:result
（何も出力されない。）
```

- PostgreSQL公式yumリポジトリから最新版をインストールします。（確認プロンプトにはyで答える。）

```:command
# yum install https://download.postgresql.org/pub/repos/yum/10/redhat/rhel-7-x86_64/pgdg-centos10-10-2.noarch.rpm
# yum install postgresql10*
# yum list installed|grep -i postgres
```

- クラスタを作成します。

```:command
# /usr/pgsql-10/bin/postgresql-10-setup initdb
```

クラスタディレクトリは標準の/var/lib/pgsql/10/data/です。

### firewalld設定

- postgresqlサービスのパケットを許可します。

```:command
# firewall-cmd --permanent --zone=internal --add-service=postgresql
```

- firewalldをリロードして反映します。

```:command
# firewall-cmd --reload
```

### レプリケーション専用ユーザログインパスワード不要設定

- 後程作成するレプリケーション専用ユーザでPostgreSQLにログインする際にパスワードを求められないように設定しておきます。後程実装するスクリプト内でpg_basebackupコマンドを自動実行するために必要です。

postgresユーザのホームディレクトリ/var/lib/pgsqlに.pgpassファイルを作成して以下のように記載します。

```:file-info
ファイルパス：/var/lib/pgsql/.pgpass
ユーザ/グループ：postgres/postgres
権限：600
ファイル内容：
```

```:/var/lib/pgsql/.pgpass
#hostname:port:database:username:password
192.168.56.121:5432:*:repuser:repuser
192.168.56.122:5432:*:repuser:repuser
192.168.56.123:5432:*:repuser:repuser
192.168.56.124:5432:*:repuser:repuser
```

### pgpool-IIユーザ作成とssh鍵交換

pgpool-IIユーザを作成します。PostgreSQLノードにpgpool-IIはインストールしませんが、pgpool-IIプロセスからスクリプトでsshコマンドによる処理実行用として、専用のpgpoolユーザを使用することにします。

- pgpool-IIユーザを作成してパスワード設定をします。

```:command
# useradd pgpool
# passwd pgpool
```

- ssh鍵を作成します。

以下を参考に作成します。
[【前提】CentOS検証環境初期設定](https://qiita.com/sankaku/items/073683cfe674cb73d5de)

rootユーザ向けに作成した鍵をそのまま使いまわす場合の例を以下に記します。

```:command
# cd /home/pgpool/
# cp -rp /root/.ssh ./
# chown -R pgpool:pgpool .ssh
# cd .ssh/
# vi authorized_keys
```

```:変更内容
（行末の root@localhost.localdomain を pgpool@localhost.localdomain に変更します。）
```

### pgpoolユーザ向けsudo設定

ssh接続はpgpoolユーザで実行しますが、そこから実行するコマンドはroot権限で実行する必要があるため、sudo設定します。

- sudoers設定

```:command
# visudo -f /etc/sudoers.d/pgpool
```

```:追記
Cmnd_Alias FORSHELL=/usr/bin/touch,\
/usr/bin/systemctl stop postgresql-10,\
/usr/bin/rm -rf /var/lib/pgsql/10/data/,\
/usr/bin/mkdir /var/lib/pgsql/10/data,\
/usr/bin/chmod -R 700 /var/lib/pgsql/10/data,\
/usr/bin/chown -R postgres\:postgres /var/lib/pgsql/10/data,\
/usr/bin/sh -c cd;pg_basebackup -h * -D /var/lib/pgsql/10/data/ -R -U repuser,\
/usr/bin/sh -c echo * >> /var/lib/pgsql/10/data/recovery.conf,\
/usr/bin/systemctl start postgresql-10
pgpool ALL=(ALL) NOPASSWD:FORSHELL
```

### pgpool-IIのyumインストール

pgpool-recovery.sqlを適用するためにpgpool-IIをインストールしておきます。起動することはありません。

- pgpool-II公式リポジトリからyumインストールします。（確認プロンプトにはyで答える。）

```:command
# yum install http://www.pgpool.net/yum/rpms/3.7/redhat/rhel-7-x86_64/pgpool-II-release-3.7-1.noarch.rpm
# yum install pgpool-II-pg10* 
```

## マスター設定

### postgresql.confの設定変更

- postgresql.confファイルの設定を変更します。

ファイルパス：/var/lib/pgsql/10/data/postgresql.conf

---

| 項目 | デフォルト値 | 設定値 | 備考 |
|:-----------|:---|:---|:---|
| listen_addresses | localhost | * | 全てのアドレスでサービスを待ち受ける。 |
| synchronous_commit | on | off | slaveサーバダウン時にmasterノード更新不可とならないようにoffとする。<br>※slaveへのwalログ転送が保証されないままmasterへの更新が完了してしまうことを許容する必要がある。 |
| log_statement | none | all | 全てのSQLをログに記録する。<br>※検証用 |
| pgpool.pg_ctl | （設定無し） | /usr/pgsql-10/bin/pg_ctl' | pgpool-IIのインストール手順に従い追加。<br>http://www.pgpool.net/docs/latest/ja/html/install-pgpool-recovery.html |
| hot_standby | on | on | リードレプリカ設定で必須だが、バージョン10ではデフォルトで対応している。 |
| wal_level | replica | replica | リードレプリカ設定で必須だが、バージョン10ではデフォルトで対応している。 |

---

### pg_hba.confの設定変更

- pg_hba.confファイルの設定を変更します。

ファイルパス：/var/lib/pgsql/10/date/pg_hba.conf

---

*# "local" is for Unix domain socket connections only*

| | TYPE | DATABASE | USER | ADDRESS | METHOD | 備考 |
|:---|:---|:---|:---|:---|:---|:---|
| 維持 | local | all | all |  | peer | デフォルト |

*# IPv4 local connections:*

| | TYPE | DATABASE | USER | ADDRESS | METHOD | 備考 |
|:---|:---|:---|:---|:---|:---|:---|
| 削除 | host | all | all | 127.0.0.1/32 | ident | デフォルト<br>identからmd5に変更。 |
| 追加 | host | all | all | 127.0.0.1/32 | trust | ローカルからの接続は信頼する。<br>検証向け。 |
| 追加 | host | all | all | 192.168.56.0/24 | md5 |  |

*# IPv6 local connections:*

| | TYPE | DATABASE | USER | ADDRESS | METHOD | 備考 |
|:---|:---|:---|:---|:---|:---|:---|
| 削除 | host | all | all | ::1/128 | ident | デフォルト<br>IPv6は使用しない。 |

*# Allow replication connections from localhost, by a user with the<br># replication privilege.*

| | TYPE | DATABASE | USER | ADDRESS | METHOD | 備考 |
|:---|:---|:---|:---|:---|:---|:---|
| 維持 | local | replication | all |  | peer | デフォルト |
| 削除 | host | replication | all | 127.0.0.1/32 | ident | デフォルト |
| 追加 | host | replication | repuser | 192.168.56.0/24 | md5 | レプリケーション用 |
| 削除 | host | replication | all | ::1/128 | ident | デフォルト<br>IPv6は使用しない。 |

---

## DBユーザ設定

- PostgreSQLを起動します。また、自動起動設定しておきます。

```:command
# systemctl status postgresql-10
# systemctl enable postgresql-10
# systemctl start postgresql-10
# systemctl status postgresql-10
```

- レプリケーション専用ユーザを追加します。

```:command
# psql -h 127.0.0.1 -U postgres -d postgres
postgres=# create role repuser login replication password 'repuser';
```

- postgresユーザにパスワードを付与します。

```:command
# alter role postgres with password 'postgres';
```

- 確認して切断します。

```:command
postgres=# alter role postgres with password 'postgres';
postgres=# \q
```

### テスト用DB作成

- テスト用DBとしてtestdb01とテーブルtbl01を作成しておく。

```:command
# sudo -u postgres createdb -U postgres testdb01
# psql -h 192.168.56.121 -U postgres -d testdb01
postgres=# create table tbl01(col1 varchar(10),col2 varchar(10));
postgres=# \d
postgres=# \q
```

### PostgreSQL template1に対してpgpool-recovery.sqlを実行

- PostgreSQL template1に対してpgpool-recovery.sqlを実行します。

```:command
# cd /usr/pgsql-10/share/extension/
# psql -h 192.168.56.121 -U postgres -f pgpool-recovery.sql -d template1
```

## スタンバイ設定

### 前提

作成したマスターノードのクローンを3ノード作成（クローン時にMACアドレスは初期化）して、スタンバイノード用のIPアドレスを付与しておきます。


**[ノード1] 192.168.56.122/24 スタンバイノード向け**
**[ノード2] 192.168.56.123/24 スタンバイノード向け**
**[ノード3] 192.168.56.124/24 スタンバイノード向け**

- PostgreSQLを停止します。

```:command
# systemctl status postgresql-10
# systemctl stop postgresql-10
# systemctl status postgresql-10
```

- /var/lib/pgsql/10/dataディレクトリは残して、配下のクラスタファイルを削除します。

```:command
# cd /var/lib/pgsql/10/data
# rm -rf *
# sudo -u postgres pg_basebackup -h 192.168.56.121 -D /var/lib/pgsql/10/data/ -R --progress -U repuser
```

（-R でrecovery.confを自動作成します。）


- recovery.confにtrigger_file設定を追加します。

```:/var/lib/pgsql/10/data/recovery.conf(追記)
trigger_file = '/var/lib/pgsql/10/trigger'
```

- PostgreSQLを起動します。

```:command
# systemctl status postgresql-10
# systemctl start postgresql-10
# systemctl status postgresql-10
```

## その他操作備忘

### レプリケーションノードをマスター昇格

レプリケーションノードをマスター昇格させます。既存のマスターはそのままマスターとして動き続けます。

- トリガーファイルでマスター昇格

```:command
# touch /var/lib/pgsql/10/trigger
```

- コマンドでマスター昇格

```:command
# sudo -u postgres /usr/pgsql-10/bin/pg_ctl -D /var/lib/pgsql/10/data/ promote
```

PostgreSQL公式リポジトリからインストールしたPostgreSQLのpg_ctlコマンドはRedHatのalternative対象にはなっていないため、パスが通っていません。ここではフルパス指定で実行しています。

### マスターノードからレプリケーションノードを確認

マスターノードからレプリケーションノードの一覧を表示します。

```:command
# psql -h 192.168.56.121 -U postgres -d postgres -xc 'select * from pg_stat_replication'
```

### pg_walディレクトリ配下のファイル構成について

/var/lib/pgsql/10/data/pg_wal配下のファイルが各ノードで同一となるのかと思いきや、そんなことは無かったです。データの中身が一致していてもファイル構成は異なっていました。walファイルの生成は各ノードそれぞれで実施しているようです。