PostgreSQLとPacemakerによる高可用ソリューション PG-REX 9.6 の構築

# 目的
- HAについての勉強として、PG-REXをVM環境に構築する
    - 手順書はコミュニティから公開されているので、それを試してみる

# PG-REXとは
- PostgreSQLの同期レプリケーションとPacemakerを組み合わせたHAクラスタの名称
    - PG-REXは製品名ではない。
- PacemakerがPostgreSQLを管理しており、以下のようなことができる
    - 障害検知時の自動フェイルオーバ
    - スイッチオーバ
    - VIPの管理（PGのマスタ、スレーブを監視して自動で設定してくれる）
- 設定が大変ということで有名？
    - 山場はPacemakerの設定

# 資材の取得先
- PG-REX9.6 構築手順書等
    - https://ja.osdn.net/projects/pg-rex/releases/68042
- PostgreSQL 9.6
    - https://yum.postgresql.org/9.6/redhat/rhel-7-x86_64/repoview/
- Pacemaker-1.1.16
    - http://linux-ha.osdn.jp/wp/archives/4618

# 構成の概要
## NW周り
- NWの設定は以下のようにする。
    ※ 手順書だと、NICが6本必要だがそんなに用意できないのでBONDINGなしでやる。
    ※ ネットマスクは255.255.255.0とする。

    |  |hostname|S-LAN|D-LAN|IC-LAN|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|1系|yama|192.168.1.1|192.168.2.1|192.168.3.1</br> 192.168.2.1(※1)|
|2系|kawa|192.168.1.2|192.168.2.2|192.168.3.2</br> 192.168.2.2(※1)|
    (※1)　IC-LANは2本必要以上が推奨のため、今回はD-LANを兼用する。
    - 用語説明
        - S-LAN：DBがクライアントからの接続を受け付けるのに使用
        - D-LAN：DBのレプリケーションに使用
        - IC-LAN：Pacemaker同士が死活監視に使用

- Pacemaker側で作成する各VIPは以下のようにする。
    - ユーザやAPは基本的にVIPを接続先としてDBを使用する。
    - VIPはPacemakerが自動で制御してくれるので、フェイルオーバが発生しても接続の変更が不要。

    |vip-master|vip-slave|vip-rep|
|:----:|:----:|:----:|
|192.168.1.10|192.168.1.20|192.168.2.3|

- 用語説明
    - vip-master：マスタ接続用のVIP
    - vip-slave：スレーブ接続用のVIP
    - vip-rep：レプリケーション接続用のVIP

## 概要図
<img width="323" alt="image-zu.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/125929/760d8cf2-e943-9a0e-fd6b-d58299f5461c.png">

# 構築手順
## VM準備
- VM作成
    - OSはCentOS7.3をインストールする
    - NICは4本
        - PG-REXとしては3本を使用
        - 1本はNATで使用（各RPMを取得する用）

## Pacemakerのセットアップ
1. （両系）RPMインストール、セットアップ
    - 手順はLinux-HA Japnaの[ページ](http://linux-ha.osdn.jp/wp/archives/4618)を参考に進める。
        - 注意：PG-REX9.6 構築手順書「3.3. Pacemaker」に必要な設定が書いてあるので、こちらも合わせて参照すること。
    - 手順の詳細はリンクを参照してもらうとして、ざっくりの流れは以下のとおり。
        - 既存yumリポジトリの設定変更し、新しくPacemakerリポジトリを設定する
        - yumでPacemakerをインストール（corosyncもまとめてインストールされる）
        - corosync設定（corosyncとは、HAクラスタとして制御するための機能を提供する製品）
            - bindnetaddrには自分のIPアドレスを2つ設定する。~~(expected_votes: 1にすることで、1つのIPで設定するのも可能)~~
            - 1つだけ設定することも可能。ただし、IC-LANが切れると危ないので、複数本のほうが安全という話。

      ```/etc/corosync/corosync.conf
      totem {
          version: 2
          token: 1000
          rrp_mode: active
          interface {
                ringnumber: 0
                bindnetaddr: 192.168.3.1★
                mcastaddr: 239.255.1.1
                mcastport: 5405
          }
          interface {
                ringnumber: 1
                bindnetaddr: 192.168.2.1★
                mcastaddr: 239.255.1.2
                mcastport: 5405
          }
      }

      logging {
              syslog_facility: daemon
              debug: off
      }

      quorum {
              provider: corosync_votequorum
              expected_votes: 2
      }
      ```
    - あとは以下の設定が必要です。「PG-REX9.6 構築手順書」を参照しながら設定すること。
        - Pacemakerの設定ファイル（/etc/sysconfig/pacemaker）を編集
        - Pacemaker, corosyncのSeviceファイルを編集
        - ログ(rsyslog, logconv)の出力設定
            - とりあえず、NW監視、ディスク監視も全部やる設定にしておく。
        - Pacemaker, corosyncの自動起動を停止
        - pg_logconv, ifcheckd の自動起動を設定
    
1. 動作確認
    - （両系）Pacemakerを起動する。

    ```
    # systemctl start pacemaker
    ```
    - 1系または2系で「crm_mof -fA」を実行して、両ノードがOnlineになればOK！
    
    ```
    #  crm_mon -fA
    2 nodes configured
    0 resources configured

    Online: [ kawa yama ]★

    No active resources


    Node Attributes:
    * Node kawa:
        + ringnumber_0                      : 192.168.3.2 is UP
        + ringnumber_1                      : 192.168.2.2 is UP
    * Node yama:
        + ringnumber_0                      : 192.168.3.1 is UP
        + ringnumber_1                      : 192.168.2.1 is UP

    Migration Summary:
    * Node yama:
    * Node kawa:
    ```

1. （両系）Pacemaker停止

    ```
    # systemctl stop pacemaker
    ```

やることは多いけど、意外と簡単にできた気がする。

## PostgreSQLのセットアップ
「PG-REX9.6 構築手順書」を参照しながら作業を進める。

流れはこんなところ。

1. （両系）RPMインストール
1. （両系）/dbfp とその配下のディレクトリを作成
    - PG-REXでは、PostgreSQLの領域は/dbfp配下をデフォルトとしている
        - PGDATAの領域：/dbfp/pgdata
        - WALの領域：/dbfp/pgxlog
        - アーカイブログの領域：/dbfp/pgarch/arc1
1. （1系）initdb を実行する
    - 2系はpg_basebackupで構築するので、以降は1系のみで操作する。
1. postgresql.confを推奨値に変更する

    ```postgresql.conf
  listen_addresses = '*'
  wal_level = replica
  max_wal_senders = 4
  wal_keep_segments = 32
  hot_standby = on
  max_standby_streaming_delay = -1
  max_standby_archive_delay = -1
  archive_mode = on
  archive_command = '/bin/cp %p /dbfp/pgarch/arc1/%f'
  #synchronous_standby_names = ''
  synchronous_commit = on
  restart_after_crash = off
  wal_sender_timeout = 20s
  wal_receiver_status_interval = 5s
  hot_standby_feedback = on
  ```
1. replication用のユーザ(repuser)作成
1. pg_hba.confを設定する
   本当は必要な口しか開けないほうがよいが、手元環境なのでザル設定にする。

    ```pg_hba.conf
host    all             all             192.168.1.0/24          trust
host    replication     repuser         192.168.2.0/24          trust
```

## PG-REX運用補助ツールのセットアップ
1. （両系）PG-REX運用補助ツールをインストールする
    名前のとおり運用補助ツールとはPG-REXの操作を行うための便利ツール。これがないと手順がより複雑になるので必須。

    ```
  # wget https://ja.osdn.net/projects/pg-rex/downloads/68042/pg-rex96-1.0.2-CentOS7-NoSTONITH-1.tar.gz
  # tar -xvf pg-rex96-1.0.2-CentOS7-NoSTONITH-1.tar.gz
  # cd pg-rex96-1.0.2-CentOS7-NoSTONITH-1
  # rpm -ivh Net_OpenSSH-0.62-1.el7.x86_64.rpm  IO_Tty-1.11-1.el7.x86_64.rpm  pg-rex_operation_tools_script-1.8.1-1.el7.noarch.rpm
  Preparing...                          ################################# [100%]
  Updating / installing...
     1:Net_OpenSSH-0.62-1.el7           ################################# [ 33%]
     2:pg-rex_operation_tools_script-1.8################################# [ 67%]
     3:IO_Tty-1.11-1.el7                ################################# [100%]
  ```
1. （両系）運用補助ツールの設定を行う

    ```/etc/pg-rex_tools.conf
  D-LAN_IPAddress = 192.168.2.1 , 192.168.2.2
  Archive_dir = /dbfp/pgarch/arc1
  STONITH = disable
  VIP_SLAVE = enable
  PGPATH = /usr/pgsql-9.6/bin
  DISKD_ResourceID = clnDiskd1
  ```
1. ssh鍵交換（必須ではない）
  運用補助ツールはD-LAN上でrootでssh接続を行っています。今回はお試しなので、操作を端折るために鍵交換しておきます。
  **注意：利用マニュアル上では、セキュリティを考慮して必要に応じてpasswordを入力することを推奨しています。**

## PG-REXの構築
ココが最後にして最大級にややこしい部分なので、気を引き締めて作業しよう！

1. リソースエージェントの概要
    - 手順ではないけど、簡単に リソースエージェント（以降、RAと呼ぶ）の説明
        - RAとは、Pacemakerが監視を行うために使用するシェルスクリプト。
        - PacemakerはRAから吸い上げた情報を元にクラスタを管理している。
            - 例えば、PingRAというNWを監視するRAがあるが、こいつがOKを返せばNWは正常、NGになれば故障として検知する仕組みになっている。
  - PG-REXは、PostgreSQLを監視するRA、NWを監視するRA、ディスクを監視するRA、VIPのRA等、様々なRAによって成り立っている。

1. RAの設定表（xls）の編集を行う
    おそらくココが一番むずかしい。。。どこの行を修正すべきかわかりにくい。。。

    設定ファイルは「pg-rex96-1.0.2-CentOS7-NoSTONITH-1.tar.gz」に同梱されている「PG-REX9.6_RHEL7_NoSTONITH_pm_crmgen.xls」というファイル。

    ※エクセルが無い場合、googleスプレッドシートを使えば編集できる。
    - 基本的にオレンジの枠を設定していく（見やすくしてくれて助かる）
    - 今回の環境では、監視対象のディスクが1つしかないので、以下の項目は今回は使用しないのでコメントアウト（A列に「#」を追記）した
        - prmDiskd2, clnDiskd2, diskcheck_status の項目
            - 48, 48, 228-240, 248, 249, 264, 275行目をコメントアウト

1. 修正した設定表をcsv形式に変換し、winscp等で 1系 に送る
1. （1系）csvファイルをcrm形式に変換する

    ```
  # # pm_crmgen -o PG-REX9.6_RHEL7_NoSTONITH_pm_crmgen.crm PG-REX9.6_RHEL7_NoSTONITH_pm_crmgen.csv
  # ls -l PG-REX9.6_RHEL7_NoSTONITH_pm_crmgen.crm
  -rwxrwx--- 1 root vboxsf 5216 Aug 19 08:16 PG-REX9.6_RHEL7_NoSTONITH_pm_crmgen.crm
  ```
1. （1系）運用補助ツールを利用してPacemakerとPostgreSQLのマスタを起動する

    ```
  # pg-rex_master_start PG-REX9.6_RHEL7_NoSTONITH_pm_crmgen.crm
  ```
1. 「crm_mon -fA」で1系がマスタ（以下のようなステータス）になったことを確認する。
    - pgsql-data-status                 : LATEST
    - pgsql-status                      : PRI

    ```
  Node Attributes:
  * Node yama:
      + default_ping_set                  : 100       
      + diskcheck_status_internal         : normal    
      + master-pgsql                      : 1000      
      + pgsql-data-status                 : LATEST★    
      + pgsql-master-baseline             : 0000000004000098
      + pgsql-status                      : PRI★       
      + ringnumber_0                      : 192.168.3.1 is UP
      + ringnumber_1                      : 192.168.2.1 is UP
  ```

1. （2系）運用補助ツールを利用してPacemakerとPostgreSQLのスレーブを起動する

    ```
  # pg-rex_slave_start -b
  root@192.168.2.1's password:
  パスワードが入力されました
  1. Pacemaker および Corosync が停止していることを確認
  ...[OK]
  2. 稼働中の Master が存在していることを確認
  ...[OK]
  （・・・中略・・・）
  9. Slave の起動 (アーカイブリカバリ対象 WAL セグメント数: 1)
  ...[OK]
  10. Slave の起動確認
  ...[OK]
  ノード(kawa)が Slave として起動しました
  ```
1. PG-REX構成完成！
     pg-rex_slave_startコマンドが完了していれば、以下のように2系がsync状態になっているはず。

    ```
  * Node kawa:
    + default_ping_set                  : 100       
    + diskcheck_status_internal         : normal    
    + master-pgsql                      : 100       
    + pgsql-data-status                 : STREAMING|SYNC
    + pgsql-status                      : HS:sync   
    + ringnumber_0                      : 192.168.3.2 is UP
    + ringnumber_1                      : 192.168.2.2 is UP
  ```

# FOの動作確認
せっかく組んだので、試しにFOをさせてみます。

一つのコンソールで「crm_mon -fA」を動かしておくことで、変化を見れるのでおすすめ。

1系（現在、マスタとして稼働中）のPostgreSQLを強制停止してい挙動を確認してみます。

```
# su - postgres
$ pg_ctl -m immediate stop
サーバ停止処理の完了を待っています....完了
サーバは停止しました
```

crm_monの結果が以下のようになり、2系がマスタとなり、FOが完了したことを確認できました。

```
* Node kawa:
    + default_ping_set                  : 100       
    + diskcheck_status_internal         : normal    
    + master-pgsql                      : 1000      
    + pgsql-data-status                 : LATEST    
    + pgsql-master-baseline             : 00000000060003E0
    + pgsql-status                      : PRI       
    + ringnumber_0                      : 192.168.3.2 is UP
    + ringnumber_1                      : 192.168.2.2 is UP
```

もちろん、VIPも2系に貼り変わっているので、APはそのままサービスを継続できます。

最後、PacemakerとPostgreSQLを停止したいときは「pg-rex_stop」でOK。

# さいごに
いちから作ってみてわかったのが、やはり一番難しいのは、「RAの設定表（xls）の編集」でした。

pg-rex_master_startコマンドが失敗する場合、十中八九、設定ファイルのどこかが間違っています。
実際、今回作ってみてRAを定義する設定ファイルの修正に一番時間が掛かりました。

一応、Pacemakerのログとかは、/var/log/ha-log に出ていますが、中身を読んで何が起きているのか理解するのは結構たいへんです。

とは言いつつ、やってやれないことはないので、ぜひチャレンジしてHAなPostgreSQLライフを楽しんでください。