ストレージ

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

重要

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

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

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

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

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

ローカルストレージは、シェアードナッシングアーキテクチャを有効にします。これは、より高い予測可能なパフォーマンスを保証するため、高トランザクションおよびVery Large Database(VLDB)ワークロードにより適しています。

警告

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

注釈

CloudNativePGは、データの永続性を管理するために`StatefulSet` sを使用しません。むしろ、永続的なボリュームクレーム(PVC)を直接管理します。もっと詳しく知りたい場合は、 カスタムポッドコントローラー ドキュメントをお読みください。

CloudNativePGのベンチマーク

EDBは、データベースを本番環境にデプロイする前に、制御されたKubernetes環境でCloudNativePGをベンチマーク評価するためのオープンソースのガイドラインとHelmチャートのオープンソースセットである

cnp-bench を維持します。

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

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

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

重要

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

保存時の暗号化

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

永続ボリュームクレーム

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

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

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

注釈

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

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

  • I/Oパフォーマンス :WALファイルをPGDATA とは別のストレージに保存することにより、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に適用されます。基になるストレージクラスがそれをサポートしていない場合は、ポッドを削除してサイズ変更をトリガーする必要があります。

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

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

`docs <https://github.com/kubernetes-sigs/azuredisk-csi-driver/blob/master/docs/known-issues/sizegrow.md>`__ で説明されているように、Azureディスクは「非接続」状態でのみ拡張できます。

つまり、PostgreSQLクラスターで使用されるディスクのサイズを変更するには、手動ロールアウトを実行し、最初にディスクにバインドされたPVCを使用してPodをホストするノードを遮断する必要があります。これにより、オペレーターはバックグラウンドのディスクサイズ変更が完了する前に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.

次に、ノードのコルドンを解除できます。

kubectl uncordon <node of cluster-example-3>

Podが正しく再作成され、 Running and 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}

そのため、残りのポッドに対してこれらの手順を繰り返すことができます。

重要

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

ストレージの再作成

ストレージクラスがボリューム拡張をサポートしていない場合でも、ストレージを増やして新しい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を削除する必要があります。さらに、 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は動的ボリュームプロビジョニングと連携するように設計されています。これにより、ユーザーが要求したときに、前述のストレージクラスと永続ボリュームクレームテンプレートを介して、ストレージボリュームをオンデマンドで自動的に作成できます。

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

重要

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

次の手順に従って、CloudNativePGで事前にプロビジョニングされたボリュームを使用できます。

1.Kubernetesの外部にボリュームを手動で作成する

2.実際のCSIドライバー(つまり、 volumeHandle 、fsType 、storageClassName など)で必要とされる正しいパラメーターを使用して、上記のボリュームと一致するPersistentVolume オブジェクトを作成します

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

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

警告

静的プロビジョニングでは、クラスターのアフィニティルールに基づいて、事前にプロビジョニングされたボリュームが存在するKubernetesによってPostgresポッドを正しくスケジュールできることを保証するのはあなたの責任です。クラスターをデプロイした後、ポッドが`Pending` でスタックしていないかどうかを確認し、状態が解決しない場合は、なぜこれが起こっているのかを調査してください。