2. CSI 架构解析:三大组件的职责划分
Container Storage Interface (CSI) 是 Kubernetes 与存储后端之间的标准插件接口。CSI 规范将存储插件的逻辑拆分为三个独立的 gRPC 服务:Controller Plugin、Node Plugin 和 Identity Service。这种拆分使得控制面操作与数据面操作可以独立部署、独立升级,并适配不同的 Kubernetes 调度与运行环境。
2.1 整体架构概览
下图展示了 CSI 插件在 Kubernetes 集群中的部署位置与通信关系。Controller Plugin 通常以 Deployment 形式运行在控制节点上,Node Plugin 以 DaemonSet 形式运行在每个工作节点上,Identity Service 则作为公共接口嵌入在两个 Plugin 中。
2.2 三大组件职责详解
| 组件 | 部署方式 | 核心 RPC 接口 | 职责描述 |
|---|---|---|---|
| Controller Plugin | Deployment(通常 1~2 副本) | CreateVolume, DeleteVolume, ControllerPublishVolume, ControllerUnpublishVolume, CreateSnapshot, DeleteSnapshot, ListVolumes | 负责存储卷的生命周期管理:创建、删除、挂载到节点、快照等控制面操作。与存储后端 API 直接交互。 |
| Node Plugin | DaemonSet(每个节点 1 副本) | NodePublishVolume, NodeUnpublishVolume, NodeGetVolumeStats, NodeExpandVolume | 负责节点级别的卷挂载、卸载、统计信息收集。操作本地文件系统和设备。 |
| Identity Service | 嵌入 Controller 和 Node Plugin 中 | GetPluginInfo, GetPluginCapabilities, Probe | 提供插件元数据:名称、版本、支持的能力集、健康检查。Kubernetes 通过 Probe 判断插件是否存活。 |
2.3 Controller Plugin 深度解析
Controller Plugin 是 CSI 架构中的“大脑”,负责所有控制面操作。它通过 gRPC 接口接收来自 Kubernetes 外部控制器(external-provisioner、external-attacher 等)的请求,然后调用存储后端的 API 完成实际操作。
2.3.1 核心接口与调用流程
- CreateVolume / DeleteVolume:创建和删除存储卷。external-provisioner 监听 PVC 对象,当发现新的 PVC 时调用 CreateVolume,将返回的 VolumeId 绑定到 PV 上。
- ControllerPublishVolume / ControllerUnpublishVolume:将卷挂载到指定节点(例如:将云硬盘挂载到云主机)。external-attacher 负责调用此接口。
- CreateSnapshot / DeleteSnapshot:创建和删除卷快照。external-snapshotter 负责调用。
- ListVolumes / ControllerExpandVolume:卷列表查询和在线扩容。
2.4 Node Plugin 深度解析
Node Plugin 运行在每个 Kubernetes 工作节点上,负责将存储卷挂载到 Pod 的文件系统。它直接与 kubelet 交互,kubelet 在 Pod 调度到节点后调用 Node Plugin 完成挂载操作。
2.4.1 核心接口与调用流程
- NodePublishVolume:将卷挂载到 Pod 的挂载路径。kubelet 在 Pod 启动前调用此接口,传入目标路径和挂载选项。
- NodeUnpublishVolume:卸载卷。Pod 删除时 kubelet 调用此接口。
- NodeGetVolumeStats:返回卷的容量使用情况(已用空间、总空间等)。kubelet 定期调用以更新 PV 的指标。
- NodeExpandVolume:节点级别的卷扩容(文件系统扩展)。
2.4.2 挂载流程示例
// NodePublishVolume 典型实现步骤
1. 检查目标挂载路径是否存在,不存在则创建
2. 根据 volume_context 获取存储后端连接信息
3. 调用存储后端 API 或系统命令挂载设备
- 块存储:mount /dev/sdb /var/lib/kubelet/pods/xxx/volumes/...
- 文件存储:mount -t nfs 192.168.1.100:/share /var/lib/kubelet/...
4. 设置挂载选项(只读、noexec 等)
5. 返回成功状态给 kubelet
2.5 Identity Service 深度解析
Identity Service 是 CSI 插件的基础元数据服务,必须同时嵌入 Controller Plugin 和 Node Plugin 中。Kubernetes 在注册 CSI 驱动时首先调用 Identity Service 获取插件信息。
2.5.1 核心接口
| RPC 接口 | 返回值 | 用途 |
|---|---|---|
| GetPluginInfo | name, vendor_version, manifest | Kubernetes 通过此接口获取插件名称和版本,用于注册和日志标识。 |
| GetPluginCapabilities | 支持的能力列表(Controller, Node, VolumeExpansion, Snapshot 等) | Kubernetes 根据能力列表决定启用哪些外部控制器。例如不支持 Snapshot 则不会启动 external-snapshotter。 |
| Probe | ready 状态 | 健康检查接口。Kubernetes 定期调用,如果返回 not ready 则标记插件不可用。 |
2.6 组件间通信机制
CSI 插件与 Kubernetes 组件之间通过 gRPC over Unix Domain Socket 进行通信。每个 Plugin 启动时监听一个 Unix Socket 文件,Kubernetes 组件通过该 Socket 调用 RPC 接口。
2.7 组件职责对比总结
| 对比维度 | Controller Plugin | Node Plugin | Identity Service |
|---|---|---|---|
| 运行位置 | 控制节点(可调度到任意节点) | 每个工作节点 | 嵌入 Controller 和 Node Plugin |
| 与谁通信 | external-provisioner/attacher/resizer/snapshotter | kubelet | Kubernetes CSI 注册机制 |
| 操作对象 | 存储后端 API(创建/删除卷) | 本地文件系统和设备(挂载/卸载) | 插件自身元数据 |
| 故障影响 | 无法创建/删除卷,已有卷不受影响 | 该节点无法挂载/卸载卷 | 插件无法注册,Kubernetes 拒绝使用 |
| 移植工作量 | 高(需对接存储后端 API) | 中(需处理本地挂载逻辑) | 低(固定模板,少量配置) |