Kubernetes 存储管理:PV、PVC 与 StorageClass 实战

存储是有状态应用上 K8s 的核心挑战,本文梳理 K8s 存储体系的关键概念和实战配置。

存储体系概览

Pod → PVC(申请) → PV(实际存储) → 后端存储(NFS/Ceph/云盘)

        StorageClass(动态供给)

PersistentVolume 静态供给

管理员手动创建 PV:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-100g
spec:
  capacity:
    storage: 100Gi
  accessModes:
    - ReadWriteMany    # 多节点读写
  persistentVolumeReclaimPolicy: Retain   # 删除 PVC 后保留数据
  nfs:
    server: 192.168.1.100
    path: /data/k8s/pv001

访问模式说明:

  • ReadWriteOnce (RWO):单节点读写,块存储常用
  • ReadOnlyMany (ROX):多节点只读
  • ReadWriteMany (RWX):多节点读写,NFS/CephFS 支持

PVC 申请存储

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-data
  namespace: production
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi
  storageClassName: fast-ssd   # 指定 StorageClass

在 Pod 中使用:

spec:
  containers:
  - name: mysql
    image: mysql:8.0
    volumeMounts:
    - name: data
      mountPath: /var/lib/mysql
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: mysql-data

StorageClass 动态供给

无需手动创建 PV,按需自动创建:

# 基于 AWS EBS
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
  iops: "3000"
  throughput: "125"
reclaimPolicy: Delete
allowVolumeExpansion: true   # 允许扩容
volumeBindingMode: WaitForFirstConsumer   # 延迟绑定,优化调度
# 基于本地 NFS(使用 nfs-subdir-external-provisioner)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-client
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
  archiveOnDelete: "false"
reclaimPolicy: Delete
allowVolumeExpansion: true

StatefulSet 存储配置

StatefulSet 使用 volumeClaimTemplates 为每个 Pod 自动创建独立 PVC:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-cluster
spec:
  serviceName: mysql
  replicas: 3
  template:
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: fast-ssd
      resources:
        requests:
          storage: 50Gi

这会自动创建 data-mysql-cluster-0data-mysql-cluster-1data-mysql-cluster-2 三个 PVC。

PVC 扩容

# 前提:StorageClass 设置了 allowVolumeExpansion: true
kubectl patch pvc mysql-data -n production \
  -p '{"spec":{"resources":{"requests":{"storage":"50Gi"}}}}'

# 查看扩容状态
kubectl describe pvc mysql-data -n production | grep -A5 Conditions

常用排查命令

# 查看 PV 状态
kubectl get pv

# 查看 PVC 绑定状态
kubectl get pvc -A

# PVC 一直 Pending?
kubectl describe pvc <name> -n <namespace>
# 常见原因:没有匹配的 PV 或 StorageClass 不存在

# 查看存储使用情况
kubectl exec -it <pod> -- df -h /data

存储方案选型

场景推荐方案
单节点读写,高性能云盘(EBS/云硬盘)
多节点共享读写NFS / CephFS
数据库等有状态应用本地 SSD + StatefulSet
对象存储MinIO / S3
开发测试环境hostPath / local

存储选型没有银弹,根据性能需求、数据安全级别和运维成本综合考量。

← 返回文章列表