运维实战

Kubernetes 存储实战:PV、PVC、StorageClass、CSI 与快照恢复

建立从 Pod 卷到 PVC、PV、StorageClass 和 CSI 的完整模型,并验证绑定、扩容、回收、快照与恢复。

TY
Tycho
技术博主
• 2026-09-18 • 18 分钟阅读 • 1 次浏览
Kubernetes 存储实战:PV、PVC、StorageClass、CSI 与快照恢复

实验基线:Kubernetes v1.37.0、kubectl v1.37.0。先在测试环境执行,记录变更前状态与回滚点;生产集群不得直接照抄节点地址、网段、存储类或资源额度。

四层模型

  1. Pod volume 描述容器如何挂载。
  2. PVC 表达应用对容量和访问模式的请求。
  3. PV 表示集群中的实际存储。
  4. StorageClass 通过 CSI 驱动定义动态供应参数与回收策略。

hostPath只适合单节点测试,不能当作多节点持久化方案。

动态供应示例

apiVersion: v1
kind: PersistentVolumeClaim
metadata: {name: data, namespace: lab}
spec:
  accessModes: [ReadWriteOnce]
  storageClassName: standard
  resources:
    requests: {storage: 1Gi}
kubectl apply -f pvc.yaml
kubectl get pvc,pv -n lab
kubectl describe pvc data -n lab
kubectl get storageclass
kubectl get csidriver

PVC Pending 时检查 StorageClass 名称、默认类、CSI 控制器、拓扑限制和事件。对有拓扑约束的存储,StorageClass 通常应使用 volumeBindingMode: WaitForFirstConsumer,避免卷先建到错误可用区。

扩容、回收与恢复

扩容前确认 StorageClass 的 allowVolumeExpansion及驱动能力;只增大请求,不要缩小。删除 PVC 前检查 PV 的 persistentVolumeReclaimPolicy:Delete 可能同时删除后端卷,Retain 需要人工回收。快照依赖 CSI Snapshot CRD 与控制器,创建后必须做一次“新 PVC 恢复—挂载—校验文件哈希”的演练,只有快照对象 Ready 不能证明可恢复。

从 PVC 到 Pod 的完整实验

apiVersion: v1
kind: Pod
metadata: {name: writer, namespace: lab}
spec:
  containers:
  - name: writer
    image: busybox:1.36
    command: ["sh","-c","date >> /data/history; sleep 3600"]
    volumeMounts: [{name: data, mountPath: /data}]
  volumes:
  - name: data
    persistentVolumeClaim: {claimName: data}
kubectl apply -f pvc.yaml
kubectl apply -f writer.yaml
kubectl wait -n lab --for=condition=Ready pod/writer --timeout=120s
kubectl exec -n lab writer -- cat /data/history
kubectl delete pod writer -n lab
kubectl apply -f writer.yaml
kubectl exec -n lab writer -- cat /data/history

重建 Pod 后文件仍存在,才验证了持久化基本语义。再检查 PVC 绑定的 PV、StorageClass、CSI 驱动和节点拓扑。

访问模式不是并发锁

RWO 表示卷可由单个节点读写,并不保证只有一个 Pod;同一节点上的多个 Pod 仍可能访问。RWOP 才是单 Pod 读写语义,但需要驱动支持。应用自身仍需处理文件锁、数据库一致性和故障恢复。

扩容操作

  1. 确认 StorageClass allowVolumeExpansion: true。
  2. 确认 CSI 驱动支持控制面与文件系统扩容。
  3. 备份关键数据。
  4. 仅增大 PVC requests.storage。
  5. 观察 PVC conditions、事件和文件系统容量。
kubectl patch pvc data -n lab --type=merge -p '{"spec":{"resources":{"requests":{"storage":"2Gi"}}}}'
kubectl get pvc data -n lab -w
kubectl describe pvc data -n lab
kubectl exec -n lab writer -- df -h /data

快照恢复验收

VolumeSnapshot 依赖集群安装 snapshot CRD、snapshot-controller 和驱动支持。快照 ReadyToUse 后,用它创建新的 PVC,挂载到新的校验 Pod,比较文件数量、数据库一致性和哈希;不要在原卷上直接做“恢复测试”。删除测试对象前核对 snapshot content 的删除策略。

删除前四问

  • PV reclaimPolicy 是 Delete 还是 Retain?
  • 后端存储是否还有独立快照?
  • StatefulSet 缩容/删除是否会保留 PVC?
  • 恢复演练是否在目标 RTO 内成功?

静态 PV 只用于理解绑定

apiVersion: v1
kind: PersistentVolume
metadata: {name: lab-local-pv}
spec:
  capacity: {storage: 1Gi}
  volumeMode: Filesystem
  accessModes: [ReadWriteOnce]
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  local: {path: /mnt/lab-data}
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions: [{key: kubernetes.io/hostname, operator: In, values: [replace-node]}]

local 卷必须绑定节点且不会动态供应;节点永久损坏时数据不可迁移。生产优先使用满足故障域、性能、加密和快照要求的 CSI 存储。

快照清单与恢复链

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata: {name: data-snapshot, namespace: lab}
spec:
  volumeSnapshotClassName: replace-snapshot-class
  source: {persistentVolumeClaimName: data}
  1. 等待 readyToUse: true并记录 boundVolumeSnapshotContentName。
  2. 创建 dataSource 指向快照的新 PVC。
  3. 挂载到只读校验 Pod。
  4. 比较业务层记录数、校验和与时间点。
  5. 记录恢复耗时,再删除测试副本。

备份矩阵

对象方法不能替代
Kubernetes 对象etcd/资源清单备份PV 业务数据
块/文件卷CSI/存储快照应用一致性
数据库原生逻辑/物理备份集群配置

数据库快照前应按产品要求冻结写入或使用一致性能力,否则“成功快照”仍可能无法恢复。

可复现记录模板

每次实验记录:集群版本、容器运行时、CNI/CSI 版本、命名空间、使用的 YAML Git 提交、开始与结束时间。命令输出至少保留对象状态、事件、关键日志和回滚结果。文中的占位符必须替换成自己的值,生产执行前应由第二人复核。

故障处理原则

  1. 先缩小影响面,不删除现场。
  2. 按对象状态—事件—日志—依赖顺序收集证据。
  3. 提出可证伪假设,一次只改变一个变量。
  4. 验证恢复后清理临时权限、调试 Pod、端口转发和测试数据。

完成检查

  • 命令退出码为 0,目标对象状态与预期一致。
  • 保存执行前后 YAML、事件与关键日志,确认没有把测试命名空间以外的对象改动。
  • 故障演练完成后执行清理或回滚,再进行下一章。

官方资料

TY

Tycho

热爱分享技术知识,帮助开发者成长。

评论 (0)

评论功能当前已关闭
暂无评论,快来抢沙发吧!