PatroniとHAProxyでの高可用性PostgreSQL

直面在数字需求不断变化的环境中维护弹性PostgreSQL数据库的挑战?如果术语“Patroni”与您的技术愿景相契合,那么您即将解锁将PostgreSQL提升为高可用性堡垒的解决方案。

当然,挑战在等待着,但不要害怕 – 您正在开始一段变革性的旅程,构建一个坚如磐石的PostgreSQL集群。设想一个未来,在那里数据库中断只是小插曲,而您的PostgreSQL设置将成为可靠性的典范。

准备好将您的PostgreSQL环境加固成一个不可动摇的堡垒!

先决条件

在为PostgreSQL实现高可用性之前,请确保已具备以下条件:

  • 五个(或更多)Linux服务器 – 本教程使用Debian 12服务器,每个服务器都有一个具有sudo/administrator权限的非root用户,如下所示:
Hostname IP Address Used as
postgres01 192.168.5.20 PostgreSQL Server
postgres02 192.168.5.21 PostgreSQL Server
postgres03 192.168.5.22 PostgreSQL Server
etcd 192.168.5.15 Cluster Data Store
haproxy 192.168.5.16 Load Balancer

安装PostgreSQL服务器和Patroni

满足所有先决条件后,将这一刻视为打下稳固、可靠的数据库环境基础的时刻。目标是通过PostgreSQL 15创建一个高可用性的PostgreSQL部署。但首先,您必须在所有PostgreSQL服务器上安装所需的软件包(PostgreSQL服务器和Patroni)。

Patroniは、データセンターで高可用性のPostgreSQL展開を作成するためのPythonベースのアプリケーションです。Bare-metalからKubernetesまで対応しています。Patroniは公式のPostgreSQLリポジトリで利用可能であり、PostgreSQLサーバー9.5-16をサポートしています。

PostgreSQLサーバーとPatroniをインストールするには、以下の手順を実行してください。

? 注意: 以下の操作をPostgreSQLサーバーで実行してください。この場合、postgres01postgres02、およびpostgres03を使用します。

1. ターミナルを開いて、以下のcurlコマンドを実行します。このコマンドは出力を生成しませんが、PostgreSQLリポジトリのGPGキーを/usr/share/keyrings/pgdg.gpgに追加します。

? このチュートリアルでは、デモンストレーションの互換性を確保するためにrootアカウントを使用してコマンドを実行しています。ただし、sudo特権を持つ非rootアカウントを使用することを強くお勧めします。非rootアカウントを使用する場合は、セキュリティとベストプラクティスのためにコマンドの先頭にsudoを付ける必要があります。

curl -fsSL <https://www.postgresql.org/media/keys/ACCC4CF8.asc> | sudo gpg --dearmor -o /usr/share/keyrings/pgdg.gpg

2. 次に、以下のコマンドを実行します。このコマンドは出力を提供しませんが、/etc/apt/sources.list.d/pgdg.listファイルにPostgreSQLリポジトリをパッケージソースのリストに追加します。

sh -c 'echo "deb [arch=amd64 signed-by=/usr/share/keyrings/pgdg.gpg] <https://apt.postgresql.org/pub/repos/apt> $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

3. 以下のapt updateコマンドを実行して、パッケージインデックスを更新し、新しいパッケージ情報を取得します。

apt update
Adding PostgreSQL repository and updating package index

4. アップデート後、次のコマンドを実行して、以下のパッケージをインストールします:

  • postgresql-15 – PostgreSQLデータベース管理システムのバージョン15。
  • patroni – Pythonとetcdを使用したPostgreSQLの高可用性のオープンソースソリューション。Pythonとetcdを使用したPostgreSQL HAクラスターのテンプレート。
  • python3-etcd – etcdとのやり取りを行うためのPythonクライアントライブラリ。このライブラリを使用すると、Pythonアプリケーションがetcdクラスターと通信して管理できます。
  • python3-psycopg2 – Python 3用のPostgreSQLアダプター。PythonアプリケーションとPostgreSQLデータベースを接続します。
apt install postgresql-15 postgresql-server-dev-15 patroni python3-etcd python3-psycopg2

プロンプトが表示されたら、インストールを続行するにはYを入力してください。

Installing packages including PostgreSQL 15 and Patroni

5. パッケージがインストールされたら、次に各コマンドを実行します。これらのコマンドはターミナルに出力されませんが、以下の操作を実行します:

  • postgresqlpatroniサービスを停止します。Debian/Ubuntuでは、postgresqlpatroniサービスはインストール後に自動的に起動します。
  • PostgreSQLバイナリファイルのシンボリックリンクを/usr/sbinディレクトリに作成します。これにより、patroniはPostgreSQLバイナリファイルを実行してPostgreSQLの作成と管理を行うことができます。
systemctl stop postgresql patroni
ln -s /usr/lib/postgresql/15/bin/* /usr/sbin/

6. 最後に、以下のコマンドを実行してpatronipsqlのバイナリパス、およびpatroniのインストールされた--versionを確認してください。

which patroni
which psql
patroni --version

以下は、patroniのパス(/usr/bin/patroni)とpsqlのパス(/usr/sbin/psql)のバイナリファイルです。インストールされたPatroniのバージョンは3.2.1です。

Verifying binary paths for Patroni and psql

etcdサーバーのセットアップと設定

PostgreSQL ServerとPatroniがインストールされているので、PostgreSQLサーバー間の調整を強化するバックボーンが必要です。キーと値のデータストアであるetcdをセットアップして設定します。

このキーと値のデータストアは、PostgreSQLクラスターの展開に関連するデータを安全に保存し、効率的に管理するためのサイレントアーキテクトです。

? 注意:etcdを別のサーバーにインストールしてください。この例では、etcdはetcdサーバーにインストールされています。

etcdをインストールして設定するには、以下の手順に従ってください:

1. etcdサーバーで、以下のコマンドを実行してリポジトリインデックスをupdateし、最新のパッケージ情報を取得します。

apt update
Updating the Debian repository on the etcd server

2. 次に、サーバーにetcdinstallするために、以下のコマンドを実行してください。

apt install etcd-server
Installing etcd

3. etcdをインストールしたら、お好みのエディターを使用してデフォルトの設定/etc/default/etcdを開き、次の設定を挿入してください。

この設定は単一のetcdクラスターをセットアップしますので、IPアドレス192.168.5.15を内部IPアドレスに変更してください。

ETCD_LISTEN_PEER_URLS="<http://192.168.5.15:2380>"
ETCD_LISTEN_CLIENT_URLS="<http://localhost:2379>,<http://192.168.5.15:2379>"
ETCD_INITIAL_ADVERTISE_PEER_URLS="<http://192.168.5.15:2380>"
ETCD_INITIAL_CLUSTER="default=http://192.168.5.15:2380,"
ETCD_ADVERTISE_CLIENT_URLS="<http://192.168.5.15:2379>"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new" 

変更を保存してエディターを終了してください。

Configuring an etcd single cluster mode

4. 今度は、以下のsystemctlコマンドを実行してetcdを再起動し、変更を適用してください。

このコマンドには出力がありませんが、次の手順で変更を確認します。

systemctl restart etcd

5. etcdが再起動したら、etcdサービスが実行および有効になっていることを確認してください。

systemctl is-enabled etcd
systemctl status etcd

etcdサービスが実行されている場合、出力active (running)が表示されます。有効になっている場合、出力enabledが表示され、これはetcdが起動時に自動的に開始されることを意味します。

Checking the etcd service status

6. 最後に、以下のetcdctlコマンドを実行して、etcdクラスター上で利用可能なサーバーのlistを確認してください。

etcdctl member list

この場合、etcdはローカルIPアドレスhttp://192.168.5.15:2379/で単一ノードクラスターとして実行されています。

Checking cluster members on etcd

Patroniを介したPostgreSQLクラスターのブートストラップ

etcdサーバーがしっかりと設定された今、次の重要なフェーズの扉に立っています。Patroniを使用してブートストラッププロセスを開始することで、PostgreSQLの構成を強固で障害耐性のあるクラスタに昇格させます。

? 既存のPostgreSQLサーバーにPostgreSQLクラスタを展開する場合は、まずデータベースをバックアップすることを確認してください。

Patroniを使用してPostgreSQLクラスタをブートストラップするには、各PostgreSQLサーバーで以下の手順を実行してください:

1. テキストエディタでPatroniのデフォルト設定(/etc/patroni/config.yml)を開き、以下の設定を追加します。

nameオプションの値をPostgreSQLサーバーのホスト名に置き換えてください(例:postgres01)。ただし、まだエディタを閉じないでください。

この設定は、postgresという名前のPostgreSQLクラスタを設定します。

# PostgreSQLの範囲
scope: postgres
# PostgreSQLデータベースの名前空間
namespace: /db/
# PostgreSQLインスタンスの名前
name: postgres01

2. 次に、以下の設定を追加してPatroni REST APIを192.168.5.20:8008で実行するように設定します。

クラスタ内の各PostgreSQLサーバーがAPI経由で接続できるようにする必要があります。したがって、IPアドレス192.168.5.20を各PostgreSQLサーバーの該当するIPアドレスに変更してください。

# Patroni REST APIの設定
restapi:
    # REST APIがリッスンするIPアドレスとポート
    listen: 192.168.5.20:8008

    # クライアントが接続するIPアドレスとポート
    connect_address: 192.168.5.20:8008

3. 次の設定を追加して、etcdとの統合を有効にします。この場合、etcdサーバーはIPアドレス192.168.5.15で実行されています。

# Patroni Etcdの設定
etcd3:
    # Etcdサーバーのホストアドレスとポート
    host: 192.168.5.15:2379

4. これで、initdb経由でPostgreSQLサーバーをbootstrapするための設定を追加します。

この設定は、クライアント認証のデフォルトルールと設定(pg_hba.conf)およびパスワードadminを持つ新しいユーザーadminをセットアップします。

必ず、pg_hbaセクションにPostgreSQLクラスターのIPアドレスを入力し、usersセクションでデフォルトのadminパスワードを変更してください。

# Patroniブートストラップ構成
bootstrap:
    # 分散構成ストア(DCS)の構成パラメータ
    dcs:
        ttl: 30
        loop_wait: 10
        retry_timeout: 10
        maximum_lag_on_failover: 1048576
        postgresql:
            # ブートストラップ時にpg_rewindを使用
            use_pg_rewind: true

    # Initdb構成
    initdb:
        - auth: scram-sha-256
        - encoding: UTF8
        - data-checksums

    # レプリケーションおよび一般的なアクセス用のpg_hba.confエントリ
    pg_hba:
        - host replication replicator 127.0.0.1/32 scram-sha-256
        - host replication replicator 192.168.5.20/0 scram-sha-256
        - host replication replicator 192.168.5.21/0 scram-sha-256
        - host replication replicator 192.168.5.22/0 scram-sha-256
        - host all all 0.0.0.0/0 scram-sha-256

		# デフォルトのユーザーadminをパスワードadminで追加
		users:
        admin:
            password: admin
            options:
                - createrole
                - createdb

5. PostgreSQLの起動方法を構成した後、次の構成を挿入して各サーバーでPostgreSQLが実行される方法を設定します。

「postgres01」サーバーに関して、PostgreSQLはIPアドレス192.168.5.20でデータディレクトリ/var/lib/patroni上で実行されます。

さらに、この構成ではレプリケーション操作用に新しいユーザー「replicator」が作成され、パスワード(secretpassword)でスーパーユーザー/管理者としてpostgresユーザーが作成されます。

IPアドレスとデフォルトのパスワード(secretpassword)を変更してください。

# Patroni PostgreSQL Configuration
postgresql:
    # PostgreSQL サーバのリスニングアドレスとポート
    listen: 192.168.5.20:5432
    # PostgreSQL クライアントの接続アドレス
    connect_address: 192.168.5.20:5432
    # PostgreSQL のデータディレクトリ
    data_dir: /var/lib/patroni
    # pgpass ファイルへのパス
    pgpass: /tmp/pgpass

    # 認証の設定
    authentication:
        # ユーザー資格情報のレプリケーション
        replication:
            username: replicator
            password: rep-pass
        # スーパーユーザーの資格情報
        superuser:
            username: postgres
            password: secretpassword

    # その他の PostgreSQL パラメータ
    parameters:
        # Unix ソケットのディレクトリ
        unix_socket_directories: '.'
        # パスワードの暗号化メソッド
        password_encryption: 'scram-sha-256'

6. この設定を挿入して、PostgreSQL サーバのクラスタ内での動作を決定するためのタグを設定し、変更を保存してファイルを閉じます。

# Patroni タグの設定
tags:
    # ノードが障害時に昇格しないように防止
    nofailover: false
    # ロードバランサがこのノードを考慮しないように防止
    noloadbalance: false
    # クローンによるレプリカの作成を防止
    clonefrom: false
    # 同期レプリケーションの強制を防止
    nosync: false

7. 保存された設定を使用して、以下のコマンドを実行して、Patroniのデータディレクトリの準備をまとめて行い、PostgreSQLの使用に適切に所有権が設定され、セキュリティが確保されるようにします。

これらのコマンドは出力を提供しませんが、高可用性を持つPatroniを使用したPostgreSQLデータベースクラスターのセットアップには、このステップが重要です。

# Patroniデータディレクトリを作成する
mkdir -p /var/lib/patroni

# Patroniデータディレクトリの所有権をPostgreSQLユーザーに設定する
chown -R postgres:postgres /var/lib/patroni

# Patroniデータディレクトリのセキュリティのためのアクセス権を設定する
chmod 700 /var/lib/patroni

8. 次に、以下のsystemctlコマンドを実行して、patroniサービスを起動して確認します。

systemctl start patroni
systemctl status patroni

postgres01サーバーでは、PostgreSQLサーバーが実行され、クラスターが初期化されます。また、postgres01サーバーがクラスターリーダーとして選択されます。

Checking the Patroni service and verifying PostgreSQL cluster initialization

postgres02サーバーでは、Patroniを介してPostgreSQLサーバーが起動し、REST APIを介してPostgreSQLクラスターに参加します。

すべてがうまくいけば、以下のメッセージが表示されます:

Checking the Patroni service on the postgres02 server

postgres03サーバーでは、出力はpostgres02サーバーと似ています。

Checking the Patroni service on the postgres03 server

9. PostgreSQLクラスターが初期化されたら、次のpatronictlコマンドを実行して、Patroniで管理されているPostgreSQLインスタンスのlistを表示します。

patronictl -c /etc/patroni/config.yml list

次の出力で、PostgreSQLクラスター(postgres)が実行されていることが確認できます。

クラスターはpostgres01がクラスターLeader、postgres02、およびpostgres03Replicaでモード/状態がstreamingで実行されていることに注意してください。

Checking the list of servers in the PostgreSQL Cluster

10. 最後に、システムの起動時にpostgresqlサービスの自動起動を無効にするために、次のsystemctlコマンドを実行します。

このコマンドは成功した場合には出力がありませんが、これはPatroniが新しいPostgreSQLサーバーを制御するために重要です。

sudo systemctl disable --now postgresql

HAProxyをロードバランサーとしてインストールおよび構成する

PostgreSQLクラスターを展開した場合、クライアントからアクセス可能にし、問題が発生したときにフェイルオーバーを有効にする方法は何ですか?その解決策は、PostgreSQLクラスターの前にロードバランサーとしてのHAProxyです。

HAProxyは、PostgreSQLクラスターがさまざまなワークロードを処理し、リクエストを知的に分散し、高可用性を維持するのに役立つ要となります。

? 注意:HAProxyは別のサーバーにインストールしてください。この場合、HAProxyサーバーはIPアドレスが192.168.5.16のhaproxyサーバーにインストールされています。

PostgreSQLクラスターのためにHAProxyをロードバランサーとしてインストールおよび構成する手順は次のとおりです:

1. お好みのテキストエディタを使用して、/etc/hostsファイルを開き、PostgreSQLサーバーのIPアドレスとホスト名を挿入し、変更内容を保存してファイルを閉じます。

192.168.5.20    postgres01
192.168.5.21    postgres02
192.168.5.22    postgres03

2. 次に、以下のコマンドを実行してパッケージインデックスを更新します。

apt update
Updating the repository on the HAProxy server

3. 更新が完了したら、以下のコマンドを実行してシステムにhaproxyパッケージをinstallします。

apt install haproxy
Installing HAProxy via APT

4. 今度は、デフォルトのHARPOXY設定を/etc/haproxy/haproxy.cfg.origにバックアップするために、次のコマンドを実行します。

このコマンドは出力を生成しませんが、変更を加える前の予防措置です。

mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.orig

5. 次に、お好みのエディタを使用して新しいファイル/etc/haproxy/haproxy.cfgを作成し、以下の設定を挿入します。各PostgreSQLサーバーのIPアドレスを自分のものに置き換え、ファイルを保存してエディタを閉じます。

このHAProxy設定は、2つのプロキシを使用してPostgreSQLクラスターのロードバランサーとしてHAProxyをセットアップします。

  • stats – このブロックはポート8080で実行され、HAProxyサーバーのパフォーマンスとバックエンドを監視します。
  • postgres – このブロックは、PostgreSQLクラスターのロードバランサーの設定です。
# グローバル設定の設定値
global
    # グローバルな最大接続数
    maxconn 100      
    # ログ設定      
    log 127.0.0.1 local2

# デフォルト設定
defaults
    # グローバルログ設定
    log global
    # モードをTCPに設定
    mode tcp
    # リトライ回数
    retries 2
    # クライアントのタイムアウト
    timeout client 30m
    # 接続のタイムアウト
    timeout connect 4s
    # サーバーのタイムアウト
    timeout server 30m
    # チェックのタイムアウト
    timeout check 5s

# 統計情報の設定
listen stats
    # モードをHTTPに設定
    mode http
    # ポート8080でバインド
    bind *:8080
    # 統計情報を有効にする
    stats enable
    # 統計情報のURI
    stats uri /

# PostgreSQLの設定
listen postgres
    # ポート5432でバインド
    bind *:5432
    # HTTPチェックを有効にする
    option httpchk
    # ステータス200を期待する
    http-check expect status 200
    # サーバーの設定
    default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
    # PostgreSQLサーバーを定義する
    server postgres01 192.168.5.20:5432 maxconn 100 check port 8008
    server postgres02 192.168.5.21:5432 maxconn 100 check port 8008
    server postgres03 192.168.5.22:5432 maxconn 100 check port 8008

6. HAProxyが設定されたら、以下のsystemctlコマンドを実行してhaproxyサービスを再起動し、statusで確認します。

systemctl restart haproxy
systemctl status haproxy
Checking the HAProxy service status

7. 最後に、お好きなウェブブラウザを開き、HAProxyのIPアドレスにポート8080でアクセスします(例:http://192.168.5.16:8080/)。以下の出力では、次のものが表示されます。

以下の出力では、次のものが表示されます。

  • statsプロキシはHAProxyの状態を監視するためのものです。
  • postgresプロキシはPostgreSQLクラスタのロードバランサーです。
    postgres02postgres03サーバーは、両方ともstreamingモードで実行されているため、ダウンとマークされていることに注意してください。
Checking HAProxy performance and information

テスト中のPostgreSQLクラスターのフェイルオーバー

信頼できる負荷分散装置としてHAProxyを設定し、これでPostgreSQLクラスターをテストする時が来ました。この重要なステップでは、高可用性のセットアップの耐久性が明らかになります。潜在的な障害に直面しても、PostgreSQLクラスターが強固で応答力があることを確認する必要があります。

PostgreSQLクラスターのフェイルオーバーをテストするために、クライアントマシンからクラスターに接続し、次の手順でフェイルオーバー操作を検証します:

1. クライアントマシンにログインし、ターミナルを開いて以下のpsqlコマンドを実行してHAProxy負荷分散装置を介してPostgreSQLに接続します。

psql -h 192.168.5.16 -p 5432 -U postgres

プロンプトが表示されたら、PostgreSQLパスワードを入力します。必要なパスワード情報は/etc/patroni/config.ymlファイルにあります。

Connecting to PostgreSQL cluster via HAProxy load balancer

2. 接続したら、次のクエリを実行してどのPostgreSQLサーバーに接続しているかを確認し、現在のPostgreSQLセッションをquitします。

SELECT inet_server_addr() AS hostname;
quit

PostgreSQLのインストールが成功していれば、postgres01サーバーに接続されます。

Checking the IP address of the PostgreSQL server

3. これで、postgres01サーバーに切り替え、次のコマンドを実行してpatroniサービスを停止し、PostgreSQLクラスターのステータスをlistします。

このステップでは、PostgreSQLのフェイルオーバーをテストできます。

systemctl stop patroni
patronictl -c /etc/patroni/config.yml list

postgres01サーバーの状態がstoppedに変わり、新しいクラスターリーダーがpostgres03サーバーに委任されたことが確認できます。

Stopping the Patroni service to test the failover

4. HAProxyの監視統計に戻り、postgres01サーバーがダウンしていることがわかります。一方、postgres03は今はUP状態です。

Verifying the failover works in the HAProxy monitoring stats report

代替として、次のpatronictlコマンドを実行して、PostgreSQLクラスターの状態を確認できます。

patronictl -c /etc/patroni/config.yml list

以下のように、postgres01サーバーはもはやクラスターにありません。

Checking the PostgreSQL Cluster members via patronictl

5. クライアントマシンに戻り、以下のpsqlコマンドを実行して、HAProxy経由でPostgreSQLサーバーに接続します。

psql -h 192.168.5.16 -p 5432 -U postgres
Connecting to the PostgreSQL server via HAProxy

6. 接続したら、現在接続しているPostgreSQLサーバーを確認するために次のクエリを実行してください。

SELECT inet_server_addr() AS hostname;
quit

フェイルオーバーが成功した場合、この場合はpostgres03のように、実行中のサーバーの1つに接続されます。

Checking the PostgreSQL server IP address

結論

この旅に乗り出し、高可用性を確保する複雑さに身を投じながら、強力なPatroniとHAProxyの組み合わせを駆使しました。PostgreSQLとPatroniのセットアップ段階をシームレスに進めながら、etcdサーバーの構成の微妙なニュアンスを巧みに扱いました。

オーケストレーションのスキルが最前線に出て、Patroniで耐障害性のあるPostgreSQLクラスターを構築し、HAProxyを使用した負荷分散の技術を洗練させました。このハイステークスの冒険の集大成は、PostgreSQLクラスターのフェイルオーバー機能の徹底的なテストでした。

堅牢で耐障害性のあるPostgreSQL環境の構築における成果を振り返りながら、専門知識を拡大することを検討してみてください。より動的な環境を実現するために、Patroni with Kubernetesの導入を探求してみるのはいかがでしょうか?また、複数のデータセンターにわたるPostgreSQLの高可用性の設定の詳細に深入りしてみるのも良いかもしれません。

Source:
https://adamtheautomator.com/patroni/