4. CSI Driver 组件拆解:三大 Service 的职责与接口定义
CSI (Container Storage Interface) Driver 在逻辑上被拆分为三个独立的 gRPC Service:Identity Service、Controller Service 和 Node Service。这种拆分遵循了 Kubernetes 存储体系中“控制面与数据面分离”的核心原则,使得存储插件的部署、升级和扩展更加灵活。每个 Service 负责一组特定的 RPC 调用,共同完成从存储系统发现、卷生命周期管理到节点挂载的全流程。
4.1 三大 Service 职责总览
下表从职责范围、部署模式、关键接口三个维度对比了三个 Service 的核心差异:
| Service 名称 | 核心职责 | 典型部署模式 | 关键 RPC 接口 |
|---|---|---|---|
| Identity Service | 插件身份识别、版本协商、能力声明 | 与 Controller 或 Node 合并部署 | GetPluginInfo, GetPluginCapabilities, Probe |
| Controller Service | 卷的创建/删除、快照管理、容量感知、卷发布/取消发布 | Deployment(控制面) | CreateVolume, DeleteVolume, ControllerPublishVolume, CreateSnapshot |
| Node Service | 卷在节点上的挂载/卸载、文件系统格式化、设备准备 | DaemonSet(数据面) | NodePublishVolume, NodeUnpublishVolume, NodeGetCapabilities |
4.2 Identity Service:插件的“身份证”
Identity Service 是 CSI Driver 的元数据入口,Kubernetes 的 csi-provisioner 和 csi-attacher 等 sidecar 容器在启动时首先调用该 Service 来验证插件的身份和能力。它通常只包含三个 RPC 方法,实现简单但至关重要。
- GetPluginInfo:返回插件的名称(如
csi.huawei.com)和版本号。Kubernetes 使用该名称作为 CSIDriver 对象的标识。 - GetPluginCapabilities:声明插件支持的能力集,例如是否支持 Controller Service、是否支持卷扩展、是否支持拓扑感知等。这些能力决定了 sidecar 容器后续的行为。
- Probe:健康检查接口。Kubernetes 的 liveness probe 会定期调用此接口,确保插件进程处于可用状态。
4.3 Controller Service:存储控制面的“大脑”
Controller Service 是 CSI Driver 中最复杂的组件,它负责与外部存储系统(如华为 OceanStor、AWS EBS、Ceph RBD)的 API 进行交互,执行卷的生命周期管理。该 Service 运行在控制面,通常由 csi-provisioner 和 csi-attacher 两个 sidecar 容器驱动。
Controller Service 的核心接口按功能可分为以下四类:
| 功能分类 | RPC 接口 | 说明 |
|---|---|---|
| 卷管理 | CreateVolume |
根据请求参数(容量、类型、拓扑约束)在存储后端创建卷,返回卷 ID 和属性 |
DeleteVolume |
根据卷 ID 删除存储后端上的卷,释放资源 | |
| 卷发布 | ControllerPublishVolume |
将卷附加(attach)到指定节点,返回设备路径或连接信息 |
ControllerUnpublishVolume |
将卷从节点上分离(detach) | |
| 快照管理 | CreateSnapshot |
基于指定卷创建快照 |
DeleteSnapshot |
删除指定快照 | |
| 容量感知 | GetCapacity |
返回存储后端在指定拓扑范围内的可用容量,用于调度决策 |
CreateVolume 请求因网络超时而重试时,插件应能识别已存在的卷并返回成功,而不是创建重复卷。CSI 规范要求所有修改操作都支持幂等重试。
4.4 Node Service:节点数据面的“执行者”
Node Service 运行在每个 Kubernetes 工作节点上,负责处理卷在节点本地的挂载、卸载和设备管理。它不直接与存储后端 API 通信,而是操作本地设备文件、文件系统和挂载点。该 Service 由 csi-node-driver-registrar sidecar 容器注册到 kubelet 的插件注册机制中。
Node Service 的核心接口包括:
- NodePublishVolume:将已经附加到节点的卷挂载到 Pod 指定的目标路径。该接口接收卷 ID、目标路径、挂载选项(如文件系统类型、读写权限)等参数。通常执行的操作包括:格式化(如果首次使用)、挂载文件系统、创建绑定挂载。
- NodeUnpublishVolume:卸载指定目标路径上的卷,清理挂载点。
- NodeGetCapabilities:声明 Node Service 支持的能力,例如是否支持卷扩展、是否支持文件系统类型选择等。
- NodeGetInfo:返回节点标识和拓扑信息(如可用区、机架位置),用于卷的拓扑感知调度。
- NodeExpandVolume:在节点上扩展卷的文件系统大小(如果支持在线扩展)。
NodePublishVolume 和 NodeUnpublishVolume 是 Pod 启动和销毁的关键路径,必须保证低延迟和高可靠性。建议使用 mount 系统调用的直接绑定挂载,避免不必要的进程 fork。
4.5 三大 Service 的通信架构
下图展示了 CSI Driver 三大 Service 与 Kubernetes 核心组件(kubelet、External Provisioner、External Attacher)之间的通信关系:
4.6 接口定义与 gRPC 协议示例
CSI 规范使用 Protocol Buffers (protobuf) 定义所有 RPC 接口。以下是一个简化的 CreateVolume 接口定义示例,展示了请求和响应的核心字段:
service Controller {
rpc CreateVolume(CreateVolumeRequest) returns (CreateVolumeResponse) {}
}
message CreateVolumeRequest {
// 卷名称,由 Kubernetes 生成,全局唯一
string name = 1;
// 容量范围,包含最小值(required_bytes)和最大值(limit_bytes)
CapacityRange capacity_range = 2;
// 卷能力,如访问模式(单节点读写、多节点只读等)
repeated VolumeCapability volume_capabilities = 3;
// 参数,由 StorageClass 的 parameters 字段传递
map<string, string> parameters = 4;
// 拓扑约束,指定卷必须可用的节点拓扑
TopologyRequirement accessibility_requirements = 5;
}
message CreateVolumeResponse {
// 卷信息,包含卷 ID、容量、拓扑等
Volume volume = 1;
}
message Volume {
// 存储后端返回的唯一卷 ID
string volume_id = 1;
// 实际分配的容量(字节)
int64 capacity_bytes = 2;
// 卷可访问的拓扑范围
repeated Topology accessible_topology = 3;
}
CreateVolumeRequest.parameters 中的自定义参数。这些参数通常来自 StorageClass 的 parameters 字段,用于传递存储后端的特定配置(如存储池名称、性能等级、协议类型等)。建议在插件文档中明确列出所有支持的参数及其默认值。
4.7 三大 Service 的部署拓扑
下图展示了 CSI Driver 在 Kubernetes 集群中的典型部署拓扑,清晰呈现了控制面与数据面的物理分离: