ククログ

株式会社クリアコード > ククログ > 2026 > Kubernetes Operatorを使うとPostgreSQL + PGroongaが楽に運用できる!かも

Kubernetes Operatorを使うとPostgreSQL + PGroongaが楽に運用できる!かも

最近、KubernetesにてPostgreSQL Operatorで楽に冗長構成が作れることを知った阿部です。

クラウドサービスのマネージドなPostgreSQLではPGroongaが使えないところが多く、自分で運用しないといけないケースがあります。 そんなときに、KubernetesのPostgreSQL Operatorで作った冗長構成でPGroongaを使えれば、運用が楽になるかもしれません。

ということで、その楽に作れる冗長構成にPGroongaも乗せられるか試してみます。

はじめに

Kubernetes関連の準備は整っているとします。今回はkindで検証するので、具体的にはdocker、kind、kubectlコマンドが使える状態になっているとします。

まずはPostgreSQLの冗長構成がどのようなものか確認し、PGroongaも乗せるとどうなるか確認していきます。 今回の確認はKubernetes上でPGroongaの冗長構成が作れるかを確かめるための簡易的なものです。 テーブル構成はシンプル、データ量は数行、障害はkubectl deleteでPodを停止させただけ、など実際のサービスの環境や発生しそうな障害を再現しているとは言えない検証であることを踏まえてご覧ください。

次の流れで説明します。

  1. KubernetesでPostgreSQLの冗長構成を作る
  2. KubernetesでPGroongaを1台構成で動かす
  3. KubernetesでPostgreSQL + PGroongaの冗長構成を作る

0. 準備

検証用のKubernetesクラスタを作っておきます。

kind create cluster

CloudNativePGをインストールします。 (バージョンは適宜変えてください。)

kubectl apply --server-side -f \
  https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.30/releases/cnpg-1.30.1.yaml

CloudNativePGは、Kubernetes上でPostgreSQLを自動で運用してくれるOperatorです。 Operatorは運用担当者に代わって自動でいろいろやってくれるKubernetesの拡張です。 簡単な設定でprimaryとreplicaを作ってくれて、何かトラブルがあったらフェイルオーバーもしてくれます。

参考: https://kubernetes.io/ja/docs/concepts/extend-kubernetes/operator/

1. KubernetesでPostgreSQLの冗長構成を作る

cat <<YAML > ha.yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: postgres
spec:
  instances: 3
  storage:
    size: 1Gi
YAML

kubectl apply --filename ha.yaml

↑のコマンドを実行する前に、別のターミナルで↓のコマンドを実行しておくと起動の様子が確認できます。 今回はPodの役割(primary or replica)も確認したいのでcnpg.io/instanceRoleも一緒に表示しつつ状況を確認します。

$ kubectl get pods --label-columns cnpg.io/instanceRole --watch
NAME                      READY   STATUS    RESTARTS   AGE   INSTANCEROLE
postgres-1-initdb-8fghk   0/1     Pending   0          0s
postgres-1-initdb-8fghk   0/1     Pending   0          0s
postgres-1-initdb-8fghk   0/1     Pending   0          4s
postgres-1-initdb-8fghk   0/1     Init:0/1   0          4s
postgres-1-initdb-8fghk   0/1     Init:0/1   0          5s
postgres-1-initdb-8fghk   0/1     Init:0/1   0          5s
postgres-1-initdb-8fghk   0/1     PodInitializing   0          6s
postgres-1-initdb-8fghk   1/1     Running           0          27s
postgres-1-initdb-8fghk   0/1     Completed         0          29s
postgres-1-initdb-8fghk   0/1     Completed         0          30s
postgres-1-initdb-8fghk   0/1     Completed         0          30s
postgres-1                0/1     Pending           0          0s
postgres-1                0/1     Pending           0          0s
postgres-1                0/1     Init:0/1          0          0s
postgres-1                0/1     Init:0/1          0          1s
postgres-1                0/1     Init:0/1          0          1s
postgres-1                0/1     PodInitializing   0          2s
postgres-1                0/1     Running           0          2s
postgres-1                0/1     Running           0          4s    primary
postgres-1                0/1     Running           0          11s   primary
postgres-1                1/1     Running           0          11s   primary
postgres-2-join-md67l     0/1     Pending           0          0s
postgres-2-join-md67l     0/1     Pending           0          0s
postgres-2-join-md67l     0/1     Pending           0          3s
postgres-2-join-md67l     0/1     Init:0/1          0          3s
postgres-2-join-md67l     0/1     Init:0/1          0          3s
postgres-2-join-md67l     0/1     Init:0/1          0          4s
postgres-2-join-md67l     0/1     PodInitializing   0          4s
postgres-2-join-md67l     1/1     Running           0          4s
postgres-2-join-md67l     0/1     Completed         0          7s
postgres-2-join-md67l     0/1     Completed         0          8s
postgres-2-join-md67l     0/1     Completed         0          9s
postgres-2                0/1     Pending           0          0s
postgres-2                0/1     Pending           0          0s
postgres-2                0/1     Init:0/1          0          0s
postgres-2                0/1     Init:0/1          0          0s
postgres-2                0/1     Init:0/1          0          1s
postgres-2                0/1     PodInitializing   0          1s
postgres-2                0/1     Running           0          1s
postgres-2                0/1     Running           0          3s    replica
postgres-2                0/1     Running           0          10s   replica
postgres-2                1/1     Running           0          11s   replica
postgres-3-join-gkclv     0/1     Pending           0          0s
postgres-3-join-gkclv     0/1     Pending           0          0s
postgres-3-join-gkclv     0/1     Pending           0          3s
postgres-3-join-gkclv     0/1     Init:0/1          0          3s
postgres-3-join-gkclv     0/1     Init:0/1          0          4s
postgres-3-join-gkclv     0/1     Init:0/1          0          4s
postgres-3-join-gkclv     0/1     PodInitializing   0          4s
postgres-3-join-gkclv     1/1     Running           0          4s
postgres-3-join-gkclv     0/1     Completed         0          5s
postgres-3-join-gkclv     0/1     Completed         0          6s
postgres-3-join-gkclv     0/1     Completed         0          6s
postgres-3                0/1     Pending           0          0s
postgres-3                0/1     Pending           0          0s
postgres-3                0/1     Init:0/1          0          0s
postgres-3                0/1     Init:0/1          0          1s
postgres-3                0/1     Init:0/1          0          1s
postgres-3                0/1     PodInitializing   0          1s
postgres-3                0/1     Running           0          1s
postgres-3                0/1     Running           0          3s    replica
postgres-3                0/1     Running           0          11s   replica
postgres-3                1/1     Running           0          11s   replica
postgres-1-initdb-8fghk   0/1     Completed         0          78s
postgres-2-join-md67l     0/1     Completed         0          37s
postgres-1-initdb-8fghk   0/1     Completed         0          78s
postgres-3-join-gkclv     0/1     Completed         0          17s
postgres-2-join-md67l     0/1     Completed         0          37s
postgres-3-join-gkclv     0/1     Completed         0          17s

起動したら、次の3点を確認していきます。

  • primaryに書き込み + レプリケーションされていることを確認
  • primaryを停止、その後replicaがprimaryに昇格するのを確認
  • 新primaryに書き込み + レプリケーションされていることを確認
    • 旧primaryを含めレプリケーションされていることを確認

primaryに書き込み + レプリケーションされていることを確認

CloudNativePGはアプリ用にappというデータベースを作ってくれるのでそれを使います。

primaryであるpostgres-1にテーブルを作ってデータをinsertします。

$ kubectl exec -it postgres-1 --container=postgres -- psql -d app --command "
CREATE TABLE test (id serial, message text);
INSERT INTO test (message) VALUES ('MESSAGE 1');
SELECT * FROM test;
"
CREATE TABLE
INSERT 0 1
 id |  message
----+-----------
  1 | MESSAGE 1
(1 row)

replicaであるpostgres-2とpostgres-3にも届いているか確認します。

$ kubectl exec -it postgres-2 --container=postgres -- psql -d app --command "SELECT * FROM test;"
 id |  message
----+-----------
  1 | MESSAGE 1
(1 row)

$ kubectl exec -it postgres-3 --container=postgres -- psql -d app --command "SELECT * FROM test;"
 id |  message
----+-----------
  1 | MESSAGE 1
(1 row)

primaryがpostgres-1、replicaがpostgres-2とpostgres-3で起動したことが確認できました。

ちゃんとreplicaには書き込めません。

$ kubectl exec -it postgres-2 --container=postgres -- \
  psql -d app --command "INSERT INTO test (message) VALUES ('MESSAGE ERROR');"
ERROR:  cannot execute INSERT in a read-only transaction
command terminated with exit code 1

primaryを停止、その後replicaがprimaryに昇格するのを確認

「postgres-1に何かトラブルがあって落ちた」というテイでprimaryのpostgres-1をdeleteします。

その後、replicaがprimaryに切り替わり、落ちたpostgres-1がreplicaとして復活してくることを確認します。 切り替わる様子を確認するために、起動の様子を確認した次のコマンドを別ターミナルで実行しておくと良いです。

kubectl get pods --label-columns cnpg.io/instanceRole --watch

primaryをdeleteします。

kubectl delete pod postgres-1

get podsには次のように表示され、postgres-2がprimaryになり、停止されたpostgres-1がreplicaで復活してきたことが確認できます。

postgres-1                1/1     Terminating       0          23h   primary
postgres-1                1/1     Terminating       0          23h   primary
postgres-1                1/1     Terminating       0          23h   unhealthy
postgres-1                0/1     Completed         0          23h   unhealthy
postgres-1                0/1     Completed         0          23h   unhealthy
postgres-1                0/1     Completed         0          23h   unhealthy
postgres-2                1/1     Running           0          23h   primary
postgres-1                0/1     Pending           0          0s
postgres-1                0/1     Pending           0          0s
postgres-1                0/1     Init:0/1          0          0s
postgres-1                0/1     Init:0/1          0          0s
postgres-1                0/1     Init:0/1          0          0s
postgres-1                0/1     PodInitializing   0          0s
postgres-1                0/1     Running           0          0s
postgres-1                0/1     Running           0          2s    replica
postgres-1                0/1     Running           0          10s   replica
postgres-1                1/1     Running           0          10s   replica

新primaryに書き込み + レプリケーションされていることを確認

primaryであるpostgres-2にinsertします。先ほどreplicaだったときはエラーになりましたが、今回は書き込めます。

$ kubectl exec -it postgres-2 --container=postgres -- psql -d app --command "
SELECT * FROM test;
INSERT INTO test (message) VALUES ('MESSAGE 2');
SELECT * FROM test;
"
 id |  message
----+-----------
  1 | MESSAGE 1
(1 row)

INSERT 0 1
 id |  message
----+-----------
  1 | MESSAGE 1
 34 | MESSAGE 2
(2 rows)

replicaに届いていることも確認します。

$ kubectl exec -it postgres-1 --container=postgres -- psql -d app --command "SELECT * FROM test;"
 id |  message
----+-----------
  1 | MESSAGE 1
 34 | MESSAGE 2
(2 rows)

$ kubectl exec -it postgres-3 --container=postgres -- psql -d app --command "SELECT * FROM test;"
 id |  message
----+-----------
  1 | MESSAGE 1
 34 | MESSAGE 2
(2 rows)

フェイルオーバーの詳細: https://cloudnative-pg.io/docs/1.30/failover/

補足: CloudNativePGのkubectlプラグインを使う

CloudNativePGのkubectlプラグインを使うとreplicaをprimaryに昇格させる、などの操作ができます。

参考: https://cloudnative-pg.io/docs/1.30/kubectl-plugin/#promote

# プラグインのインストール
curl -sSfL https://github.com/cloudnative-pg/cloudnative-pg/raw/main/hack/install-cnpg-plugin.sh | sh -s -- -b /usr/local/bin
kubectl cnpg version

get podsしておくと切り替えの様子が確認できます。

次のコマンドでpostgres-1をprimaryに戻せます。

kubectl cnpg promote postgres postgres-1

ログ:

postgres-2                1/1     Running           0          23h   unhealthy
postgres-2                0/1     Completed         0          23h   unhealthy
postgres-2                0/1     Running           1 (1s ago)   23h   unhealthy
postgres-1                1/1     Running           0            18m   primary
postgres-2                0/1     Running           1 (6s ago)   23h   replica
postgres-2                0/1     Running           1 (13s ago)   23h   replica
postgres-2                1/1     Running           1 (13s ago)   23h   replica

2. KubernetesでPGroongaを1台構成で動かす

PostgreSQLで冗長構成が作れたことが確認できました。 次はこれにPGroongaを乗せても動くのか!?を確認します。

ということで、冗長構成の前にKubernetesでPGroongaを動かす方法を見ていきます。

いろいろやり方はあるのですが、今回はCloudNativePGのImage Catalogを使って、PGroongaの公式Dockerイメージで起動する方法を試します。 とりあえず1台だけ起動してPGroongaが動く様子を確認します。

cat <<YAML > pgroonga.yaml
apiVersion: postgresql.cnpg.io/v1
kind: ImageCatalog
metadata:
  name: pgroonga-image
spec:
  images:
    - major: 18
      image: groonga/pgroonga:4.1.0-debian-18
---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pgroonga
spec:
  instances: 1
  imageCatalogRef:
    apiGroup: postgresql.cnpg.io
    kind: ImageCatalog
    name: pgroonga-image
    major: 18
  postgresUID: 999
  postgresGID: 999
  storage:
    size: 1Gi
YAML
kubectl apply --filename pgroonga.yaml

補足: CloudNativePGの公式イメージとUID/GIDが違うのでそれも指定しています。

これも別ターミナルでget podsしておくと起動の様子が確認できますが、表示される内容はPostgreSQLのときとだいたい同じなので割愛します。

起動したらデータを投入して全文検索ができるか確認します。

$ kubectl exec -it pgroonga-1 --container=postgres -- psql -d app --command "
CREATE EXTENSION pgroonga;

CREATE TABLE memos (id integer, content text);
CREATE INDEX pgroonga_content_index ON memos USING pgroonga (content);

INSERT INTO memos VALUES (1, 'PostgreSQLはリレーショナル・データベース管理システムです。');
INSERT INTO memos VALUES (2, 'Groongaは日本語対応の高速な全文検索エンジンです。');
INSERT INTO memos VALUES (3, 'PGroongaはインデックスとしてGroongaを使うためのPostgreSQLの拡張機能です。');
INSERT INTO memos VALUES (4, 'groongaコマンドがあります。');

SET enable_seqscan = off;
EXPLAIN SELECT * FROM memos WHERE content &@ '全文検索';
SELECT * FROM memos WHERE content &@ '全文検索';
"
CREATE EXTENSION
CREATE TABLE
CREATE INDEX
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
SET
                                      QUERY PLAN
--------------------------------------------------------------------------------------
 Index Scan using pgroonga_content_index on memos  (cost=0.00..43.18 rows=1 width=36)
   Index Cond: (content &@ '全文検索'::text)
(2 rows)

 id |                      content
----+---------------------------------------------------
  2 | Groongaは日本語対応の高速な全文検索エンジンです。
(1 row)

全文検索できました!

3. KubernetesでPostgreSQL + PGroongaの冗長構成を作る

いよいよ本題のKubernetesでPostgreSQL + PGroongaで冗長構成が作れるのか!?を確認します。

postgresql:でPGroongaのレプリケーションに最低限必要な設定をします。 あくまで検証用の設定なので、実際の運用時はドキュメントを参照の上、必要な設定をしてください。

参考: WALリソースマネージャーを使ったストリーミングレプリケーション

kubectl delete cluster pgroonga
cat <<YAML > pgroonga-ha.yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: pgroonga-ha
spec:
  instances: 3
  imageCatalogRef:
    apiGroup: postgresql.cnpg.io
    kind: ImageCatalog
    name: pgroonga-image
    major: 18
  postgresUID: 999
  postgresGID: 999
  postgresql:
    shared_preload_libraries:
      - pgroonga_wal_resource_manager
    parameters:
      pgroonga.enable_wal_resource_manager: "on"
  storage:
    size: 1Gi
YAML
kubectl apply --filename pgroonga-ha.yaml

これも別ターミナルでget podsしておくと起動の様子が確認できます。 上述したプラグインを使うとどれがprimaryでどれがreplicaかを確認することもできます。

$ kubectl cnpg status pgroonga-ha
Cluster Summary
Name                     default/pgroonga-ha
System ID:               7703151592466559006
PostgreSQL Image:        groonga/pgroonga:4.1.0-debian-18
Primary instance:        pgroonga-ha-1
Primary promotion time:  2026-11-01 23:42:28 +0000 UTC (4m52s)
Status:                  Cluster in healthy state
Instances:               3
Ready instances:         3
Size:                    129M
Current Write LSN:       0/61F8220 (Timeline: 1 - WAL File: 000000010000000000000006)

Continuous Backup not configured

Streaming Replication status
Replication Slots Enabled
Name           Sent LSN   Write LSN  Flush LSN  Replay LSN  Write Lag  Flush Lag  Replay Lag  State      Sync State  Sync Priority  Replication Slot
----           --------   ---------  ---------  ----------  ---------  ---------  ----------  -----      ----------  -------------  ----------------
pgroonga-ha-2  0/61F8220  0/61F8220  0/61F8220  0/61F8220   00:00:00   00:00:00   00:00:00    streaming  async       0              active
pgroonga-ha-3  0/61F8220  0/61F8220  0/61F8220  0/61F8220   00:00:00   00:00:00   00:00:00    streaming  async       0              active

Instances status
Name           Current LSN  Replication role  Status  QoS         Manager Version  Node
----           -----------  ----------------  ------  ---         ---------------  ----
pgroonga-ha-1  0/61F8220    Primary           OK      BestEffort  1.30.1           kind-control-plane
pgroonga-ha-2  0/61F8220    Standby (async)   OK      BestEffort  1.30.1           kind-control-plane
pgroonga-ha-3  0/61F8220    Standby (async)   OK      BestEffort  1.30.1           kind-control-plane

pgroonga-ha-1がprimaryで、pgroonga-ha-{2,3}がreplicaです。

さっそくpgroonga-ha-1にデータをinsertして、pgroonga-ha-{2,3}にもレプリケーションされているか確認します。

$ kubectl exec -it pgroonga-ha-1 --container=postgres -- psql -d app --command "
CREATE EXTENSION pgroonga;

CREATE TABLE memos (id integer, content text);
CREATE INDEX pgroonga_content_index ON memos USING pgroonga (content);

INSERT INTO memos VALUES (1, 'PostgreSQLはリレーショナル・データベース管理システムです。');
INSERT INTO memos VALUES (2, 'Groongaは日本語対応の高速な全文検索エンジンです。');
INSERT INTO memos VALUES (3, 'PGroongaはインデックスとしてGroongaを使うためのPostgreSQLの拡張機能です。');
INSERT INTO memos VALUES (4, 'groongaコマンドがあります。');

SET enable_seqscan = off;
EXPLAIN SELECT * FROM memos WHERE content &@ '全文検索';
SELECT * FROM memos WHERE content &@ '全文検索';
"
CREATE EXTENSION
CREATE TABLE
CREATE INDEX
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
SET
                                      QUERY PLAN
--------------------------------------------------------------------------------------
 Index Scan using pgroonga_content_index on memos  (cost=0.00..43.18 rows=1 width=36)
   Index Cond: (content &@ '全文検索'::text)
(2 rows)

 id |                      content
----+---------------------------------------------------
  2 | Groongaは日本語対応の高速な全文検索エンジンです。
(1 row)

primaryにinsertして全文検索ができました。replicaの確認もします。

$ kubectl exec -it pgroonga-ha-2 --container=postgres -- psql -d app --command "
SET enable_seqscan = off;
EXPLAIN SELECT * FROM memos WHERE content &@ '全文検索';
SELECT * FROM memos WHERE content &@ '全文検索';
"
SET
                                      QUERY PLAN
--------------------------------------------------------------------------------------
 Index Scan using pgroonga_content_index on memos  (cost=0.00..43.18 rows=1 width=36)
   Index Cond: (content &@ '全文検索'::text)
(2 rows)

 id |                      content
----+---------------------------------------------------
  2 | Groongaは日本語対応の高速な全文検索エンジンです。
(1 row)


$ kubectl exec -it pgroonga-ha-3 --container=postgres -- psql -d app --command "
SET enable_seqscan = off;
EXPLAIN SELECT * FROM memos WHERE content &@ '全文検索';
SELECT * FROM memos WHERE content &@ '全文検索';
"
SET
                                      QUERY PLAN
--------------------------------------------------------------------------------------
 Index Scan using pgroonga_content_index on memos  (cost=0.00..43.18 rows=1 width=36)
   Index Cond: (content &@ '全文検索'::text)
(2 rows)

 id |                      content
----+---------------------------------------------------
  2 | Groongaは日本語対応の高速な全文検索エンジンです。
(1 row)

レプリケーションもOKです。 次はprimaryがトラブルで落ちたテイでdeleteします。

$ kubectl delete pod pgroonga-ha-1
pod "pgroonga-ha-1" deleted from default namespace
$ kubectl cnpg status pgroonga-ha
Cluster Summary
Name                     default/pgroonga-ha
System ID:               7703151592466559006
PostgreSQL Image:        groonga/pgroonga:4.1.0-debian-18
Primary instance:        pgroonga-ha-2
Primary promotion time:  2026-11-01 23:54:26 +0000 UTC (30s)
Status:                  Cluster in healthy state
Instances:               3
Ready instances:         3
Size:                    178M
Current Write LSN:       0/B000000 (Timeline: 2 - WAL File: 00000002000000000000000B)

Continuous Backup not configured

Streaming Replication status
Replication Slots Enabled
Name           Sent LSN   Write LSN  Flush LSN  Replay LSN  Write Lag  Flush Lag  Replay Lag  State      Sync State  Sync Priority  Replication Slot
----           --------   ---------  ---------  ----------  ---------  ---------  ----------  -----      ----------  -------------  ----------------
pgroonga-ha-1  0/B000000  0/B000000  0/B000000  0/B000000   00:00:00   00:00:00   00:00:00    streaming  async       0              active
pgroonga-ha-3  0/B000000  0/B000000  0/B000000  0/B000000   00:00:00   00:00:00   00:00:00    streaming  async       0              active

Instances status
Name           Current LSN  Replication role  Status  QoS         Manager Version  Node
----           -----------  ----------------  ------  ---         ---------------  ----
pgroonga-ha-2  0/B000000    Primary           OK      BestEffort  1.30.1           kind-control-plane
pgroonga-ha-1  0/B000000    Standby (async)   OK      BestEffort  1.30.1           kind-control-plane
pgroonga-ha-3  0/B000000    Standby (async)   OK      BestEffort  1.30.1           kind-control-plane

pgroonga-ha-2がprimaryになって、pgroonga-ha-1はreplicaになりました。

新primaryにinsertして確認します。

$ kubectl exec -it pgroonga-ha-2 --container=postgres -- psql -d app --command "
INSERT INTO memos VALUES (5, 'pgroonga-ha-2 new primary! Groongaは日本語対応の高速な全文検索エンジンです。');

SET enable_seqscan = off;
EXPLAIN SELECT * FROM memos WHERE content &@ '全文検索';
SELECT * FROM memos WHERE content &@ '全文検索';
"
INSERT 0 1
SET
                                      QUERY PLAN
--------------------------------------------------------------------------------------
 Index Scan using pgroonga_content_index on memos  (cost=0.00..50.16 rows=1 width=36)
   Index Cond: (content &@ '全文検索'::text)
(2 rows)

 id |                                   content
----+------------------------------------------------------------------------------
  2 | Groongaは日本語対応の高速な全文検索エンジンです。
  5 | pgroonga-ha-2 new primary! Groongaは日本語対応の高速な全文検索エンジンです。
(2 rows)

replicaも確認します。(pgroonga-ha-1の結果だけ記載しますが、pgroonga-ha-3も同じ結果でした。)

$ kubectl exec -it pgroonga-ha-1 --container=postgres -- psql -d app --command "
SET enable_seqscan = off;
EXPLAIN SELECT * FROM memos WHERE content &@ '全文検索';
SELECT * FROM memos WHERE content &@ '全文検索';
"
SET
                                      QUERY PLAN
--------------------------------------------------------------------------------------
 Index Scan using pgroonga_content_index on memos  (cost=0.00..50.16 rows=1 width=36)
   Index Cond: (content &@ '全文検索'::text)
(2 rows)

 id |                                   content
----+------------------------------------------------------------------------------
  2 | Groongaは日本語対応の高速な全文検索エンジンです。
  5 | pgroonga-ha-2 new primary! Groongaは日本語対応の高速な全文検索エンジンです。
(2 rows)

replicaにも反映されました!

KubernetesでPostgreSQL + PGroongaの冗長構成ができました!

注意

今回はkubectl deleteで正常に停止させたので、pgroonga-ha-1は問題なくreplicaとして起動できました。 しかし、実際の障害ではプロセスが突然終了するなど、想定外の止まり方をすることがあります。 そのようなケースでは復活したpgroonga-ha-1のPGroongaのインデックスが壊れている可能性があります。 壊れていた場合はインデックスを作り直すなどの対応が必要です。

まとめ

KubernetesでPostgreSQL + PGroongaの冗長構成を確認できました。 ただし「はじめに」に書いた通り、実際のサービスの環境や発生しそうな障害を再現しているとは言えない検証での確認です。

もう少し実際の環境に近い検証もしたいと思います。

今回は簡易的な検証でしたが、より実環境に近い環境を構築し検証、改善案の提案もできますので、PGroongaやPostgreSQLの運用でお困りの場合はお問い合わせよりご連絡ください。