Deploying PostgreSQL as a StatefulSet in Kubernetes

KubernetesでStatefulSetとしてPostgreSQLをデプロイする

  • ITOps・DevOps
6分で読めます 更新日 Jul 2, 2021

ポイント: KubernetesでPostgreSQLをStatefulSetとしてデプロイすることで、永続ストレージとユニークなポッドIDを提供し、ステートフルアプリケーションの効率的な管理が可能になります。これにより、順序付きのデプロイメント、スケーリング、およびConfigMapsを通じた環境変数の管理が簡素化されます。

  • StatefulSetsは、ステートフルアプリケーションの順序付きデプロイメントとスケーリングを可能にします。
  • ConfigMapsを利用することで、デプロイメントにおける環境変数の管理が簡素化されます。

アプリケーションには、単一の大きなアプリケーションからマイクロサービスベースのアプリケーションまで、さまざまな種類があります。それらのアプリケーションの状態に関しては、2つの状態があります:

  • ステートレスアプリケーションは、過去のトランザクションについての知識がなく、独立して隔離して実行できます。
  • ステートフルアプリケーションは、過去の情報(状態)についての完全な知識を持っています。

私たちが使用するアプリケーションのほとんどはステートフルアプリケーションであり、その状態データはユーザーの好み、最近の活動、データベーストランザクション、資格情報、設定などで構成される可能性があります。

Kubernetesは、Kubernetesクラスター内でステートフルアプリケーションを作成する際にStatefulSetsを提供します。コンテナ化された環境内で状態を管理することは、Kubernetesでデータベースクラスターをデプロイする人気が高まる中、さらに重要になっています。

この記事では、StatefulSetsを使用してKubernetesクラスター上にPostgreSQLデータベースをデプロイする方法に焦点を当てます。

Kubernetes StatefulSetsとは?

StatefulSetは、ステートフルアプリケーションを管理するために使用できるKubernetesワークロードAPIオブジェクトです。

通常のデプロイメントでは、ユーザーはポッドがどのようにスケジュールされるかを気にしませんが、デプロイされたアプリケーションに悪影響を与えなければ問題ありません。しかし、永続ストレージを持つステートフルアプリケーションでは、状態を保持するためにポッドを適切に特定する必要があります。

StatefulSetは、再スケジュールに関係なくその値に関連する永続的な識別子を持つポッドを作成することによって、この機能を提供します。このようにして、ポッドが再作成されても、ストレージボリュームに正しくマッピングされ、アプリケーションの状態が保持されます。

StatefulSetsのユースケース

StatefulSetsには、いくつかのユースケースがあります。

Kubernetes StatefulSetsユースケース

順序付きのデプロイとスケーリング

アプリケーションが複数のコンテナに依存する場合、順序付きのスケーリングアプローチは、デプロイメントとスケーリングシナリオで依存するコンテナが秩序正しく作成されることを保証します。

順序付きの自動ローリングアップデート

依存するアプリケーションやマイクロサービスを更新する際にも、秩序正しく更新される必要があります。さらに、更新は機能に影響を与えてはなりません。

そのため、ユーザーはStatefulSetを使用して、アプリケーションやマイクロサービスの更新順序を決定できます。

永続ストレージのマッピング

データベースを考慮する場合、永続ストレージはアプリケーションがデータを保存するために非常に重要です。StatefulSetを使用すると、ユーザーは:

  1. 各永続ストレージに対応するポッドを定義する
  2. 回復力のあるアプリケーションデプロイメントを作成する

固有のネットワーク識別子を使用して永続的なネットワーク接続を作成する

固有の識別子を使用すると、ネットワークユーザーは再スケジュール時にIP変更を気にせず特定のポッドへのトラフィックを管理およびルーティングできます。これにより、ポッド間のネットワーク通信を制御する能力が向上し、望ましいポッド用に永続的なルーティング、ポリシー、およびセキュリティ設定を構成することができます。

これらの利点があるにもかかわらず、StatefulSetsはすべての要件に対するソリューションを提供するわけではありません。たとえば、StatefulSetsはデプロイメントやReplicaSetsと交換可能ではありません。これらは代わりにステートレス構成を目指しています。

StatefulSetsの欠点

StatefulSetsには、アプリケーションをデプロイする前にユーザーが認識しておくべき制限がいくつかあります。

  • StatefulSetのストレージは、ストレージクラスに基づくPersistentVolumeプロビジョナーによってプロビジョニングされる必要があるか、あらかじめプロビジョニングされる必要があります。
  • ポッドをスケーリングまたは削除しても、データの安全性を確保するために基盤となる永続ストレージには影響しません。プロビジョニングされたボリュームはKubernetes内に残ります。
  • ユーザーは、StatefulSetsのネットワークアイデンティティを確保するためにヘッドレスサービスを手動で作成する必要があります。
  • StatefulSetが削除されるときに、現在のポッドが終了することは保証されません。したがって、ベストプラクティスとして、ユーザーはStatefulSetをゼロポッドにスケールダウンしてから削除するためのSOPを実装することをお勧めします。
  • デフォルトのポッド管理ポリシーでのローリングアップデートは、ポッドが破損した場合(アプリケーション設定エラー、不良バイナリなど)にデプロイ時に問題を引き起こす可能性があります。このような場合、ユーザーは:
    • 以前のデプロイメントテンプレートに手動で戻す必要があります。
    • 新しい更新を再実行する前に、壊れたポッドを削除する必要があります。

KubernetesクラスターでStatefulSetを設定する

StatefulSetの基本的な理解が得られたので、サンプルのStatefulSetデプロイメントを見てみましょう。

StatefulSetsはデータベースデプロイメントに最適です。この例では、永続ストレージボリュームを持つStatefulSetとしてPostgreSQLデプロイメントを作成します。

postgresql.yaml

    # PostgreSQL StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgresql-db
spec:
  serviceName: postgresql-db-service
  selector:
    matchLabels:
      app: postgresql-db
  replicas: 2
  template:
    metadata:
      labels:
        app: postgresql-db
    spec:
      containers:
        - name: postgresql-db
          image: postgres:latest
          volumeMounts:
            - name: postgresql-db-disk
              mountPath: /data
          env:
            - name: POSTGRES_PASSWORD
              value: testpassword
            - name: PGDATA
              value: /data/pgdata
  # Volume Claim
  volumeClaimTemplates:
    - metadata:
        name: postgresql-db-disk
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 25Gi

上記のYAMLファイルでは、PostgreSQLデータベースをデプロイするためのシンプルなStatefulSetを定義しました。replicas: 2の2つのポッドを持つpostgresql-dbという名前のStatefulSetを作成しています。

さらに、volumeClaimTemplateを使用して永続ボリュームを作成し、PostgreSQLデータを格納するためにStatefulSetで使用しています。デフォルトの永続ボリュームプロビジョナーがボリュームをプロビジョニングし、次のコマンドを実行することでデプロイできます。

    kubectl apply -f postgresql.yaml

結果:

PostGreSQL結果

これで、Kubernetesクラスターの外部に公開するためのサービスが必要なPostgreSQL StatefulSetが正常に作成されました。それは、StatefulSetを指すサービスを作成することによって行うことができます。

postgresql-service.yaml

    # PostgreSQL StatefulSet Service
apiVersion: v1
kind: Service
metadata:
  name: postgres-db-lb
spec:
  selector:
    app: postgresql-db
  type: LoadBalancer
  ports:
    - port: 5432
      targetPort: 5432

これにより、ロードバランサーが作成され、サービスは「app: postgresql-db」というセレクターを使用してPostgreSQLデータベースを公開します。以下のコマンドを実行することでサービスを作成できます。

    kubectl apply -f postgresql-service.yaml

結果:

PostGreSQLサービス

次に、以下のコマンドを実行して、StatefulSetとサービスの両方がKubernetesで正常に作成されたかどうかを確認しましょう。

    kubectl get all

結果:

StatefulSetsサービス結果

結果は、2つのポッドが作成され、IP 10.111.253.4を使用してポート5432でStatefulSetを公開するロードバランサーサービスが稼働していることを示しています。

接続性のテスト

PostgreSQLをデプロイしたので、問題なくアクセスできることを確認する必要があります。接続を初期化するためにpgAdmin4クライアントを使用します:

  1. 環境にpgAdminクライアントをダウンロードします。
  2. 接続して初期化を試みます。

上記のデプロイメントで、postgres-db-lbサービスの外部IP(10.111.253.4)をポート5432で使用します。PostgreSQL StatefulSetの環境変数でパスワードのみを定義したため、構成には定義したパスワードで「postgres」というデフォルトのユーザー名が含まれます。

pgAdmin環境

すべての詳細が正しければ、「保存」をクリックすると接続が開始され、ユーザーは接続されたデータベースを見ることができます。

pgAdminコンソール

StatefulSetでのConfigMapの使用

前述の例では、StatefulSet YAMLで環境変数を定義しました。

ただし、最良のプラクティスは、環境変数をConfigMapsを使用して分離し、StatefulSetデプロイメントからConfigMapを呼び出すことです。これにより、デプロイメントの各コンポーネントを管理および維持しやすくなります。

それでは、ConfigMapを作成し、以下のようにStatefulSet YAMLを修正しましょう。

postgresql-configmap.yaml

    # PostgreSQL StatefulSet ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-db-config
  labels:
    app: postgresql-db
data:
  POSTGRES_DB: testdb
  POSTGRES_USER: testdbuser
  POSTGRES_PASSWORD: testdbuserpassword
  PGDATA: /data/pgdata

上記のConfigMapでは、PostgreSQLデータベース、ユーザー、パスワード、データストアを指定するために環境変数を拡張しました。次に、このコマンドを使用してconfigMapを作成し、構成を表示しましょう:

    kubectl apply -f .postgresql-configmap.yaml

結果:

PostGreSQL Configmap

describe関数を使用して作成されたConfigMapの情報を取得できます:

    kubectl describe configmap postgres-db-config

結果:

PostGreSQL DB Config

次のステップは、ConfigMapからデータを呼び出すようにStatefulSetを修正することです。これは、envFromフィールドを使用して上記のConfigMapを指すことによって行うことができます。これにより、ConfigMapのデータを使用してStatefulSetを作成できます。

postgresql.yaml

    # PostgreSQL StatefulSet - ConfigMap
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgresql-db
spec:
  serviceName: postgresql-db-service
  selector:
    matchLabels:
      app: postgresql-db
  replicas: 2
  template:
    metadata:
      labels:
        app: postgresql-db
    spec:
      containers:
        - name: postgresql-db
          image: postgres:latest
          volumeMounts:
            - name: postgresql-db-disk
              mountPath: /data
          # Config from ConfigMap
          envFrom:
          - configMapRef:
              name: postgres-db-config
  # Volume Claim
  volumeClaimTemplates:
    - metadata:
        name: postgresql-db-disk
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 25Gi

永続ボリュームを使用すると、基盤となるデータベースの削除は、ポッドのエラーが発生した場合でも保持されます。StatefulSetとして、ポッドの状態も保持され、再作成時に正しいボリュームに割り当てられます。

次のコマンドを使用してポッドを特定できます:

    kubectl get pvc

結果:

ポッドの結果を特定する

状態の管理はアプリケーション機能にとって重要

Kubernetes StatefulSetsは、ユーザーがKubernetesクラスター内でステートフルアプリケーションやサービスを簡単に作成および管理できるようにします。しかし、これらのStatefulSets構成にはいくつかの複雑さが伴うため、展開を実施する前に慎重に計画する必要があります。

さらに、StatefulSetsは、データベースアプリケーション、支払いサービスなど、状態を管理することがアプリケーション機能の重要な部分である場合に最適なソリューションです。

これらの投稿は私自身のものであり、必ずしもBMCの立場、戦略、または意見を表すものではありません。

ITOps・DevOpsの関連記事

The Briefを購読する

このオファーに登録することで、あなたはBMCのプライバシーポリシーを読み、同意したことを確認します。

ありがとう

あなたはThe Briefに登録されました
The Briefはメインフレームとエンタープライズオーケストレーション—BMC AMIとControl-M—および、両者に関するアナリストの研究、顧客の展開、イベントをカバーしています。