当前位置: 首页 > news >正文

K8s 存储核心:一文读懂 PV 和 PVC 的设计逻辑与实践

在 Kubernetes 中,Pod 是 “临时的”—— 重启、重建后数据会丢失;而数据库、日志这类应用需要 “持久化存储”(数据保存在磁盘,不受 Pod 生命周期影响)。但直接让 Pod 对接物理磁盘或云存储,会导致 “存储与应用强耦合”(比如换个云厂商,存储配置全要改)。

PV(Persistent Volume,持久卷)和 PVC(Persistent Volume Claim,持久卷声明)就是为解决这个问题而生的 —— 它们通过 “解耦存储与应用”,让开发者不用关心底层存储细节,运维人员统一管理存储资源。下面从 “是什么→怎么协作→怎么用” 三个维度,彻底搞懂 PV 和 PVC。

一、先搞懂:PV 和 PVC 分别是什么?

PV 和 PVC 的关系,类似 “商品” 和 “订单”—— 运维人员提前准备好 “商品”(PV,存储资源),开发者提交 “订单”(PVC,存储需求),K8s 负责 “匹配订单与商品”。

1. PV:集群级的 “存储资源池”

  • 定义:PV 是 Kubernetes 集群中的 “持久化存储资源”,由运维人员创建,对应底层实际的存储设备(如本地磁盘、云硬盘 EBS、NFS 共享存储)。
  • 核心属性
    • 存储容量(capacity.storage):如 10Gi、100Gi;
    • 存储类型(storageClassName):给 PV 打 “标签”,方便 PVC 按类型匹配(如 “fast” 对应 SSD,“slow” 对应 HDD);
    • 访问模式(accessModes):定义 PV 能被如何使用,常见三种:

访问模式

含义

适用场景

ReadWriteOnce (RWO)

仅允许一个节点以 “读写” 方式挂载

数据库(如 MySQL,避免多节点同时写导致数据混乱)

ReadOnlyMany (ROX)

允许多个节点以 “只读” 方式挂载

静态资源共享(如 Nginx 挂载静态网页目录)

ReadWriteMany (RWX)

允许多个节点以 “读写” 方式挂载

分布式应用(如 GlusterFS、Ceph 共享存储)

    • 回收策略(persistentVolumeReclaimPolicy):PV 释放后如何处理数据,常见三种:
      • Retain(保留):数据保留,需运维人员手动清理(适合重要数据,避免误删);
      • Delete(删除):PV 被释放后,自动删除底层存储(如云硬盘 EBS 会被删除,适合测试环境);
      • Recycle(回收):清空数据后 PV 重新进入资源池(已废弃,推荐用 Retain 或 Delete)。
  • 示例 PV 配置(NFS 类型存储):

apiVersion: v1

kind: PersistentVolume

metadata:

name: nfs-pv-10gi # PV 名称

spec:

capacity:

storage: 10Gi # 容量 10Gi

accessModes:

- ReadWriteMany # 支持多节点读写

storageClassName: nfs-storage # 存储类型标签

nfs: # 底层存储为 NFS

server: 192.168.1.100 # NFS 服务器 IP

path: /nfs/share/data # NFS 共享目录

persistentVolumeReclaimPolicy: Retain # 释放后保留数据

2. PVC:Pod 的 “存储需求订单”

  • 定义:PVC 是 Pod 对存储资源的 “需求声明”,由开发者创建,描述 Pod 需要的存储容量、类型、访问模式等,不关心底层是 NFS 还是云硬盘。
  • 核心逻辑:PVC 不直接对接存储设备,而是 “请求匹配” 集群中符合条件的 PV—— 匹配成功后,PVC 与 PV 绑定,Pod 再通过 PVC 挂载存储。
  • 示例 PVC 配置(请求 10Gi NFS 存储):

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

name: app-pvc-10gi # PVC 名称

spec:

accessModes:

- ReadWriteMany # 需与 PV 的访问模式匹配

resources:

requests:

storage: 10Gi # 请求 10Gi 容量(需 ≤ PV 容量)

storageClassName: nfs-storage # 需与 PV 的存储类型匹配(精确匹配)

二、核心关系:PV 与 PVC 的 “绑定逻辑”

PV 和 PVC 不是 “手动指定绑定”,而是由 Kubernetes 自动匹配,核心遵循 “3 个匹配条件”,缺一不可:

  1. 存储类型匹配:PVC 的 storageClassName 必须与 PV 的 storageClassName 完全一致(若都为 "",表示 “无类型”,可互相匹配);
  1. 访问模式兼容:PVC 请求的 accessModes 必须是 PV 支持的 accessModes 子集(如 PV 支持 RWO+RWX,PVC 请求 RWX 是兼容的);
  1. 容量满足:PVC 请求的 storage 必须 ≤ PV 的 capacity.storage(如 PV 是 10Gi,PVC 请求 8Gi 可行,请求 12Gi 不可行)。

绑定后的特点:

  • 一对一绑定:一个 PV 只能绑定一个 PVC,一个 PVC 也只能绑定一个 PV(绑定后 PV 状态变为 Bound,不再接受其他 PVC 请求);
  • 生命周期独立:PV 是集群级资源(不属于任何命名空间),PVC 是命名空间级资源(仅在所属命名空间内可见)—— 这意味着,不同命名空间的 PVC 不能绑定同一个 PV。

三、生命周期:从 “创建” 到 “释放” 的完整流程

PV 和 PVC 的生命周期分为 5 个阶段,清晰反映了资源的流转过程:

  1. Provisioning(供给):运维人员创建 PV(静态供给),或通过 StorageClass 自动创建 PV(动态供给,后面补充);
  1. Binding(绑定):开发者创建 PVC,K8s 匹配符合条件的 PV,绑定后两者状态均变为 Bound;
  1. Using(使用):Pod 通过 volumes 字段引用 PVC,挂载 PV 对应的存储,开始读写数据(Pod 运行期间,PVC 与 PV 持续绑定,不可解绑);
  1. Releasing(释放):删除 PVC(或 Pod 被删除且 PVC 无其他引用),PVC 状态变为 Released,PV 状态也变为 Released(此时 PV 中的数据按回收策略处理);
  1. Reclaiming(回收):根据 PV 的 persistentVolumeReclaimPolicy 处理:
    • Retain:PV 状态变为 Available,数据保留,需运维人员手动清理数据后,PV 才能重新被绑定;
    • Delete:PV 自动删除,底层存储(如 EBS)也会被删除,资源彻底释放;
    • Recycle(废弃):自动清空数据,PV 状态变回 Available,可重新绑定。

生命周期状态流转图(简化版):

PV:Provisioning(创建)→ Available(可用)→ Bound(绑定)→ Released(释放)→ Reclaimed(回收)

PVC:Pending(等待匹配)→ Bound(绑定)→ Released(释放)→ Terminating(删除中)

四、进阶:动态供给(StorageClass)—— 自动创建 PV

手动创建 PV 存在 “效率低”“资源浪费” 的问题(比如开发者需要 5Gi 存储,运维人员得提前创建 5Gi PV,否则 PVC 会一直 Pending)。

StorageClass(存储类) 解决了这个问题 —— 它允许 K8s 根据 PVC 的需求,自动创建 PV,无需运维人员手动干预。

核心逻辑:

  1. 运维人员创建 StorageClass,定义 “如何动态生成 PV”(如底层用云硬盘 EBS、NFS,以及 PV 的回收策略、访问模式等);
  1. 开发者创建 PVC 时,指定 storageClassName 为该 StorageClass 名称;
  1. K8s 检测到 PVC 请求后,调用 StorageClass 对应的 “存储插件”(如云厂商提供的插件),自动创建 PV 并与 PVC 绑定。

示例:用 StorageClass 动态创建 NFS 类型 PV

  1. 创建 StorageClass(需提前部署 NFS 存储插件):

apiVersion: storage.k8s.io/v1

kind: StorageClass

metadata:

name: dynamic-nfs-sc # StorageClass 名称

provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # NFS 存储插件

parameters:

server: 192.168.1.100 # NFS 服务器 IP

path: /nfs/dynamic # NFS 动态存储根目录

onDelete: retain # 删除 PVC 时,保留 NFS 目录(避免数据丢失)

reclaimPolicy: Retain # 动态创建的 PV 回收策略

allowVolumeExpansion: true # 允许 PVC 扩容(需底层存储支持)

  1. 创建 PVC 触发动态 PV

apiVersion: v1

kind: PersistentVolumeClaim

metadata:

name: dynamic-pvc-5gi

spec:

accessModes:

- ReadWriteMany

resources:

requests:

storage: 5Gi # 请求 5Gi 容量

storageClassName: dynamic-nfs-sc # 指定 StorageClass,触发动态创建 PV

  1. 验证结果

执行 kubectl get pv 会发现,K8s 已自动创建一个名为 pvc-xxxxxx 的 PV(名称包含 PVC ID),且状态为 Bound,无需运维人员手动创建 PV。

五、实践:Pod 如何使用 PVC 挂载存储?

最终目的是让 Pod 用上存储,只需在 Pod 配置中通过 volumes 引用 PVC,再通过 volumeMounts 挂载到容器内的目录。

示例:MySQL Pod 使用 PVC 持久化数据

apiVersion: v1

kind: Pod

metadata:

name: mysql-pod

spec:

containers:

- name: mysql

image: mysql:5.7

env:

- name: MYSQL_ROOT_PASSWORD

value: "123456"

volumeMounts:

- name: mysql-data # 与下面 volumes 名称对应

mountPath: /var/lib/mysql # 容器内挂载目录(MySQL 数据存储目录)

volumes:

- name: mysql-data

persistentVolumeClaim:

claimName: app-pvc-10gi # 引用已绑定的 PVC 名称

关键验证:

  1. 执行 kubectl apply -f mysql-pod.yaml 创建 Pod;
  1. 进入容器写入数据:kubectl exec -it mysql-pod -- mysql -uroot -p123456 -e "create database testdb;";
  1. 删除 Pod 并重建:kubectl delete pod mysql-pod,再重新创建 Pod;
  1. 再次进入容器查看:kubectl exec -it mysql-pod -- mysql -uroot -p123456 -e "show databases;",会发现 testdb 仍存在 —— 说明数据通过 PV 持久化,不受 Pod 重建影响。

六、常见问题与避坑指南

  1. PVC 一直 Pending,无法绑定 PV?
    • 检查 storageClassName 是否匹配(大小写敏感);
    • 检查 PV 的 accessModes 是否包含 PVC 请求的模式;
    • 检查 PV 容量是否 ≥ PVC 请求容量;
    • 检查 PV 是否已被其他 PVC 绑定(kubectl get pv 看状态是否为 Available)。
  1. Pod 挂载 PVC 失败,提示 “permission denied”?

securityContext:

fsGroup: 1000 # 容器内用户组 ID,与存储目录权限匹配

    • 底层存储目录权限问题(如 NFS 共享目录的权限不是 777,需执行 chmod 777 /nfs/share/data);
    • 容器内用户无读写权限,可在 Pod 中添加 securityContext 配置:
  1. 如何扩容 PVC?
    • 前提:StorageClass 开启 allowVolumeExpansion: true,且底层存储支持扩容(如 EBS、NFS);
    • 直接修改 PVC 的 storage 字段(如从 10Gi 改为 20Gi),K8s 会自动扩容 PV 和底层存储。

总结:PV/PVC 的核心价值

PV 和 PVC 的设计,本质是 **“解耦存储管理与应用使用”**:

  • 对运维人员:统一管理存储资源(创建 PV/StorageClass),不用关心哪个 Pod 在用;
  • 对开发者:只需声明存储需求(创建 PVC),不用关心底层是 NFS 还是云硬盘;
  • 对集群:存储资源可复用(PV 释放后可重新绑定),且支持动态扩缩容,适配不同场景。

掌握 PV 和 PVC,是 K8s 持久化存储的基础 —— 无论是数据库、日志系统,还是需要保存配置的应用,都离不开这套机制。建议从 “静态 PV+PVC” 入手实践,熟悉后再尝试动态供给(StorageClass),逐步掌握 K8s 存储的核心能力。

http://www.dtcms.com/a/553192.html

相关文章:

  • p2p借贷网站开发微信公众号推文制作软件
  • k8s pod oom排查攻略
  • 成都市青羊区城乡建设局网站网页制作用什么软件
  • Unity使用AnimeGANv3实现动漫风格化效果(一)
  • (七)TRPO 算法 PPO 算法
  • RK3568前置知识
  • 逻辑回归正则化强度实验报告:不同 λ 值对模型系数与泛化能力的影响
  • LeetCode每日一题——反转链表
  • 南京市网站叫企业做的网站可不可以自己改主题
  • 怎么查询网站是谁做的seo查询工具网站
  • 【开源鸿蒙-AVCodec Kit】音视频编解码封装解封装部件介绍,转自开源鸿蒙官媒OpenAtom OpenHarmony
  • 【保姆级教程】MySQL 5.7 彻底卸载与重新安装全流程(附常见问题解决)
  • Debian 安装 Domain Admin
  • Java Maven+lombok+MySql+HikariCP 操作数据库
  • Golang 镜像拉取与 Docker 部署全教程
  • 纯css:一个好玩的按钮边框动态动画
  • html5网站建设基本流程图更改wordpress标签分割符合
  • 山东中讯网站建设专业外贸网站制作价格
  • harbor-从源码理解镜像清理的逻辑实现
  • 为什么安装epel-release
  • Apache Maven 项目的开发指南
  • NET系列算法
  • 基于可视化天气系统demo,基于python+ matplotlib+request爬虫,开发语言python,数据库无,10个可视化界面,需要的可以了联系。
  • 被网站开发公司坑湖北网站设计
  • 可视化视角:AI + 实时流 + 可访问性时代的 3 大改变
  • Rust `std::iter` 深度解析:`Iterator` Trait、适配器与性能
  • MacOS学习笔记
  • 搭建网站程序网站域名和服务器到期
  • 从零开发一款实用插件,掌握VSCode扩展生态核心技术
  • mapbox高阶,使用自定义图层实现雷达扫描效果