—— Volume、PV、PVC、StorageClass 深度解析与生产实践


前言:为什么 Kubernetes 存储最容易“看懂却用错”?

在 Kubernetes 中,计算是短暂的,数据是永久的

Pod 可以随时被调度、重建、迁移,但数据一旦丢失,业务往往无法恢复。
Kubernetes 为此设计了一套解耦、分层、可扩展的存储模型:

Pod 不直接使用存储,而是通过 PVC 间接声明需求

这套机制功能强大,但也因此成为:

  • 新手最难理解

  • 生产事故最多

  • 配置最容易“差一行就翻车”的模块之一

本文将从原理 → 配置 → 生产实战 → 故障排查,系统性吃透 Kubernetes 持久化存储。


一、Kubernetes 存储对象整体关系(必读)

在进入细节前,先建立全局认知

图片


核心设计思想

层级

关注点

Pod

怎么用

PVC

我要多少、什么能力

PV

真实存储资源

StorageClass

如何创建存储

👉 应用只关心 PVC,不关心底层存储实现


二、Volume:Pod 级别的存储抽象

apiVersion: v1

kind: Podmetadata:  name: volume-demospec:  containers:  - name: nginx    image: nginx    volumeMounts:    - name: html-volume      mountPath: /usr/share/nginx/html    - name: config-volume      mountPath: /etc/nginx/conf.d  volumes:  - name: html-volume    emptyDir: {}  - name: config-volume    configMap:      name: nginx-config

常见 Volume 类型与定位

类型

生命周期

典型用途

emptyDir

Pod 级

临时数据、缓存

hostPath

节点级

本地调试(生产慎用)

configMap / secret

集群级

配置、证书

downwardAPI

Pod 级

Pod 元信息

persistentVolumeClaim

跨 Pod

生产持久化数据

👉 真正的生产数据,必须走 PV / PVC


三、PersistentVolume(PV):真实存储资源

    apiVersion: v1kind: PersistentVolumemetadata:  name: nfs-pv-demo  labels:    environment: productionspec:  capacity:    storage: 100Gi  volumeMode: Filesystem  accessModes:    - ReadWriteMany  persistentVolumeReclaimPolicy: Retain  storageClassName: nfs-storage  nfs:    server: 192.168.1.100    path: /data/nfs-share
    
    

    核心参数速览

    参数

    说明

    capacity

    存储容量

    accessModes

    访问模式

    volumeMode

    文件系统 / 块

    reclaimPolicy

    回收策略

    storageClassName

    所属存储类


    四、PersistentVolumeClaim(PVC):存储需求声明

    apiVersion: v1kind: PersistentVolumeClaimmetadata:  name: app-data-pvcspec:  accessModes:    - ReadWriteOnce  storageClassName: fast  resources:    requests:      storage: 50Gi
    
    

    PVC 的本质

    PVC ≠ 存储本身,而是“存储需求说明书”

    Kubernetes 负责:

    • 匹配已有 PV

    • 或通过 StorageClass 动态创建 PV


    五、StorageClass:动态制备的核心

    apiVersion: storage.k8s.io/v1kind: StorageClassmetadata:  name: fast-ssdprovisioner: kubernetes.io/gce-pdparameters:  type: pd-ssdallowVolumeExpansion: truevolumeBindingMode: WaitForFirstConsumer
    
    

    为什么 StorageClass 至关重要?

    • 解耦应用与存储实现

    • 统一性能、加密、扩容策略

    • 是 “平台级存储能力” 的入口


    六、关键机制深度解析(生产必懂)

    6.1 accessModes 选型

    模式

    含义

    常见场景

    RWO

    单节点读写

    MySQL / Kafka

    RWX

    多节点读写

    NFS / CephFS

    ROX

    多节点只读

    配置分发

    ⚠️ 是否支持 RWX 取决于存储类型,而不是 Kubernetes


    6.2 回收策略 reclaimPolicy

    策略

    行为

    建议

    Retain

    保留数据

    生产核心数据

    Delete

    自动删除

    云盘

    Recycle

    已废弃


    6.3 延迟绑定(极易踩坑)

    volumeBindingMode: WaitForFirstConsumer
    
    

    作用:

    • 等 Pod 调度后再创建 / 绑定 PV

    • 确保节点拓扑一致

    必用场景:

    • 本地存储

    • 拓扑受限云盘


    七、StatefulSet + 存储的隐性规则(重点)

    volumeClaimTemplates:- metadata:    name: data  spec:    accessModes: ["ReadWriteOnce"]    storageClassName: fast-ssd    resources:      requests:        storage: 200Gi
    
    

    你必须知道的事实

    行为

    结果

    每个 Pod

    一个独立 PVC

    删除 Pod

    PVC 不会删除

    删除 StatefulSet

    PVC 仍然存在

    数据是否删除

    只取决于 reclaimPolicy

    👉 StatefulSet 天生“数据优先”


    八、真实生产事故案例:PVC Pending

    ❌ 事故描述

    • 使用 local-storage

    • PVC 长期 Pending

    • Pod 无法启动

    根因分析

    • local PV 绑定节点

    • StorageClass 未设置 WaitForFirstConsumer

    • 调度器无法同时满足 Pod + PV 约束

    正确配置

    provisioner: kubernetes.io/no-provisioner
    volumeBindingMode: WaitForFirstConsumer
    

    九、生产存储选型速查表(收藏级)

    场景

    推荐方案

    accessMode

    MySQL / PostgreSQL

    云盘 / 本地 SSD

    RWO

    Kafka

    本地 NVMe

    RWO

    CI 缓存

    NFS / CephFS

    RWX

    配置文件

    ConfigMap

    ROX

    临时任务

    emptyDir

    -


    十、监控、扩容与安全

    10.1 PVC 使用率监控

    kubelet_volume_stats_available_bytes/kubelet_volume_stats_capacity_bytes < 0.2
    
    

    10.2 PVC 在线扩容

    前提:

    • StorageClass allowVolumeExpansion: true

    • 文件系统支持 resize


    10.3 安全最佳实践

    securityContext:  fsGroup: 1000  runAsUser: 1000  readOnlyRootFilesystem: true
    
    

    十一、常用排障命令

    kubectl get pv,pvc,sc -Akubectl describe pvc xxxkubectl get eventskubectl exec pod -- df -h
    
    

    更多推荐