このブログ記事では、Kubernetesにおける永続ボリュームとステートフルセットについて紹介します。

ほぼすべてのアプリケーションでは、データを永続的に保存するためのファイルストレージやデータベースが必要です。 しかし、デフォルトのコンテナは根本的にデータの永続性を提供していません。 Dockerでは、ボリュームを使用してこれを実現できます(以前に開発環境のセットアップの文脈で説明しました)。 これに対し、Kubernetesは水平スケーリングシステム向けにボリュームに関する様々な抽象化を提供しています。 そのため、この記事では、Kubernetesでデータの永続性を実現するための永続ボリュームとステートフルセットについて簡単に説明します。
永続ボリューム
永続ボリュームを設定する方法は複数ありますが、推奨されるアプローチは永続ボリューム要求(PVC)とストレージクラスを使用することです。 PVCはポッドが必要とする永続ボリュームを指定するもので、通常は開発者によって設定されます。 ストレージクラスは、基盤となるローカルまたはクラウドストレージの抽象化であり、PVCに基づいて永続ボリュームを作成・提供します。 これは通常、クラスター管理者によって設定されます。これらの抽象化により、開発者とクラスター管理者の間でシームレスな連携が可能になります。

上は、ポッドに永続的なストレージを提供するためにPVCとストレージクラスをどのように設定できるかを示した簡略化された図です。 この図ではクラウドストレージのみに言及していますが、これはローカルストレージに紐づけられた永続ボリュームがクラスター内の特定のノードに紐づけられ、 クラスターがクラッシュした場合に存続せず、真に永続的なファイルストレージやデータベースには適してないためです。 また、図が示すように、永続ボリュームは名前空間化されておらず、クラスター全体からアクセス可能です。
# ポッド ("postgres.yaml")
# ...
spec:
containers:
- name: postgres
image: postgres
ports:
- containerPort: 5432
volumeMounts: # コンテナにマウント
- mountPath: "/var/lib/postgresql/data"
name: postgres_volume
volumes: # ポッドにマウント
- name: postgres_volume
persistentVolumeClaim:
claim-name: pvc-postgres
# PVC ("pvc-postgres.yaml")
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-postgres
spec:
storageClassName: sc-default # pvをリクエストするストレージクラスの名前
accessModes:
- ReadWriteOnce # 1つのノードからのみ読み書きが可能
# (他にReadWriteOncePod, ReadOnlyMany, ReadWriteManyなどがある)
resources:
requests:
storage: 10Gi # 10GiB (gibibyte)を要求
上記は、開発者がPostgreSQLのポッドとPVCを設定するためのYAMLファイルの例を示しています。 PVCの抽象化により、開発者はストレージの場所や選択したクラウドソリューションに関係なく、宣言的に永続ボリュームを要求できることがわかります。 同様に、ConfigMapやSecretsに対してもPVCを設定し、同じファイル構造を使用してポッドやコンテナにマウントすることができ、 コンテナがボリュームを通じて設定やシークレット(PostgreSQL設定や認証情報など)にアクセスできるようになります。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: sc-default
annotations:
storageclass.kubernetes.io/is-default-class: "true" # storageClassName=""のPVCはこのストレージクラスにリクエストする
provisioner: csi-driver.example-vendor.example
reclaimPolicy: Retain # ボリュームが解放されたらどうするか(Deleteがデフォルト)
allowVolumeExpansion: true # プロビジョナーによっては設定可能
parameters: # プロビジョナーによる
#...
上記は、管理者がストレージクラスを設定するためのYAMLファイルの例を示しています。 ストレージクラスを作成することで、管理者は各ポッドに対して永続ボリュームを設定する必要がなくなります。 プロビジョナー(AWS、Azureなど)によって利用可能なパラメータが異なるため、 管理者はストレージクラスを適切に設定するために利用可能なパラメータを確認する必要があります。
ステートフルセット
前のセクションでは、PostgreSQLポッド用の永続ボリューム要求(PVC)をセットアップし、 永続ボリュームをポッドとそのコンテナにマウントする方法について説明しました。 しかし、通常はボトルネックを避けるためにこのポッドの複数のレプリカを作成したいのですが、 これはステートレスアプリケーションほど簡単ではありません。レプリケーションによってデータベースを水平方向にスケーリングする場合、 マスターデータベース(読み取りと書き込みを許可)と、読み取り専用で同期されるワーカーデータベースを設定することでデータの一貫性を確保する必要があります。
デプロイメントは、ランダムな順序でランダムなハッシュを持つ同一の交換可能なポッドを前提としているため、
ポッドに異なる役割を設定することができません。そのため、代わりにステートフルセットを使用する必要があります。
ステートフルセットでは、ポッドに異なる役割を割り当て、特定の順序で固定のIDとエンドポイントを持つポッドを作成できます。
これにより、読み書き用のマスターデータベースpostgres-0
(postgres-0.svc-db
経由でアクセス可能)と、
マスターか直前に作成されたワーカーのレプリカであるワーカーデータベース(読み取り用にpostgres-<number>.svc-db
経由でアクセス可能)を作成できます。
ステートフルセットは、ファイルストレージやデータベースなどのステートフルアプリケーションのレプリカを設定するのに役立つ特性を提供しますが、 クローニング、データ同期、バックアップは手動で管理する必要があります。また、コンテナ化は本質的にファイルストレージやデータベースなどのステートフルアプリケーションのスケーリングに適しておらず、 これらのアプリケーションには多くの場合、シャーディング(データベースシリーズで簡単に触れました)などの水平スケーリングのための独自のソリューションがあります。 したがって、永続的なストレージを必要とするスケーラブルなステートフルアプリケーションには、 AWS S3やRDSなどのクラウドソリューションを使用する方が良いことが多いです。
結論
この記事では、ステートフルアプリケーションの設定とスケーリングに重要な永続ボリュームとステートフルセットについて簡単に説明しました。 これらは、データ永続性を必要とする社内の拡張可能なソリューション開発を含む比較的大規模なプロジェクトで関連する可能性がありますが、 ステートフルアプリケーションとコンテナ化の本質的な非互換性のため、クラウドソリューションと比較して使用頻度は低いです。 小規模なプロジェクトでは、PVCとストレージクラスから永続ボリュームをポッドに対して使用することもできますが、 そのような過剰に設計されたソリューションを使用する代わりに、単純にDocker Composeとボリュームを使用してデータベースとストレージ用の単一のコンテナを設定することもできます。
リソース
- Kubernetes. n.d. Kubernetes Documentation. Kubernetes.
- TechWorld with Nana. 2021. Kubernetes StatefulSet simply explained | Deployment vs StatefulSet. YouTube.
- TechWorld with Nana. 2021. Kubernetes Volumes explained | Persistent Volume, Persistent Volume Claim & Storage Class. YouTube.