Skip to content

09 — 存储编排深度教材

PV/PVC/StorageClass/CSI 是 K8s 存储编排的核心。本章覆盖存储生命周期、CSI 架构、StorageClass 设计、快照与克隆。


1. PV/PVC 生命周期

存储生命周期:
  Provisioning → Binding → Using → Releasing → Reclaiming

  Static Provisioning(手动创建 PV):
    Admin 创建 PV → User 创建 PVC → 系统绑定 → Pod 使用 → PVC 删除 → PV 根据策略处理

  Dynamic Provisioning(StorageClass 自动创建):
    User 创建 PVC(指定 StorageClass)→ CSI Provisioner 自动创建 PV → 绑定 → 使用

1.1 AccessModes 与 ReclaimPolicy

AccessMode含义支持此模式的存储
ReadWriteOnce (RWO)单节点读写所有块存储
ReadOnlyMany (ROX)多节点只读NFS、Ceph RBD
ReadWriteMany (RWX)多节点读写NFS、CephFS
ReadWriteOncePod单 Pod 读写K8s 1.22+
ReclaimPolicyPVC 删除后 PV 处理场景
Retain保留数据,手动清理生产数据
Delete自动删除底层存储临时数据
Recycle已废弃

2. CSI(Container Storage Interface)

2.1 CSI 架构

CSI 架构分层:
┌──────────────────────────────────────┐
│             kubelet                   │
├──────────────────────────────────────┤
│      CSI Volume Plugin (in-tree)      │
├──────────────┬───────────────────────┤
│ CSI Provisioner │ CSI Node Driver     │
│ (Controller)    │ (Node Plugin)       │
│ 创建/删除卷      │ 挂载/卸载卷        │
├──────────────┴───────────────────────┤
│         Storage Backend              │
│  (Ceph/NFS/云盘/本地盘)              │
└──────────────────────────────────────┘

CSI Controller 组件(通常 Deployment):
  - 监听 PVC 创建 → 调用后端 API 创建存储 → 创建 PV

CSI Node 组件(DaemonSet):
  - 监听 Pod 调度 → 挂载存储到 Pod → 格式化/挂载

2.2 常用 CSI Driver

CSI Driver后端存储支持特性
Rook-CephCeph 集群快照、克隆、扩容
NFS CSINFS 服务器RWX、动态供给
Local Path Provisioner本地目录简单、性能好
云厂商 CSIEBS/云盘快照、加密

3. StorageClass 生产配置

yaml
# Ceph RBD StorageClass(生产推荐)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ceph-rbd
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
  clusterID: rook-ceph
  pool: replicapool
  imageFormat: "2"
  imageFeatures: layering
reclaimPolicy: Delete
allowVolumeExpansion: true     # 允许在线扩容
volumeBindingMode: WaitForFirstConsumer  # 等待 Pod 调度后再创建 PV
yaml
# NFS StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs
provisioner: nfs.csi.k8s.io
parameters:
  server: 192.168.1.100
  share: /data/k8s
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: Immediate
bash
# volumeBindingMode 对比:
# Immediate:PVC 创建时立即绑定 PV(默认)
# WaitForFirstConsumer:等待 Pod 调度后再绑定
#   优势:避免 PV 创建在不合适的节点(本地存储场景必须用)

4. 快照与克隆

yaml
# VolumeSnapshot 类
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: ceph-rbd-snapclass
driver: rook-ceph.rbd.csi.ceph.com
deletionPolicy: Delete
---
# 创建快照
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: mysql-snap
spec:
  volumeSnapshotClassName: ceph-rbd-snapclass
  source:
    persistentVolumeClaimName: mysql-data
---
# 从快照恢复(创建新 PVC)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-data-restored
spec:
  storageClassName: ceph-rbd
  dataSource:
    name: mysql-snap
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  accessModes: [ReadWriteOnce]
  resources:
    requests:
      storage: 100Gi

5. 面试高频问题

Q: PVC 一直处于 Pending 怎么排查?

bash
# 1. 查看 PVC 事件
kubectl describe pvc <name>

# 2. 常见原因
# a. StorageClass 不存在 → 检查 sc 名称
# b. 没有可用的 PV 匹配 → 检查 accessMode/capacity
# c. CSI Provisioner 未运行 → 检查 CSI Controller Pod
# d. WaitForFirstConsumer → 正常,等 Pod 调度后绑定
# e. 存储后端资源不足 → 检查 Ceph/云盘容量

Q: 如何实现存储在线扩容?

bash
# 1. StorageClass 必须设置 allowVolumeExpansion: true
# 2. 修改 PVC 的 storage 大小
kubectl patch pvc <name> -p '{"spec":{"resources":{"requests":{"storage":"200Gi"}}}}'
# 3. CSI Driver 执行扩容(可能需要重启 Pod)
# 4. 验证:kubectl get pvc <name> -o jsonpath='{.status.capacity.storage}'