K8S 之 持久卷 PV 和 PVC
摘要
-
本文介绍 K8S 的 持久卷 PV 和 PVC ,本文以 CentOS 8 为例。
-
本文底层存储卷是 NFS
PV 和 PVC 介绍
-
PV(PersistentVolume) 是 Kubernetes 中的一种存储资源,用于将底层的物理存储(如 NFS、iSCSI、Ceph、云存储等)抽象成 Kubernetes 资源,供 Pod 使用。它是对存储的一种“声明式”管理,类似于 Pod 声明计算资源。PV 是集群级别的存储资源,不支持 Namespace。
-
PVC(PersistentVolumeClaim),持久卷声明, 是 Kubernetes 中用于申请存储资源的对象。PVC 是 Namespace 级别的资源。
-
简而言之:
- PV 是集群中的一块存储,由管理员提前配置或动态创建。
- PVC(PersistentVolumeClaim) 是用户对存储的申请。
- Pod 通过 PVC 绑定到 PV,使用持久化存储。
- 开发者用 PVC 来申请存储空间,不关心存储的具体实现方式。
- PVC 通过 Kubernetes 自动匹配一个合适的 PersistentVolume(PV)进行绑定。
-
PV 与 PVC 的基本流程
- 管理员创建 PV(或者集群通过 StorageClass 自动创建)。
- 用户提交 PVC,声明自己需要多少容量、什么访问模式。
- Kubernetes 查找可用的 PV,条件符合(容量、访问模式、StorageClass)就自动绑定。
- Pod 挂载 PVC,实现持久化存储。
PV 示例
-
一个使用 NFS 存储卷的 PV 示例
1 | # pv-nfs.yaml |
存储卷模式
-
Kubernetes 支持两种卷模式(volumeModes):Filesystem(文件系统) 和 Block(块)。
-
如果该参数被省略,默认的卷模式是 Filesystem。
-
volumeMode 属性设置为 Filesystem 的卷会被 Pod 挂载(Mount) 到某个目录。
持久卷类型
-
✅ 当前支持的插件
插件类型 | 描述 |
---|---|
csi | 容器存储接口(CSI),推荐的现代存储接口 |
fc | Fibre Channel 存储 |
hostPath | HostPath 卷(仅供单节点测试使用;多节点不推荐,推荐使用 local 卷替代) |
iscsi | iSCSI(基于 IP 的 SCSI 存储) |
local | 节点本地存储设备 |
nfs | 网络文件系统(NFS)存储 |
-
⚠️ 已弃用但仍可用(需 CSI 迁移)
插件类型 | 描述 | CSI 迁移状态 |
---|---|---|
awsElasticBlockStore | AWS EBS 块存储 | 从 v1.23 开始默认迁移 |
azureDisk | Azure 磁盘存储 | 从 v1.23 开始默认迁移 |
azureFile | Azure 文件存储 | 从 v1.24 开始默认迁移 |
cinder | OpenStack 块存储 | 从 v1.21 开始默认迁移 |
flexVolume | FlexVolume(无迁移计划,但未计划移除) | 从 v1.23 开始弃用 |
gcePersistentDisk | GCP 持久磁盘 | 从 v1.23 开始默认迁移 |
portworxVolume | Portworx 存储卷 | 从 v1.31 开始默认迁移 |
vsphereVolume | vSphere VMDK 卷 | 从 v1.25 开始默认迁移 |
-
❌ 已废弃/即将移除的 In-Tree 插件
插件类型 | 描述 | 弃用/移除版本 |
---|---|---|
cephfs | Ceph 文件系统卷 | v1.31 之后不可用 |
flocker | Flocker 存储 | v1.25 之后不可用 |
glusterfs | GlusterFS 存储 | v1.26 之后不可用 |
photonPersistentDisk | Photon 持久磁盘 | v1.15 之后不可用 |
quobyte | Quobyte 卷 | v1.25 之后不可用 |
rbd | Rados 块设备(Ceph RBD) | v1.31 之后不可用 |
scaleIO | ScaleIO 卷 | v1.21 之后不可用 |
storageos | StorageOS 卷 | v1.25 之后不可用 |
accessModes 访问模式
访问模式 | 说明 | 是否跨节点挂载 | 是否支持多 Pod 挂载 | 是否支持读写 |
---|---|---|---|---|
ReadWriteOnce (RWO) | 卷可以被一个节点以读写方式挂载,同一节点内多个 Pod 可共享使用。 | ❌ 否 | ✅ 是(同一节点) | ✅ 是 |
ReadOnlyMany (ROX) | 卷可以被多个节点以只读方式挂载。 | ✅ 是 | ✅ 是 | ❌ 否(只读) |
ReadWriteMany (RWX) | 卷可以被多个节点以读写方式挂载。 | ✅ 是 | ✅ 是 | ✅ 是 |
ReadWriteOncePod (RWOP) | 卷只能被单个 Pod 以读写方式挂载,确保集群中只有一个 Pod 使用该卷(v1.29+稳定)。 | ❌ 否 | ❌ 否(只能一个 Pod) | ✅ 是 |
-
NFS 支持前三种访问模式,hostPath 只支持 ReadWriteOnce。
persistentVolumeReclaimPolicy 回收策略
回收策略 | 含义 | 回收行为 | 典型使用场景 |
---|---|---|---|
Retain | 保留:删除 PVC 后,PV 和后端存储仍然保留 | 手动回收,PVC 删除后 PV 状态为 Released ,需要手动清理或重新绑定 |
重要数据,避免误删;如数据库数据盘 |
Delete | 删除:删除 PVC 后,PV 和后端存储都会被删除 | 自动回收,PVC 删除时自动删除 PV 和后端存储资源(如云盘) | 临时数据、不重要的存储 |
Recycle | 回收:简单清空数据 | 自动执行 rm -rf /thevolume/* ,然后 PV 变回 Available 状态 |
旧版本集群的小文件临时存储 |
-
注意: 创建 Recycle 的 PV 时,会提示如下内容
1 | Warning: spec.persistentVolumeReclaimPolicy: The Recycle reclaim policy is deprecated. Instead, the recommended approach is to use dynamic provisioning. |
-
意思就是 Recycle 策略已被弃用,建议使用
动态供应模式
。但官方文档中却提示对于 Kubernetes 1.33 来说,只有 nfs 和 hostPath 卷类型支持回收(Recycle)。
-
本人在 Kubernetes 1.33.2 中测试,NFS 支持 Recycle,删除 PVC 后 PV 状态会变为 Available
管理 PV
1 | # 创建 |
PVC 示例
-
Pod 通过 PVC 向 PV 申请存储空间,如果 PVC 一直无法匹配到 PV,则 PVC 处于 Pending 状态。
-
Pod 必须与 PVC 处于同一命名空间。
-
PVC 与 PV 是 1:1 的关系。一旦 PV 绑定到 PVC,则 PVC 状态变为 Bound。该 PV 将不再被其他 PVC 绑定。
-
PVC 与 PV 匹配的条件
匹配条件 | 说明 |
---|---|
容量 | PVC 请求的容量 ≤ PV 提供的容量。PV 必须至少满足 PVC 的容量请求。 |
访问模式 | PV 支持 PVC 请求的访问模式。PVC 要求的所有访问模式,PV 都必须具备。例如:PVC 要求 ReadWriteOnce ,PV 至少要支持 ReadWriteOnce 。 |
StorageClass | PVC 和 PV 的 storageClassName 必须一致。如果 PVC 指定了 storageClassName ,只能绑定同名的 PV。 |
Selector(可选) | 如果 PVC 有设置 selector (基于标签),PV 的标签也必须匹配。 |
小贴士
- PV 中声明的
accessModes
仅作为与 PVC 的访问模式进行匹配,实际挂载到 Pod 后,不会限制 Pod 的读写访问
-
一个简单的 yaml
1 | # pvc.yaml |
管理 PVC
1 | # 创建 PVC |
Pod 绑定 PVC
-
这里以 nginx deployment 为例
1 | # nginx-pvc-deployment.yaml |
-
一个 PVC 对应一个 PV,但是一个 PVC 可以对应多个 Deployment 等控制器。下面我们就再创建一个 Deployment,将 相同的 PVC 挂载到容器中,并且每隔5秒修改一次 PVC 挂载的网页,并通过 nginx 容器查看结果
1 | # busybox-deployment.yaml |
-
创建后查看 pod ip
1 | $ k get pod -o wide |
-
访问任意一个 nginx pod
1 | # 此时会看到页面内容在变化 |
后记
-
为 pod 绑定 pvc时,每次都要先创建 pv 和 pvc,非常麻烦。有什么好的解决方案吗?
使用 StorageClass 实现自动创建 PV,我们下文将介绍如何实现。
-
如果 PVC 被 Pod 使用,则此时可以删除 PVC 吗?
不可以,PVC 被 Pod 使用,此时只能等待 Pod 删除后才能删除 PVC。
若此时执行了删除 PVC 命令,终端会一直等待,ctrl + c 退出后再次查看 PVC 状态,会看到 PVC 状态为 Terminating。但此时不会影响存Pod对储卷的使用。
此时一旦Pod 删除,PVC 就会被删除。 -
如果PV 被 PVC 使用,则此时可以删除 PV 吗?
不可以,PV 被 PVC 使用,此时只能等待 PVC 删除后才能删除 PV。
若此时执行了删除 PV 命令,终端会一直等待,ctrl + c 退出后再次查看 PV 状态,会看到 PV 状态为 Terminating。但此时不会影响Pod对存储卷的使用。
此时一旦 PVC 删除,PV 就会被删除。