保管所

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

重要

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

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

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

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

Kubernetes で最も一般的な使用パターンであるネットワーク ストレージでは、従来の環境で発生する可能性があるのと同じスループットと待機時間の問題が発生します。これらは、複数のアプリケーションとの I/O 競合によってパフォーマンス結果の変動性が高まる共有環境で強調される可能性があります。

ローカル ストレージを使用すると、シェアード ナッシング アーキテクチャが可能になります。これは、より高い予測可能なパフォーマンスが保証されるため、高いトランザクションおよび超大規模データベース (VLDB) のワークロードにより適しています。

警告

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

CloudNativePG のベンチマーク

EDB は、データベースを本番環境にデプロイする前に、制御された Kubernetes 環境で CloudNativePG をベンチマークするためのガイドラインと Helm チャートのオープン ソース セットである cnp-bench を維持しています。

簡単に言うと、cnp-bench は 2 つのレベルで動作するように設計されています。

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

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

重要

ストレージとデータベースの両方のパフォーマンスを測定することは、データベースが運用に入る前に**実行する必要があるアクティビティです。ただし、このような結果は、計画段階 (キャパシティ プランニングなど) だけでなく、特に緊急事態 (この種のテストを実行する余裕がない場合) の生産ライフサイクルでも非常に価値があります。データベースは確かに時間の経過とともに変化し、進化し、データの分散も変化し、パフォーマンスに影響を与える可能性があります。シーケンシャルな読み取りまたは書き込みの理論上の最大スループットを知ることは、そのような状況で非常に役立つことがわかります.特にシェアード ナッシング コンテキストでは、外部ワークロードの影響によって結果が変化することはありません。 **あなたのシステムを知り、ベンチマークしましょう。

永続ボリュームの要求

オペレーターは、PGDATA を格納することを目的として、PostgreSQL インスタンスごとに永続ボリューム要求 (PVC) を作成し、それを各 Pod にマウントします。

さらに、以下の WALのボリューム で説明されているように、PostgreSQL Write-Ahead Log (WAL) を保存する別の PVC を使用したクラスターの作成をサポートしています。

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

ストレージ クラスによる構成

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

重要

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

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 (歴史的に PostgreSQL では pg_xlog として知られている) で、データベースで発生したトランザクション変更のログがセグメント ファイルの形式で含まれています。

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

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

  • 信頼性の向上 : WAL ファイル専用のディスク スペースを予約することで、PGDATA ボリュームのスペースが枯渇しても WAL 書き込みが妨げられず、PostgreSQL プライマリが正しくシャットダウンされることを常に確認できます。

  • より細かい制御 : PGDATA と pg_wal の両方に専用のスペースの量を定義し、WAL configuration とチェックポイントを微調整し、コスト最適化のために別のストレージ クラスを使用することもできます

  • より良いI/O監視 : PGDATA と pg_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 クラスターから削除することはできません。

ボリューム拡張

Kubernetes は expanding PVCs を許可する API を公開します

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

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

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

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

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

StorageClass が online volume resizing をサポートする場合

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

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

AKS での PVC ボリュームの拡張

現時点では、 Azure is not able to resize the PVC's volume without restarting the pod . CloudNativePG は、 オペレーター構成 の ENABLE_AZURE_PVC_UPDATES 環境変数によってこの制限を克服しました。 'true' に設定すると、CloudNativePG は Postgres クラスターのローリング更新をトリガーします。

または、次の回避策に従って、AKS でボリュームのサイズを手動で変更することもできます。

AKS でのボリューム拡張の回避策

次の手順に従って、AKS で 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

Azure ディスクは、 docs で説明されているように、「接続されていない」状態でのみ拡張できます。 つまり、PostgreSQL クラスターで使用されるディスクのサイズを変更するには、手動でロールアウトを実行する必要があります。最初に、ディスクにバインドされた PVC を使用して Pod をホストするノードを封鎖します。 .これにより、Operator が Pod を再作成し、バックグラウンド ディスクのサイズ変更が完了する前にすぐにその PVC に再接続することが防止されます。

最初のステップは、次のように、新しいサイズ (たとえば “2Gi”) を適用してクラスター定義を編集することです。

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

  storage:
    storageClass: default
    size: 2Gi

cluster-example-1 Pod がクラスターのプライマリであると仮定すると、最初にレプリカに進むことができます。たとえば、cluster-example-3 Pod をホストする kubernetes ノードを封鎖することから始めます。

kubectl cordon <node of cluster-example-3>

次に、cluster-example-3 Pod を削除します。

$ kubectl delete pod/cluster-example-3

次のコマンドを実行します。

kubectl get pvc -w -o=jsonpath={.status.conditions[].message} cluster-example-3

次の出力が表示されるまで待ちます。

Waiting for user to (re-)start a Pod to finish file system resize of volume on node.

次に、ノードを uncordon できます。

kubectl uncordon <node of cluster-example-3>

Pod が正しく再作成され、Running および Ready 状態になるまで待ちます。

kubectl get pods -w cluster-example-3
cluster-example-3   0/1     Init:0/1   0          12m
cluster-example-3   1/1     Running   0          12m

次に、次のコマンドを実行して PVC 拡張を確認します。構成どおりに「2Gi」が返されます。

kubectl get pvc cluster-example-3 -o=jsonpath={.status.capacity.storage}

したがって、残りの Pod に対してこれらの手順を繰り返すことができます。

重要

kubectl cnpg promote (たとえば、cluster-example-3 をプライマリに昇格させるための kubectl cnpg promote cluster-example 3 ) を使用して、スイッチオーバーによって新しいサイズ変更された Pod を昇格させた後、プライマリ インスタンスに関連付けられたディスクのサイズ変更を最後のディスクとして残してください。

ストレージを再作成しています

ストレージ クラスがボリューム拡張をサポートしていない場合でも、ストレージを増やした新しい 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 とすべての Pod を再作成する必要があります。次の例のように、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 を削除する必要があります。さらに、.spec.walStorage セクションの resizeInUseVolumes も無効にすることで、WAL ボリューム PVC を再生成する場合にも同じ手順が適用されます。

例 (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