repmgrによるPostgreSQLのクラスタリング

どんなのか使ってみたかったけど、紹介している人があまりいなかったので、自分で動かしてみました。

# repmgr概要
repmgrはコマンドラインツールで以下の管理タスクを実行し、PostgreSQLをHAクラスタとするためのツールです。

- スタンバイサーバの設定
- スタンバイサーバの昇格
- スイッチオーバ
- クラスタのサーバステータス

repmgrは2ndQuadrant社が作成し、GitHubで[公開](https://github.com/2ndQuadrant/repmgr)しています。

# repmgrでのPostgreSQLクラスタ化までの構築手順

## 1. 前提条件、及び環境構築
今回はVirtualBoxでのCentOS7、PostgreSQL 9.5.2の環境でやります。
まずは、PostgreSQL(ソースビルド版)がインストールされた2台のVMを準備しておいてください。
※本書では、PostgreSQLのインストール方法やSSHの設定等の説明を省きます。
　後半でもPostgreSQLの説明については割愛している箇所が多いです。

その他の条件

- localhostとクラスタリングを組む対象のノード間では**sshがパス無しで通る**ように設定しておく。
- マスタ、スレーブ側のノードではPostgreSQLをインストール済み
- マスタ側ではinitdbを実行済み。

ちなみに今回のノードでは/etc/hostsは以下の様な設定にしています。

```
192.168.1.1 neko
192.168.1.2 inu
```

neko：マスタノード、inu：スタンバイノードとして構築を進めていきます。

## 2. repmgrのソースをダウンロードする。（マスタ、スタンバイで実施）
[PostgreSQLコミュニティ](http://yum.postgresql.org/9.5/redhat/rhel-7-x86_64/repoview/)からRPMは配布されていますが、敢えてソースビルドで構築していきます。

ソースはrepmgrの[公式サイト](http://repmgr.org/)または[GitHub](https://github.com/2ndQuadrant/repmgr)からダウンロードできます。

## 3. ダウンロードしたrepmgrをビルドする（マスタ、スタンバイで実施）
tar.gzで落としたファイルをcontribディレクトリ配下に置き、ビルドします。

```
$ tar -xvf repmgr-3.1.2.tar.gz
$ mv ~/repmgr-3.1.2 ~/postgresql-9.5.2/contrib/
$ cd ~/postgresql-9.5.2/contrib/repmgr-3.1.2
$ make
$ make install
```

## 4. repmgrのセットアップ（マスタのみで実施）

### 4-1. repmgrの設定ファイルを作成する

```
$ vi ~/local/pg952/pgsql/etc/repmgr.conf
```

```repmgr.conf
cluster=test
node=1
node_name=neko
conninfo='host=neko user=repmgr dbname=repmgr'
```

| 項目名 | 説明 |
|:-----------|:------------|
|cluster|レプリケーションクラスタの任意の名前。※すべてのノードで同一である必要があります|
|node|識別用の個別の整数|
|node_name|ノードを識別する文字列|
|conninfo|自身のrepmgrDBに接続可能な接続情報|

### 4-2. PostgreSQLを起動する
最低限必要な設定として、以下の設定を行ってください。

```postgresql.conf
wal_level = 'hot_standby'
max_wal_senders = 10
wal_keep_segments = 5000
hot_standby = on
archive_mode = on
archive_command = '/bin/true'
```

自分が試した限り、wal_keep_segmentsの値が小さいと5000以上にしろ！とrepmgrに怒られました。

```
[2016-05-23 21:51:04] [NOTICE] destination directory '/home/ikki/local/pg952/data' provided
[2016-05-23 21:51:04] [ERROR] parameter 'wal_keep_segments' must be be set to 5000 or greater (see the '-w' option or edit the postgresql.conf of the upstream server.)
[2016-05-23 21:51:04] [HINT] in PostgreSQL 9.4 and later, replication slots can be used, which do not require 'wal_keep_segments' to be set to a high value (set parameter 'use_replication_slots' in the configuration file to enable)
```

repmgrがWALファイルの管理をしてくれるということなのかな？
今回は詳細なところまで調査はしないので、スルーしますが今後どういう仕組なのかも調べたいです。

### 4-3. repmgrがクラスタを管理するためのユーザとDBを作成する

```
$createuser -s repmgr
$createdb repmgr -O repmgr
``` 

### 4-4. PostgreSQLの認証の設定を行う
pg_hba.confに以下の内容を追記する。

```pg_hba.conf
local   replication   repmgr                              trust
host    replication   repmgr      127.0.0.1/32            trust
host    replication   repmgr      192.168.1.0/24          trust

local   repmgr        repmgr                              trust
host    repmgr        repmgr      127.0.0.1/32            trust
host    repmgr        repmgr      192.168.1.0/24          trust
```

### 4-5. repmgrユーザのsearch_pathを設定する

```
$ psql repmgr -c 'ALTER ROLE repmgr SET search_path TO repmgr_test, "$user", public' -U repmgr
```

### 4-6. PostgreSQLを再起動
編集したpg_hba.confを有効にする

```
$ pg_ctl -D ~/local/pg952/data restart
```

## 5. repmgrにマスタノードを登録する（マスタのみで実施）
マスタノードで以下のコマンドを実行し、ノードをrepmgrに登録する。

```
$ repmgr -f ~/local/pg952/pgsql/etc/repmgr.conf master register
[2016-05-23 21:34:18] [NOTICE] master node correctly registered for cluster test with id 1 (conninfo: host=neko user=repmgr dbname=repmgr)
```

登録された情報は以下のコマンドで確認することができます。

```
$ psql repmgr -c 'SELECT * FROM repmgr_test.repl_nodes' -U repmgr -x
-[ RECORD 1 ]----+------------------------------------
id               | 1
type             | master
upstream_node_id | 
cluster          | test
name             | neko
conninfo         | host=neko user=repmgr dbname=repmgr
slot_name        | 
priority         | 100
active           | t
```

## 6. スタンバイとなるDBを作成する（スタンバイのみで実施）

```
$ repmgr -h neko -U repmgr -d repmgr -D ~/local/pg952/data -f ~/local/pg952/pgsql/etc/repmgr.conf standby clone
[2016-05-23 21:52:55] [NOTICE] destination directory '/home/ikki/local/pg952/data' provided
[2016-05-23 21:52:55] [NOTICE] starting backup (using pg_basebackup)...
[2016-05-23 21:52:55] [HINT] this may take some time; consider using the -c/--fast-checkpoint option
NOTICE:  pg_stop_backup complete, all required WAL segments have been archived
[2016-05-23 21:53:07] [NOTICE] standby clone (using pg_basebackup) complete
[2016-05-23 21:53:07] [NOTICE] you can now start your PostgreSQL server
[2016-05-23 21:53:07] [HINT] for example : pg_ctl -D /home/ikki/local/pg952/data start
[2016-05-23 21:53:07] [HINT] After starting the server, you need to register this standby with "repmgr standby register"
```

この段階でスタンバイノードには以下のrecover.confが作られます。

```recovery.conf
standby_mode = 'on'
primary_conninfo = 'port=5432 host=neko user=repmgr application_name=inu'
recovery_target_timeline = 'latest'
```

## 7. PostgreSQL起動（スタンバイでのみ実施）

```
$ pg_ctl -D ~/local/pg952/data start
```

```
$ ps -ef |grep postgres
ikki      7790     1  0 19:04 pts/0    00:00:00 /home/ikki/local/pg952/pgsql/bin/postgres -D /home/ikki/local/pg952/data
ikki      7794  7790  0 19:04 ?        00:00:00 postgres: logger process   
ikki      7795  7790  0 19:04 ?        00:00:00 postgres: startup process   recovering 00000001000000000000002D
ikki      7796  7790  2 19:04 ?        00:00:00 postgres: wal receiver process   streaming 0/2D0001A0
ikki      7797  7790  0 19:04 ?        00:00:00 postgres: checkpointer process   
ikki      7798  7790  0 19:04 ?        00:00:00 postgres: writer process   
ikki      7799  7790  0 19:04 ?        00:00:00 postgres: stats collector process   
ikki      7812  2623  0 19:04 pts/0    00:00:00 grep --color=auto postgres
```

マスタの統計情報ビューを確認する。

```
$ psql -h neko repmgr -c 'SELECT * FROM pg_stat_replication' -U repmgr -x
-[ RECORD 1 ]----+------------------------------
pid              | 8732
usesysid         | 20997
usename          | repmgr
application_name | inu
client_addr      | 192.168.1.2
client_hostname  | 
client_port      | 49837
backend_start    | 2016-05-24 19:04:10.347144+09
backend_xmin     | 
state            | streaming
sent_location    | 0/2D0001A0
write_location   | 0/2D0001A0
flush_location   | 0/2D0001A0
replay_location  | 0/2D0001A0
sync_priority    | 0
sync_state       | async
```

## 8. 起動したスタンバイをrepmgrに登録する
スタンバイサーバで以下のコマンドを実行する。

```
$ repmgr -f ~/local/pg952/pgsql/etc/repmgr.conf standby register
[2016-05-24 19:08:40] [NOTICE] standby node correctly registered for cluster test with id 2 (conninfo: host=inu user=repmgr dbname=repmgr)
```

マスタ、スタンバイサーバで以下のコマンドを実行すると登録されたことを確認できます。
これでrepmgrによるクラスタが組めました。

```
$ psql repmgr -c 'SELECT * FROM repmgr_test.repl_nodes' -U repmgr
 id |  type   | upstream_node_id | cluster | name |              conninfo       
        | slot_name | priority | active 
----+---------+------------------+---------+------+-------------------------------------+-----------+----------+--------
  1 | master  |                  | test    | neko | host=neko user=repmgr dbname=repmgr |           |      100 | t
  2 | standby |                1 | test    | inu  | host=inu user=repmgr dbname=repmgr  |           |      100 | t
(2 rows)
```

## 9. スタンバイのpromote
まずはスタンバイであることを確認します。

```
$ psql postgres -c "SELECT pg_is_in_recovery()"
 pg_is_in_recovery 
-------------------
 t
(1 row)
```

マスタをダウンさせます。

```
$ pg_ctl -D ~/local/pg952/data stop
waiting for server to shut down..... done
server stopped
```

repmgrを使用してスタンバイをpromoteさせます。

```
$ repmgr -f ~/local/pg952/pgsql/etc/repmgr.conf standby promote
[2016-05-25 00:34:14] [ERROR] connection to database failed: could not connect to server: Connection refused
	Is the server running on host "neko" (192.168.1.1) and accepting
	TCP/IP connections on port 5432?

[2016-05-25 00:34:14] [NOTICE] promoting standby
[2016-05-25 00:34:14] [NOTICE] promoting server using 'pg_ctl -D /home/ikki/local/pg952/data promote'
server promoting
[2016-05-25 00:34:16] [NOTICE] STANDBY PROMOTE successful
```

スタンバイがマスタに昇格したことを確認します。

```
$ psql -h inu postgres -c "SELECT pg_is_in_recovery()"
 pg_is_in_recovery 
-------------------
 f
(1 row)
```

成功！！
無事にpromoteさせることができました。


## ちなみに・・・
マスタを停止する前にpromoteさせようとするとエラーになります。
ちゃんとクラスタとして管理されていますね。

```
$ repmgr -f ~/local/pg952/pgsql/etc/repmgr.conf standby promote
[2016-05-25 00:29:48] [ERROR] this cluster already has an active master server
```



以上です。
長々と書きましたが今日はここまで。

**注意：repmgrだけでは自動フェイルオーバーはできません。**
自動フェイルオーバーにはrepmgrdというデーモンを起動する必要があります。
次はrepmgrdについて書きます。