在Kubernetes集群中管理存储资源时,我们经常会遇到两个核心概念:PersistentVolume(PV)和PersistentVolumeClaim(PVC)。这对组合就像云计算时代的"存储租赁系统"——PV相当于物业公司提供的标准房源,而PVC则是租户根据自身需求提交的租赁申请。
PV是集群中的一块网络存储资源,由管理员预先配置好。它就像是数据中心里的一个标准化存储单元,具有明确的容量、访问模式(ReadWriteOnce/ReadOnlyMany/ReadWriteMany)和回收策略(Retain/Recycle/Delete)。PV的生命周期独立于Pod,这意味着即使使用该PV的Pod被删除,存储数据依然存在。
PVC则是用户对存储资源的"需求声明"。开发者不需要关心底层具体的NFS、iSCSI还是云存储,只需在PVC中声明需要的存储大小、访问模式等参数。Kubernetes的控制器会自动寻找匹配的PV并完成绑定,这个过程类似于租房平台根据你的预算和户型需求自动匹配房源。
下面是一个基于NFS的PV定义示例,展示了最完整的参数配置:
yaml复制apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
labels:
storage-tier: standard
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /data/nfs/share
server: 192.168.1.100
关键参数解析:
volumeMode:支持Filesystem(文件系统挂载)或Block(原始块设备)accessModes:ReadWriteOnce(RWO)、ReadOnlyMany(ROX)、ReadWriteMany(RWX)persistentVolumeReclaimPolicy:删除Pod后的处理策略storageClassName:用于PVC的动态供给匹配PV的状态流转遵循以下路径:
Available(可用) → Bound(已绑定) → Released(已释放) → (根据回收策略变为)Available/Deleted/Failed
当PV处于Released状态时,根据回收策略不同会有以下处理:
重要提示:生产环境强烈建议使用Retain策略,避免误删数据。Recycle策略在较新版本中已被废弃。
PVC通过以下字段与PV进行匹配:
accessModes:必须完全匹配PV支持的访问模式storageClassName:空字符串""会匹配没有storageClassName的PVselector:通过label选择器匹配特定PVresources.requests.storage:请求的存储容量必须小于等于PV容量示例PVC定义:
yaml复制apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: web-data-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: standard
selector:
matchLabels:
storage-tier: ssd
当没有合适的静态PV时,可以通过StorageClass实现动态供给:
yaml复制apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
fsType: ext4
yaml复制apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dynamic-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
storageClassName: fast
动态供给的工作流程:
访问模式选择:
存储后端选型:
容量规划:
PVC一直处于Pending状态:
kubectl logs -n kube-system <provisioner-pod>挂载失败报错:
journalctl -u kubelet -f数据无法删除:
kubectl edit pv <pv-name>yaml复制apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
name: disk-snapshot-class
driver: ebs.csi.aws.com
deletionPolicy: Delete
yaml复制apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: db-snapshot
spec:
volumeSnapshotClassName: disk-snapshot-class
source:
persistentVolumeClaimName: mysql-pvc
yaml复制apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc-restore
spec:
storageClassName: standard
dataSource:
name: db-snapshot
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
通过以下方式实现PV共享:
示例共享PVC配置:
yaml复制apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: shared-data
namespace: app1
spec:
accessModes:
- ReadOnlyMany
resources:
requests:
storage: 1Gi
volumeName: shared-pv
yaml复制securityContext:
fsGroup: 2000
runAsUser: 1000
确保容器进程对挂载卷有适当权限
yaml复制volumeMounts:
- name: data-vol
mountPath: /data
readOnly: true
yaml复制securityContext:
seLinuxOptions:
level: "s0:c123,c456"
bash复制kubectl get pv
kubectl get pvc --all-namespaces
kubectl describe pvc <name> -n <namespace>
bash复制kubectl top pod --containers | grep <container-name>
yaml复制apiVersion: v1
kind: ResourceQuota
metadata:
name: storage-quota
spec:
hard:
requests.storage: 500Gi
persistentvolumeclaims: "10"