Kubernetes StatefulSetにおける永続的アイデンティティとストレージの管理手法
分散システムやデータベース(MySQL、PostgreSQL、Kafkaなど)の運用において、ポッドの再起動後も同一のアイデンティティとデータを保持することは、システムの整合性を維持するための必須要件です。標準的なDeploymentでは、ポッドはエフェメラル(一時的)な存在として扱われ、再起動のたびにランダムなホスト名とIPアドレスが割り当てられます。このようなステートレスな設計は、データの永続性やマスター・スレーブ間の固定的な通信が必要なワークロードにおいて、重大な運用上の制約となります。本稿では、これらの課題を解決するStatefulSetの内部構造と、Headless ServiceおよびVolumeClaimTemplatesを用いた実装手法について技術的分析を行います。
1. StatefulSetとDeploymentの構造的相違
StatefulSetは、ポッドの「順序性」と「一意性」を保証するために設計されています。Deploymentとの主な違いは以下の通りです。
- 識別子: Deploymentはランダムなサフィックスを付与しますが、StatefulSetは
mysql-0,mysql-1のように固定の序数インデックスを付与します。 - ストレージ: Deploymentは全レプリカで同一のボリュームを共有(またはボリュームなし)しますが、StatefulSetは各ポッドに専用のPVC(PersistentVolumeClaim)を1対1で割り当てます。
- デプロイ順序: Deploymentは並列で作成・削除されますが、StatefulSetはインデックス0から順次作成され、削除時は逆順(OrderedReady)で実行されます。
2. Headless Serviceによるネットワーク識別子の固定
StatefulSetのポッドが固定のFQDN(Fully Qualified Domain Name)を持つためには、Headless Serviceとの連携が不可欠です。clusterIP: None を設定することで、Serviceは仮想IPを持たず、DNSクエリに対して個々のポッドのIPアドレスを直接返します。
apiVersion: v1
kind: Service
metadata:
name: sfs-service01
spec:
selector:
app.kubernetes.io/name: web-sfs01
type: ClusterIP
clusterIP: None
ports:
- protocol: TCP
port: 80
この設定により、各ポッドは [Pod Name].[Service Name].[Namespace].svc.cluster.local という形式で相互に通信可能となります。これは、クラスタ内でのリーダー選定やデータ同期において、特定のノードを明示的に指定する必要がある分散データベースにおいて極めて重要です。
3. StatefulSetの実装とポッドのライフサイクル
以下は、Nginxイメージを使用したStatefulSetの基本構成です。serviceName フィールドによって、前述のHeadless Serviceと明示的に紐付けられます。
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: sfs-test01
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: web-sfs01
serviceName: sfs-service01
template: metadata:
labels:
app.kubernetes.io/name: web-sfs01
spec:
containers:
- name: nginx
image: nginx:latest
4. VolumeClaimTemplatesによる動的プロビジョニング
StatefulSetの最も強力な機能の一つは、volumeClaimTemplates です。これにより、ポッドごとに独立したストレージが自動的にプロビジョニングされます。ポッドが削除されてもPVCは保持されるため、再起動後のポッドは以前と同じデータボリュームに再マウントされます。
volumeClaimTemplates:
- metadata:
name: sfs-vol01
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: pv-sfs-test01
resources:
requests:
storage: 5Mi
Troubleshooting
StatefulSetの運用において最も頻繁に遭遇する問題は、スケーリング時の PVCのPending状態 です。手動でPersistentVolume(PV)を管理している環境において、replicas を増やした際、対応する storageClassName を持つ利用可能なPVが不足していると、新しいポッドは Pending のまま起動しません。⚠️
また、StatefulSetを削除してもPVCは自動削除されないため、ディスク容量の枯渇を招く可能性があります。不要になったデータは、StatefulSetの削除後に手動で kubectl delete pvc を実行してクリーンアップする必要があります。
Operational Verifications
デプロイ後のリソース状態およびネットワーク疎通の確認ログを以下に示します。
# リソースの起動確認
% kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
sfs-test01-0 1/1 Running 0 80s 10.244.2.9 worker-node-01
sfs-test01-1 1/1 Running 0 80s 10.244.1.17 worker-node-02
sfs-test01-2 1/1 Running 0 79s 10.244.1.18 worker-node-02
# Headless Serviceの確認
% kubectl get svc sfs-service01
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
sfs-service01 ClusterIP None <none> 80/TCP 14m
# 特定ポッドへの疎通確認 (Pod 1への直接アクセス)
% kubectl exec -it nginx-client -- curl -I sfs-test01-1.sfs-service01.default.svc.cluster.local
HTTP/1.1 200 OK
Server: nginx/1.25.x
Content-Type: text/html
Lessons Learned
StatefulSetの導入は、単なるポッドの管理を超え、インフラ層におけるストレージのライフサイクル管理とネットワークトポロジの固定化を意味します。特にデータベースのコンテナ化においては、volumeClaimTemplates によるデータの局所性確保と、Headless Serviceによる安定したエンドポイントの提供が、システムの信頼性を左右する決定的な要因となります。💡 運用設計においては、ポッドの異常終了時におけるPVCの再アタッチ時間や、スケーリング時のPV供給能力を事前に検証しておくことが推奨されます。