PV 与 PVC 持久化存储
上一章的 emptyDir、hostPath 要么随 Pod 消失、要么绑定节点,数据库等应用需要「Pod 没了数据还在」的存储。PV(PersistentVolume)与 PVC(PersistentVolumeClaim)把存储从 Pod 中抽象出来:管理员提供存储、应用声明需求,两者解耦后由系统自动绑定。
核心概念
- PV:集群里的存储资源,由管理员预先创建,或由 StorageClass 动态生成,与具体节点无关。
- PVC:应用提出的「存储申请」,声明容量与访问模式。
- Pod 只引用 PVC,不关心背后是 NFS 还是云盘。
静态供给:先建 PV 再申请
管理员先创建 PV,声明容量、访问模式与回收策略:
| accessModes | 含义 |
|---|---|
| ReadWriteOnce | 单节点读写 |
| ReadOnlyMany | 多节点只读 |
| ReadWriteMany | 多节点读写 |
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-10g
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain # Retain/Delete
nfs:
server: 192.168.1.100
path: /exports/pv1
回收策略决定 PVC 释放后 PV 的去向:Retain 保留数据待管理员处理,Delete 连底层存储一起删除(Recycle 已废弃)。对应的 PVC 声明容量与访问模式:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-claim
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
PVC 会挑选容量足够、访问模式匹配的空闲 PV 并绑定。Pod 里通过 claimName 引用:
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: data
mountPath: /var/lib/data
volumes:
- name: data
persistentVolumeClaim:
claimName: data-claim
动态供给:StorageClass
静态供给每次都要手动建 PV,StorageClass 可让它自动化:定义 provisioner(存储插件),PVC 声明 storageClassName 后由插件自动创建 PV:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: cloud-fast
provisioner: kubernetes.io/aws-ebs # 以云盘插件为例,可替换为 nfs 等其他插件
PVC 里加 storageClassName: cloud-fast 即可触发动态创建。
PV 状态机与排错
PV 生命周期:Available(空闲)→ Bound(已被 PVC 绑定)→ Released(PVC 删除后)。PVC 卡在 Pending 时按顺序排查:
kubectl get pvc # STATUS=Pending
kubectl describe pvc xxx # 事件会写明原因
kubectl get pv # 有没有容量/访问模式匹配的空闲 PV
kubectl get sc # 声明的 storageClass 是否存在
常见原因:声明的 storageClassName 不存在、静态供给下没有匹配的 PV、容量或访问模式不符。
小结:PV 是存储资源、PVC 是申请单、Pod 引用 PVC;静态供给手动建 PV,动态供给由 StorageClass 自动完成;PVC 一直 Pending 时优先核对 storageClass、PV 容量与访问模式。