PostgreSQL ストリーミングレプリケーション

PostgreSQLBeginner
オンラインで実践に進む

はじめに

この実験 (Lab) では、PostgreSQL のストリーミングレプリケーションを設定する方法を学びます。この強力な機能により、プライマリデータベースのライブで読み取り専用のコピーを、レプリカとして知られるセカンダリサーバーに維持することができます。レプリカはプライマリからのデータ変更を継続的に受信・適用するため、高可用性、読み取りクエリの負荷分散、バックアップに役立ちます。

プライマリサーバーのレプリケーションを許可するように設定することから始め、プロセス全体を順を追って説明します。次に、ベースバックアップを取得してレプリカサーバーを作成します。最後に、レプリカを開始し、2 つのサーバー間のデータフローをテストして、レプリカがプライマリと同期を保つ方法を確認します。

プライマリサーバーのレプリケーション設定

最初のステップとして、プライマリ PostgreSQL サーバーをレプリケーション用に準備します。これには、ネットワーク接続を許可するための設定ファイルの変更、必要な Write-Ahead Log (WAL) レベルの有効化、およびレプリケーション用の特別なユーザーの作成が含まれます。

1. PostgreSQL 設定ファイルの変更

レプリケーションの準備をするために、メインの設定ファイルである postgresql.conf を変更する必要があります。この大きなファイルを nano のようなテキストエディタで手動編集すると、多数のオプションがあるため困難でエラーが発生しやすくなります。より効率的で信頼性の高い方法は、コマンドラインツールを使用して、変更が必要な特定のセッティングを表示および更新することです。これにより、何百行ものスクロールを避け、誤った操作を防ぐことができます。

まず、変更が必要な設定である listen_addresseswal_level、および max_wal_senders の現在の値を確認しましょう。

CONF_FILE="/etc/postgresql/14/main/postgresql.conf"
echo "--- Current Settings ---"
sudo grep -E "^#?\s*(listen_addresses|wal_level|max_wal_senders)" $CONF_FILE

これらの行は、おそらく # でコメントアウトされているでしょう。

次に、これらの設定を自動的に更新しましょう。以下のコマンドは、設定ファイルのバックアップを作成してから、各必要なパラメータを更新します。

CONF_FILE="/etc/postgresql/14/main/postgresql.conf"
## 変更を加える前にバックアップを作成
sudo cp $CONF_FILE ${CONF_FILE}.bak.$(date +%s)

## すべてのIPアドレスからの接続を許可するように listen_addresses を設定
sudo sed -i -E "s/^[#\s]*listen_addresses\s*=.*/listen_addresses = '*'/" "$CONF_FILE"

## レプリケーションログを有効にするために wal_level を 'replica' に設定
sudo sed -i -E "s/^[#\s]*wal_level\s*=.*/wal_level = replica/" "$CONF_FILE"

## 同時レプリケーション接続の最大数を設定
sudo sed -i -E "s/^[#\s]*max_wal_senders\s*=.*/max_wal_senders = 10/" "$CONF_FILE"

最後に、変更が正しく適用されたことを確認しましょう。以下のコマンドは、コメントアウトされた行を除外して、新しい値を表示します。

echo "--- Verified Settings ---"
sudo grep -E "^(listen_addresses|wal_level|max_wal_senders)" $CONF_FILE

出力は、更新されたアクティブな設定を示すはずです。

listen_addresses = '*'
wal_level = replica
max_wal_senders = 10

これらの設定が確認されたことで、サーバーは次のステップの準備が整いました。

2. 専用レプリケーションユーザーの作成

スーパーユーザーではなく、レプリケーション専用のユーザーを使用することはベストプラクティスです。replicator という名前のロールを作成しましょう。

psql コマンドラインクライアントを使用して PostgreSQL に接続します。

sudo -u postgres psql

次に、以下の SQL コマンドを実行して、レプリケーション権限とパスワードを持つユーザーを作成します。

CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'replicapass';

CREATE ROLE という出力が表示されるはずです。これで、psql クライアントを終了します。

\q

3. レプリケーション接続の許可

次に、レプリカサーバーからの replicator ユーザーの接続を許可するようにサーバーを設定する必要があります。これは pg_hba.conf ファイルを編集することで行います。

nano でファイルを開きます。

sudo nano /etc/postgresql/14/main/pg_hba.conf

ファイルの末尾に以下の行を追加します。このルールは、ユーザー replicatorreplication 疑似データベースに任意の IP アドレス (0.0.0.0/0) から接続することを許可することを示しています。この実験では、両方のサーバーが同じマシン上にあるため 127.0.0.1/32 を使用します。

host    replication     replicator      127.0.0.1/32            md5

Ctrl+XYEnter を押して保存して終了します。

4. プライマリサーバーの再起動

これらのすべての設定変更を適用するには、PostgreSQL サービスを再起動する必要があります。

sudo service postgresql restart

これでプライマリサーバーはレプリケーション接続を受け入れる準備ができました。

ベースバックアップからレプリカを作成する

プライマリサーバーの設定が完了したら、次はレプリカを作成します。標準的な方法は、プライマリサーバーの「ベースバックアップ」を取得することです。これにより、プライマリのデータディレクトリの正確なコピーが作成され、これがレプリカの開始点となります。

1. レプリカ用のデータディレクトリ作成

まず、レプリカのデータが保存される新しいディレクトリを作成します。パーミッションの問題を避けるため、ユーザーのホームディレクトリではなく、システムの場所で作成するのがベストプラクティスです。PostgreSQL の標準ディレクトリ内に、postgres ユーザーとして作成します。

sudo -u postgres mkdir -p /var/lib/postgresql/14/replica

2. ベースバックアップの取得

次に、pg_basebackup ユーティリティを使用して、プライマリサーバーからデータをコピーします。このコマンドは、replicator ユーザーとしてプライマリに接続し、データを新しいレプリカディレクトリにストリームします。ディレクトリは postgres ユーザーとして作成したため、解決すべきパーミッションの問題はありません。

以下のコマンドを実行します。replicator ユーザーのパスワード(replicapass)を求められます。

sudo -u postgres pg_basebackup -h localhost -p 5432 -U replicator -D /var/lib/postgresql/14/replica -P -v -R

このコマンドの内訳を見てみましょう。

  • sudo -u postgres: 必要な権限を持つ postgres システムユーザーとしてコマンドを実行します。
  • pg_basebackup: ベースバックアップを取得するためのユーティリティです。
  • -h localhost -p 5432: プライマリサーバーのホストとポートを指定します。
  • -U replicator: 接続に使用するユーザー名です。
  • -D /var/lib/postgresql/14/replica: バックアップのターゲットディレクトリです。
  • -P: 進捗レポートを表示します。
  • -v: 詳細モードを有効にします。
  • -R: これは非常に便利なオプションです。standby.signal ファイルを作成し、ターゲットディレクトリ内の postgresql.auto.conf ファイルに接続設定を追記します。これにより、新しいデータディレクトリがレプリカとして自動的に設定されます。

3. 設定ファイルのコピー

ベースバックアップはメインのデータファイルをコピーしますが、多くの Debian ベースのシステム(この Ubuntu 環境など)では、設定ファイル(pg_hba.conf および pg_ident.conf)は /etc/postgresql/ に個別に保存されており、バックアップには含まれません。これらをレプリカのデータディレクトリに手動でコピーする必要があります。コピー後、サーバープロセスがそれらを読み取れるように、postgres ユーザーが所有していることを確認する必要があります。

sudo cp /etc/postgresql/14/main/pg_hba.conf /var/lib/postgresql/14/replica/
sudo cp /etc/postgresql/14/main/pg_ident.conf /var/lib/postgresql/14/replica/
sudo chown postgres:postgres /var/lib/postgresql/14/replica/pg_hba.conf
sudo chown postgres:postgres /var/lib/postgresql/14/replica/pg_ident.conf

データファイルと設定が配置されたことで、レプリカディレクトリは最終的な設定ステップの準備が整いました。

レプリカサーバーの設定と起動

ベースバックアップにより、レプリカのデータディレクトリが準備されました。しかし、プライマリサーバーとレプリカサーバーを同じマシンで実行しているため、両方が同じネットワークポート(デフォルトは 5432)を使用することはできません。このステップでは、レプリカが別のポートを使用するように設定し、その後起動します。

1. レプリカのポート設定

レプリカのデータディレクトリ内にある postgresql.conf ファイルを編集して、リスニングポートを変更します。このファイルは現在 postgres ユーザーが所有しているため、sudo が必要であることに注意してください。

sudo nano /var/lib/postgresql/14/replica/postgresql.conf

ポートを 5433 に設定するために、ファイルの末尾に以下の行を追加します。

port = 5433

Ctrl+XYEnter を押して保存して終了します。

2. データディレクトリのパーミッション設定

セキュリティのため、PostgreSQL はデータディレクトリが他のユーザーからアクセスできないように要求します。パーミッションを 700 に設定する必要があります。これは、所有者(postgres)のみに読み取り、書き込み、実行権限を与えます。

sudo chmod 0700 /var/lib/postgresql/14/replica

3. レプリカサーバーの起動

これでレプリカサーバーを起動できます。データベースサーバーを制御するための標準的な PostgreSQL ユーティリティである pg_ctl を使用します。

レプリカを起動するには、以下のコマンドを実行します。sudo コマンドが pg_ctl の場所を認識しない可能性があるため、pg_ctl のフルパスを使用する必要があります。また、サーバーの状態を簡単に確認できるように、/tmp にログファイルを指定します。

sudo -u postgres /usr/lib/postgresql/14/bin/pg_ctl -D /var/lib/postgresql/14/replica -l /tmp/replica.log start
  • pg_ctl: サーバー制御ユーティリティです。
  • -D /var/lib/postgresql/14/replica: このサーバーインスタンスのデータディレクトリを指定します。
  • -l /tmp/replica.log: ログファイルを指定します。
  • start: 実行するアクションです。

以下のメッセージが表示されるはずです。

waiting for server to start.... done
server started

4. レプリカのログファイルの確認

レプリカが正しく起動し、プライマリに接続したことを確認するために、ログファイル(postgres ユーザーが所有しているため sudo を使用)を表示します。

sudo cat /tmp/replica.log

データベースシステムが読み取り専用接続を受け入れる準備ができたこと、およびプライマリからの WAL ストリーミングを開始したことを示す行を探してください。以下のような表示が見られるはずです。

...
LOG:  database system is ready to accept read-only connections
LOG:  started streaming WAL from primary at 0/4000000 on timeline 1
...

これにより、レプリカサーバーが稼働しており、プライマリに正常に接続されていることが確認できます。

レプリケーションのテスト

両方のサーバーが起動したので、レプリケーションが期待通りに機能しているかテストする時です。プライマリサーバーにテーブルを作成し、それがレプリカに表示されることを確認します。また、レプリカが読み取り専用であることを確認します。

1. プライマリでのレプリケーションステータスの確認

まず、プライマリサーバー(ポート 5432)に接続し、pg_stat_replication ビューを確認します。このビューは、接続されているレプリカに関する監視情報を提供します。

sudo -u postgres psql -p 5432

以下のクエリを実行します。

SELECT client_addr, state, sync_state FROM pg_stat_replication;

出力には、レプリカが接続されており、その状態が streamingsync_stateasync または sync であることが表示されるはずです。

 client_addr |   state   | sync_state
-------------+-----------+------------
 127.0.0.1   | streaming | async
(1 row)

2. プライマリでのデータ作成

プライマリに接続したまま、新しいテーブルを作成し、いくつかのデータを挿入します。

CREATE TABLE replication_test (id INT, message TEXT);
INSERT INTO replication_test VALUES (1, 'Hello from primary!');

次に、テーブルをクエリしてデータが存在することを確認します。

SELECT * FROM replication_test;

挿入した行が表示されるはずです。プライマリの psql シェルを終了します。

\q

3. レプリカでのデータの検証

新しいターミナルを開くか、既存のターミナルを使用して、ポート 5433 のレプリカサーバーに接続します。postgres ユーザーのパスワード(labex)を入力する必要があります。

psql -h localhost -p 5433 -U postgres -d postgres

次に、レプリカで replication_test テーブルをクエリします。

SELECT * FROM replication_test;

プライマリで作成したデータと全く同じデータが表示されるはずです。これにより、ストリーミングレプリケーションが機能していることが確認できます!

 id |      message
----+---------------------
  1 | Hello from primary!
(1 row)

4. レプリカの読み取り専用性のテスト

レプリカでテーブルにデータを挿入してみてください。

INSERT INTO replication_test VALUES (2, 'Hello from replica?');

レプリカサーバーはデフォルトで読み取り専用モードになっているため、コマンドはエラーで失敗します。

ERROR:  cannot execute INSERT in a read-only transaction

これは予期される動作であり、ストリーミングレプリカの重要な特徴です。レプリカの psql シェルを終了します。

\q

環境のクリーンアップ

最終ステップとして、サーバーをシャットダウンし、実験中に作成されたファイルやディレクトリを削除して、環境を初期状態に戻します。

1. レプリカサーバーの停止

まず、pg_ctl を使用してレプリカサーバーを停止します。実行可能ファイルのフルパスを使用することを忘れないでください。

sudo -u postgres /usr/lib/postgresql/14/bin/pg_ctl -D /var/lib/postgresql/14/replica stop

サーバーが停止したという確認メッセージが表示されます。

waiting for server to shut down.... done
server stopped

2. プライマリサーバーの停止

次に、service コマンドを使用してプライマリサーバーを停止します。

sudo service postgresql stop

3. レプリカのデータとログの削除

サーバーが停止したので、レプリカのデータディレクトリと作成したログファイルを安全に削除できます。これらのファイルは postgres ユーザーが所有しているため、sudo が必要であることに注意してください。

sudo rm -rf /var/lib/postgresql/14/replica /tmp/replica.log

これでクリーンアッププロセスは完了です。PostgreSQL ストリーミングレプリケーション環境のセットアップ、テスト、および解体を正常に完了しました。

まとめ

この実験では、PostgreSQL のストリーミングレプリケーションをゼロから設定することに成功しました。postgresql.conf および pg_hba.conf を変更し、専用のレプリケーションユーザーを作成してプライマリサーバーを準備する方法を学びました。次に、pg_basebackup を使用してレプリカを作成し、別のポートで実行するように設定しました。

セットアップをテストすることで、プライマリに書き込まれたデータがセカンダリサーバーにほぼリアルタイムで自動的にレプリケートされることを確認しました。また、レプリカサーバーは読み取り専用であり、これはその設計の基本的な側面であることを確認しました。これらのスキルは、堅牢でスケーラブルな PostgreSQL デプロイメントを管理するために不可欠です。