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-0、data-mysql-cluster-1、data-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 |
存储选型没有银弹,根据性能需求、数据安全级别和运维成本综合考量。