在 Kubernetes 中,PV (Persistent Volume) 和 PVC (Persistent Volume Claim) 是管理集群持久化存储的核心机制。它们的作用是将存储的提供(基础设施层) 与 存储的消费(应用层) 分离开来,提供更大的灵活性和抽象性。
核心作用:
- 解耦存储管理与应用部署: 开发者无需关心底层存储细节(如 NFS 服务器地址、云存储桶名、存储类型),只需声明应用需要什么样的存储(容量、访问模式等)。运维人员则可以集中管理各种存储资源。
- 提供持久化存储: 确保 Pod 重启、迁移或重建后,其数据仍然存在并可访问。这是运行有状态应用(如数据库、消息队列)的基础。
- 抽象存储细节: PVC 作为应用请求存储的抽象接口,应用只与 PVC 交互。底层使用的具体存储技术(NFS, iSCSI, AWS EBS, GCP PD, Azure Disk, Ceph 等)对应用是透明的。
详细解释:
-
PV (Persistent Volume):
- 是什么: PV 是 Kubernetes 集群中的一块网络存储资源。它是由集群管理员预先配置好的,或者由 StorageClass 动态配置出来的。
- 作用:
- 代表实际的存储: 它指向一个具体的、可用的存储后端(如 NFS 共享目录、云硬盘、Ceph 卷等)。
- 定义存储特性: PV 描述了这块存储的具体属性:
- 容量: 例如 10Gi, 100Gi。
- 访问模式: 定义了 Pod 如何挂载和使用这个卷。常见模式:
ReadWriteOnce
:可被单个节点读写挂载。ReadOnlyMany
:可被多个节点只读挂载。ReadWriteMany
:可被多个节点读写挂载 (支持此模式的存储较少,如 NFS, CephFS)。
- 持久卷回收策略: 当与之绑定的 PVC 被删除后,PV 如何处理:
Retain
:保留 PV 和数据(手动清理)。Delete
:自动删除 PV 和底层存储(需要存储插件支持)。Recycle
:废弃策略(基本不用)。
- 存储类: 指向一个 StorageClass 名称(如果是动态配置的 PV)。
- 挂载选项: 特定存储系统支持的额外挂载参数。
- 卷模式:
Filesystem
(文件系统,最常见) 或Block
(原始块设备)。
- 生命周期: 独立于 Pod。即使使用它的 Pod 被删除,PV 及其数据通常仍然存在(除非回收策略是
Delete
且 PVC 被删)。 - 创建者: 通常由集群管理员或自动化工具(如 StorageClass)创建。
-
PVC (Persistent Volume Claim):
- 是什么: PVC 是用户(通常是应用开发者)对存储资源的需求声明。它表达了 Pod 需要什么样的存储。
- 作用:
- 申请存储资源: 用户/应用通过创建 PVC 来请求特定大小和特定访问模式的存储。
- 绑定到 PV: Kubernetes 系统会尝试找到一个满足 PVC 需求的、状态为
Available
的 PV,并将其与 PVC 绑定。一旦绑定成功,该 PV 状态变为Bound
,不能再被其他 PVC 使用。 - 作为卷提供给 Pod: 在 Pod 的
volumes
配置中,可以引用 PVC 名称。当 Pod 调度到某个节点时,kubelet 会:- 找到该 Pod 引用的 PVC。
- 找到与该 PVC 绑定的 PV。
- 根据 PV 的描述,挂载底层的实际存储到 Pod 指定的容器路径。
- 生命周期: 通常与应用(或更准确地说是需要该存储的工作负载)紧密相关。当不再需要存储时,删除 PVC 可能会触发 PV 的回收(取决于 PV 的回收策略)。
- 创建者: 应用开发者或 Helm Chart 等部署工具创建,作为应用部署清单的一部分。
它们如何协同工作 (工作流程):
- 管理员配置存储: 管理员预先创建一批 PV(静态配置),或者配置好 StorageClass 对象(定义如何动态创建 PV 的模板)。
- 用户部署应用:
- 用户在部署应用的 YAML 文件中定义一个 PVC,指定所需存储的大小、访问模式(可选地指定 StorageClass)。
- 用户在 Pod 模板的
volumes
部分引用这个 PVC 的名称。
- Kubernetes 绑定:
- 当用户创建 PVC 时,Kubernetes 控制平面(主要是 PersistentVolume Controller)开始工作。
- 静态绑定: 查找集群中是否存在满足 PVC 要求(容量、访问模式等)且状态为
Available
的 PV。如果找到,则将其与 PVC 绑定。 - 动态配置: 如果 PVC 指定了 StorageClass 或者集群有默认 StorageClass,并且没有找到合适的静态 PV,则 StorageClass 中配置的 Provisioner(存储插件)会根据 PVC 的请求自动创建一个新的 PV,并立即将其绑定到该 PVC。
- Pod 调度与挂载:
- 调度器将 Pod 调度到一个合适的节点上。
- 该节点上的 kubelet 准备挂载 Pod 声明的所有卷。
- 对于 PVC 类型的卷,kubelet:
- 查找 Pod 引用的 PVC。
- 确认 PVC 已绑定到某个 PV。
- 根据 PV 的描述(类型、访问模式、挂载选项等),调用对应的存储插件(Volume Plugin)。
- 存储插件连接到实际的存储后端(如 NFS 服务器、云存储 API),将存储挂载到节点上的指定路径。
- 最后,kubelet 将这个路径挂载到 Pod 内的容器中指定的目录。
- 使用与回收:
- Pod 中的容器读写挂载目录,数据实际保存在底层的持久化存储中。
- 当 Pod 被删除时,挂载点被卸载,但 PV 和 PVC 以及底层数据通常仍然存在。
- 当用户删除 PVC 时:
- 如果 PV 的回收策略是
Retain
:PV 状态变为Released
,但 PV 对象和数据保留,需要管理员手动清理。 - 如果 PV 的回收策略是
Delete
:Kubernetes 会自动删除 PV 对象,并调用存储插件删除底层存储资源。
- 如果 PV 的回收策略是
总结比喻:
- PV 就像一块物理硬盘或云硬盘。 它是实实在在的存储资源。
- PVC 就像一张硬盘申请单。 应用说:“我需要一块至少 100GB 大小、能让我单个机器读写的硬盘”。
- Kubernetes 就像 IT 管理员。 它负责:
- 查看仓库(集群)里有没有现成的符合要求的硬盘(PV)可以给你(静态绑定)。
- 或者根据申请单的要求,自动去买一块新硬盘(动态配置 PV),然后交给你。
- 最后把这块硬盘安装(挂载)到你申请的服务器(Pod 运行的节点)上供你的程序使用。
- StorageClass 就像硬盘型号目录/自动采购流程。 它定义了管理员提供了哪些类型的硬盘(高性能 SSD、普通 HDD)以及如何自动采购(创建)它们。
关键价值:
- 应用可移植性: 应用清单(YAML)只需声明 PVC,无需硬编码存储细节,使得应用更容易在不同集群(使用不同底层存储)间迁移。
- 简化开发: 开发者只需关注“我需要多大、怎么用的存储”,无需学习底层存储配置。
- 运维灵活性: 管理员可以灵活管理、更换、扩缩容底层存储基础设施,只要它能通过 PV 提供给 PVC 使用。
- 资源管理: 可以精确控制分配给不同应用/命名空间的存储资源。
- 支持有状态应用: 是运行数据库(MySQL, PostgreSQL)、消息队列(Kafka, RabbitMQ)、监控系统(Prometheus)等有状态服务的基础设施。