Logical Replication
===================

PostgreSQLは、
`logical replication <https://www.postgresql.org/docs/current/logical-replication.html>`_ を提供することにより、レプリケーション機能を物理的レプリケーションを超えて拡張します。これは、正確なブロックアドレスとバイトごとのコピーのレベルで動作します。論理レプリケーションは、定義されたレプリケーションID通常は主キーに基づいて、データオブジェクトとその変更をレプリケートします。

論理レプリケーションでは、パブリッシュアンドサブスクライブモデルを使用し、サブスクライバーはパブリッシャーノードでパブリケーションに接続します。サブスクライバーはこれらのパブリケーションからデータの変更をプルし、再公開できるため、カスケードレプリケーションと複雑なトポロジが有効になります。

この柔軟なモデルは、次の場合に特に役立ちます。

- オンラインデータの移行

- ライブPostgreSQLバージョンのアップグレード

- システム間のデータ分散

- リアルタイム分析

- 外部アプリケーションとの統合

..  Note::
   詳細、例、および制限については、 :ref:`official PostgreSQL documentation on Logical Replication <Replication>` を参照してください。

**EDB Postgres for Kubernetes**
は、主要なPostgreSQL論理レプリケーションオブジェクトの宣言的サポートを提供することにより、この機能を強化します。

- ``Publication`` リソースを介した **出版物**

- ``Subscription`` リソースを介した **サブスクリプション**

出版物
------

PostgreSQLのパブリッシュアンドサブスクライブレプリケーションモデルでは、
:ref:`**publication** <Replication>` 

データ変更のソースです。これは、データベース内の1つ以上のテーブルから生成された変更セット_replication
set_としても知られる論理コンテナとして機能します。パブリケーションは、\_publisher_として機能するPostgreSQL
10+インスタンスで定義できます。パブリッククラウドで人気のDBaaSソリューションによって管理されているインスタンスを含みます。各パブリケーションは単一のデータベースに関連付けられ、どのテーブルと変更をレプリケートするかについての詳細な制御を提供します。

Kubernetes外部のパブリッシャーの場合、次のことができます `create publications using SQL <https://www.postgresql.org/docs/current/sql-createpublication.html>`_ 

または :ref:`cnp publication create <EDB Postgres for Kubernetes Plugin>`  を活用します。

**EDB Postgres for Kubernetes** で\ ``Cluster``
オブジェクトを管理する場合、
PostgreSQLパブリケーションは\ ``Publication``
リソースを介して宣言的に定義できます。

..  Note::
   :ref:`API Reference - v1.25.1 <API Reference - v1.25.1>` を参照してください。

各\ ``Publication``
オブジェクトに定義できる属性の完全なリストについては、

``freddie`` という名前のクラスターがあり、 ``app``
データベース内のすべてのテーブルをレプリケートするとします。これは\ ``Publication``
マニフェストです。

.. code:: yaml

   apiVersion: postgresql.k8s.enterprisedb.io/v1
   kind: Publication
   metadata:
     name: freddie-publisher
   spec:
     cluster:
       name: freddie
     dbname: app
     name: publisher
     target:
       allTables: true

上記の例では

- パブリケーションオブジェクトの名前は\ ``freddie-publisher``
  ``metadata.name`` です。

- パブリケーションは、\ ``publisher`` ``spec.name``
  という名前の\ ``freddie`` クラスター ``spec.cluster.name``
  のプライマリを介して作成されます。

- ``app`` データベース ``spec.dbname`` のすべてのテーブル
  ``spec.target.allTables: true`` が含まれます。

..  Important::
   `allTables` は構成を簡素化しますが、PostgreSQLは特定のテーブルまたはターゲットを絞ったデータ変更をレプリケートするためのきめの細かい制御を提供します。高度な構成については、 :ref:`PostgreSQL documentation <Replication>`  を参照してください。さらに、 :ref:`EDB Postgres for Kubernetes API reference <API Reference - v1.25.1>` を参照してください。

レプリケーションターゲットの宣言によるカスタマイズの詳細については、

``Publication`` マニフェストの必須フィールド
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

``Publication`` オブジェクトには次のフィールドが必要です。

- ``metadata.name`` Kubernetes ``Publication``
  オブジェクトの一意の名前。

- ``spec.cluster.name`` PostgreSQLクラスターの名前。

- ``spec.dbname`` パブリケーションが作成されるデータベース名。

- ``spec.name`` PostgreSQLでのパブリケーション名。

- ``spec.target``
  パブリケーションに含めるテーブルまたは変更を指定します。

``Publication`` オブジェクトは特定の\ ``Cluster``
を参照し、パブリケーションを作成する場所を決定する必要があります。これはクラスターのプライマリインスタンスによって管理され、必要に応じてパブリケーションが作成または更新されます。

調整とステータス
^^^^^^^^^^^^^^^^

``Publication`` を作成すると、 EDB Postgres for
Kubernetesは、指定されたクラスターのプライマリインスタンスでそれを管理します。リコンシリエーションサイクルが成功すると、\ ``Publication``
ステータスは次を反映します。

- ``applied: true`` 、構成が正常に適用されたことを示します。

- ``observedGeneration`` は\ ``metadata.generation``
  と一致し、適用された構成が最新の変更に対応することを確認します。

リコンシリエーション中にエラーが発生した場合、\ ``status.applied``
は\ ``false`` になり、エラーメッセージは\ ``status.message``
フィールドに含まれます。

パブリケーションの削除
^^^^^^^^^^^^^^^^^^^^^^

``publicationReclaimPolicy`` フィールドは、\ ``Publication``
オブジェクトを削除するときの動作を制御します。

- ``retain`` デフォルト
  手動管理のためにPostgreSQLにパブリケーションを残します。

- ``delete`` PostgreSQLからパブリケーションを自動的に削除します。

次の例を考えます。

.. code:: yaml

   apiVersion: postgresql.k8s.enterprisedb.io/v1
   kind: Publication
   metadata:
     name: freddie-publisher
   spec:
     cluster:
       name: freddie
     dbname: app
     name: publisher
     target:
       allTables: true
     publicationReclaimPolicy: delete

この場合、 ``Publication`` オブジェクトを削除すると、 ``freddie``
クラスターの\ ``app`` データベースから\ ``publisher``
パブリケーションも削除されます。

サブスクリプション
------------------

PostgreSQLのパブリッシュアンドサブスクライブレプリケーションモデルでは、
:ref:`**subscription** <Replication>` 

は、データの変更を消費するダウンストリームコンポーネントを表します。サブスクリプションは、パブリッシャーのデータベースへの接続を確立し、サブスクライブするパブリケーションのセット1つ以上を指定します。サブスクリプションは、\_subscriber_として機能するサポートされているPostgreSQLインスタンスで作成できます。

..  Important::
   スキーマ定義はレプリケートされないため、サブスクライバーは、データレプリケーションを開始する前に、対応するテーブルを既に定義している必要があります。

KubernetesのEDB Postgresは、 ``Subscription``
リソースを使用して宣言的に定義できることにより、サブスクリプション管理を簡素化します。

..  Note::
   :ref:`API Reference - v1.25.1 <API Reference - v1.25.1>` を参照してください。

各\ ``Subscription``
オブジェクトに定義できる属性の完全なリストについては、

``freddie`` クラスター_publisher_の\ ``app``
データベースの\ ``publisher`` パブリケーションから\ ``king``
クラスター_subscriber_の\ ``app``
データベースに変更をレプリケートするとします。次に、\ ``Subscription``
マニフェストの例を示します。

.. code:: yaml

   apiVersion: postgresql.k8s.enterprisedb.io/v1
   kind: Subscription
   metadata:
     name: freddie-to-king-subscription
   spec:
     cluster:
       name: king
     dbname: app
     name: subscriber
     externalClusterName: freddie
     publicationName: publisher

上記の例では

- サブスクリプションオブジェクトの名前は\ ``freddie-to-king-subscriber``
  ``metadata.name`` です。

- サブスクリプションは、\ ``king`` クラスター\ ``spec.cluster.name``
  の\ ``app`` データベース\ ``spec.dbname`` に、\ ``subscriber``
  ``spec.name`` という名前で作成されます。

- ``spec.externalClusterName`` によって参照される、外部\ ``freddie``
  クラスターの\ ``publisher`` パブリケーションに接続します。

この設定を容易にするには、 ``king`` クラスターの構成で\ ``freddie``
外部クラスターを定義する必要があります。以下は、 ``king``
マニフェストで外部クラスターを定義する方法を示す抜粋例です。

.. code:: yaml

   externalClusters:
     - name: freddie
       connectionParameters:
         host: freddie-rw.default.svc
         user: postgres
         dbname: app

..  Note::
   `externalClusters` セクションの構成の詳細については、ドキュメントの :ref:`BootstrapConfiguration <BootstrapConfiguration>` を参照してください。

ご覧のとおり、サブスクリプションは、ネットワーク経由でアクセス可能なPostgreSQLデータベースに接続できます。この柔軟性により、ほぼゼロのダウンタイムでデータをKubernetesにシームレスに移行できます。これは、人気のクラウドベースのDBaaSプラットフォームを含むさまざまな環境から移行するための優れたオプションです。

``Subscription`` マニフェストの必須フィールド
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

次のフィールドは\ ``Subscription``
オブジェクトを定義するために必須です。

- ``metadata.name`` 名前空間内のKubernetes ``Subscription``
  オブジェクトの一意の名前。

- ``spec.cluster.name``
  サブスクリプションが作成されるPostgreSQLクラスターの名前。

- ``spec.dbname`` サブスクリプションが作成されるデータベースの名前。

- ``spec.name`` PostgreSQLに表示されるサブスクリプションの名前。

- ``spec.externalClusterName`` ``spec.cluster.name``
  クラスターの構成で定義された外部クラスターの名前。これは、発行者データベースを参照します。

- ``spec.publicationName``
  サブスクリプションが接続するパブリッシャーデータベース内のパブリケーションの名前。

``Subscription`` オブジェクトは特定の\ ``Cluster``
を参照し、サブスクリプションを管理する場所を決定する必要があります。 EDB
Postgres for
Kubernetesは、指定されたクラスターのプライマリインスタンスでサブスクリプションが作成または更新されるようにします。

.. _調整とステータス-1:

調整とステータス
^^^^^^^^^^^^^^^^

``Subscription`` を作成すると、 EDB Postgres for
Kubernetesは、指定されたクラスターのプライマリインスタンスでそれを管理します。リコンシリエーションサイクルが成功すると、\ ``Subscription``
ステータスは次を反映します。

- ``applied: true`` 、構成が正常に適用されたことを示します。

- ``observedGeneration`` は\ ``metadata.generation``
  と一致し、適用された構成が最新の変更に対応することを確認します。

リコンシリエーション中にエラーが発生した場合、\ ``status.applied``
は\ ``false`` になり、エラーメッセージは\ ``status.message``
フィールドに含まれます。

サブスクリプションの削除
^^^^^^^^^^^^^^^^^^^^^^^^

``subscriptionReclaimPolicy`` フィールドは、\ ``Subscription``
オブジェクトを削除するときの動作を制御します。

- ``retain`` デフォルト
  手動管理のためにPostgreSQLにサブスクリプションを残します。

- ``delete`` PostgreSQLからサブスクリプションを自動的に削除します。

次の例を考えます。

.. code:: yaml

   apiVersion: postgresql.k8s.enterprisedb.io/v1
   kind: Subscription
   metadata:
     name: freddie-to-king-subscription
   spec:
     cluster:
       name: king
     dbname: app
     name: subscriber
     externalClusterName: freddie
     publicationName: publisher
     subscriptionReclaimPolicy: delete

この場合、 ``Subscription`` オブジェクトを削除すると、 ``king``
クラスターの\ ``app`` データベースから\ ``subscriber``
サブスクリプションも削除されます。

制限事項
--------

:ref:`official documentation <Replication>` で概要を示しているように、
PostgreSQLの論理レプリケーションには、いくつかの固有の制限があります。特に、次のオブジェクトはレプリケートされません。

- **データベーススキーマとDDLコマンド**

- **シークエンスデータ**

- **大きなオブジェクト**

スキーマレプリケーションのアドレス指定
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

最初の制限はスキーマレプリケーションに関連しており、Kubernetesの機能のEDB
Postgresを使用して簡単に対処できます。たとえば、 ``import``
ブートストラップ機能を活用して、レプリケートが必要なテーブルのスキーマをコピーできます。または、PostgreSQLデータベースの場合と同様に、スキーマを手動で作成できます。

シーケンスの処理
^^^^^^^^^^^^^^^^

シーケンスは、論理レプリケーションを介して自動的に同期は保たれませんが、KubernetesのEDB
Postgresは、ライブマイグレーションで使用されるソリューションを提供します。
:ref:``kubectl` の`cnp` プラグインを使用する <`kubectl` の`cnp` プラグインを使用する>` を使用できます

シーケンス値を同期し、パブリッシャーとサブスクライバーデータベース間の一貫性を保証します。

論理レプリケーションを使用したライブ移行とメジャーPostgresアップグレードの例
----------------------------------------------------------------------------

論理レプリケーションの強力な機能を強調するために、この例では、
PostgreSQL 16を実行しているパブリッシャーデータベース ``freddie``
から最新のPostgreSQLバージョンを実行しているサブスクライバデータベース
``king``
にデータをレプリケートする方法を示します。このセットアップは、評価と実践学習のためにKubernetesクラスターに展開できます。

この例は、論理レプリケーションがデータの一貫性を保証しながら、PostgreSQLバージョン間のライブマイグレーションとアップグレードを促進する方法を示しています。論理レプリケーションをKubernetesのEDB
Postgresと組み合わせることで、Kubernetes環境でこのようなシナリオを簡単にセットアップ、管理、および評価できます。

ステップ1パブリッシャーの設定 ``freddie``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

最初のステップでは、バージョン16での\ ``freddie``
PostgreSQLクラスターを作成します。クラスターには、単一のインスタンスが含まれ、10,000の数値を保存するテーブル\ ``n``
で初期化された\ ``app`` データベースが含まれます。 ``publisher``
という名前の論理レプリケーションパブリケーションも、データベース内のすべてのテーブルを含むように構成されています。

``freddie``
クラスターとそのパブリケーションリソースをセットアップするためのマニフェストは次のとおりです。

.. code:: yaml

   apiVersion: postgresql.k8s.enterprisedb.io/v1
   kind: Cluster
   metadata:
     name: freddie
   spec:
     instances: 1

     imageName: quay.io/enterprisedb/postgresql:16

     storage:
       size: 1Gi

     bootstrap:
       initdb:
         postInitApplicationSQL:
           - CREATE TABLE n (i SERIAL PRIMARY KEY, m INTEGER)
           - INSERT INTO n (m) (SELECT generate_series(1, 10000))
           - ALTER TABLE n OWNER TO app

     managed:
       roles:
         - name: app
           login: true
           replication: true
   - --
   apiVersion: postgresql.k8s.enterprisedb.io/v1
   kind: Publication
   metadata:
     name: freddie-publisher
   spec:
     cluster:
       name: freddie
     dbname: app
     name: publisher
     target:
       allTables: true

ステップ2サブスクライバー ``king`` の設定
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

次に、最新バージョンのPostgreSQLを実行して、\ ``king``
PostgreSQLクラスターを作成します。このクラスターは、外部クラスター構成を使用して\ ``freddie``
クラスター上の\ ``app``
データベースからスキーマをインポートすることにより初期化します。
``Subscription`` リソース ``freddie-to-king-subscription`` は、
``freddie`` の\ ``publisher``
によって公開された変更を消費するように構成されます。

以下は、\ ``king``
クラスターとそのサブスクリプションをセットアップするためのマニフェストです。

.. code:: yaml

   apiVersion: postgresql.k8s.enterprisedb.io/v1
   kind: Cluster
   metadata:
     name: king
   spec:
     instances: 1

     storage:
       size: 1Gi

     bootstrap:
       initdb:
         import:
           type: microservice
           schemaOnly: true
           databases:
             - app
           source:
             externalCluster: freddie

     externalClusters:
       - name: freddie
         connectionParameters:
           host: freddie-rw.default.svc
           user: app
           dbname: app
         password:
           name: freddie-app
           key: password
   - --
   apiVersion: postgresql.k8s.enterprisedb.io/v1
   kind: Subscription
   metadata:
     name: freddie-to-king-subscription
   spec:
     cluster:
       name: king
     dbname: app
     name: subscriber
     externalClusterName: freddie
     publicationName: publisher

``king`` クラスターが実行されたら、 ``app``
データベースに接続し、\ ``n``
テーブルのレコードをカウントすることにより、レプリケーションが機能していることを確認できます。次の例では、簡単にするために\ ``cnp``
プラグインが提供する\ ``psql`` コマンドを使用しています。

.. code:: console

   kubectl cnp psql king -- app -qAt -c SELECT count(*) FROM n
   10000

このコマンドは\ ``10000`` を返し、 ``freddie``
クラスターからのデータが\ ``king``
クラスターに正常にレプリケートされたことを確認します。

``cnp``
プラグインを使用して、既存のシーケンスを同期して、パブリッシャーとサブスクライバー間の一貫性を保証することもできます。次の例は、\ ``king``
クラスターのシーケンスを同期する方法を示しています。

.. code:: console

   kubectl cnp subscription sync-sequences king --subscription=subscriber
   SELECT setval("public"."n_i_seq", 10000);

   10000

このコマンドは、現在の値と一致するように\ ``king``
クラスターのシーケンス\ ``n_i_seq``
を更新し、ソースデータベースと同期していることを確認します。
