OSS Fan ~OSSでLinuxサーバ構築~

このエントリーをはてなブックマークに追加

PostgreSQL 9.4.8をCentOS 7.2へインストールしてストリーミングレプリケーションのマスタサーバ構築

カテゴリ:OSSセットアップ | ソフトウェア:PostgreSQL | タグ:
最終更新日:2020/12/31 | 公開日:2016/07/25

目次

概要

 PostgreSQLのサーバを2台準備し、ストリーミングレプリケーションを構成します。 2台のうち1台目をマスタサーバとして、通常通りデータの参照、更新を行えるようにします。 2台目をスタンバイサーバとして、マスタサーバでのデータ更新を非同期で取り込むようにします。 なお、スタンバイサーバはホットスタンバイとして構成することで、更新(insert文、updatet文等)はできませんが、参照(select文)のみ行えるようにします。

 運用形態としては、マスタサーバで本番運用し、マスタサーバが障害時にスタンバイサーバをマスタに昇格させます。 ただし、ストリーミングレプリケーションの機能だけでスタンバイか自動でマスタに昇格させることはできません。 別途クラスタウェア等を利用してマスタサーバの障害検知、スタンバイのマスタへの昇格を組み込む必要があります。

 今回の手順ではストリーミングレプリケーションの構成をとるところまでとし、 クラスタウェアとの連携は行わないものとします。

 まずはマスタサーバを構築します。

構成

想定環境

PostgreSQL 9.4.8のストリーミングレプリケーション構成

サーバ構成

OSバージョン

CentOS 7.2.1511 x86_64

パッケージ一覧

  • postgresql94-9.4.8-1PGDG.rhel7.x86_64.rpm
  • postgresql94-libs-9.4.8-1PGDG.rhel7.x86_64.rpm
  • postgresql94-server-9.4.8-1PGDG.rhel7.x86_64.rpm

環境構築

インストール

 PostgreSQLサーバに必要なパッケージを3つインストールします。 CentOS 7.2のインストールメディアに収録されているPostgreSQLパッケージは、バージョン9.2.13と少し古いので、 コミュニティで公開されている、より新しいバージョンを利用します。 2016年7月24日時点での最新バージョンは 9.5.3 ですが、9.5用のJDBCドライバが提供されていなかったので、 9.4の最新マイナーバージョンの 9.4.8 を採用しました。 下記URLよりファイルをダウンロードして /media/installer/ に配置した前提でインストールを開始します。

【関連サイト】
Red Hat系Linux向けPostgreSQL 9.4(x86_64)ダウンロードページ

 以下のコマンドを実行します。

# cd /media/installer/
# ls -l
合計 5228
-rw-r--r-- 1 root root 1087476  7月  7 22:42 postgresql94-9.4.8-1PGDG.rhel7.x86_64.rpm
-rw-r--r-- 1 root root  215152  7月  7 22:43 postgresql94-libs-9.4.8-1PGDG.rhel7.x86_64.rpm
-rw-r--r-- 1 root root 4044904  7月  7 22:44 postgresql94-server-9.4.8-1PGDG.rhel7.x86_64.rpm
# rpm -ihv ./postgresql94-*
警告: ./postgresql94-9.4.8-1PGDG.rhel7.x86_64.rpm: ヘッダー V4 DSA/SHA1 Signature、鍵 ID 442df0f8: NOKEY
準備しています...              ################################# [100%]
更新中 / インストール中...
   1:postgresql94-libs-9.4.8-1PGDG.rhe################################# [ 33%]
   2:postgresql94-9.4.8-1PGDG.rhel7   ################################# [ 67%]
   3:postgresql94-server-9.4.8-1PGDG.r################################# [100%]

設定

postgresユーザのパスワード設定

 PostgreSQLのパッケージをインストールすると、自動で postgres ユーザ(Linuxのユーザ)が作成されます。 作成直後はパスワードが設定されていないため、設定します。

# passwd postgres
ユーザー postgres のパスワードを変更。
新しいパスワード: ←パスワードを入力(表示されません)
新しいパスワードを再入力してください: ←上と同じパスワードを入力(表示されません)
passwd: すべての認証トークンが正しく更新できました。

postgresユーザの環境変数設定

 環境変数としてデータベースクラスタとPostgreSQLのコマンドへのパスを設定します。

# grep postgres /etc/passwd
postgres:x:26:26:PostgreSQL Server:/var/lib/pgsql:/bin/bash
# cd /var/lib/pgsql/
# vi .bash_profile
ファイル名:/var/lib/pgsql/.bash_profile
PGDATA=/var/lib/pgsql/9.4/data
export PGDATA
   ↓変更
PGDATA=/data/pgdata1
export PGDATA

※ファイルの末尾に追加※
export PATH=$PATH:/usr/pgsql-9.4/bin

データベースクラスタ用ディレクトリ($PGDATA)作成

 インストールしたRPMパッケージで初期設定されているデータベースクラスタは /var/lib/pgsql/9.4/data/ となっています。 このままでも良いのですが、ディレクトリ階層が深くて分かりづらいため /data/pgdata1/ に変更します。 ディレクトリを作成して必要なパーミッションを設定します。 データベースクラスタ用のディレクトリは管理者ユーザのpostgresユーザのみが参照、更新できるようにします。 また、同様にアーカイブログを格納するディレクトリとして /bkup/pgdata1/pg_arch/ を作成します。

# cd /
# mkdir -m 777 data
# ls -ld data
drwxrwxrwx 2 root root 6  7月 20 00:34 data
# mkdir -m 777 bkup
# ls -ld bkup
drwxrwxrwx 3 root root 6  7月 21 23:15 bkup
# su - postgres
-bash-4.2$ cd /data/
-bash-4.2$ mkdir -m 700 pgdata1
-bash-4.2$ ls -ld pgdata1
drwx------ 2 postgres postgres 6  7月 20 00:36 pgdata1
-bash-4.2$ cd /bkup/
-bash-4.2$ mkdir -m 700 pgdata1
-bash-4.2$ ls -ld pgdata1
drwx------ 19 postgres postgres 4096  7月 20 00:37 pgdata1
-bash-4.2$ cd pgdata1/
-bash-4.2$ mkdir -m 700 pg_arch
-bash-4.2$ ls -ld pg_arch
drwx------ 2 postgres postgres 6  7月 21 23:16 pg_arch

データベースクラスタ作成

 前の手順で作成したデータベースクラスタ用ディレクトリ内にデータベースクラスタを作成します。 initdbコマンドを使用しますが、必ず管理者ユーザであるpostgresユーザで実行してください。 エンコーディングは UTF8、ロケールは設定しません。 PostgreSQLでロケールを選択した場合、検索性能に問題が出る(性能が低下する?)らしく、 ロケールを選択しないことが推奨とされています。(9.4でもそうなのかな?)

-bash-4.2$ initdb --encoding=UTF8 --no-locale --pgdata=/data/pgdata1 --auth=ident
データベースシステム内のファイルの所有者は"postgres"ユーザでした。
このユーザがサーバプロセスを所有しなければなりません。

データベースクラスタはロケール"C"で初期化されます。
デフォルトのテキスト検索設定はenglishに設定されました。

データベージのチェックサムは無効です。

ディレクトリ/data/pgdata1の権限を設定しています ... ok
サブディレクトリを作成しています ... ok
デフォルトのmax_connectionsを選択しています ... 100
デフォルトの shared_buffers を選択しています ... 128MB
selecting dynamic shared memory implementation ... posix
設定ファイルを作成しています ... ok
/data/pgdata1/base/1にtemplate1データベースを作成しています ... ok
pg_authidを初期化しています ... ok
依存関係を初期化しています ... ok
システムビューを作成しています ... ok
システムオブジェクトの定義をロードしています ... ok
照合順序を作成しています ... ok
変換を作成しています ... ok
ディレクトリを作成しています ... ok
組み込みオブジェクトに権限を設定しています ... ok
情報スキーマを作成しています ... ok
PL/pgSQL サーバサイド言語をロードしています ... ok
template1データベースをバキュームしています ... ok
template1からtemplate0へコピーしています ... ok
template1からpostgresへコピーしています ... ok
データをディスクに同期しています...ok

成功しました。以下を使用してデータベースサーバを起動することができます。

    postmaster -D /data/pgdata1
または
    pg_ctl -D /data/pgdata1 -l logfile start

-bash-4.2$

 initdb コマンドの --auth=ident オプションは pg_hba.conf の認証設定初期値を決めるものです。 後続の設定手順で書き換えてしまうため指定してもあまり意味がありません。 ただ、省略した場合は認証方式が trust (認証なし)となっているため、 pg_hba.conf の設定を忘れた場合の保険の意味で指定しています。

PostgreSQLマスタサーバの設定

 ここではPostgreSQLインスタンスがリッスンするIPアドレスとWAL、レプリケーション、 ログ出力に関する設定を行います。

 初期設定では localhost(127.0.0.1)のみでリッスンする設定になっています。 そのため、他のサーバからTCP/IP接続することができません。 ローカルからもリモートからもTCP/IP接続できるように、 このサーバが持つ全てのIPアドレスでリッスンする設定とします。

 ログの出力先は /data/pgdata1/pg_log/ ディレクトリ内とします。 ログファイル名は postgresql-20160721.log のように ログファイルが作成された年月日を付与します。 ログファイルは7日間経過後に自動でローテーションされ、 新しいログファイルに出力が切り替わるようにします。 一定のファイルサイズに達した際にローテーションされる機能は使用しません。 あくまで日数経過後にローテーションします。 ログファイルには標準では発生したイベントの内容のみが記録されます。 ただ、これでは後から見たときに分かりづらいので、 イベントが発生した年月日時分秒とプロセスIDが出力されるように設定します。 ログメッセージの形式は以下のようになります。

【ログメッセージの出力例】
2016-07-21 23:22:27 JST [2414] LOG: shutting down 2016-07-21 23:22:28 JST [2414] LOG: database system is shut down

 データベースクラスタ内の postgresql.conf ファイルを設定します。

-bash-4.2$ cd /data/pgdata1/
-bash-4.2$ vi postgresql.conf
ファイル名:/data/pgdata1/postgresql.conf
#------------------------------------------------------------------------------
# CONNECTIONS AND AUTHENTICATION
#------------------------------------------------------------------------------
#listen_addresses = 'localhost'         # what IP address(es) to listen on;
   ↓変更
listen_addresses = '*'                  # what IP address(es) to listen on;

#------------------------------------------------------------------------------
# WRITE AHEAD LOG
#------------------------------------------------------------------------------
#wal_level = minimal                    # minimal, archive, hot_standby, or logical
   ↓変更
wal_level = hot_standby                 # minimal, archive, hot_standby, or logical

#archive_mode = off             # allows archiving to be done
   ↓変更
archive_mode = on               # allows archiving to be done

#archive_command = ''           # command to use to archive a logfile segment
   ↓変更
archive_command = 'cp %p /bkup/pgdata1/pg_arch/%f'              # command to use to archive a logfile segment

#------------------------------------------------------------------------------
# REPLICATION
#------------------------------------------------------------------------------
#max_wal_senders = 0            # max number of walsender processes
   ↓変更
max_wal_senders = 2             # max number of walsender processes

#------------------------------------------------------------------------------
# ERROR REPORTING AND LOGGING
#------------------------------------------------------------------------------
※変更なし※
log_destination = 'stderr'              # Valid values are combinations of
logging_collector = on                  # Enable capturing of stderr and csvlog
log_directory = 'pg_log'                # directory where log files are written,

log_filename = 'postgresql-%a.log'      # log file name pattern,
   ↓変更
log_filename = 'postgresql-%Y%m%d.log'  # log file name pattern,

log_truncate_on_rotation = on           # If on, an existing log file with the
   ↓変更
log_truncate_on_rotation = off          # If on, an existing log file with the

log_rotation_age = 1d                   # Automatic rotation of logfiles will
   ↓変更
log_rotation_age = 7d                   # Automatic rotation of logfiles will

※変更なし※
log_rotation_size = 0                   # Automatic rotation of logfiles will

log_line_prefix = '< %m >'                      # special values:
   ↓変更
log_line_prefix = '%t [%p] '                    # special values:

※変更なし※
log_timezone = 'Japan'

スーパーユーザのパスワード設定とレプリケーション用ユーザ作成

 データベースクラスタ作成時点では、スーパーユーザ(データベースユーザ) postgres のパスワードが 設定されていません。一度PostgreSQLのインスタンスを起動してパスワードを設定します。 パスワードを設定する前にクライアント認証を設定すると、ログインできなくなってしまう可能性がありますので要注意です。 パスワード設定後は再度インスタンスを停止します。 以下では postgres ユーザのパスワードを password に設定します。

 また、レプリケーション時にスタンバイサーバから接続するユーザを新規で作成します。 ユーザ名を pgrep01 とし、レプリケーション属性を与えます。パスワードは password とします。

-bash-4.2$ pg_ctl start -w
サーバの起動完了を待っています....2016-07-21 23:18:22 JST [2411] LOG:  redirecting log output to logging collector process
2016-07-21 23:18:22 JST [2411] HINT:  Future log output will appear in directory "pg_log".
完了
サーバ起動完了
-bash-4.2$ psql -c "alter role postgres with password 'password';"
ALTER ROLE
-bash-4.2$ psql -c "create role pgrepl01 login replication password 'password';"
CREATE ROLE
-bash-4.2$ psql -c "\du";
                                         ロール一覧
 ロール名 |                                 属性                                 | メンバー
----------+----------------------------------------------------------------------+----------
 pgrepl01 | レプリケーション                                                     | {}
 postgres | スーパーユーザ, ロールを作成できる, DBを作成できる, レプリケーション | {}

-bash-4.2$ pg_ctl stop -m fast
サーバ停止処理の完了を待っています....完了
サーバは停止しました

クライアント認証の設定

 クライアントからPostgreSQLに接続する際の認証設定を行います。 デフォルトで設定されている内容は全てコメントアウトし、必要な設定をファイルの末尾に追加します。 設定する認証ルールは以下の通りとします。

  • postgresユーザ(管理者ユーザ)がUNIXドメインソケット接続(ローカル接続)を行った場合は、 パスワードの入力を求めない。
  • postgresユーザ(管理者ユーザ)以外のユーザ(一般ユーザ)がUNIXドメインソケット接続(ローカル接続)を行った場合は、 PostgreSQLユーザ名とパスワードで認証する。パスワードはMD5で暗号化して送信する。
  • ユーザに関係なくTCP/IP接続(リモート接続)を行った場合は、PostgreSQLユーザ名とパスワードで認証する。 PostgreSQLが稼働するサーバと同一のネットワークセグメント(192.168.0.0/24)からの接続のみ許可する。 パスワードはMD5で暗号化して送信する。
  • 192.168.0.77/32(ストリーミングレプリケーションのスタンバイサーバ)からpgrepl01ユーザ(レプリケーション用ユーザ)で TCP/IP接続(リモート接続)を行った場合は、パスワードなしで接続することを許可する。
-bash-4.2$ cd /data/pgdata1/
-bash-4.2$ vi pg_hba.conf
ファイル名:/data/pgdata1/pg_hba.conf
# "local" is for Unix domain socket connections only
local   all             all                                     peer
   ↓変更
# "local" is for Unix domain socket connections only
#local   all             all                                     peer ※コメントアウト

# IPv4 local connections:
host    all             all             127.0.0.1/32            ident
   ↓変更
# IPv4 local connections:
#host    all             all             127.0.0.1/32            ident ※コメントアウト

# IPv6 local connections:
host    all             all             ::1/128                 ident
   ↓変更
# IPv6 local connections:
#host    all             all             ::1/128                 ident ※コメントアウト

※ファイルの末尾に追加※
local   all             postgres                                peer
local   all             all                                     md5
host    replication     pgrepl01        192.168.0.77/32         trust
host    all             all             192.168.0.0/24          md5

 以上で設定は終了です。

インスタンス起動

 PostgreSQLのインスタンスを起動します。 起動には pg_ctl コマンドを使用します。

-bash-4.2$ pg_ctl start -w
サーバの起動完了を待っています....2016-07-21 23:29:06 JST [2476] LOG:  redirecting log output to logging collector process
2016-07-21 23:29:06 JST [2476] HINT:  Future log output will appear in directory "pg_log".
完了
サーバ起動完了

動作テスト

プロセス起動確認

 PostgreSQLのプロセスが起動していることを確認します。 今回の設定ではマスタサーバプロセス1つとワーカプロセス7つが起動します。

-bash-4.2$ ps -ef | grep postgres
(前略)
                                                ↓マスタサーバプロセス(1つ)
postgres  2476     1  0 23:29 pts/0    00:00:00 /usr/pgsql-9.4/bin/postgres
                                                ↓ワーカプロセス(7つ)
postgres  2477  2476  0 23:29 ?        00:00:00 postgres: logger process
postgres  2479  2476  0 23:29 ?        00:00:00 postgres: checkpointer process
postgres  2480  2476  0 23:29 ?        00:00:00 postgres: writer process
postgres  2481  2476  0 23:29 ?        00:00:00 postgres: wal writer process
postgres  2482  2476  0 23:29 ?        00:00:00 postgres: autovacuum launcher process
postgres  2483  2476  0 23:29 ?        00:00:00 postgres: archiver process
postgres  2484  2476  0 23:29 ?        00:00:00 postgres: stats collector process
(後略)

ログ出力確認

 設定したログファイルに起動ログが出力されていることを確認します。

-bash-4.2$ cd /data/pgdata1/pg_log/
-bash-4.2$ ls -l
合計 4
-rw------- 1 postgres postgres 998  7月 21 23:29 postgresql-20160721.log
-bash-4.2$ cat postgresql-20160721.log
2016-07-21 23:18:22 JST [2413] LOG:  database system was shut down at 2016-07-21 22:24:07 JST
2016-07-21 23:18:22 JST [2413] LOG:  MultiXact member wraparound protections are now enabled
2016-07-21 23:18:22 JST [2417] LOG:  autovacuum launcher started
2016-07-21 23:18:22 JST [2411] LOG:  database system is ready to accept connections
2016-07-21 23:22:27 JST [2411] LOG:  received fast shutdown request
2016-07-21 23:22:27 JST [2411] LOG:  aborting any active transactions
2016-07-21 23:22:27 JST [2417] LOG:  autovacuum launcher shutting down
2016-07-21 23:22:27 JST [2414] LOG:  shutting down
2016-07-21 23:22:28 JST [2414] LOG:  database system is shut down
2016-07-21 23:29:06 JST [2478] LOG:  database system was shut down at 2016-07-21 23:22:28 JST
2016-07-21 23:29:06 JST [2478] LOG:  MultiXact member wraparound protections are now enabled
2016-07-21 23:29:06 JST [2482] LOG:  autovacuum launcher started
2016-07-21 23:29:06 JST [2476] LOG:  database system is ready to accept connections

SQL実行確認

 psqlコマンドで、SQLを実行できることを確認します。

-bash-4.2$ psql
psql (9.4.8)
"help" でヘルプを表示します.

postgres=# select now();
              now
-------------------------------
 2016-07-21 23:30:08.071626+09
(1 行)

postgres=# select oid, datname from pg_database;
  oid  |  datname
-------+-----------
     1 | template1
 13051 | template0
 13056 | postgres
(3 行)

postgres=# \q
-bash-4.2$

インスタンス再起動

 PostgreSQLインスタンスを再起動します。 pg_ctl コマンド1つで再起動できますが、ここでは確認のため停止・起動に分けて実行します。

-bash-4.2$ pg_ctl stop -m fast
サーバ停止処理の完了を待っています....完了
サーバは停止しました
-bash-4.2$ ps -ef | grep postgres
root      2345  2073  0 23:15 pts/0    00:00:00 su - postgres
postgres  2346  2345  0 23:15 pts/0    00:00:00 -bash
postgres  2505  2346  0 23:32 pts/0    00:00:00 ps -ef
postgres  2506  2346  0 23:32 pts/0    00:00:00 grep --color=auto postgres
↑マスタサーバプロセスとワーカプロセスが停止した
-bash-4.2$ pg_ctl start -w
サーバの起動完了を待っています....2016-07-21 23:33:00 JST [2509] LOG:  redirecting log output to logging collector process
2016-07-21 23:33:00 JST [2509] HINT:  Future log output will appear in directory "pg_log".
完了
サーバ起動完了

WALとWALアーカイブの出力確認

 WAL(Write Ahead Logging)とWALアーカイブを出力するよう設定したので、 ファイルが生成されていることを確認します。

-bash-4.2$ ls -l /data/pgdata1/pg_xlog/ ←WALディレクトリ
合計 49152
-rw------- 1 postgres postgres 16777216  7月 21 23:31 000000010000000000000002
-rw------- 1 postgres postgres 16777216  7月 21 23:33 000000010000000000000003
-rw------- 1 postgres postgres 16777216  7月 21 23:22 000000010000000000000004
drwx------ 2 postgres postgres       42  7月 21 23:31 archive_status
-bash-4.2$ ls -l /bkup/pgdata1/pg_arch/ ←WALアーカイブディレクトリ
合計 32768
-rw------- 1 postgres postgres 16777216  7月 21 23:22 000000010000000000000001
-rw------- 1 postgres postgres 16777216  7月 21 23:31 000000010000000000000002