Kubernetes PV 和 PVC 有什么区别?如何管理持久化存储?
PV 和 PVC 的区别可以用一句话概括:PV 是集群里真实或即将创建的存储资源,PVC 是业务在命名空间里提出的存储申请。Pod 不直接挑磁盘,而是引用 PVC;控制器再根据容量、访问模式、StorageClass、selector 等条件,把 PVC 绑定到合适的 PV。这样做的好处是把“应用要多大空间”和“底层用 EBS、NFS 还是本地盘”解耦,但代价是排障时要同时看 PVC、PV、StorageClass、Pod 事件,不能只盯一个对象。
PV、PVC 和 StorageClass 怎么配合?
动态供给是最常见的方式:开发者创建 PVC,指定 StorageClass,存储插件自动创建 PV。下面是一个比较典型的写法:
yamlapiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast-ssd provisioner: ebs.csi.aws.com reclaimPolicy: Delete volumeBindingMode: WaitForFirstConsumer allowVolumeExpansion: true --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: data-pvc spec: accessModes: - ReadWriteOnce storageClassName: fast-ssd resources: requests: storage: 20Gi
volumeBindingMode: WaitForFirstConsumer 很关键,它会等 Pod 出现后再结合调度结果创建或绑定卷,避免卷先在 A 可用区创建,Pod 却被调度到 B 可用区。reclaimPolicy: Delete 适合临时环境,PVC 删除后底层卷也会被删;生产数据库通常更倾向 Retain,防止误删 PVC 直接丢数据。这个取舍没有绝对答案,关键看数据是否可再生,以及团队有没有成熟的备份和恢复流程。
Pod 怎么挂载 PVC?
Pod 里只引用 PVC 名称,不关心底层 PV 是谁:
yamlapiVersion: v1 kind: Pod metadata: name: app spec: containers: - name: app image: nginx:1.25 volumeMounts: - name: data mountPath: /usr/share/nginx/html volumes: - name: data persistentVolumeClaim: claimName: data-pvc
如果是 Deployment 多副本,要特别注意访问模式。ReadWriteOnce 通常只能被一个节点读写挂载,多个副本被调度到不同节点时可能挂载失败;需要多节点同时读写时,应选择支持 ReadWriteMany 的后端,比如 NFS、CephFS 或云厂商文件存储。别把 PVC 当成“共享目录万能解法”,有状态服务还要考虑锁、并发写入、数据一致性和备份窗口。
追问
静态 PV 和动态 PV 怎么选?
动态 PV 适合大多数云上和标准化环境,开发者只需要申请容量,底层卷由 CSI 插件创建,运维成本低。静态 PV 适合已有存储、特殊挂载参数、本地盘或者迁移场景,管理员先创建 PV,再让 PVC 通过 storageClassName、容量和 selector 去绑定。取舍点在于灵活性和自动化:动态供给快,但受 StorageClass 能力限制;静态供给可控,但人工维护更容易出错。生产里常见做法是通用应用走动态,数据库迁移或本地高性能盘走静态。
RWO、RWX、RWOP 有什么区别?
RWO 是单节点读写,不等于单 Pod;同一节点上的多个 Pod 在某些场景下可能同时使用它。RWX 是多节点读写,适合共享文件,但底层必须真的支持多写,不是 YAML 写了就生效。RWOP 是单 Pod 读写,边界更严格,适合希望从 Kubernetes 层面避免两个 Pod 同时挂同一卷的场景。踩坑点是访问模式表达的是挂载能力,不保证你的应用层并发写入一定安全。
为什么 PVC 一直 Pending?
先看 PVC 事件和 StorageClass:
bashkubectl describe pvc data-pvc kubectl get storageclass kubectl describe storageclass fast-ssd kubectl get pv
常见原因包括 storageClassName 写错、没有默认 StorageClass、CSI 插件异常、容量或访问模式没有匹配 PV。使用 WaitForFirstConsumer 时,PVC 在 Pod 创建前 Pending 是正常的,因为它要等调度器确定节点和可用区。真正的坑是 Pod 也因为其他原因 Pending,导致你误以为是存储问题;这时要同时 kubectl describe pod 看调度事件。
reclaimPolicy 选 Delete 还是 Retain?
Delete 的优点是干净,PVC 删除后底层存储自动释放,测试环境和可再生数据很适合。Retain 的优点是安全,误删 PVC 时底层数据还在,但需要人工清理 PV 的 claimRef、回收磁盘或重新导入。生产数据库、用户上传文件、审计数据更适合 Retain,再配合备份策略;缓存、临时索引和 CI 产物通常可以 Delete。边界是 Retain 不等于备份,它只是“不自动删”,磁盘损坏、误写入和勒索加密仍然需要快照或异地备份解决。
扩容 PVC 有哪些限制?
首先 StorageClass 必须设置 allowVolumeExpansion: true,底层 CSI 也要支持扩容。扩容命令很简单:
bashkubectl patch pvc data-pvc -p '{"spec":{"resources":{"requests":{"storage":"50Gi"}}}}' kubectl describe pvc data-pvc
但缩容通常不支持,文件系统在线扩容也可能依赖节点插件和文件系统类型。踩坑最多的是只看到 PVC 容量变大,却没确认容器内文件系统是否完成扩展;可以进入容器用 df -h 验证。对数据库类应用,扩容前仍建议做快照,因为存储层操作成功不代表应用层一定能平滑消化。