概要

在 Kubernetes 的生产环境下,使用 StorageClass + 动态供应(Provisioner)的 NFS、云厂商 CSI 插件(如阿里云、AWS EBS)已经成为有状态服务持久化的主流。然而,很多人遇到“服务挂掉重建后卷丢失”、“PVC 不小心被删就数据没了”这类生产事故。本篇就结合实战,系统梳理 K8s 动态供应存储卷的生命周期管理和高可用恢复策略。


1. Kubernetes 动态供应存储的核心机制

  • PVC(PersistentVolumeClaim)创建时,Kubernetes StorageClass 动态供应器会自动生成 PV(PersistentVolume)和后端实际存储盘。
  • 服务重建,只要继续挂载原 PVC,数据依然不变!
  • 一旦 PVC 删除,PV 及其盘会根据 StorageClass 的回收策略 (reclaimPolicy) 决定是“删除”还是“保留”。
    • Delete:PV 和底层存储盘一起删除(危险,数据全无,云磁盘直接销毁)
    • Retain:PV/PVC 解绑但数据和 PV 依然保留(可手动恢复,最安全)

结论: 只要 PVC 没被删,Pod/Deployment/StatefulSet 怎么重建都不会丢数据。
丢数据的唯一风险是 PVC 被误删且 reclaimPolicy: Delete


2. StorageClass 回收策略详解

回收策略决定了“PVC删除后,数据的命运”:

  • Delete(默认)

    PVC删掉,PV和物理盘也被删,数据彻底消失。

  • Retain(生产强烈推荐!)

    PVC删掉,PV和物理盘还在,可以重新绑定恢复,且未引用前不会自动分给别人。


3. 正确的存储恢复与数据保护策略

3.1 日常状态:服务崩溃/Pod重建

  • 只要继续挂载同名PVC,Pod重建过程100%不会丢数据
  • 不要删除PVC,只操作服务Deployment/StatefulSet对象即可。

3.2 误删了PVC怎么办?(reclaimPolicy: Retain)

恢复原理说明

Retain 策略下,PVC删除后:

  • PV 变为 Released,实际数据盘没被删。
  • 只需简单操作,将这块盘再挂给新的 PVC。

恢复流程

  1. 查找孤立的PV

    1
    kubectl get pv | grep Released
  2. 编辑PV,移除claimRef(变为Available)

    1
    2
    kubectl edit pv <pv-name>
    # spec.claimRef 字段整段删掉,保存
  3. 新建一个“与原PVC参数配置完全一致”的PVC

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
    name: app-data
    spec:
    accessModes: [ReadWriteMany]
    resources:
    requests:
    storage: 20Gi
    storageClassName: nfs-client-retain
  4. 新PVC会自动与老PV绑定,Pod可重新挂载数据恢复!


3.3 若为云磁盘类 PersistentVolume(如 AWS EBS/阿里云云盘)

  • PV被Retain下来后,可以在云厂商后台直接看到原有数据盘。
  • 只需新 PVC “手动指定”已存在云盘的 pv,Pod 新建后数据不变。
  • 可在紧急情况下导出快照再分配新服务。

3.4 极端情况:用了 Delete 策略,PVC/PV/物理盘都没了?

  • 这时,没有自动恢复办法,只能靠备份或云盘快照。
  • 建议所有业务关键数据,即便是 NFS,也应定期备份目录,云盘要自动快照。

4. 生产最佳实践集锦

  1. StorageClass 必须生产强制 Retain
    1
    reclaimPolicy: Retain
    保证即使误删 PVC,PV和数据盘还在。
  2. 业务重建/故障恢复都只动服务 YAML,PVC 绝不轻易删
  3. 有重要数据,还应定期做 volume 级备份和快照
  4. 异常情况建议做一次全链路“PVC回收后手动恢复”演练,有备无患
  5. 用云盘的 PV,生产环境建议做多可用区高可用(如 EBS Multi-AZ),NFS建在稳定服务上!

5. 常见问题FAQ

Q1. Pod/Deployment/StatefulSet挂掉,数据会丢吗?

不会,只要你用同一个PVC,数据始终在原盘/原PV上。

Q2. 误删了有数据的PVC,能救吗?

只要 StorageClass 是 Retain,100% 能救!
操作就是:edit PV 去掉claimRef,重建PVC配置绑定即可。

Q3. 默认的StorageClass不改成Retain会怎样?

删掉PVC就数据全无,云盘或NFS目录会被系统或者Provisioner自动清空,极其危险。

Q4. 手动PV管理和StorageClass/自动动态供应应该怎么选?

建议能用StorageClass就别手写PV,但储回策略一定写成Retain!(deployment也是,存活全靠PVC)

Q5. NFS挂了怎么办?

及时恢复NFS服务,Pod自动重挂卷,不会丢数据,但高可用要靠NFS和备份体系。


6. YAML Example 区

推荐 StorageClass 配置

1
2
3
4
5
6
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-ha-retain
provisioner: nfs-client
reclaimPolicy: Retain

PVC 创建与恢复 YAML

1
2
3
4
5
6
7
8
9
10
11
# 新建
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myapp-data
spec:
storageClassName: nfs-ha-retain
accessModes: [ReadWriteMany]
resources:
requests:
storage: 10Gi

7. 总结与建议

  • 重服务轻数据:“应用随时可删重建,数据卷要细心呵护”。PVC 就是数据生命线!
  • 务必审查你的 StorageClass 回收策略,强推 Retain!
  • Pod、Deployment、StatefulSet 宕机/删除、升级都没关系,只要 PVC 没动,数据就不会丢。
  • 日常做好定期自动化备份 & PVC 恢复演练,敢删干净,底气更大。