リカバリー
==========

PostgreSQLの用語では、リカバリーは、以前に取得したバックアップを使用してPostgreSQLインスタンスを起動するプロセスです。
PostgreSQLのリカバリメカニズムは非常に堅牢で豊富です。また、ポイントインタイムリカバリーもサポートし、カタログ内の最初に使用可能なバックアップから最後にアーカイブされたWALまで、特定のクラスターを任意の時点に復元できます。ご覧のとおり、この場合、WALアーカイブは必須です。
。

CloudNativePGでは、既存のクラスターでリカバリーを「インプレース」で実行できません。リカバリーは、むしろ、使用可能な物理的バックアップから新しいPostgresクラスターをブートストラップする方法です。

..  Note::
   `bootstrap` スタンザの詳細については、 :ref:`Bootstrap <Bootstrap>` を参照してください。

``recovery``
ブートストラップモードでは、既存の物理ベースバックアップから新しいクラスターを作成し、アーカイブからREDOログを含むWALファイルを再適用できます。

WALファイルは、定義された *リカバリオブジェクトストア*
からプルされます。

ベースバックアップは、オブジェクトストアまたはボリュームスナップショットバージョン1.21以降を使用して取得できます。

..  Warning::
   ボリュームスナップショットを使用したリカバリーの初期リリースは1.20.1でした。 1.21.0の機能の進歩の量のため、ボリュームスナップショットを使用するには、1.21.0以上のアドバンスリリースにアップグレードすることを強くお勧めします。

*リカバリオブジェクトストア* からのリカバリは、2つの方法で実現できます。

-  リカバリオブジェクトストア、つまりBarman
   Cloudによって作成され、\ ``externalClusters``
   セクションの\ ``barmanObjectStore``
   オプションを介して定義された別のクラスターのバックアップを使用する
   *推奨*

-  同じ名前空間内の既存の\ ``Backup``
   オブジェクトを使用しますこれはバージョン1.8.0より前に使用可能な唯一のオプションでした。

どちらの復旧方法も、完全な復旧最後に使用可能なWALまでまたは最大
 :ref:`ポイント インタイム リカバリーPITR <ポイント インタイム リカバリーPITR>` 
までのいずれかが有効になります。完全なリカバリーを実行する場合、クラスターをレプリカモードで起動することもできます
 :ref:`レプリカクラスター <レプリカクラスター>` を参照してください。レプリカモードを使用する場合、復旧したクラスターのPostgreSQL構成\ ``.spec.postgresql.parameters``
が、物理レプリケーションの観点から、元のクラスターと互換性があることを確認します。

ボリュームスナップショットを使用したリカバリの場合

-  ``kubectl cnpg backup``
   コマンドを使用して、スタンバイからPostgresクラスターの一貫したコールドバックアップを取得します。
   :ref:`plugin document <バックアップ>` を参照してください

参照用)、これは、必要な\ ``VolumeSnapshot``
オブジェクトWAL用の別個のボリュームがある場合は2つ、ない場合は1つを作成します
- :ref:``VolumeSnapshot` オブジェクトからのリカバリー <`VolumeSnapshot` オブジェクトからのリカバリー>` で説明しているように、\ ``.spec.bootstrap.recovery``
スタンザの\ ``volumeSnapshots`` オプションを介して上記の
*VolumeSnapshot* オブジェクトからリカバリします

以下

オブジェクトストアからのリカバリー
----------------------------------

Barman
Cloudによって作成され、サポートされているオブジェクトストアに保存されているバックアップから復元できます。
``barmanObjectStore``
セクションで必要な構成をすべて含む外部クラスターを定義したら、
``.spec.recovery.source``
オプションで参照する必要があります。次の例では、AzureのBLOBコンテナにリカバリオブジェクトストアを定義します。

.. code:: yaml

   apiVersion: postgresql.cnpg.io/v1
   kind: Cluster
   metadata:
     name: cluster-restore
   spec:
     [...]
     
     superuserSecret:
       name: superuser-secret
       
     bootstrap:
       recovery:
         source: clusterBackup

     externalClusters:
       - name: clusterBackup
         barmanObjectStore:
           destinationPath: https://STORAGEACCOUNTNAME.blob.core.windows.net/CONTAINERNAME/
           azureCredentials:
             storageAccount:
               name: recovery-object-store-secret
               key: storage_account_name
             storageKey:
               name: recovery-object-store-secret
               key: storage_account_key
           wal:
             maxParallel: 8

..  Important::
   デフォルトでは、 `recovery` メソッドは、通常サーバーの名前用に予約されているオブジェクトストア内のバックアップデータのメインフォルダーの名前として、 `externalClusters` セクションのクラスターの`name` を厳密に使用します。 `barmanObjectStore.serverName` プロパティで別のフォルダー名を指定できます。

..  Note::
   上記の例では、並列WALリストア機能を利用し、最大8つのジョブを専用に使用して、アーカイブから必要なWALファイルを同時に取得します。この機能により、復旧時間を大幅に短縮できます。このシナリオを事前に計画し、ご使用の環境に合わせてこのパラメーターの値を正しく調整してください。それは確かに違いを生みます必要になる場合**場合ではなく。

``VolumeSnapshot`` オブジェクトからのリカバリー
-----------------------------------------------

..  Warning::
   ボリュームスナップショットからプライマリインスタンスをリカバリした後、レプリカを作成する場合、オペレーターは`pg_basebackup` を使用して同期することになり、データベースのサイズによってはプロセスが遅くなる場合があります。この制限は、将来的にオンラインバックアップのサポートが導入されるときに解除される予定です。 CloudNativePGは、 :ref:`ボリュームスナップショットバックアップを構成する方法 <ボリュームスナップショットバックアップを構成する方法>` の宣言APIを使用して取得された既存の`Cluster` のPVCの`VolumeSnapshot` から新しいクラスターを作成できます。次の例のように、スナップショットの名前を指定する必要があります。

.. code:: yaml

   apiVersion: postgresql.cnpg.io/v1
   kind: Cluster
   metadata:
     name: cluster-restore
   spec:
     [...]

   bootstrap:
       recovery:
         volumeSnapshots:
           storage:
             name: <snapshot name>
             kind: VolumeSnapshot
             apiGroup: snapshot.storage.k8s.io

バックアップされたクラスターが別のPVCを使用してWALファイルを保存していた場合、リカバリーにはそれも含める必要があります。

.. code:: yaml

   apiVersion: postgresql.cnpg.io/v1
   kind: Cluster
   metadata:
     name: cluster-restore
   spec:
     [...]

   bootstrap:
       recovery:
         volumeSnapshots:
           storage:
             name: <snapshot name>
             kind: VolumeSnapshot
             apiGroup: snapshot.storage.k8s.io

           walStorage:
             name: <snapshot name>
             kind: VolumeSnapshot
             apiGroup: snapshot.storage.k8s.io

..  Warning::
   スナップショットからレプリカモードクラスターをブートストラップして、プライマリだけでなくスタンバイインスタンスのスナップショットを活用する場合、次のことをお勧めします。

1.単一のインスタンスレプリカクラスターから開始します。プライマリインスタンスは、ソースクラスタからのスナップショットと利用可能なWALを使用して復旧されます。
2.レプリカクラスタでプライマリのスナップショットを取得します。
3.必要に応じて、レプリカクラスタのインスタンスの数を増やします。

``Backup`` オブジェクトからのリカバリー
---------------------------------------

..  Important::
   `Backup` オブジェクトからのリカバリーは、オブジェクトストアのバックアップでのみ機能し、ボリュームスナップショットでは機能しません。

クラスターを作成する名前空間で\ ``Backup``
リソースが既に利用可能な場合、次の例のように、\ ``.spec.bootstrap.recovery.backup.name``
を介してその名前を指定できます。

.. code:: yaml

   apiVersion: postgresql.cnpg.io/v1
   kind: Cluster
   metadata:
     name: cluster-example-initdb
   spec:
     instances: 3

     superuserSecret:
       name: superuser-secret

     bootstrap:
       recovery:
         backup:
           name: backup-example

     storage:
       size: 1Gi

このブートストラップ方法では、復元する必要があるバックアップへの参照のみを指定できます。

前の例は、アプリケーションデータベースとその所有ユーザーがデフォルトの\ ``app``
であることを示しています。復元されるPostgreSQLクラスターが別の名前を使用していた場合、
`Configure the application
database <#configure-the-application-database>`__\ セクションの文書に従って指定できます。

追加の考慮事項
--------------

リカバリオブジェクトストア、ボリュームスナップショット、または既存の\ ``Backup``
リソースからリカバリするかどうかにかかわらず、次の考慮事項が適用されます。

-  アプリケーションデータベース名とアプリケーションデータベースユーザーは、復元されるバックアップから保持されます。これは、Kubernetesクラスター自分自身の通常のメンテナンスアクティビティの一部であるため、現在基になるシークレットのバックアップを試みていません。

-  ``superuserSecret``
   を指定しない場合、安全でランダムなパスワードで新しいものが自動的に生成されます。次に、シークレットは、クラスターの\ ``postgres``
   ユーザーのパスワードをリセットするために使用されます。

-  デフォルトでは、リカバリはデフォルトのターゲットタイムラインで利用可能な最新のWALまで続行されます11までのPostgreSQLの場合は\ ``current``
   、バージョン12以降は\ ``latest`` 。オプションで\ ``recoveryTarget``
   を指定して、ポイントインタイムリカバリーを実行できます
   :ref:`ポイント インタイム リカバリーPITR <ポイント インタイム リカバリーPITR>` を参照してください。

..  Important::
   `barmanObjectStore.wal.maxParallel` オプションを使用して、リカバリオブジェクトストアからトランザクションログを同時にダウンロードすることにより、アーカイブからのWAL取得を高速化することを検討します。

ポイント インタイム リカバリーPITR
----------------------------------

最新のWALまでのすべてのWALを再生する代わりに、ベースバックアップを抽出した後、任意の時点でWALの再生を停止するようにPostgreSQLに依頼できます。
PostgreSQLは、この技術を使用して *ポイントインタイム*
リカバリーPITRを実現します。 WALアーカイブの存在は必須です。

..  Important::
   PITRでは、以下の :ref:`リカバリーターゲット <リカバリーターゲット>` で説明するオプションを使用して、**リカバリターゲット**を指定する必要があります。

オペレーターは、リカバリターゲットが指定されている場合に、この機能が動作するために必要な構成パラメーターを生成します。

オブジェクトストアからのPITR
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

次の例では、ベースバックアップとWALアーカイブの両方を含むAzureのリカバリオブジェクトストアを使用します。リカバリターゲットは、要求されたタイムスタンプに基づいています。

.. code:: yaml

   apiVersion: postgresql.cnpg.io/v1
   kind: Cluster
   metadata:
     name: cluster-restore-pitr
   spec:
     instances: 3

     storage:
       size: 5Gi

     bootstrap:
       recovery:
         # Recovery object store containing WAL archive and base backups
         source: clusterBackup
         recoveryTarget:
           # Time base target for the recovery
           targetTime: "2023-08-11 11:14:21.00000+02"

     externalClusters:
       - name: clusterBackup
         barmanObjectStore:
           destinationPath: https://STORAGEACCOUNTNAME.blob.core.windows.net/CONTAINERNAME/
           azureCredentials:
             storageAccount:
               name: recovery-object-store-secret
               key: storage_account_name
             storageKey:
               name: recovery-object-store-secret
               key: storage_account_key
           wal:
             maxParallel: 8

上記の例では、タイムスタンプの形式で\ ``targetTime``
を指定するだけで済み、リカバリを開始するベースバックアップの指定を心配する必要がないことに気付いたかもしれません。

``backupID``
オプションは、リカバリプロセスを開始するベースバックアップを指定できるオプションです。デフォルトでは、この値は空です。

BarmanバックアップIDの形式で値を割り当てると、オペレーターはそのバックアップをリカバリのベースとして使用します。

..  Important::
   このようなバックアップが存在し、アクセス可能であることを確認する必要があります。

バックアップIDが指定されない場合、オペレーターは次のようにリカバリのベースバックアップを自動的に検出します。

-  ``targetTime`` または\ ``targetLSN``
   を使用する場合、オペレーターはそのターゲットより前に完了した最も近いバックアップを選択します

-  それ以外の場合、オペレーターは時系列で最後の使用可能なバックアップを選択します。

``VolumeSnapshot`` オブジェクトからのPITR
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

以下の例では、以下を使用します。

-  リカバリプロセスを開始するベースバックアップを含む\ ``PGDATA``
   のKubernetesボリュームスナップショット。\ ``recovery.volumeSnapshots``
   セクションで指定され、\ ``test-snapshot-1`` と呼ばれます。

-  外部クラスター定義の形式で\ ``recovery.source``
   オプションで指定される、WALアーカイブを含むMinIOのリカバリオブジェクトストア

リカバリターゲットは、要求されたタイムスタンプに基づいています。

.. code:: yaml

   apiVersion: postgresql.cnpg.io/v1
   kind: Cluster
   metadata:
     name: cluster-example-snapshot
   spec:
     # ...
     bootstrap:
       recovery:
         source: cluster-example-with-backup
         volumeSnapshots:
           storage:
             name: test-snapshot-1
             kind: VolumeSnapshot
             apiGroup: snapshot.storage.k8s.io
         recoveryTarget:
           targetTime: "2023-07-06T08:00:39"
     externalClusters:
       - name: cluster-example-with-backup
         barmanObjectStore:
           destinationPath: s3://backups/
           endpointURL: http://minio:9000
           s3Credentials:
             accessKeyId:
               name: minio
               key: ACCESS_KEY_ID
             secretAccessKey:
               name: minio
               key: ACCESS_SECRET_KEY

..  Note::
   バックアップされたクラスターで`walStorage` が有効になっていた場合、 :ref:`Recovery from VolumeSnapshot objects <リカバリー>` で記載されているように、 `PGWAL` ディレクトリを含むボリュームスナップショットも指定する必要があります

セクション。

..  Warning::
   ボリュームスナップショットのベースバックアップの終了時刻がリカバリターゲットのタイムスタンプより前であることを確認するのは自分の責任です。

リカバリーターゲット
^^^^^^^^^^^^^^^^^^^^

次に、使用可能なリカバリターゲット基準を示します。

targetTime
 `RFC 3339 <https://datatracker.ietf.org/doc/html/rfc3339>`_ 形式で表現される、リカバリーが進行するまでのタイムスタンプ
正確な停止ポイントは\ ``exclusive`` オプションの影響も受けます。

targetXID リカバリーが続行されるトランザクションID
正確な停止ポイントは\ ``exclusive``
オプションの影響も受けます。トランザクションIDはトランザクションの開始時にシークエンシャルに割り当てられますが、トランザクションは別の数値オーダーで完了する場合があることに注意してください。回復されるトランザクションは、指定されたトランザクションより前にコミットされたトランザクション、およびオプションで含まれるトランザクションです。

targetName ``pg_create_restore_point()``
で作成された名前付けリストアポイント
リカバリーが続行される名前付けリストアポイント

targetLSN リカバリーが続行されるログ先行書き込みの場所のLSN
正確な停止ポイントは、 ``exclusive`` オプションの影響も受けます。

targetImmediate
リカバリは、一貫した状態に到達するとすぐに、つまりできるだけ早く終了する必要があります。オンラインバックアップから復元する場合、これはバックアップの取得が終了したポイントを意味します

..  Important::
   `targetTime` または`targetLSN` のいずれかが指定された場合、オペレーターは最も近いバックアップを自動的に取得できますが、これは残りのターゲット`targetName` 、`targetXID` 、および`targetImmediate` では不可能です。このような場合、カタログ内の最後の使用可能なバックアップでOKでない限り、 `backupID` を指定することが重要です。

次の例では、\ ``targetName`` ベースのリカバリターゲットを使用します。

.. code:: yaml

   apiVersion: postgresql.cnpg.io/v1
   kind: Cluster
   [...]
     bootstrap:
       recovery:
         source: clusterBackup
         recoveryTarget:
           backupID: 20220616T142236
           targetName: restore_point_1
   [...]

各\ ``recoveryTarget``
構成では、上記のターゲットから1つだけを選択できます。

さらに、特定のタイムラインに\ ``targetTLI``
強制リカバリーを指定できます。

デフォルトでは、以前のパラメーターは包括的であるとみなされ、リカバリターゲットの直後で停止し、
 `the behavior in PostgreSQL <https://www.postgresql.org/docs/current/runtime-config-wal.html#GUC-RECOVERY-TARGET-INCLUSIVE>`_ と一致します

次の例のように、\ ``exclusive`` パラメーターを\ ``true``
に設定することにより、排他的動作を要求できます。ベースバックアップとWALアーカイブの両方でAzureのBLOBコンテナーに依存します。

.. code:: yaml

   apiVersion: postgresql.cnpg.io/v1
   kind: Cluster
   metadata:
     name: cluster-restore-pitr
   spec:
     instances: 3

     storage:
       size: 5Gi

     bootstrap:
       recovery:
         source: clusterBackup
         recoveryTarget:
           backupID: 20220616T142236
           targetName: "maintenance-activity"
           exclusive: true

     externalClusters:
       - name: clusterBackup
         barmanObjectStore:
           destinationPath: https://STORAGEACCOUNTNAME.blob.core.windows.net/CONTAINERNAME/
           azureCredentials:
             storageAccount:
               name: recovery-object-store-secret
               key: storage_account_name
             storageKey:
               name: recovery-object-store-secret
               key: storage_account_key
           wal:
             maxParallel: 8

アプリケーションデータベースの構成
----------------------------------

復旧したクラスターの場合、追加の構成でアプリケーションデータベース名と資格情報を構成できます。アプリケーションデータベースの資格情報を更新するには、独自のパスワードを生成し、シークレットとして保存し、シークレットを使用してデータベースを更新できます。または、オペレーターにランダムで安全なパスワードを使用してシークレットを生成させて使用することもできます。
 :ref:`空のクラスターをブートストラップする `initdb` <空のクラスターをブートストラップする `initdb`>` を参照してください。

シークレットの詳細については、セクションを参照してください。

次の例では、所有者が\ ``app`` 、提供されたシークレットが\ ``app-secret``
を使用してアプリケーションデータベース\ ``app`` を構成します。

.. code:: yaml

   apiVersion: postgresql.cnpg.io/v1
   kind: Cluster
   [...]
   spec:
     bootstrap:
       recovery:
         database: app
         owner: app
         secret:
           name: app-secret
         [...]

上記の構成では、復旧が完了すると次が発生します。

1.データベース ``app`` が存在しない場合、新しいデータベース ``app``
が作成されます。

2.ユーザー\ ``app`` が存在しない場合、新しいユーザー\ ``app``
が作成されます。

3.ユーザー ``app`` がデータベースの所有者でない場合、ユーザー ``app``
はデータベース ``app`` の所有者として付与されます。

4. ``username`` の値がシークレットの\ ``owner``
   の値と一致する場合、アプリケーションデータベースのパスワードはシークレットの\ ``password``
   の値に変更されます。

..  Important::
   レプリカモードが有効になっているレプリカクラスターの場合、オペレーターはPostgreSQLインスタンスにデータベースまたはユーザーを作成しません。これらは元のクラスターからリカバリーされるためです。

リカバリーの内部的な仕組み
--------------------------

オブジェクトストレージにアップロードされたデータを使用して、以前に取得したバックアップから新しいクラスターを
*ブートストラップ* できます。オペレーターは、 ``barman-cloud-restore``
ツールベースバックアップ用と\ ``barman-cloud-wal-restore``
ツールWALファイル用、要求に応じて並列サポートを含むを使用して、リカバリプロセスをオーケストレーションします。

``recovery`` ブートストラップ方法の詳細と手順については、
 :ref:`バックアップからのブートストラップ `recovery` <バックアップからのブートストラップ `recovery`>` を参照してください。

..  Important::
   `PostgreSQL PITR <https://www.postgresql.org/docs/current/continuous-archiving.html#BACKUP-PITR-RECOVERY>`_ の方法がよくわからない場合

は動作しますが、 ``.spec.postgresql.parameters``
に関しては、リカバリクラスターを元のクラスターとして構成することをお勧めします。新しいクラスターが復元されたら、必要に応じて設定を変更できます。

内部では、オペレーターは新しいクラスターの最初のインスタンスにinitコンテナを注入し、initコンテナはオブジェクトストレージからバックアップのリカバリーを開始します。

..  Important::
   新しいPVCのベースバックアップコピーの期間は、バックアップのサイズ、およびネットワークとストレージの両方の速度によって異なります。

ベースバックアップ復旧プロセスが完了すると、オペレーターはリカバリモードでPostgresインスタンスを起動します。このフェーズでは、PostgreSQLは起動していますが、接続を受け入れることができず、ポッドはlivenessプローブによれば正常です。
``restore_command``
を介して、PostgreSQLはアーカイブからWALファイルの取得を開始します。
``maxParallel``
オプションを設定し、並列WALリストア機能を有効にすることにより、このフェーズを高速化できます。

このフェーズは、PostgreSQLがターゲットWALの端またはポイントインタイムリカバリの場合に必要なターゲットに到達すると終了します。実際、オプションで\ ``recoveryTarget``
を指定してポイントインタイムリカバリーを実行できます。指定しない場合、リカバリはデフォルトのターゲットタイムラインで利用可能な最新のWALまで続行されます11までのPostgreSQLの\ ``current``
、バージョン12以降の\ ``latest`` 。

復旧が完了すると、オペレーターは必要なスーパーユーザーのパスワードをインスタンスに設定します。新しいプライマリインスタンスは通常どおり起動し、残りのインスタンスはレプリカとしてクラスターに参加します。

プロセスはユーザーに対して透過的であり、ポッドで実行されているインスタンスマネージャーによって管理されます。

バックアップセクションを使用したクラスターへのリストア
------------------------------------------------------

クラスターリストアのマニフェストには、\ ``backup``
セクションが含まれる場合があります。これは、新しいクラスターが復旧後に、WALのアーカイブとバックアップの取得を開始するように構成されている場合を意味します。

たとえば、以下のセクションは、クラスター\ ``cluster-example-backup``
からブートストラップするクラスターのマニフェストの一部であり、復旧したクラスターのベースバックアップとWALが保存される\ ``recoveredCluster``
という名前のストレージバケットに新しいフォルダーを作成します。

.. code:: yaml

     backup:
       barmanObjectStore:
         destinationPath: s3://backups/
         endpointURL: http://minio:9000
         serverName: "recoveredCluster"
         s3Credentials:
           accessKeyId:
             name: minio
             key: ACCESS_KEY_ID
           secretAccessKey:
             name: minio
             key: ACCESS_SECRET_KEY
       retentionPolicy: "30d"

     externalClusters:
     - name: cluster-example-backup
       barmanObjectStore:
         destinationPath: s3://backups/
         endpointURL: http://minio:9000
         s3Credentials:

異なるクラスターでまったく同じ\ ``barmanObjectStore``
構成を再利用しないでください。ストレージバケットの既存の情報が新しいクラスターによって上書きされる場合が考えられます。

..  Warning::
   オペレーターには、クラスターが情報を含むストレージバケットを上書きしないことを確認する安全チェックが含まれます。既存のストレージを上書きするクラスターは、ポッドがError状態になると`Setting up primary` 状態のままになります。ポッドログには次のものが表示されます `ERROR: WAL archive check failed for server recoveredCluster: Expected empty archive` 

..  Important::
   復旧したクラスターで`cnpg.io/skipEmptyWalArchiveCheck` アノテーションを`enabled` に設定すると、上記のチェックをスキップできます。一般的な使用ケースでは、上記のチェックは正常に動作するため、これはお勧めできません。これは、重大なデータの損失につながる可能性があるため、PostgreSQLリカバリシステムに精通していない限りこれを行わないでください。
