Skip to content

存储卷声明 / 存储卷 / 存储类(PVC / PV / StorageClass)

Kubernetes 的持久化存储由三个互相配合的资源构成,Kuboard 在 集群详情 → 配置与存储 → 存储 分组下提供三者的管理页面。

三个概念与完整链路

资源英文一句话定位
存储类StorageClass(SC)动态供给的模板:声明"用哪个存储后端、按什么策略创建卷"
存储卷PersistentVolume(PV)集群里的存储资源池:一块真实存在的存储(NFS 导出目录、云盘、本地路径等)
存储卷声明PersistentVolumeClaim(PVC)用户对存储的申领:应用声明"我要多大容量、什么读写模式"的卷

完整链路:

  1. 管理员准备 StorageClass(或集群中已有默认存储类);
  2. 用户创建 PVC,指定存储类与容量;
  3. Kubernetes 为 PVC 绑定一个 PV:
    • 动态供给(Dynamic Provisioning):provisioner 按 PVC 的要求现场创建 PV 并绑定,不需要管理员预先准备;
    • 静态绑定:PVC 直接指定已存在的 PV(volumeName),适合管理员预先准备好存储的场景;
  4. 工作负载(Deployment / StatefulSet / Pod)在卷配置中引用该 PVC;
  5. Pod 调度到节点后,kubelet 把 PV 挂载进容器,应用开始读写数据。

一句话记忆

StorageClass 是"图纸",PV 是"仓库里的货",PVC 是"领料单"。PVC 领到的货(PV)可能是仓库按图纸现场生产的(动态供给),也可能是仓库里提前备好的(静态绑定)。

创建 StorageClass

StorageClass 是集群级资源,通常由集群管理员操作。入口:配置与存储 → 存储 → 存储类 → 创建

创建表单字段:

字段对应 spec 字段说明
名称metadata.name存储类名称,集群内唯一
默认存储类注解 storageclass.kubernetes.io/is-default-class打开后,创建 PVC 不指定存储类时默认使用它
注解 / 标签metadata.annotations / metadata.labels可选
绑定模式volumeBindingMode立刻绑定(Immediate,默认):创建 PVC 后立即分配卷;需要时绑定(WaitForFirstConsumer):第一个 Pod 调度到节点后才分配,适合本地盘等按节点分布的存储
回收策略reclaimPolicy删除(Delete,默认):PVC 删除后连 PV 带数据一并删除;保留(Retain):PV 保留,数据由管理员手工处理
制备器类型provisionerKuboard 提供两类动态供给向导:本地路径(动态制备)NFS(动态制备),见下文

本地路径(LocalPath)动态供给

选择"本地路径(动态制备)"后,配置每个节点上的存储根路径

  • 默认根路径(DEFAULT_PATH_FOR_NON_LISTED_NODES):默认 /opt/local-path-provisioner,未单独配置的节点都使用它;
  • 节点配置:可为指定节点配置独立根路径;某节点配置 0 个路径 = 禁止在该节点制备存储卷;配置多个路径 = 制备时随机选择。

保存后,向导会在 kube-system 名称空间下一并创建制备器所需的附属对象:ServiceAccount、RBAC、ConfigMap(保存上面的路径配置)以及 Deployment(镜像 rancher/local-path-provisioner)。

NFS 动态供给

选择"NFS(动态制备)"后,填写:

字段说明
NFS ServerNFS 服务器地址,如 192.168.1.100
NFS Path导出路径,必须以 / 开头,如 /exports/k8s
MountOptions挂载选项(可选)
可使用容量向导用来生成制备器自身卷的容量,如 100Gi
镜像制备器镜像:eipwork/nfs-subdir-external-provisioner:v4.0.18 或华为云镜像源

表单下方提供了一条测试命令,请确认集群任意节点都能成功执行(挂载、写入、读取):

sh
mkdir /tmp/testnfs \
&& mount -t nfs <NFS Server>:<NFS Path> /tmp/testnfs \
&& echo "hello nfs" >> /tmp/testnfs/test.txt \
&& cat /tmp/testnfs/test.txt

保存后,向导会在 kube-system 下创建制备器 Deployment 及配套 RBAC,并创建一对供制备器自身使用的 PV / PVC(命名 nfs-provisioner-<存储类名>-pv / -pvc)。

默认存储类

默认存储类 开关打开后,Kuboard 会自动写入注解 storageclass.kubernetes.io/is-default-class: "true"。这样创建 PVC 时不选择存储类也会使用该存储类。

默认存储类只能有一个

同一集群内 is-default-class 注解只能指向一个存储类。切换默认存储类前,先把旧的默认存储类开关关闭。

等价的 YAML(以本地路径为例):

yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-path
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: rancher.io/local-path
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

创建 PVC

PVC 是名称空间级资源。入口:配置与存储 → 存储 → 存储卷声明 → 创建(列表页顶部先选择集群与名称空间)。

表单字段:

字段对应 spec 字段说明
名称空间metadata.namespace固定为当前选择的名称空间
名称metadata.namePVC 名称,名称空间内唯一
存储类spec.storageClassName下拉选择已有存储类;留空时:使用默认存储类(若存在),或走静态绑定
存储卷类型spec.volumeMode文件系统(Filesystem,默认)或 存储块(Block)
读写模式spec.accessModes至少选择 1 个:只能被单节点读写(ReadWriteOnce)/ 可被多节点只读(ReadOnlyMany)/ 可被多节点读写(ReadWriteMany)/ 被单个容器组读写(ReadWriteOncePod)
需求容量spec.resources.requests.storage必填,如 10Gi2GB5Mi8MB
存储卷名称spec.volumeName通常留白,由存储类的 provisioner 自动分配;只有静态绑定时才手工填写

填写完成后点击 保存,在弹出的 YAML 预览 对话框中确认无误后创建。

动态供给

选择存储类(或留空使用默认存储类),其余字段按需填写。对应的 YAML 形如:

yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-data
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  storageClassName: local-path
  resources:
    requests:
      storage: 10Gi

创建后 PVC 会很快被 provisioner 绑定到新建的 PV,状态由 Pending(等待中) 变为 Bound(已绑定)

静态绑定(手动指定现有 PV)

适合存储已由管理员预先准备好(如手工创建的 PV)的场景:

  1. 创建 PVC 时不选择存储类
  2. 存储卷名称 中填写要绑定的 PV 名称(或通过 YAML 预览补充 volumeName);
  3. 需求容量与读写模式需与目标 PV 匹配,且目标 PV 状态必须为 Available(可用)
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-data-static
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  storageClassName: ""
  volumeName: pv-nfs-01
  resources:
    requests:
      storage: 10Gi

权限说明

创建 PVC 需要当前用户在目标名称空间对资源 persistentvolumeclaims 具备 create 权限;StorageClass / PV 是集群级资源,创建它们需要集群级权限。Kuboard 会依据当前用户权限自动置灰无权限的操作按钮。

查看 PVC 与 PV 状态

列表页与 K8s 其他资源列表一致,支持集群 / 名称空间切换、按名称搜索、批量删除:

  • PVC 列表:额外展示 存储类状态 两列;
  • PV 列表:展示集群、名称、创建时间、操作(PV 是集群级资源,无名称空间列)。

PVC 详情页展示:存储类、卷类型、需求读写模式实际读写模式需求容量实际容量、状态,以及 关联存储卷(PV)事件(排障入口)。

PVC 的常见状态(status.phase):

状态含义
Pending等待中:尚未找到可绑定的 PV(动态供给的卷还没建好,或没有匹配的 PV)
Bound已绑定:已与某个 PV 完成绑定
Lost丢失:绑定的 PV 不存在或已被删除,数据可能丢失

PV 的常见状态(status.phase):

状态含义
Available可用:空闲,可被 PVC 绑定
Bound已绑定:已被某个 PVC 占用
Released已释放:绑定的 PVC 已删除,但 PV 尚未被回收(Retain 策略下常见)
Failed失败:自动回收(Delete)失败

PV 详情页可查看卷源类型、容量、读写模式、回收策略与绑定的 PVC;PVC 详情页中的"关联存储卷"区块可直接跳转到对应 PV,并支持查看其 YAML。

创建 PV(静态供给时)

需要预先准备存储时,可手工创建 PV。入口:配置与存储 → 存储 → 存储卷 → 创建(集群级资源)。

表单字段:

字段对应 spec 字段说明
名称metadata.namePV 名称,集群内唯一
容量spec.capacity.storage必填,如 10Gi
读写模式spec.accessModes与 PVC 相同的四种模式,可多选
卷类型spec.volumeMode文件系统(默认)/ 存储块
回收策略spec.persistentVolumeReclaimPolicy保留(Retain,默认)/ 删除(Delete)/ 回收(Recycle,已弃用)
存储类名称spec.storageClassName可选;建议与要绑定的 PVC 一致,方便匹配
卷源类型spec.<卷源>hostPath / NFS / 本地存储 / CSI / iSCSI / RBD / FC / GlusterFS / CephFS
高级设置spec.mountOptions / spec.nodeAffinity挂载选项、节点亲和性(折叠展开)

选择卷源后按类型填写:hostPath 填主机路径与类型(如"目录(不存在时创建)");NFS 填服务器地址导出路径、是否只读;CSI 填驱动名称卷句柄等。

等价的 YAML(NFS 与 hostPath 各一例):

yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-01
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  persistentVolumeReclaimPolicy: Retain
  storageClassName: ""
  nfs:
    server: 192.168.1.100
    path: /exports/data
yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-hostpath-01
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /data/k8s-vol
    type: DirectoryOrCreate

创建成功后 PV 处于 Available,之后按上文"静态绑定"方式让 PVC 绑定它。

hostPath 仅用于开发 / 单节点验证

hostPath 直接把节点上的目录当作存储,数据不跨节点共享、不做冗余,生产环境请使用 NFS、云盘(CSI)等真正的共享 / 分布式存储。

把 PVC 挂载到工作负载

PVC 本身不产生数据读写,必须挂载到工作负载中:

  1. 进入 Deployment(部署)StatefulSet(有状态副本集)Pod 的创建 / 编辑页;
  2. 容器组模板 → 卷 中点击 添加卷,卷类型选择 存储卷声明(persistentVolumeClaim);
  3. 在下拉中选择要挂载的 PVC(卷编辑处支持 快速创建 新 PVC);
  4. 在容器设置中把该卷挂载到目标目录(如 /data)。

有状态应用(数据库、消息队列等)建议使用 StatefulSet:副本按序创建,每个副本可以稳定绑定各自的 PVC。

PVC 与副本的关系

一个 ReadWriteOnce(只能被单节点读写) 的 PVC 同一时刻只能被一个节点上的 Pod 使用。需要多副本共享读写时,存储类与 PV 必须支持 ReadWriteMany(可被多节点读写),否则多副本会因抢占同一卷而启动失败。

常见注意点

注意点说明
删除策略决定数据去向PVC 删除后,其存储类的 reclaimPolicy 决定 PV 与数据的命运:Delete 连卷带数据删除(不可恢复);Retain 保留 PV 与数据,需管理员手工处理(删除 PV、清理后端数据、释放配额)
扩容受 allowVolumeExpansion 限制只有存储类声明了 allowVolumeExpansion: true 且存储后端支持时,PVC 才能在线扩容,且只能增大、不能缩小。Kuboard 的存储类表单未提供该开关,需要时可在存储类详情 → YAML 中补充该字段
编辑 PVC 的容量PVC 编辑页可修改需求容量,但实际是否生效仍取决于上一条的扩容条件
读写模式创建后不可改RWO(ReadWriteOnce)单节点读写、RWX(ReadWriteMany)多节点共享读写,需在创建前规划好
绑定关系不可换绑PVC 一旦与 PV 绑定,除非删除 PVC,否则不能换绑到其他 PV;需要换绑时先删除 PVC 并等待原 PV 被回收
静态绑定要匹配手工绑定时,PVC 的容量(≤ PV 容量)、读写模式、存储类必须与目标 PV 匹配,且 PV 须为 Available
LocalPath 数据在节点本地本地路径供给的卷数据只存在所在节点上,Pod 调度到其他节点后数据不随之迁移;节点损坏即数据丢失,仅适合非关键数据或配合备份

相关页面