導入
「Pod が別のノードで作り直されても、DB のデータは確実に残っていてほしい」。この本物の永続化を実現するのが PersistentVolume(パーシステントボリューム、PV) と PersistentVolumeClaim(PVC) のペアです。少し登場人物が多いので、役割分担で整理します。
説明
k8s は、ストレージを「供給する側」と「要求する側」に分けて考えます。
- PV(PersistentVolume) … 実体のストレージそのもの。クラウドのディスクや社内のストレージ装置を、管理者やクラウドが用意しておく「供給」側。
- PVC(PersistentVolumeClaim) … アプリ側が出す「これだけの容量が、この読み書き条件で欲しい」という要求書。
利用者(アプリ開発者)は PV の細かい実体を知る必要はありません。PVC で「10Gi ください」と要求を出すと、k8s が条件に合う PV を探して**バインド(結び付け)**します。Pod は PV を直接ではなく、PVC の名前で使います。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-pvc
spec:
accessModes:
- ReadWriteOnce # 1ノードから読み書き可
resources:
requests:
storage: 10Gi # 欲しい容量
---
apiVersion: v1
kind: Pod
metadata:
name: db
spec:
containers:
- name: db
image: postgres:16
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumes:
- name: data
persistentVolumeClaim:
claimName: data-pvc # PVCの名前で使う
毎回 PV を手作業で用意するのは大変です。そこで StorageClass(ストレージクラス) を使うと、PVC が来た瞬間にクラウドへディスクを自動で発注して用意してくれます(動的プロビジョニング)。管理者が先回りして PV を作っておく必要がなくなります。
graph LR
App["アプリ"] --> PVC["PVC<br/>(10Gi欲しい・要求)"]
PVC -->|バインド| PV["PV<br/>(供給された実体)"]
PV --> Disk[("クラウドの<br/>実ディスク")]
SC["StorageClass"] -.->|動的に自動用意| PV
データを持ち続けるアプリ(DB など)は、Pod を1つずつ安定した名前と専用ストレージ付きで管理する StatefulSet(ステートフルセット) と組み合わせるのが定番です。StatefulSet は各 Pod に固有の PVC を割り当て、作り直しても同じデータに戻れるようにします。PV/PVC は、その土台となる仕組みです。