主题
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+ |
| ReclaimPolicy | PVC 删除后 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-Ceph | Ceph 集群 | 快照、克隆、扩容 |
| NFS CSI | NFS 服务器 | RWX、动态供给 |
| Local Path Provisioner | 本地目录 | 简单、性能好 |
| 云厂商 CSI | EBS/云盘 | 快照、加密 |
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 调度后再创建 PVyaml
# 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: Immediatebash
# 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: 100Gi5. 面试高频问题
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}'