Kubernetes存储架构与CSI接口调用实战 - 第3节
3.1 PersistentVolume(PV)与 PersistentVolumeClaim(PVC)定义
在 Kubernetes 存储体系中,PersistentVolume(PV) 和 PersistentVolumeClaim(PVC) 是一对核心抽象,将存储的供给与消费彻底解耦。PV 由管理员预先配置或通过 StorageClass 动态供给,PVC 则是用户对存储资源的请求。这种设计让应用开发者无需关心底层存储实现,而存储管理员可以集中管理存储资源池。
3.1.1 PersistentVolume(PV)—— 存储资源
PV 是集群中的一块存储资源,独立于任何 Pod 存在。它可以是 NFS、iSCSI、Ceph RBD、GCE Persistent Disk、AWS EBS 等任意存储后端。PV 的生命周期由集群管理员管理,包含容量、访问模式、回收策略、存储类等关键属性。
| 属性 | 说明 | 常见值 |
|---|---|---|
| capacity.storage | PV 的存储容量 | 10Gi, 100Gi, 1Ti |
| accessModes | 支持的访问模式 | ReadWriteOnce, ReadOnlyMany, ReadWriteMany |
| persistentVolumeReclaimPolicy | PVC 释放后的回收行为 | Retain, Recycle, Delete |
| storageClassName | 关联的 StorageClass 名称 | fast, slow, ssd |
| mountOptions | 挂载时附加选项 | ro, hard, nfsvers=4.1 |
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs-01
spec:
capacity:
storage: 50Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs-storage
nfs:
path: /data/k8s-volumes
server: 192.168.1.100
3.1.2 PersistentVolumeClaim(PVC)—— 存储请求
PVC 是用户对存储资源的请求声明。用户只需声明所需容量、访问模式和存储类,Kubernetes 控制平面会自动寻找或动态创建满足条件的 PV 并完成绑定。PVC 是 Pod 与 PV 之间的中间层,Pod 通过 PVC 挂载存储,无需感知 PV 的具体后端类型。
| 属性 | 说明 | 示例值 |
|---|---|---|
| resources.requests.storage | 请求的存储容量 | 10Gi |
| accessModes | 期望的访问模式 | ReadWriteOnce |
| storageClassName | 指定 StorageClass(可选) | fast |
| selector | 通过标签选择 PV(可选) | matchLabels: { tier: ssd } |
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-app-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: nfs-storage
3.2 PV 与 PVC 的绑定关系
当用户创建 PVC 后,Kubernetes 控制平面中的 PersistentVolumeController 会持续扫描集群中的 PV,寻找满足 PVC 条件的 PV 进行绑定。绑定过程遵循以下匹配规则:
- 容量匹配:PV 的容量必须 大于等于 PVC 请求的容量。
- 访问模式匹配:PV 必须支持 PVC 声明的访问模式。
- StorageClass 匹配:PVC 指定 storageClassName 时,PV 必须具有相同的类名;PVC 未指定时,仅匹配未设置 storageClassName 的 PV。
- 标签选择器匹配:如果 PVC 设置了 selector,PV 必须满足所有标签条件。
- 状态约束:PV 必须处于
Available状态。
Bound,PVC 状态也变为 Bound。如果找不到匹配的 PV,PVC 将保持 Pending 状态,直到有合适的 PV 出现或动态供给完成。
3.3 PV 生命周期管理
PV 的生命周期包含五个阶段:Provisioning → Available → Bound → Released → Reclaim。理解每个阶段的状态转换和回收策略,是生产环境中存储管理的关键。
3.3.1 生命周期阶段
| 阶段 | 状态 | 说明 |
|---|---|---|
| Provisioning | — | PV 的创建过程,可以是静态(管理员手动创建)或动态(StorageClass 自动创建) |
| Available | Available |
PV 已就绪,等待 PVC 绑定 |
| Bound | Bound |
PV 已绑定到某个 PVC,可以被 Pod 使用 |
| Released | Released |
PVC 被删除,PV 上的数据保留,但尚未回收 |
| Reclaim | Available / Failed |
根据回收策略处理 PV 中的数据,完成后可重新使用或废弃 |
3.3.2 回收策略(Reclaim Policy)
当 PVC 被删除后,PV 的回收策略决定了后续行为:
- Retain(保留):PV 进入
Released状态,数据保留,管理员可以手动恢复或清理数据后重新使用。这是最安全的策略,适合生产环境。 - Delete(删除):PV 及其关联的后端存储资源(如 AWS EBS 卷、GCE PD)会被自动删除。适合动态供给场景。
- Recycle(回收):已废弃,Kubernetes 1.20+ 不再推荐。执行
rm -rf /volume/*清空数据后 PV 回到Available状态。
Retain 策略。误删 PVC 后,数据仍保留在 PV 中,管理员可以手动恢复绑定。对于临时或可重建的数据,可以使用 Delete 策略以简化运维。
3.4 绑定模式与动态供给
Kubernetes 支持两种 PV 供给模式:
- 静态供给(Static Provisioning):管理员预先创建一批 PV,PVC 创建时从中匹配绑定。适合存储资源固定、容量可预估的场景。
- 动态供给(Dynamic Provisioning):通过 StorageClass 定义存储模板,PVC 创建时自动触发后端存储卷的创建和 PV 的生成。适合云环境或需要按需分配的场景。
3.5 Pod 使用 PVC 的完整流程
Pod 通过 volumes 字段引用 PVC,Kubernetes 将 PVC 对应的 PV 挂载到容器的指定路径。以下是完整的声明式配置示例:
apiVersion: v1
kind: Pod
metadata:
name: app-with-storage
spec:
containers:
- name: app
image: nginx:latest
volumeMounts:
- name: data-volume
mountPath: /usr/share/nginx/html
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: pvc-app-data
当 Pod 调度到某个节点后,kubelet 会执行以下步骤:
- 读取 Pod 的 volume 定义,找到 PVC
pvc-app-data。 - 通过 API Server 查询 PVC 的绑定状态,获取对应的 PV 信息。
- 根据 PV 的存储后端类型(如 NFS、Ceph、AWS EBS),调用相应的卷插件或 CSI 驱动。
- 在节点上执行挂载操作,将远程存储映射到宿主机路径。
- 将宿主机路径绑定到容器内的
mountPath。
Pending 状态,Pod 将无法启动。排查时使用 kubectl describe pvc <pvc-name> 查看事件信息,常见原因包括:没有匹配的 PV、StorageClass 不存在、存储后端资源不足、访问模式冲突。
3.6 核心概念总结
| 概念 | 角色 | 创建者 | 生命周期 | 关键属性 |
|---|---|---|---|---|
| PV | 存储资源 | 管理员 / StorageClass | 独立于 Pod | 容量、访问模式、回收策略、存储类 |
| PVC | 存储请求 | 用户 | 与 Pod 关联 | 容量请求、访问模式、存储类、选择器 |
| StorageClass | 存储模板 | 管理员 | 持久存在 | Provisioner、参数、回收策略、绑定模式 |