Citusのサポート¶
Patroniを使用すると、「マルチノードCitus」__クラスターの展開が非常に簡単になります。
TL;DR¶
従う必要がある簡単なルールはいくつかだけです。
Citus _PostgreSQLのデータベース拡張機能は、すべてのノードで使用できる必要があります。サポートされる絶対最小Citusバージョンは10.0ですが、透過的なスイッチオーバーとワーカーの再起動のメリットを最大限に活用するには、少なくともCitus11.2を使用することをお勧めします。
クラスター名(
scope)はすべてのCitusノードで同じである必要があります。スーパーユーザーの資格情報はコーディネーターノードとすべてのワーカーノードで同じである必要があり、
pg_hba.confはすべてのノード間のスーパーユーザーアクセスを許可する必要があります。ワーカーノードからコーディネーターへの REST API アクセスを許可する必要があります。たとえば、資格情報は同じである必要があり、構成されている場合は、ワーカーノードからのクライアント証明書がコーディネーターによって受け入れられる必要があります。
次のセクションを
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を起動するだけで残りはすべて処理されます。
citus拡張子はshared_preload_librariesに自動的に追加されます。max_prepared_transactionsがグローバルmax_prepared_transactionsに明示的に設定されていない場合、Patroniは自動的に2*max_connectionsに設定します。citus.local_hostnameGUC値は、localhostからローカルPostgreSQLインスタンスに接続するためにPatroniが使用している値に調整されます。PostgreSQLがこの値をリッスンしていない可能性があるため、この値はlocalhostとは異なる必要がある場合があります。citus.databaseが自動的に作成され、続いてCREATE EXTENSION citusが作成されます。現在のスーパーユーザー credentials が
pg_dist_authinfoテーブルに追加され、クロスノード通信が可能になります。後でスーパーユーザーのユーザー名/パスワード/sslcert/sslkeyを変更する場合は、忘れずに更新してください。コーディネータープライマリノードは、ワーカープライマリノードを自動的に検出し、
citus_add_node()関数を使用してそれらをpg_dist_nodeテーブルに追加します。Patroniは、コーディネーターまたはワーカークラスターでフェイルオーバー/スイッチオーバーが発生した場合に備えて
pg_dist_nodeも維持します。
Patroni¶
コーディネータークラスターとワーカークラスターは物理的に異なるPostgreSQL/Patroniクラスターであり、PostgreSQLの Citus _データベース拡張機能を使用して論理的にグループ化されているだけです。したがって、ほとんどの場合、それらを単一のエンティティとして管理することはできません。
patroni.yaml に citus セクションがある場合、通常と比較して Patroni の動作に2つの大きな違いが生じます。
listとtopologyは、デフォルトでCitusフォーメーションのすべてのメンバー(コーディネーターとワーカー)を出力します。新しい列Groupは、それらがどのCitusグループに属しているかを示します。すべての
patronictlコマンドに、--groupという名前の新しいオプションが導入されています。一部のコマンドでは、グループのデフォルト値がpatroni.yamlから取得される場合があります。たとえば、patronictlは、citusセクションで設定されているgroupのメンテナンスモードをデフォルトで有効にしますが、たとえばpatronictlまたはpatronictlの場合は、グループを明示的に指定する必要があります。
Citusクラスターの Patroniリスト 出力の例:
postgres@coord1:~$ patronictl list demo
+ Citus cluster: demo ----------+--------------+---------+----+-----------+
| Group | Member | Host | Role | State | TL | Lag in MB |
+-------+---------+-------------+--------------+---------+----+-----------+
| 0 | coord1 | 172.27.0.10 | Replica | running | 1 | 0 |
| 0 | coord2 | 172.27.0.6 | Sync Standby | running | 1 | 0 |
| 0 | coord3 | 172.27.0.4 | Leader | running | 1 | |
| 1 | work1-1 | 172.27.0.8 | Sync Standby | running | 1 | 0 |
| 1 | work1-2 | 172.27.0.2 | Leader | running | 1 | |
| 2 | work2-1 | 172.27.0.5 | Sync Standby | running | 1 | 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 | Lag in MB |
+--------+-------------+--------------+---------+----+-----------+
| coord1 | 172.27.0.10 | Replica | running | 1 | 0 |
| coord2 | 172.27.0.6 | Sync Standby | running | 1 | 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 | Lag in MB |
+---------+------------+--------------+---------+----+-----------+
| work1-1 | 172.27.0.8 | Sync Standby | running | 1 | 0 |
| work1-2 | 172.27.0.2 | Leader | running | 1 | |
+---------+------------+--------------+---------+----+-----------+
Citusワーカーの切り替え¶
Citusワーカーノードのスイッチオーバーが調整されると、Citusはアプリケーションに対してスイッチオーバーをほぼ透過的に行う機会を提供します。アプリケーションはコーディネーターに接続し、コーディネーターはワーカーノードに接続するため、Citusでは、ワーカーノードでホストされているシャードのコーディネーター上のSQLトラフィックを「一時停止」することができます。その後、トラフィックがコーディネーター上に保持されている間にスイッチオーバーが発生し、新しいプライマリワーカーノードが読み取り/書き込みクエリを受け入れる準備ができるとすぐに再開されます。
ワーカークラスター上の Patroni切り替え の例:
postgres@coord1:~$ patronictl switchover demo
+ Citus cluster: demo ----------+--------------+---------+----+-----------+
| Group | Member | Host | Role | State | TL | Lag in MB |
+-------+---------+-------------+--------------+---------+----+-----------+
| 0 | coord1 | 172.27.0.10 | Replica | running | 1 | 0 |
| 0 | coord2 | 172.27.0.6 | Sync Standby | running | 1 | 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 | Sync Standby | running | 1 | 0 |
| 2 | work2-1 | 172.27.0.5 | Sync Standby | running | 1 | 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. 2022-12-22T08:02 ) [now]:
Current cluster topology
+ Citus cluster: demo (group: 2, 7179854924063375386) -----------+
| Member | Host | Role | State | TL | Lag in MB |
+---------+------------+--------------+---------+----+-----------+
| work2-1 | 172.27.0.5 | Sync Standby | running | 1 | 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
2022-12-22 07:02:40.33003 Successfully switched over to "work2-1"
+ Citus cluster: demo (group: 2, 7179854924063375386) ------+
| Member | Host | Role | State | TL | Lag in MB |
+---------+------------+---------+---------+----+-----------+
| work2-1 | 172.27.0.5 | Leader | running | 1 | |
| work2-2 | 172.27.0.7 | Replica | stopped | | unknown |
+---------+------------+---------+---------+----+-----------+
postgres@coord1:~$ patronictl list demo
+ Citus cluster: demo ----------+--------------+---------+----+-----------+
| Group | Member | Host | Role | State | TL | Lag in MB |
+-------+---------+-------------+--------------+---------+----+-----------+
| 0 | coord1 | 172.27.0.10 | Replica | running | 1 | 0 |
| 0 | coord2 | 172.27.0.6 | Sync Standby | running | 1 | 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 | Sync Standby | running | 1 | 0 |
| 2 | work2-1 | 172.27.0.5 | Leader | running | 2 | |
| 2 | work2-2 | 172.27.0.7 | Sync Standby | running | 2 | 0 |
+-------+---------+-------------+--------------+---------+----+-----------+
コーディネーター側では次のようになります:
# The worker primary notifies the coordinator that it is going to execute "pg_ctl stop".
2022-12-22 07:02:38,636 DEBUG: query("BEGIN")
2022-12-22 07:02:38,636 DEBUG: query("SELECT pg_catalog.citus_update_node(3, '172.27.0.7-demoted', 5432, true, 10000)")
# From this moment all application traffic on the coordinator to the worker group 2 is paused.
# The future worker primary notifies the coordinator that it acquired the leader lock in DCS and about to run "pg_ctl promote".
2022-12-22 07:02:40,085 DEBUG: query("SELECT pg_catalog.citus_update_node(3, '172.27.0.5', 5432)")
# The new worker primary just finished promote and notifies coordinator that it is ready to accept read-write traffic.
2022-12-22 07:02:41,485 DEBUG: query("COMMIT")
# From this moment the application traffic on the coordinator to the worker group 2 is unblocked.
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オブジェクトは、「ラベルセレクター」__を使用してPatroniによって検出されます。そのため、Patroni&CitusおよびEndpoints/ConfigMapを含むすべてのPodには同様のラベルが必要であり、Kubernetes settings または settings を使用してラベルを使用するようにPatroniを構成する必要があります。
Pods環境変数を使用したPatroni構成の例をいくつか示します。
コーディネータクラスタの場合
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"
グループ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 ラベルと同じ値を持つ PATRONI_CITUS_GROUP 環境変数もあります。Patroniが新しいKubernetesオブジェクトConfigMapsまたはEndpointsを作成すると、それらに 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}
CitusをサポートするKubernetes上でのPatroniデプロイメントの完全な例は、Patroniリポジトリの`kubernetes`__フォルダーにあります。
次の2つの重要なファイルがあります。
Dockerfile.citus
citus_k8s.yaml
CitusのアップグレードとPostgreSQLのメジャーアップグレード¶
まず、「ドキュメント」__のCitusバージョンのアップグレードについてお読みください。プロセスには小さな変更が1つあります。アップグレードを実行する場合、 systemctl restart の代わりに Patroni再起動 を使用してPostgreSQLを再起動する必要があります。
Citusを使用したPostgreSQLのメジャーアップグレードはもう少し複雑です。メジャーアップグレードに関するCitusドキュメントと PostgreSQL major upgrade に関するPatroniドキュメントで使用されているテクニックを組み合わせる必要があります。Citusクラスターは多くのPatroniクラスター(コーディネーターとワーカー)で構成されており、それらはすべて個別にアップグレードする必要があることに注意してください。