Kubernetes

PV & PVC 完整深度详解

·11 分钟阅读·4242 字
📋 目录

PV & PVC 完整深度详解

核心概念 PV(PersistentVolume)是底层真实存储载体,PVC(PersistentVolumeClaim)是存储需求申请单,两者解耦了存储资源与业务 Pod。

1. 设计初衷

K8s 将存储资源业务 Pod解耦,拆分两层资源:

  1. PV(PersistentVolume):底层真实存储载体(一块磁盘/分区/NAS),集群级资源,独立于 Namespace、独立于 Pod;
  2. PVC(PersistentVolumeClaim):存储需求申请单,命名空间内资源,业务侧只描述“我要多大盘、什么读写模式”,不关心底层硬件。

核心优势:

  • 开发只操作 PVC,无需了解云盘、本地盘、NAS 差异;
  • 运维统一管理 PV/存储介质,更换底层存储不改动业务 YAML;
  • Pod 删除不会销毁 PV 数据,实现数据持久化。

2. PV 完整详解(PersistentVolume)

2.1. 资源定位

集群级资源,不在任何 namespace,全局可见;
代表真实存储:本地磁盘、阿里云/腾讯云云盘、Ceph RBD、NAS、LocalPV 本地SSD。

2.2. PV 核心字段

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-local-10g
spec:
  # 1. 存储容量
  capacity:
    storage: 10Gi

  # 2. 访问模式(核心,决定挂载限制)
  accessModes:
    - ReadWriteOnce

  # 3. 回收策略:PVC删除后PV如何处理数据
  persistentVolumeReclaimPolicy: Retain

  # 4. 存储类,用于和PVC匹配动态供给
  storageClassName: local-ssd

  # 5. 卷模式:文件系统 / 裸块设备
  volumeMode: Filesystem

  # 6. 绑定本地盘专用:限制Pod只能调度到指定节点
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values: ["node-01"]

  # 底层存储来源(示例本地目录)
  local:
    path: /data/ssd/pv1

2.2.1. ① accessModes 三种访问模式(重中之重)

  1. ReadWriteOnce (RWO)
  • 只能单个节点同时读写;
  • 云块盘、本地LocalPV默认;
  • 限制:同一个PV不能同时挂载到两台节点,多副本Pod会调度冲突。
  1. ReadOnlyMany (ROX)
  • 多个节点同时只读挂载;
  • 静态资源、只读数据场景。
  1. ReadWriteMany (RWX)
  • 多节点同时读写;
  • 仅支持NAS、CephFS等共享存储;
  • 不适合数据库等高随机IO业务,共享锁损耗性能。

2.2.2. ② persistentVolumeReclaimPolicy 回收策略

控制 PVC 被删除后,PV 和底层数据如何处理:

  1. Retain(默认)
    PVC 删除,PV 保留、状态变为 Released,数据完整留存;
    需要运维手动清理数据、删除PV才能复用。
  2. Delete
    PVC 删除 → 自动删除PV,并销毁底层存储(云盘自动释放、本地盘清空);
    动态CSI存储类推荐配置。
  3. Recycle(废弃,新版本已移除)
    自动 rm -rf 清空目录,重新变为可用PV,安全性差淘汰。

2.2.3. ③ volumeMode

  1. Filesystem 默认:存储会自动格式化挂载文件系统,业务直接读写目录;
  2. Block 裸块设备:不格式化,直接把磁盘裸设备透传给容器;数据库原生裸盘优化性能使用。

2.3. PV 完整生命周期状态

  1. Available:空闲未绑定,可被PVC匹配绑定;
  2. Bound:已和某PVC一对一绑定,独占;
  3. Released:PVC被删除,但回收策略是Retain,PV保留,数据还在;
    此时无法被新PVC绑定,需要人工清理;
  4. Failed:底层存储故障、挂载失败。

3. PVC 完整详解(PersistentVolumeClaim)

3.1. 资源定位

命名空间级资源,每个业务应用单独创建;
相当于“存储申请表”,开发者只需要描述需求,不需要定义底层存储。

3.2. PVC 标准示例

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-data
  namespace: business
spec:
  # 需要的容量
  resources:
    requests:
      storage: 10Gi
  # 和PV保持一致的访问模式
  accessModes:
    - ReadWriteOnce
  # 绑定对应StorageClass实现动态创建PV
  storageClassName: local-ssd
  # 裸盘场景开启
  volumeMode: Filesystem

3.3. PVC 核心逻辑

  1. 匹配规则:K8s 控制器自动筛选满足以下全部条件的空闲PV:
  • storage 容量 ≥ PVC 请求容量;
  • accessModes 完全兼容;
  • storageClassName 完全一致;
  1. 一对一独占绑定:一个PVC只能绑定一个PV,一个PV只能给一个PVC;
  2. 绑定后不可更换PV,PVC删除才会解除绑定。

3.4. PVC 生命周期状态

  1. Pending:未匹配到可用PV(静态无空闲PV / 动态CSI正在创建磁盘);
  2. Bound:成功绑定PV,可以被Pod挂载使用;
  3. Lost:绑定的PV被删除、底层存储丢失。

4. PV与PVC两种工作模式

4.1. 模式1:静态供给(手动创建PV)

流程:

  1. 运维预先编写YAML,创建大量PV;
  2. 业务创建PVC,控制器自动匹配符合条件的空闲PV;
  3. PVC状态变为Bound,Deployment/StatefulSet挂载PVC启动Pod;
  4. 删除Pod,PV数据保留;删除PVC,根据reclaimPolicy处理PV。

缺点:集群节点、磁盘扩容时,需要人工新增PV,大规模集群运维繁琐,现在仅小规模测试使用。

4.2. 模式2:动态供给(StorageClass + CSI,生产主流)

无需运维提前创建PV:

  1. 集群部署CSI驱动、创建StorageClass;
  2. PVC指定storageClassName
  3. PVC创建后处于Pending状态,CSI Controller感知并调用存储API,自动创建底层磁盘;
  4. 自动生成对应PV,与PVC绑定,状态变为Bound;
  5. 删除PVC,StorageClass配置Delete策略时,自动删除PV和底层磁盘。

5. Pod 如何使用 PVC

Pod 不能直接挂载PV,只能引用PVC:

spec:
  volumes:
  - name: data-volume
    persistentVolumeClaim:
      claimName: mysql-data # 引用当前命名空间下的PVC名称
  containers:
  - name: mysql
    image: mysql:8.0
    volumeMounts:
    - name: data-volume
      mountPath: /var/lib/mysql

6. StatefulSet 专属:volumeClaimTemplates

普通Deployment所有Pod共用同一个PVC,有状态服务每个实例需要独立磁盘,因此STS提供PVC模板:

volumeClaimTemplates:
- metadata:
    name: data
  spec:
    accessModes: [ "ReadWriteOnce" ]
    storageClassName: local-ssd
    resources:
      requests:
        storage: 20Gi

控制器自动为每个有序Pod生成独立PVC:
sts-name-0 → data-sts-name-0
sts-name-1 → data-sts-name-1
每个Pod独占一块PV,删除重建Pod依旧绑定原有PVC,数据不丢失。

7. 绑定失败常见故障排查

7.1. PVC 一直 Pending

  1. 静态模式:无满足容量、accessModes、storageClass的空闲PV;
  2. 动态模式:CSI驱动异常、StorageClass名称写错、云厂商权限不足;
  3. LocalPV场景:storageClass未配置WaitForFirstConsumer,无节点接收Pod无法创建PV。

7.2. PV 状态 Released 无法重新绑定新PVC

根因:回收策略 Retain,旧PVC删除后PV残留数据;
解决:手动删除PV,或登录底层磁盘清空数据后重建PV。

7.3. Pod 调度失败,提示PV冲突

RWO模式PV已挂载到其他节点,调度器不会将新Pod调度到其他机器;
解决:删除占用PV的旧Pod,释放挂载点。

8. PV/PVC 核心命令

# 查看所有PV
kubectl get pv
# 查看指定namespace下PVC
kubectl get pvc -n ns-name
# 查看详细绑定信息、事件
kubectl describe pv pv-name
kubectl describe pvc pvc-name
# 删除PVC
kubectl delete pvc mysql-data -n business

9. 核心总结区分

  1. PV:集群级资源,代表真实存储磁盘,定义硬件、容量、访问模式、回收策略;
  2. PVC:命名空间存储申请单,业务只声明需求,自动匹配/自动创建PV;
  3. 匹配逻辑:容量、accessModes、storageClass三者同时匹配才能绑定;
  4. 静态:人工提前建PV;动态:StorageClass+CSI自动创建PV,企业标准;
  5. RWO单节点读写、RWX多节点共享;Retain保留数据、Delete自动销毁磁盘;
  6. STS通过volumeClaimTemplates批量生成独立PVC,适配MySQL/Kafka/ES等有状态中间件。

关联文档