1. CSI 架构基础:存储插件与 Kubernetes 的桥梁
Container Storage Interface (CSI) 是 Kubernetes 生态中存储插件的标准接口规范。它定义了存储系统(如 SAN、NAS、云硬盘)与容器编排平台之间的通信协议,使得存储厂商只需实现一套 CSI 驱动,即可被 Kubernetes、Mesos、Docker Swarm 等平台统一调用。本章聚焦 CSI 在 Kubernetes 中的实现,剖析其核心组件、交互流程以及与 Kubernetes 存储体系的集成关系。
1.1 CSI 规范概述
CSI 规范由 Kubernetes SIG-Storage 与存储厂商共同推动,目前已成为容器存储的事实标准。其核心设计原则包括:
- 解耦:存储逻辑与编排平台分离,驱动独立部署。
- 可移植:同一驱动可跨 Kubernetes、Mesos 等平台运行。
- 声明式:通过 gRPC 接口实现卷的生命周期管理。
| 版本 | 关键特性 | Kubernetes 支持版本 |
|---|---|---|
| v0.3 | 基础卷管理、节点挂载 | v1.10+ (Alpha) |
| v1.0 | 稳定 GA,支持拓扑感知 | v1.13+ (GA) |
| v1.5 | 卷快照、卷克隆 | v1.20+ |
| v1.9 | 卷组快照、可恢复性增强 | v1.28+ |
性能调优视角: CSI 规范定义了 30+ 个 gRPC 方法,其中
ControllerPublishVolume、NodeStageVolume、NodePublishVolume 是压测重点。这些方法的延迟直接决定 Pod 启动速度和卷挂载效率。
1.2 CSI 组件角色与交互流程
CSI 驱动在 Kubernetes 中由三个核心组件构成:Controller、Node、Identity。每个组件负责不同的 RPC 服务,协同完成卷的创建、挂载、卸载等操作。
1.2.1 组件角色定义
| 组件 | 部署形态 | 核心 RPC 方法 | 职责 |
|---|---|---|---|
| Controller | Deployment / StatefulSet | CreateVolume, DeleteVolume, ControllerPublishVolume, ControllerUnpublishVolume, CreateSnapshot |
管理卷的创建、删除、挂载到节点、快照等控制面操作 |
| Node | DaemonSet | NodeStageVolume, NodePublishVolume, NodeUnstageVolume, NodeUnpublishVolume, NodeGetVolumeStats |
在节点上执行卷的格式化、挂载、卸载、状态查询 |
| Identity | 与 Controller/Node 同进程 | GetPluginInfo, GetPluginCapabilities, Probe |
提供驱动元数据、能力声明、健康检查 |
1.2.2 交互流程:从 PVC 创建到 Pod 挂载
下图展示了 CSI 驱动在 Kubernetes 中处理一个 PVC 创建并挂载到 Pod 的完整流程:
1.2.3 关键交互步骤详解
- PVC 创建:用户创建 PVC,API Server 持久化对象。
- Provisioner 调用 CreateVolume:External Provisioner 监听到 PVC 事件,调用 CSI Controller 的
CreateVolume方法。 - Controller 创建卷:CSI Controller 与存储后端交互,创建实际存储卷。
- Attacher 调用 ControllerPublishVolume:Pod 调度到节点后,External Attacher 调用
ControllerPublishVolume将卷附加到节点。 - Kubelet 调用 NodeStageVolume:Kubelet 调用 CSI Node 的
NodeStageVolume方法,在节点上格式化并挂载卷到全局目录。 - Node 挂载卷:CSI Node 执行
NodePublishVolume,将卷绑定挂载到 Pod 的容器路径。
压测关注点: 步骤 ② 和 ④ 是控制面操作,延迟受存储后端性能影响;步骤 ⑤ 和 ⑥ 是数据面操作,涉及文件系统格式化、mount 系统调用,是节点 I/O 瓶颈的高发区。
1.3 CSI 与 Kubernetes 存储体系的关系
CSI 驱动是 Kubernetes 存储体系中的“执行层”,它与上层的存储抽象(PV、PVC、StorageClass)以及下层的存储后端紧密协作。下图展示了 CSI 在 Kubernetes 存储架构中的位置:
1.3.1 与 Kubernetes 原生存储的对比
| 特性 | Kubernetes 原生 In-Tree 驱动 | CSI 驱动 (Out-of-Tree) |
|---|---|---|
| 部署方式 | 内嵌在 kube-controller-manager / kubelet 中 | 独立容器,通过 DaemonSet / Deployment 部署 |
| 升级影响 | 需升级 Kubernetes 版本 | 独立升级,不影响集群核心组件 |
| 存储厂商适配 | 需提交 Kubernetes 社区 PR,周期长 | 厂商自行开发,快速迭代 |
| 性能隔离 | 与核心组件共享资源,故障影响面大 | 独立资源限制,故障隔离性好 |
| 功能扩展 | 受 Kubernetes 版本限制 | 支持快照、克隆、拓扑感知等高级特性 |
1.3.2 CSI 与 StorageClass 的绑定
StorageClass 是 Kubernetes 中定义存储“类”的抽象,CSI 驱动通过 provisioner 字段与 StorageClass 绑定:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-csi
provisioner: csi.example.com # 与 CSI 驱动的 Identity 服务返回的 driver name 一致
parameters:
type: ssd
iopsPerGB: "10"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer # 拓扑感知延迟绑定
allowVolumeExpansion: true
性能调优陷阱:
volumeBindingMode: WaitForFirstConsumer 会延迟卷创建直到 Pod 调度完成,这有助于拓扑感知调度,但会增加首次 Pod 启动延迟。在压测时需区分“卷创建延迟”和“Pod 启动延迟”。
1.4 本章小结
- CSI 规范通过 gRPC 接口标准化了存储插件与编排平台的交互,Controller/Node/Identity 三个组件各司其职。
- 交互流程从 PVC 创建开始,经过 Provisioner、Attacher、Kubelet 的协调,最终由 CSI Node 完成卷挂载。
- CSI 驱动作为 Kubernetes 存储抽象与存储后端之间的适配层,相比 In-Tree 驱动具有更好的可移植性、隔离性和扩展性。
- 理解 CSI 架构是后续进行驱动压测和故障排查的基础,尤其是控制面与数据面的延迟分布。