2. 容器持久化存储基础
在 Kubernetes 中,容器本身是无状态的、可随时被调度或重建的,但数据库、日志、消息队列、AI 训练数据集等负载却必须把数据写到容器生命周期之外的地方。Kubernetes 为此抽象出一套“声明式存储”模型:用户只描述“我需要多大、什么访问模式的存储”,由控制器和存储驱动去完成实际的卷创建与挂载。理解这套模型,是后续把 Pure Storage FlashArray/FlashBlade 接入 Kubernetes 的前提。
一、五个核心对象各自扮演什么角色
持久卷 PV(PersistentVolume)是集群层面的存储资源对象,代表一块真实可用的存储,例如 FlashArray 上的一个卷、一个 NFS 导出目录或云盘。PV 由管理员静态创建,或由供给器动态创建,它记录容量、访问模式、回收策略、后端标识等属性,独立于任何 Pod 存在。
持久卷声明 PVC(PersistentVolumeClaim)是命名空间内用户对存储的“申请单”。用户不关心底层是 FlashArray 还是别的设备,只声明 storage: 100Gi、accessModes: ReadWriteOnce 等需求。PVC 被绑定到某个满足条件的 PV 后,Pod 才能通过 volumes.persistentVolumeClaim 引用它。
存储类 StorageClass描述“一类存储的能力与供给方式”,包含 provisioner(如 pure-csi)、parameters(如后端阵列、精简置备、复制策略)、reclaimPolicy、volumeBindingMode 等。它把“用户需求”翻译成“后端如何创建卷”。
容器存储接口 CSI(Container Storage Interface)是 Kubernetes 与存储厂商之间的标准 gRPC 接口。Pure Storage 的 CSI 驱动以 DaemonSet 与 Controller 形式部署,实现 CreateVolume、ControllerPublishVolume、NodeStageVolume、NodePublishVolume、DeleteVolume 等方法,把 Kubernetes 的存储动作翻译成对 FlashArray 的 REST 调用。
动态卷供给(Dynamic Provisioning)是当 PVC 找不到现成 PV 时,由 StorageClass 指定的 provisioner 实时创建 PV 的机制。它是 CSI 驱动最常被使用的路径,也是“用户只写 PVC 就能拿到存储”的关键。
二、对象之间的协作链路
下面这张图把五个对象放在同一条链路上:用户提交 PVC,StorageClass 决定由谁供给,CSI 驱动调用后端阵列创建卷并生成 PV,PV 与 PVC 绑定,最终由 kubelet 通过 CSI 节点插件把卷挂载进 Pod。
三、动态供给的完整过程
假设管理员已部署 Pure CSI 驱动并创建了名为 pure-block 的 StorageClass,用户提交如下 PVC:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data
namespace: prod
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: pure-block
resources:
requests:
storage: 100Gi
提交后,Kubernetes 的 PersistentVolumeController 发现该 PVC 没有匹配的 PV,且 storageClassName 指向一个存在且允许动态供给的 StorageClass,于是调用 pure-csi 的 CreateVolume。CSI 驱动读取 StorageClass 的 parameters(例如 backend: flasharray-prod、pure_volume_type: thin),通过 REST 在 FlashArray 上创建一个 100GiB 的精简置备卷,并返回卷名、容量、拓扑等信息。控制器据此生成一个 PV 对象,其 claimRef 指向该 PVC,状态变为 Bound。
当引用该 PVC 的 Pod 被调度到某节点后,kubelet 调用 CSI 节点插件:先 NodeStageVolume 把卷挂到节点的全局目录,再 NodePublishVolume 把它绑定到 Pod 的 /var/lib/kubelet/pods/<uid>/volumes/... 路径,最终以 /data 出现在容器内。整个过程用户只写了一个 PVC,其余动作全部由控制器与 CSI 驱动完成。
四、访问模式与绑定模式的关键差异
访问模式决定卷能被多少个节点同时挂载:ReadWriteOnce 只允许单节点读写,适合数据库;ReadOnlyMany 允许多节点只读;ReadWriteMany 允许多节点读写,通常需要 FlashBlade 的 NFS/SMB 或文件类后端;ReadWriteOncePod 则进一步限制为单个 Pod。选择错误会导致 Pod 卡在 ContainerCreating,事件里出现 Multi-Attach error 或 volume is already exclusively attached。
绑定模式由 StorageClass 的 volumeBindingMode 控制。Immediate 表示 PVC 一创建就供给,不等待 Pod 调度;WaitForFirstConsumer 则等到 Pod 被调度后才创建卷,从而让卷落在与 Pod 相同的可用区或节点拓扑上。对于跨可用区的 FlashArray 部署,WaitForFirstConsumer 能避免“卷在 A 区、Pod 调度到 B 区”的挂载失败。
五、回收策略与生命周期
PV 的 persistentVolumeReclaimPolicy 决定 PVC 删除后卷如何处理:Delete 会调用 CSI 的 DeleteVolume 删除后端卷,是动态供给的默认值;Retain 保留后端卷和 PV 对象,仅把 PV 置为 Released,需要管理员手动清理或重新绑定;Recycle 已废弃,不应再使用。生产环境中,数据库类 PVC 常配合 Retain 或后端快照策略,防止误删 PVC 导致数据丢失。
把这五个对象的关系记成一句话:PVC 是需求,StorageClass 是模板,CSI 是翻译官,PV 是结果,Pod 是最终消费者。后续接入 Pure Storage 时,所有配置与排障都围绕这条链路展开。