系列导航
本系列从 K8s 存储模型入手,逐步展开到 CSI 插件实现与云原生存储全景。
① 概念 → ② Volume 生命周期 → ③ CSI 架构 → ④ FlexVolume 演进 → ⑤ 对比 → ⑥ 排障 ‖ ⑦ 开发 → ⑧ 高级特性 → ⑨ 演进展望
| 顺序 | 文章 | 定位 |
|---|---|---|
| ① | 概念与入门 | 基础——K8s 存储模型、PV/PVC/StorageClass、Volume 分类树 |
| ② | 本篇 - Volume 生命周期全解析 | 全貌——两阶段处理、动态/静态供应、Volume 流转路径 |
| ③ | CSI 架构详解 | 标准——gRPC 三服务、Sidecar 模式、External Components |
| ④ | FlexVolume 与 CSI 演进 | 演进——FlexVolume 原理、CSI 设计思想 |
| ⑤ | 存储方案对比与选型 | 选型——主流 CSI 插件横向对比 + 决策树 |
| ⑥ | 排障思路与常用命令 | 运维——工具链 + 场景排查 + 性能 |
| — | 核心路径 ↑ | 扩展展望 ↓ |
| ⑦ | CSI 插件开发指南 | 扩展——从零开发一个 CSI 插件 |
| ⑧ | 高级特性详解 | 进阶——快照、克隆、扩容、拓扑感知 |
| ⑨ | 云原生存储演进与展望 | 展望——容器原生存储、DPU 卸载、未来方向 |
重要
Volume 从创建到销毁,经历供应(Provision)→ 绑定(Bind)→ 挂载(Attach+Mount)→ 使用 → 卸载(Unmount+Detach)→ 回收(Reclaim)六个阶段。本文逐阶段拆解,重点说明"两阶段处理"机制和动态/静态供应的区别。
1. Volume 生命周期总览
PVC 创建 ↓ 供应(Provision) ├── 静态供应:运维预先创建 PV,PVC 匹配绑定 └── 动态供应:Provisioner 根据 StorageClass 自动创建 PV + 底层存储 ↓ 绑定(Bind):PersistentVolumeController 匹配 PVC 与 PV ↓ 调度(Schedule):Pod 被调度到某节点 ↓ Attach:Volume Controller 将远程存储挂载到该节点(块存储特有) ↓ Mount:kubelet 将 Volume 挂载到 Pod 容器目录 ↓ Pod 运行,容器读写 Volume ↓ Pod 删除 ↓ Unmount:kubelet 卸载容器内 Volume ↓ Detach:Volume Controller 从节点卸载远程存储 ↓ 回收(Reclaim):Retain / Delete
2. 供应阶段
2.1 静态供应
运维人员手动创建 PV,开发人员创建 PVC,由 PersistentVolumeController 匹配绑定。
匹配条件:
| 条件 | 说明 |
|---|---|
storageClassName | PV 和 PVC 必须一致(或都为空) |
accessModes | PV 的模式必须包含 PVC 请求的模式 |
capacity.storage | PV 的容量必须 ≥ PVC 的请求量 |
| |
2.2 动态供应
开发人员只创建 PVC(引用 StorageClass),Provisioner 自动创建 PV 和底层存储。
| |
3. 两阶段处理:Attach + Mount
Volume 挂载到 Pod 分两步,这是理解 K8s 存储机制的核心:
3.1 第一阶段:Attach(挂接到节点)
由 Volume Attach Controller(kube-controller-manager 的循环)负责,将远程存储设备挂接到 Pod 所在节点。
| 存储类型 | 是否需要 Attach | 说明 |
|---|---|---|
| 块存储(EBS、Ceph RBD、iSCSI) | 是 | 将远程块设备映射为节点的 /dev/xvdX |
| 文件存储(NFS、CephFS) | 否 | 直接走网络协议,无需设备挂接 |
| 本地存储(Local PV、hostPath) | 否 | 设备已在节点上 |
| |
3.2 第二阶段:Mount(挂载到容器目录)
由 kubelet 负责,在节点上将 Volume 挂载到 Pod 的目录,再 bind mount 到容器内。
节点上的流程:
/dev/xvdf(块设备)
↓ format + mount
/var/lib/kubelet/pods/<podID>/volumes/<plugin>/<volumeName>/
↓ bind mount
容器 rootfs 的 mountPath(如 /usr/share/nginx/html) | |
4. 绑定模式
4.1 Immediate Binding(立即绑定)
PVC 创建后立即匹配 PV。适用于网络存储(NFS、CephFS),因为不依赖 Pod 调度位置。
4.2 WaitForFirstConsumer(延迟绑定)
PVC 创建后等待 Pod 调度完成,再根据 Pod 所在节点匹配 PV。适用于 Local PV 和拓扑感知存储。
| 模式 | 触发时机 | 适用场景 |
|---|---|---|
Immediate | PVC 创建即绑定 | NFS、CephFS 等网络存储 |
WaitForFirstConsumer | Pod 调度后绑定 | Local PV、云盘(需感知拓扑) |
5. Local PV 的特殊性
5.1 一个 PV 一块盘
Local PV 不等于 hostPath。hostPath 使用的是宿主机根目录所在磁盘,随时可能被写满。Local PV 要求使用额外挂载的独立磁盘或块设备。
| 对比 | hostPath | Local PV |
|---|---|---|
| 存储介质 | 宿主机任意目录 | 独立磁盘/分区 |
| I/O 隔离 | 无 | 有(独立设备) |
| 调度感知 | 无 | 有(nodeAffinity) |
| 持久化 | 不保证 | 保证(Retain 策略) |
5.2 调度与 Volume 分布
常规 PV:先调度 Pod → 再处理 Volume。
Local PV:调度器必须知道 Volume 在哪个节点,将 Pod 调度到有对应磁盘的节点。由 VolumeBindingChecker 过滤条件实现。
| |
5.3 Local PV 示例
| |
6. PV 回收策略
PVC 删除后,PV 的处理方式由 persistentVolumeReclaimPolicy 决定:
| 策略 | 行为 | 适用场景 |
|---|---|---|
| Retain | PV 保留,状态变为 Released,数据不删除 | 生产环境、重要数据 |
| Delete | PV 和底层存储一起删除 | 动态供应的云盘、测试环境 |
| Recycle(已废弃) | 执行 rm -rf 清空数据,PV 变为 Available | 旧版本兼容 |
7. Volume Plugin 机制
K8s 内置了 20 多种 Volume Plugin,正在从 In-tree 迁移到 CSI:
| 对比 | In-tree Plugin | CSI Plugin |
|---|---|---|
| 代码位置 | K8s 主仓库 | 独立仓库 |
| 升级方式 | 随 K8s 版本 | 独立升级 |
| 接口 | Go 接口 | gRPC |
| 部署 | 编译进 kubelet | 容器化 Sidecar |
详见 CSI 架构详解。