PV与PVC持久化存储完全指南

发布时间:2026/5/22 1:18:53

PV与PVC持久化存储完全指南 PV与PVC持久化存储完全指南前言在Kubernetes中持久化存储是运行有状态应用的关键。PersistentVolumePV和PersistentVolumeClaimPVC提供了存储资源的抽象层使得应用的存储需求与底层存储基础设施解耦。本文将深入讲解Kubernetes存储体系、PV/PVC的使用方法以及最佳实践。一、Kubernetes存储架构1.1 存储架构图┌─────────────────────────────────────────────────────┐ │ Kubernetes Storage Architecture │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ Pod 1 │ │ Pod 2 │ │ Pod 3 │ │ │ Nginx │ │ MySQL │ │ MongoDB │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │ │ │ │ ┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐ │ │ PVC 1 │ │ PVC 2 │ │ PVC 3 │ │ │ (Claim) │ │ (Claim) │ │ (Claim) │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ │ │ │ │ ┌──────▼──────────────────▼──────────────────▼────┐ │ │ Storage Class │ │ │ ┌──────────────────┐ ┌──────────────────┐ │ │ │ │ Standard SSD │ │ Network File │ │ │ │ └────────┬─────────┘ └────────┬─────────┘ │ │ └─────────────┼─────────────────────┼──────────────┘ │ │ │ │ ┌─────────────▼─────┐ ┌────────────▼─────────────┐ │ │ Local Disk │ │ Remote Storage │ │ │ (Node Local) │ │ (NFS/Ceph/Cloud) │ │ └────────────────────┘ └──────────────────────────┘ └─────────────────────────────────────────────────────┘1.2 核心概念PersistentVolume (PV)集群级别的存储资源PersistentVolumeClaim (PVC)用户对存储资源的请求StorageClass动态 provisioning 的存储类Volume Mode存储卷的访问模式二、PersistentVolume详解2.1 PV类型Kubernetes支持多种存储类型本地存储hostPath、local网络存储NFS、Ceph、GlusterFS云存储AWS EBS、GCE PD、Azure Disk分布式存储Ceph RBD、iSCSI2.2 NFS PV配置apiVersion: v1 kind: PersistentVolume metadata: name: nfs-pv labels: type: nfs capacity: 100Gi spec: capacity: storage: 100Gi volumeMode: Filesystem accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain storageClassName: nfs mountOptions: - hard - nfsvers4.1 - timeo600 nfs: server: nfs-server.example.com path: /exports/data2.3 HostPath PV配置apiVersion: v1 kind: PersistentVolume metadata: name: hostpath-pv labels: type: local spec: capacity: storage: 10Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Delete storageClassName: hostpath local: path: /mnt/disks/ssd1 nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - node-1 - node-22.4 云存储PV配置AWS EBSapiVersion: v1 kind: PersistentVolume metadata: name: ebs-pv labels: type: ebs spec: capacity: storage: 50Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: ebs-sc awsElasticBlockStore: volumeID: aws://us-west-2a/vol-0a1234567890abcdef fsType: ext4Azure DiskapiVersion: v1 kind: PersistentVolume metadata: name: azure-disk-pv spec: capacity: storage: 100Gi volumeMode: Filesystem accessModes: - ReadWriteOnce storageClassName: azure-disk azureDisk: kind: Managed diskName: my-disk diskURI: /subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Compute/disks/my-disk fsType: ext4 cachingMode: ReadWrite三、PersistentVolumeClaim详解3.1 基本PVC配置apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pvc namespace: production labels: app: mysql spec: accessModes: - ReadWriteOnce volumeMode: Filesystem resources: requests: storage: 20Gi storageClassName: standard selector: matchLabels: type: ssd3.2 PVC高级配置apiVersion: v1 kind: PersistentVolumeClaim metadata: name: app-data-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 50Gi storageClassName: ssd dataSource: kind: PersistentVolumeClaim name: source-pvc dataSourceRef: kind: PersistentVolumeClaim name: source-pvc四、StorageClass详解4.1 StorageClass配置apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: standard annotations: storageclass.kubernetes.io/is-default-class: true provisioner: kubernetes.io/gce-pd parameters: type: pd-standard replication-type: regional-pd reclaimPolicy: Retain allowVolumeExpansion: true mountOptions: - debug volumeBindingMode: WaitForFirstConsumer4.2 NFS StorageClassapiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs provisioner: nfs-client parameters: archiveOnDelete: false mountOptions: vers4.1 reclaimPolicy: Delete allowVolumeExpansion: true volumeBindingMode: Immediate --- apiVersion: v1 kind: ServiceAccount metadata: name: nfs-client-provisioner --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: nfs-client-provisioner-runner rules: - apiGroups: [] resources: [persistentvolumes] verbs: [get, list, watch, create, delete] - apiGroups: [] resources: [persistentvolumeclaims] verbs: [get, list, watch, update] - apiGroups: [storage.k8s.io] resources: [storageclasses] verbs: [get, list, watch] - apiGroups: [] resources: [events] verbs: [create, update, patch] --- apiVersion: apps/v1 kind: Deployment metadata: name: nfs-client-provisioner spec: replicas: 1 selector: matchLabels: app: nfs-client-provisioner template: metadata: labels: app: nfs-client-provisioner spec: serviceAccountName: nfs-client-provisioner containers: - name: nfs-client-provisioner image: k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2 volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: nfs-client - name: NFS_SERVER value: nfs-server.example.com - name: NFS_PATH value: /exports/data volumes: - name: nfs-client-root nfs: server: nfs-server.example.com path: /exports/data五、Pod中使用PVC5.1 基本使用apiVersion: v1 kind: Pod metadata: name: mysql-pod labels: app: mysql spec: containers: - name: mysql image: mysql:8.0 ports: - containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: root-password volumeMounts: - name: mysql-data mountPath: /var/lib/mysql - name: mysql-config mountPath: /etc/mysql/conf.d resources: requests: cpu: 500m memory: 1Gi limits: cpu: 1000m memory: 2Gi livenessProbe: exec: command: [mysqladmin, ping, -h, localhost] initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: exec: command: [mysql, -h, localhost, -u, root, -p$MYSQL_ROOT_PASSWORD, -e, SELECT 1] initialDelaySeconds: 20 periodSeconds: 5 volumes: - name: mysql-data persistentVolumeClaim: claimName: mysql-pvc - name: mysql-config configMap: name: mysql-config5.2 StatefulSet中使用PVCapiVersion: apps/v1 kind: StatefulSet metadata: name: mysql namespace: production spec: serviceName: mysql replicas: 3 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: terminationGracePeriodSeconds: 30 containers: - name: mysql image: mysql:8.0 ports: - containerPort: 3306 name: mysql env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: root-password volumeMounts: - name: data mountPath: /var/lib/mysql - name: conf mountPath: /etc/mysql/conf.d resources: requests: cpu: 500m memory: 1Gi limits: cpu: 1000m memory: 2Gi livenessProbe: exec: command: [mysqladmin, ping, -h, localhost] initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: exec: command: [mysql, -h, localhost, -u, root, -p$MYSQL_ROOT_PASSWORD, -e, SELECT 1] initialDelaySeconds: 20 periodSeconds: 5 volumeClaimTemplates: - metadata: name: data spec: accessModes: [ReadWriteOnce] storageClassName: mysql-storage resources: requests: storage: 50Gi - metadata: name: conf spec: accessModes: [ReadWriteOnce] storageClassName: standard resources: requests: storage: 1Gi六、存储扩容6.1 启用存储扩容apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: expandable-storage provisioner: kubernetes.io/gce-pd parameters: type: pd-standard allowVolumeExpansion: true6.2 在线扩容PVC# 查看当前PVC大小 kubectl get pvc my-pvc # 更新PVC大小 kubectl patch pvc my-pvc -p {spec:{resources:{requests:{storage:100Gi}}}} # 确认扩容完成 kubectl get pvc my-pvc -w七、数据持久化最佳实践7.1 使用克隆功能apiVersion: v1 kind: PersistentVolumeClaim metadata: name: cloned-pvc spec: dataSource: kind: PersistentVolumeClaim name: source-pvc resources: requests: storage: 50Gi storageClassName: standard7.2 备份与恢复apiVersion: velero.io/v1 kind: Backup metadata: name: mysql-backup namespace: velero spec: includedNamespaces: - production includedResources: - persistentvolumeclaims - persistentvolumes storageLocation: default ttl: 720h --- apiVersion: velero.io/v1 kind: Restore metadata: name: mysql-restore namespace: velero spec: backupName: mysql-backup includedNamespaces: - production八、常见问题解决方案8.1 PVC一直处于Pending状态# 检查PV是否可用 kubectl get pv # 检查StorageClass是否存在 kubectl get storageclass # 查看PVC事件 kubectl describe pvc my-pvc # 启用Volume Scheduling kubectl patch storageclass standard -p {metadata:{annotations:{volume.alpha.kubernetes.io/node-affinity:...}}}8.2 存储权限问题# 设置正确的安全上下文 apiVersion: v1 kind: Pod metadata: name: app-with-storage spec: securityContext: fsGroup: 2000 runAsUser: 1000 runAsGroup: 3000 containers: - name: app image: myapp:v1 volumeMounts: - name: storage mountPath: /data readOnly: false volumes: - name: storage persistentVolumeClaim: claimName: my-pvc总结Kubernetes的持久化存储体系通过PV、PVC和StorageClass提供了灵活、高效的存储管理方案。正确使用这些资源结合备份恢复策略和监控告警可以确保有状态应用的数据安全和可用性。

相关新闻