Citusのサポート

Patroniを使用すると、`Multi-Node Citus`__クラスターの展開が非常に簡単になります。

TL;DR

従う必要がある簡単なルールがいくつかあります。

  1. Citus _ PostgreSQLのデータベース拡張機能は、すべてのノードで利用できる必要があります。 サポートされている絶対最小のCitusバージョンは10.0ですが、ワーカーの透過的スイッチオーバーと再起動からすべてのメリットを得るには、少なくともCitus 11.2以上を使用することをお勧めします。

  2. クラスター名 scope は、すべてのCitusノードで同じである必要があります。

  3. スーパーユーザーの資格情報はコーディネーターとすべてのワーカーノードで同じである必要があり、 pg_hba.conf はすべてのノード間のスーパーユーザーのアクセスを許可する必要があります。

  4. REST API ワーカーノードからコーディネーターへのアクセスを許可する必要があります。たとえば、資格情報は同じである必要があり、構成されている場合、ワーカーノードからのクライアント証明書はコーディネーターが受け入れる必要があります。

  5. 次のセクションを patroni.yaml に追加します。

citus:
  group: X  # 0 for coordinator and 1, 2, 3, etc for workers
  database: citus  # must be the same on all nodes

その後、Patroniを起動するだけで、残りは処理されます。

  1. Patroniは bootstrap.dcs.synchronous_mode を bootstrap.dcs.synchronous_mode に明示的に設定されていない場合、 bootstrap.dcs.synchronous_mode に設定します。

  2. citus 拡張機能は shared_preload_libraries に自動的に追加されます。

  3. max_prepared_transactions がグローバル max_prepared_transactions で明示的に設定されていない場合、Patroniは自動的に 2*max_connections に設定します。

  4. citus.local_hostname GUC値は、 localhost からPatroniがローカルのPostgreSQLインスタンスに接続するために使用している値に調整されます。 PostgreSQLがリッスンしていない可能性があるため、値は localhost とは異なる必要がある場合があります。

  5. citus.database が自動的に作成され、続いて CREATE EXTENSION citus が作成されます。

  6. 現在のスーパーユーザー credentials は pg_dist_authinfo テーブルに追加されて、クロスノード通信が許可されます。後でスーパーユーザーのユーザー名/パスワード/sslcert/sslkeyを変更する場合は、それらを更新することを忘れないでください。

  7. コーディネータープライマリノードは、ワーカープライマリノードを自動的に検出し、 citus_add_node() ファンクションを使用して pg_dist_node テーブルに追加します。

  8. Patroniは、コーディネーターまたはワーカークラスターでフェールオーバー/スイッチオーバーが発生した場合に、 pg_dist_node を維持します。

patronicl

コーディネータークラスターとワーカークラスターは、物理的に異なるPostgreSQL/Patroniクラスターであり、 PostgreSQLの Citus _データベース拡張機能を使用して論理的にグループ化されているだけです。したがって、ほとんどの場合、それらを単一のエンティティとして管理することはできません。

通常と比較して、 patroni.yaml に citus セクションがある場合の patronicl の動作に2つの大きな違いがあります。

  1. list および topology は、デフォルトで、Citusフォーメーションのすべてのメンバーコーディネーターとワーカーを出力します。新しい列 Group は、それらが属しているCitusグループを示します。

  2. すべての patronictl コマンドに、 --group という名前の新しいオプションが導入されます。一部のコマンドでは、グループのデフォルト値が patroni.yaml から取得される場合があります。たとえば、 patronictl は、 citus セクションで設定された group のメンテナンスモードをデフォルトで有効にしますが、たとえば patronictl または patronictl の場合、グループを明示的に指定する必要があります。

Citusクラスターの 後援者リスト 出力の例

postgres@coord1:~$ patronictl list demo
+ Citus cluster: demo ----------+----------------+---------+----+-------------+-----+------------+-----+
| Group | Member  | Host        | Role           | State   | TL | Receive LSN | Lag | Replay LSN | Lag |
+-------+---------+-------------+----------------+---------+----+-------------+-----+------------+-----+
|     0 | coord1  | 172.27.0.10 | Replica        | running |  1 |   0/41C0368 |   0 |  0/41C0368 |   0 |
|     0 | coord2  | 172.27.0.6  | Quorum Standby | running |  1 |   0/41C0368 |   0 |  0/41C0368 |   0 |
|     0 | coord3  | 172.27.0.4  | Leader         | running |  1 |             |     |            |     |
|     1 | work1-1 | 172.27.0.8  | Quorum Standby | running |  1 |   0/31D3198 |   0 |  0/31D3198 |   0 |
|     1 | work1-2 | 172.27.0.2  | Leader         | running |  1 |             |     |            |     |
|     2 | work2-1 | 172.27.0.5  | Quorum Standby | running |  1 |   0/31CDFC0 |   0 |  0/31CDFC0 |   0 |
|     2 | work2-2 | 172.27.0.7  | Leader         | running |  1 |             |     |            |     |
+-------+---------+-------------+----------------+---------+----+-------------+-----+------------+-----+

--group オプションを追加すると、出力は次のように変更されます。

postgres@coord1:~$ patronictl list demo --group 0
+ Citus cluster: demo (group: 0, 7179854923829112860) -+-------------+-----+------------+-----+
| Member | Host        | Role           | State   | TL | Receive LSN | Lag | Replay LSN | Lag |
+--------+-------------+----------------+---------+----+-------------+-----+------------+-----+
| coord1 | 172.27.0.10 | Replica        | running |  1 |   0/41C0368 |   0 |  0/41C0368 |   0 |
| coord2 | 172.27.0.6  | Quorum Standby | running |  1 |   0/41C0368 |   0 |  0/41C0368 |   0 |
| coord3 | 172.27.0.4  | Leader         | running |  1 |             |     |            |     |
+--------+-------------+----------------+---------+----+-------------+-----+------------+-----+

postgres@coord1:~$ patronictl list demo --group 1
+ Citus cluster: demo (group: 1, 7179854923881963547) -+-------------+-----+------------+-----+
| Member  | Host       | Role           | State   | TL | Receive LSN | Lag | Replay LSN | Lag |
+---------+------------+----------------+---------+----+-------------+-----+------------+-----+
| work1-1 | 172.27.0.8 | Quorum Standby | running |  1 |   0/31D3198 |   0 |  0/31D3198 |   0 |
| work1-2 | 172.27.0.2 | Leader         | running |  1 |             |     |            |     |
+---------+------------+----------------+---------+----+-------------+-----+------------+-----+

Citusワーカーのスイッチオーバー

Citusワーカーノードのスイッチオーバーがオーケストレーションされると、Citusは、アプリケーションに対してスイッチオーバーをほぼトランスペアレントにする機会を提供します。アプリケーションはコーディネーターに接続し、コーディネーターはワーカーノードに接続するため、Citusでは、ワーカーノードでホストされているシャードのコーディネーターでSQLトラフィックを`pause`することが可能です。スイッチオーバーは、トラフィックがコーディネーターに保持されたときに発生し、新しいプライマリワーカーノードが読み取り/書き込みクエリを受け入れる準備が整うとすぐに再開されます。

ワーカークラスターでの パトロニクススイッチオーバー の例

postgres@coord1:~$ patronictl switchover demo
+ Citus cluster: demo ----------+----------------+---------+----+-------------+-----+------------+-----+
| Group | Member  | Host        | Role           | State   | TL | Receive LSN | Lag | Replay LSN | Lag |
+-------+---------+-------------+----------------+---------+----+-------------+-----+------------+-----+
|     0 | coord1  | 172.27.0.10 | Replica        | running |  1 |   0/41C0368 |   0 |  0/41C0368 |   0 |
|     0 | coord2  | 172.27.0.6  | Quorum Standby | running |  1 |   0/41C0368 |   0 |  0/41C0368 |   0 |
|     0 | coord3  | 172.27.0.4  | Leader         | running |  1 |             |     |            |     |
|     1 | work1-1 | 172.27.0.8  | Leader         | running |  1 |             |     |            |     |
|     1 | work1-2 | 172.27.0.2  | Quorum Standby | running |  1 |   0/31D3198 |   0 |  0/31D3198 |   0 |
|     2 | work2-1 | 172.27.0.5  | Quorum Standby | running |  1 |   0/31CDFC0 |   0 |  0/31CDFC0 |   0 |
|     2 | work2-2 | 172.27.0.7  | Leader         | running |  1 |             |     |            |     |
+-------+---------+-------------+----------------+---------+----+-------------+-----+------------+-----+
Citus group: 2
Primary [work2-2]:
Candidate ['work2-1'] []:
When should the switchover take place (e.g. 2024-08-26T08:02 )  [now]:
Current cluster topology
+ Citus cluster: demo (group: 2, 7179854924063375386) -+-------------+-----+------------+-----+
| Member  | Host       | Role           | State   | TL | Receive LSN | Lag | Replay LSN | Lag |
+---------+------------+----------------+---------+----+-------------+-----+------------+-----+
| work2-1 | 172.27.0.5 | Quorum Standby | running |  1 |   0/31CDFC0 |   0 |  0/31CDFC0 |   0 |
| work2-2 | 172.27.0.7 | Leader         | running |  1 |             |     |            |     |
+---------+------------+----------------+---------+----+-------------+-----+------------+-----+
Are you sure you want to switchover cluster demo, demoting current primary work2-2? [y/N]: y
2024-08-26 07:02:40.33003 Successfully switched over to "work2-1"
+ Citus cluster: demo (group: 2, 7179854924063375386) --------+---------+------------+---------+
| Member  | Host       | Role    | State   | TL | Receive LSN |     Lag | Replay LSN |     Lag |
+---------+------------+---------+---------+----+-------------+---------+------------+---------+
| work2-1 | 172.27.0.5 | Leader  | running |  1 |             |         |            |         |
| work2-2 | 172.27.0.7 | Replica | stopped |    |     unknown | unknown |    unknown | unknown |
+---------+------------+---------+---------+----+-------------+---------+------------+---------+

postgres@coord1:~$ patronictl list demo
+ Citus cluster: demo ----------+----------------+---------+----+-------------+-----+------------+-----+
| Group | Member  | Host        | Role           | State   | TL | Receive LSN | Lag | Replay LSN | Lag |
+-------+---------+-------------+----------------+---------+----+-------------+-----+------------+-----+
|     0 | coord1  | 172.27.0.10 | Replica        | running |  1 |   0/41C0368 |   0 |  0/41C0368 |   0 |
|     0 | coord2  | 172.27.0.6  | Quorum Standby | running |  1 |   0/41C0368 |   0 |  0/41C0368 |   0 |
|     0 | coord3  | 172.27.0.4  | Leader         | running |  1 |             |     |            |     |
|     1 | work1-1 | 172.27.0.8  | Leader         | running |  1 |             |     |            |     |
|     1 | work1-2 | 172.27.0.2  | Quorum Standby | running |  1 |   0/31D3198 |   0 |  0/31D3198 |   0 |
|     2 | work2-1 | 172.27.0.5  | Leader         | running |  2 |             |     |            |     |
|     2 | work2-2 | 172.27.0.7  | Quorum Standby | running |  2 |   0/31CDFC0 |   0 |  0/31CDFC0 |   0 |
+-------+---------+-------------+----------------+---------+----+-------------+-----+------------+-----+

そして、これはコーディネーター側でどのように見えるかです。

# The worker primary notifies the coordinator that it is going to execute "pg_ctl stop".
2024-08-26 07:02:38,636 DEBUG: query(BEGIN, ())
2024-08-26 07:02:38,636 DEBUG: query(SELECT pg_catalog.citus_update_node(%s, %s, %s, true, %s), (3, '172.19.0.7-demoted', 5432, 10000))
# From this moment all application traffic on the coordinator to the worker group 2 is paused.

# The old worker primary is assigned as a secondary.
2024-08-26 07:02:40,084 DEBUG: query(SELECT pg_catalog.citus_update_node(%s, %s, %s, true, %s), (7, '172.19.0.7', 5432, 10000))

# The future worker primary notifies the coordinator that it acquired the leader lock in DCS and about to run "pg_ctl promote".
2024-08-26 07:02:40,085 DEBUG: query(SELECT pg_catalog.citus_update_node(%s, %s, %s, true, %s), (3, '172.19.0.5', 5432, 10000))

# The new worker primary just finished promote and notifies coordinator that it is ready to accept read-write traffic.
2024-08-26 07:02:41,485 DEBUG: query(COMMIT, ())
# From this moment the application traffic on the coordinator to the worker group 2 is unblocked.

セカンダリノード

Patroni v4.0.0以降、 noloadbalance のないCitusセカンダリノード noloadbalance は pg_dist_node にも登録されています。ただし、読み取り専用クエリにセカンダリノードを使用するには、アプリケーションは noloadbalance _ GUCを変更する必要があります。

DCSのピーク

Citusクラスターコーディネーターとワーカーは、論理的にグループ化されたPatroniクラスターのフリートとしてDCSに保存されます。

/service/batman/              # scope=batman
/service/batman/0/            # citus.group=0, coordinator
/service/batman/0/initialize
/service/batman/0/leader
/service/batman/0/members/
/service/batman/0/members/m1
/service/batman/0/members/m2
/service/batman/1/            # citus.group=1, worker
/service/batman/1/initialize
/service/batman/1/leader
/service/batman/1/members/
/service/batman/1/members/m3
/service/batman/1/members/m4
...

ほとんどのDCSでは、単一の再帰的読み取り要求でCitusクラスター全体を取得することが可能になるため、このようなアプローチが選択されました。 Citusコーディネーターノードのみがワーカーノードを検出する必要があるため、ツリー全体を読み取ります。ワーカーノードは自分自身のグループのサブツリーのみを読み取り、場合によっては、コーディネーターグループのサブツリーを読み取ることができます。

KubernetesのCitus

Kubernetesは階層構造をサポートしていないため、Patroniが作成するすべてのK8sオブジェクトにcitusグループを含める必要がありました。

batman-0-leader  # the leader config map for the coordinator
batman-0-config  # the config map holding initialize, config, and history "keys"
...
batman-1-leader  # the leader config map for worker group 1
batman-1-config
...

つまり、命名パターンは ${scope}-${citus.group}-${type} です。

すべてのKubernetesオブジェクトは、label selector`__を使用してPatroniによって検出されます。したがって、Patroni&CitusおよびEndpoints/ConfigMapsを使用するすべてのポッドに同様のラベルが必要で、PatroniはKubernetes :ref:`settings <kubernetes_settings> または settings を使用してそれらを使用するように構成する必要があります。

ポッド環境変数を使用したPatroni構成のいくつかの例

  1. コーディネータークラスターの場合

apiVersion: v1
kind: Pod
metadata:
  labels:
    application: patroni
    citus-group: "0"
    citus-type: coordinator
    cluster-name: citusdemo
  name: citusdemo-0-0
  namespace: default
spec:
  containers:
  - env:
    - name: PATRONI_SCOPE
      value: citusdemo
    - name: PATRONI_NAME
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: metadata.name
    - name: PATRONI_KUBERNETES_POD_IP
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: status.podIP
    - name: PATRONI_KUBERNETES_NAMESPACE
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: metadata.namespace
    - name: PATRONI_KUBERNETES_LABELS
      value: '{application: patroni}'
    - name: PATRONI_CITUS_DATABASE
      value: citus
    - name: PATRONI_CITUS_GROUP
      value: "0"
  1. グループ2のワーカークラスターの場合

apiVersion: v1
kind: Pod
metadata:
  labels:
    application: patroni
    citus-group: "2"
    citus-type: worker
    cluster-name: citusdemo
  name: citusdemo-2-0
  namespace: default
spec:
  containers:
  - env:
    - name: PATRONI_SCOPE
      value: citusdemo
    - name: PATRONI_NAME
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: metadata.name
    - name: PATRONI_KUBERNETES_POD_IP
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: status.podIP
    - name: PATRONI_KUBERNETES_NAMESPACE
      valueFrom:
        fieldRef:
          apiVersion: v1
          fieldPath: metadata.namespace
    - name: PATRONI_KUBERNETES_LABELS
      value: '{application: patroni}'
    - name: PATRONI_CITUS_DATABASE
      value: citus
    - name: PATRONI_CITUS_GROUP
      value: "2"

お気づきのとおり、両方の例には citus-group ラベルセットがあります。このラベルにより、Patroniは特定のCitusグループに属するオブジェクトを識別できます。それに加えて、 citus-group labelと同じ値を持つ PATRONI_CITUS_GROUP 環境変数もあります。 Patroniは、新しいKubernetesオブジェクトのConfigMapsまたはEndpointを作成すると、それらに citus-group: ${env.PATRONI_CITUS_GROUP} ラベルを自動的に配置します。

apiVersion: v1
kind: ConfigMap
metadata:
  name: citusdemo-0-leader  # Is generated as ${env.PATRONI_SCOPE}-${env.PATRONI_CITUS_GROUP}-leader
  labels:
    application: patroni    # Is set from the ${env.PATRONI_KUBERNETES_LABELS}
    cluster-name: citusdemo # Is automatically set from the ${env.PATRONI_SCOPE}
    citus-group: '0'        # Is automatically set from the ${env.PATRONI_CITUS_GROUP}

Patroniリポジトリの`kubernetes`__フォルダーに、Citusサポートを備えたKubernetesでのPatroni展開の完全な例があります。

2つの重要なファイルがあります。

  1. Dockerfile.citus

  2. citus_k8s.yaml

CitusアップグレードとPostgreSQLメジャーアップグレード

最初に、documentation`__のCitusバージョンのアップグレードについてお読みください。プロセスには小さな変更が1つあります。アップグレードを実行するときは、 ``systemctl restart` の代わりに patronicl restart を使用してPostgreSQLを再起動する必要があります。

Citusを使用したPostgreSQLのメジャーアップグレードは、少し複雑です。メジャーアップグレードに関するCitusドキュメントと PostgreSQL major upgrade に関するPatroniドキュメントで使用されているテクニックを組み合わせる必要があります。 Citusクラスターは多くのPatroniクラスターコーディネーターとワーカーで構成されており、それらはすべて個別にアップグレードする必要があることに注意してください。