Storage

ストレージは、データベースワークロードで最も重要なコンポーネントです。ストレージは常に利用でき、スケーリング、パフォーマンスが良く、一貫性と耐久性を保証する必要があります。仮想マシンやベアメタルなどの従来の環境に適用されるのと同じ期待と要件は、Kubernetesによって管理されるコンテナコンテキストでも有効です。

注釈

動的にプロビジョニングされるストレージに関しては、Kubernetesに独自の詳細があります。これらには、ストレージクラス永続ボリューム、および*永続ボリューム要求PVC*が含まれます。 VMおよび物理サーバー上のデータベースワークロードのストレージの観点から、長年構築してきた貴重な知識に加えて、これらの概念を所有する必要があります。

ストレージへのアクセスには、主に2つの方法があります。

  • ネットワーク – 直接または間接的に。 (Kubernetesを実行しているホストにローカルにマウントされたNFSボリュームを考えます。)

  • ローカル – ポッドが実行されているノードに直接接続されます。これには、Kubernetesのベアメタルインストールに直接接続されたディスクも含まれます。

Kubernetesで最も一般的な使用パターンであるネットワークストレージは、従来の環境で経験する可能性のあるスループットとレイテンシと同じ問題を示します。これらの問題は、複数のアプリケーションとのI/O競合によりパフォーマンス結果のばらつきが増加する共有環境では強調される可能性があります。

ローカルストレージは、シェアードナッシングアーキテクチャを有効にします。これは、より高く予測可能なパフォーマンスを保証するため、高トランザクションで非常に大規模なデータベースVLDBワークロードに適しています。

警告

CloudNativePGでPostgreSQLクラスターを展開する前に、使用しているストレージがデータベースワークロードに推奨されていることを確認してください。 fio などのツールを使用してストレージをベンチマークし、パフォーマンスの期待値を明確に設定することをお勧めします

次に、 pgbench を使用したデータベース。

注釈

CloudNativePGは、データの永続性の管理に`StatefulSet` を使用しません。むしろ、PVCを直接管理します。詳細については、 Custom Pod Controller を参照してください。

バックアップ リカバリー

CloudNativePGは、バックアップとリカバリーの両方のボリュームスナップショットをサポートしているため、ストレージソリューションを選択するときに、特に非常に大規模なデータベースを管理する場合、この側面も考慮することをお勧めします。

注釈

サポートされているすべてのサービスのリストについては、Kubernetesドキュメントを参照してください container storage interface (CSI) drivers

スナップショット機能を提供します。

CloudNativePGのベンチマーク

データベースを実稼働環境に展開する前に、制御されたKubernetes環境でCloudNativePGのベンチマークを行うことをお勧めします。 Benchmarking のガイドラインに従ってください。

手短に言うと、2つのレベルで動作することをお勧めします。

  • シークエンシャル読み取り、シークエンシャル書き込み、ランダム読み取り、ランダム書き込みのスループットなど、データベースワークロードの関連メトリックを使用して、fioを使用して基になるストレージのパフォーマンスを測定する

  • PostgreSQLで配布されるデフォルトのベンチマークツール、pgbenchを使用してデータベースのパフォーマンスを測定する

注釈

データベースを本番環境に配置する前に、ストレージとデータベースのパフォーマンスの両方を測定する必要があります。これらの結果は、計画段階たとえば、キャパシティプランニングなどにおいてだけでなく、非常に価値があります。また、実稼働ライフサイクル、特にこの種のテストを実行する時間がない緊急事態においても貴重です。データベースは時間の経過とともに変更および進化し、データの分散も同様に、パフォーマンスに影響を与える可能性があります。シークエンシャルな読み取りまたは書き込みの理論的な最大スループットを知ることは、これらの状況において非常に役立ちます。これは、外部ワークロードの影響によって結果が変化しないシェアードナッシングコンテキストに特に当てはまります。

自分のシステムを知り、ベンチマークします。

保存時の暗号化

CloudNativePGでは、保存時の暗号化が可能です。オペレーターは、それを基になるストレージクラスに委任します。この重要なセキュリティ機能の詳細については、ストレージクラスを参照してください。

Persistent Volume Claim Claim PVC

オペレーターは、PGDATA を保存することを目的に、各PostgreSQLインスタンスのPVCを作成します。次に、それを各ポッドにマウントします。

さらに、次のクラスターの作成をサポートしています。

  • WALのボリューム で説明しているように、PostgreSQL WALを保存する別のPVC

  • TablespaceState で説明しているように、PostgreSQLテーブルスペース用に予約された追加の個別ボリューム

CloudNativePGでは、単一のPostgreSQLインスタンスに接続されたボリュームは PVCグループ として定義されます。

ストレージクラスを介した構成

注釈

CloudNativePGは、すべてのストレージクラスと互換的に動作するように設計されました。いつものように、運用に展開する前に、制御された環境でストレージクラスを適切にベンチマークすることをお勧めします。

PostgreSQLクラスのストレージを構成する最も簡単な方法は、次の例のように、特定のサイズのストレージを要求することです。

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: postgresql-storage-class
spec:
  instances: 3
  storage:
    size: 1Gi

前の構成を使用すると、生成されたPVCはデフォルトのストレージクラスで満たされます。ターゲットKubernetesクラスターにデフォルトのストレージクラスがない場合、または既知のストレージクラスでPVCを満たす必要がある場合でも、カスタムリソースに設定できます。

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: postgresql-storage-class
spec:
  instances: 3
  storage:
    storageClass: standard
    size: 1Gi

PVCテンプレートを介した構成

生成されたPVCをさらにカスタマイズするには、次の例のように、カスタムリソース内にPVCテンプレートを提供できます。

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: postgresql-pvc-template
spec:
  instances: 3

  storage:
    pvcTemplate:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
      storageClassName: standard
      volumeMode: Filesystem

WALのボリューム

デフォルトでは、PostgreSQLはすべてのデータをいわゆるPGDATA ディレクトリに保存します。 PGDATA 内のコアディレクトリの1つがpg_wal で、これには、データベースで発生したトランザクション変更のログがセグメントファイルの形式で含まれています。 pg_wal は、PostgreSQLでは歴史的にpg_xlog として知られています。

注釈

通常、各セグメントのサイズは16MBですが、 walSegmentSize オプションを使用してサイズを構成できます。 空のクラスターをブートストラップする `initdb <空のクラスターをブートストラップする initdb>` で説明しているように、このオプションはクラスターの初期化時に適用されます。

ほとんどの場合、PGDATA が存在するのと同じボリュームにpg_wal があっても問題ありません。ただし、WALを別のボリュームに保存すると、いくつかの利点があります。

  • I/Oパフォーマンス – WALファイルをPGDATA とは別のストレージに保存することにより、PostgreSQLはWAL操作通常はシークエンシャル書き込みとデータファイルテーブルやインデックスなどの並列I/Oを利用でき、したがって、垂直方向を向上させることができますスケーラビリティ。

  • 信頼性の向上 – WALファイルに専用のディスク領域を予約することにより、PGDATA ボリュームの領域を使い果たしてもWALの書き込みが妨げられることはありません。この動作により、PostgreSQLプライマリが正しくシャットダウンされます。

  • より細かい制御PGDATApg_wal の両方専用の領域の量を定義でき、 WAL configuration を微調整できます。

とチェックポイント、さらにはコスト最適化のために別のストレージクラスを使用します。

  • I/Oモニタリングの向上PGDATApg_wal の両方で負荷とディスク使用量を常にモニタできます。たとえば、PGDATA のサイズ変更が必要な場合に通知するアラートを設定することもできます。

詳細については、PostgreSQLドキュメントを参照してください。

.spec.walStorage オプションを使用して、WALの別のボリュームを追加できます。 storage フィールドで説明したものと同じルールに従い、専用のPVCをプロビジョニングします。例

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: separate-pgwal-volume
spec:
  instances: 3
  storage:
    size: 1Gi
  walStorage:
    size: 1Gi

注釈

walStorage の削除はサポートされていません。 WALの別のボリュームを追加すると、既存のPostgresクラスターから削除することはできません。

テーブルスペースのボリューム

CloudNativePGは、宣言的テーブルスペースをサポートしています。それぞれが単一のPostgreSQLテーブルスペース専用の1つ以上のボリュームを追加できます。詳細は、 TablespaceState を参照してください。

ボリュームの拡張

Kubernetesが expanding PVCs を許可するAPIを公開

それはデフォルトで有効になっています。ただし、基になるStorageClass でサポートされている必要があります。

特定のStorageClass がボリューム拡張をサポートしているかどうかを確認するには、ストレージクラスのallowVolumeExpansion フィールドを読み取ることができます。

$ kubectl get storageclass -o jsonpath={$.allowVolumeExpansion} premium-storage
true

ボリューム拡張Kubernetes機能の使用

ストレージクラスがボリューム拡張をサポートしている場合、 Cluster のサイズ要件を変更できます。オペレーターはすべてのPVCに変更を適用します。

StorageClassonline volume resizing をサポートしている場合、変更はすぐにポッドに適用されます。基になるストレージクラスがそれをサポートしていない場合、ポッドを削除してサイズ変更をトリガーする必要があります。

続行する最良の方法は、一度に1つのポッドを削除し、レプリカから始めて、各ポッドがバックアップされるまで待機することです。

ストレージの再作成

ストレージクラスがボリューム拡張をサポートしていない場合でも、別のPVCでクラスターを再生成できます。増加したストレージに新しいPVCを割り当て、データベースをそこに移動します。この操作は、クラスターに複数のノードが含まれる場合にのみ実行可能です。

その際、次の例のように、resizeInUseVolumes フラグを無効にすることにより、オペレーターが既存のPVCを変更しないようにする必要があります。

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: postgresql-pvc-template
spec:
  instances: 3

  storage:
    storageClass: standard
    size: 1Gi
    resizeInUseVolumes: False

クラスター全体を別の記憶領域に移動するには、すべてのPVCとすべてのポッドを再作成する必要があります。次の例のように、3つのレプリカを含むクラスターがあるとします。

$ kubectl get pods
NAME                READY   STATUS    RESTARTS   AGE
cluster-example-1   1/1     Running   0          2m37s
cluster-example-2   1/1     Running   0          2m22s
cluster-example-3   1/1     Running   0          2m10s

別のPVCを使用してクラスターを再作成するには、クラスター定義を編集してresizeInUseVolumes を無効にできます。次に、すべてのインスタンスを別のPVCで再作成します。

たとえば、 cluster-example-3 のストレージを再作成します。

$ kubectl delete pvc/cluster-example-3 pod/cluster-example-3

注釈

専用のWALボリュームを作成した場合、このプロセス中に両方のPVCを削除する必要があります。 WALボリュームPVCを再生成する場合にも、同じ手順が適用されます。これは、 .spec.walStorage セクションの`resizeInUseVolumes` も無効にすることにより実行できます。

たとえば、WALストレージ専用のPVCが存在する場合

$ kubectl delete pvc/cluster-example-3 pvc/cluster-example-3-wal pod/cluster-example-3

それが完了したら、オペレーターは、サイズ変更したPVCを使用して別のレプリカの作成を調整します。

$ kubectl get pods
NAME                           READY   STATUS      RESTARTS   AGE
cluster-example-1              1/1     Running     0          5m58s
cluster-example-2              1/1     Running     0          5m43s
cluster-example-4-join-v2      0/1     Completed   0          17s
cluster-example-4              1/1     Running     0          10s

永続ボリュームの静的プロビジョニング

CloudNativePGは、動的ボリュームプロビジョニングで動作するように設計されました。この機能により、ストレージクラスとPVCテンプレートを介してユーザーが要求したときに、ストレージボリュームをオンデマンドで作成できます。 ストレージの再作成 を参照してください。

ただし、場合によっては、Kubernetes管理者がストレージボリュームを手動で作成し、Kubernetesクラスター内での表現形式に関連するPersistentVolume オブジェクトを作成することを優先する場合があります。これは、ボリュームの 事前プロビジョニング としても知られています。

注釈

ボリュームの事前プロビジョニングは、オペレーターの高可用性と自己修復機能に影響を与えるため、回避することをお勧めします。これは、CloudNativePGが構築された完全な宣言型モデルを中断します。

CloudNativePGで事前プロビジョニングされたボリュームを使用するには

  1. Kubernetesの外部でボリュームを手動で作成します。

  2. 実際のCSIドライバーつまり volumeHandlefsTypestorageClassName などに必要な正しいパラメーターを使用して、このボリュームと一致するようにPersistentVolume オブジェクトを作成します。

  3. ストレージセクションごとに、コヒーレントな pvcTemplate を使用してPostgres Cluster を作成します

このセクションは、KubernetesがPersistentVolume と一致し、CloudNativePGが必要なPersistentVolumeClaim を作成できるようにします。

警告

静的プロビジョニングでは、事前にプロビジョニングされたボリュームが存在するKubernetesによってPostgresポッドを正しくスケジュールできることを確認するのはあなたの責任です。スケジューリング構成は、クラスターのアフィニティルールにもとづいています。クラスターを展開した後、Pending にスタックしているポッドがないかを確認してください。状態が続く場合は、それが発生した理由を調査します。

ブロックストレージの考慮事項Ceph/Longhorn

LonghornやCephなど、Kubernetesのほとんどのブロックストレージソリューションでは、復元力を強化するためにボリュームの複数のレプリカを持つことをお勧めします。このアプローチは、組み込みの復元力が不足しているワークロードに適しています。

ただし、 CloudNativePGは、 状態の同期 で説明しているように、インスタンスの数とそれらにアタッチされている永続ボリュームを介して、この復元力をPostgres Cluster に直接統合します。

その結果、ストレージレベルで追加のレプリカを定義すると、書き込み増幅が発生し、ディスクI/Oと領域の使用量が不必要に増加する可能性があります。

CloudNativePGを使用する場合、ブロックストレージレベルのレプリカの数を1つに減らしながら、 Cluster リソース全体のストレージレベルで単一障害点SPoFが存在しないことを確認することを検討します。これは通常、単一のストレージホスト、そして最終的には物理ディスクが、より広範な シェアードナッシングアーキテクチャ の原則に沿って、同じCluster の異なるインスタンスからのブロックをホストしないことを意味します。

Longhornでは、カスタムストレージクラスを作成するときに厳密なローカルデータの局所性を有効にすることにより、このリスクを軽減できます。厳密なローカルデータの局所性を使用してボリュームを作成するための詳細な手順は、 here を参照してください。この設定により、ポッドのデータボリュームがポッド自分自身と同じノードに存在します。

さらに、Postgres Cluster には pod anti-affinity rules が必要です

オペレーターがさまざまなノードにポッドを展開できるように、Longhornは対応するホストにデータボリュームを配置できます。必要に応じて、ボリュームレプリカ数を一時的に2に設定し、後で減らして、古いレプリカを削除することにより、Longhornのボリュームを手動で再配置できます。ホストが破損した場合は、 postgresql.cnpg.io/v1

影響を受けるインスタンス。 CloudNativePGは別のホストでインスタンスを再作成し、データを複製します。

Cephでは、これはCRUSHルールを介して構成できます。 CRUSHルールの構成に関するドキュメントは here で入手できます。これらのルールは、ノードごとにポッドごとに1つのボリュームを保証することを目的としています。ボリュームを別のプールにインポートすることにより、再配置することもできます。