CSI驱动变更门禁:容器镜像更新与流水线集成设计 - 第2节
2.1 CSI 标准介绍
Container Storage Interface(CSI)是 Kubernetes 社区与存储厂商共同定义的行业标准接口,旨在将存储系统与容器编排平台解耦。CSI 标准于 2018 年进入 GA 阶段,目前已成为 Kubernetes 对接外部存储的事实标准。
2.1.1 为什么需要 CSI?
在 CSI 出现之前,Kubernetes 通过 in-tree 方式将存储驱动直接编译进 kubelet 和 kube-controller-manager 二进制文件中。这种方式带来以下问题:
- 维护成本高:每个存储厂商的驱动都需要合入 Kubernetes 主干代码,评审周期长
- 版本耦合严重:kubelet 升级必须同步升级存储驱动,无法独立迭代
- 厂商锁定风险:in-tree 驱动的发布节奏受 Kubernetes 版本发布周期制约
- 安全漏洞面大:存储驱动运行在控制面组件进程中,权限隔离不彻底
2.1.2 CSI 标准核心规范
CSI 标准由 CNCF 维护的 spec 仓库 定义,核心包含以下 RPC 服务:
| 服务类型 | RPC 方法 | 功能描述 |
|---|---|---|
| Identity Service | GetPluginInfo | 返回驱动名称、版本等元信息 |
| GetPluginCapabilities | 声明驱动支持的能力(卷挂载、卷克隆、卷快照等) | |
| Probe | 健康检查,确认驱动是否正常运行 | |
| Controller Service | CreateVolume / DeleteVolume | 创建/删除存储卷 |
| ControllerPublishVolume / ControllerUnpublishVolume | 将卷挂载到/从节点上卸载 | |
| CreateSnapshot / DeleteSnapshot | 创建/删除卷快照 | |
| ListVolumes / ListSnapshots | 列举卷/快照列表 | |
| Node Service | NodeStageVolume / NodeUnstageVolume | 在节点上准备/清理卷的暂存挂载点 |
| NodePublishVolume / NodeUnpublishVolume | 将卷挂载到/从 Pod 的挂载路径上卸载 | |
| NodeGetVolumeStats | 获取卷的容量使用统计 |
2.2 CSI 驱动架构:Node / Controller Plugin
CSI 驱动采用 双组件架构 设计,分为 Controller Plugin 和 Node Plugin 两个独立组件,分别运行在控制面和工作节点上。
2.2.1 架构总览
下图展示了 CSI 驱动在 Kubernetes 集群中的部署架构与数据流关系:
2.2.2 Controller Plugin 详解
Controller Plugin 以 Deployment 形式部署在控制面节点上,负责与外部存储系统交互,执行卷的创建、删除、快照、扩容等控制面操作。它通过 gRPC 协议对外暴露 Controller Service 接口。
- 部署方式:通常以 2 副本 Deployment 运行,支持 leader election 实现高可用
- 权限要求:需要访问 kube-apiserver 的 VolumeAttachment、PersistentVolumeClaim 等资源
- 关键能力:CreateVolume、DeleteVolume、CreateSnapshot、ControllerPublishVolume
- 外部依赖:调用存储厂商提供的 SDK 或 REST API 操作后端存储
2.2.3 Node Plugin 详解
Node Plugin 以 DaemonSet 形式部署在每个工作节点上,负责将卷挂载到 Pod 的指定路径。它通过 Unix Domain Socket 与 kubelet 通信,接收挂载/卸载指令。
| 特性 | 说明 |
|---|---|
| 部署形态 | DaemonSet,确保每个节点运行一个实例 |
| 通信方式 | 通过 Unix Domain Socket(/var/lib/kubelet/plugins/<driver-name>/csi.sock)与 kubelet 通信 |
| 核心操作 | NodeStageVolume(暂存挂载)、NodePublishVolume(最终挂载)、NodeUnpublishVolume(卸载) |
| 挂载路径 | 暂存路径:/var/lib/kubelet/plugins/kubernetes.io/csi/<volume-id>/globalmount Pod 路径:/var/lib/kubelet/pods/<pod-uid>/volumes/kubernetes.io~csi/<volume-id>/mount |
| 权限要求 | 需要 privileged 模式访问宿主机设备文件、挂载命名空间 |
2.2.4 卷挂载流程(Stage → Publish)
CSI 驱动将卷挂载分为两个阶段,这种设计使得多个 Pod 可以共享同一个暂存挂载点,减少重复操作:
- NodeStageVolume:kubelet 调用 Node Plugin 将卷挂载到节点的全局暂存路径(globalmount),执行格式化、设备映射等操作
- NodePublishVolume:kubelet 调用 Node Plugin 将暂存路径绑定挂载(bind mount)到 Pod 的专用挂载路径
- NodeUnpublishVolume:Pod 删除时,卸载 Pod 路径上的绑定挂载
- NodeUnstageVolume:当所有引用该卷的 Pod 都删除后,卸载全局暂存路径
mkfs 格式化操作;对于 NFS 等文件系统存储,此阶段仅建立网络连接。合理利用暂存挂载可以避免重复格式化。
2.3 常见 CSI 驱动示例
社区和主流云厂商提供了丰富的 CSI 驱动实现,覆盖块存储、文件存储、对象存储等多种场景。下表列出最具代表性的驱动:
| 驱动名称 | 存储类型 | 适用场景 | 部署复杂度 |
|---|---|---|---|
| Ceph-CSI | 块存储 (RBD) / 文件存储 (CephFS) | 自建私有云、高性能存储池 | 中 |
| NFS-CSI | 文件存储 (NFS) | 传统 NAS 迁移、共享存储 | 低 |
| Amazon EBS CSI | 块存储 (EBS) | AWS 云原生环境 | 低 |
| Azure Disk CSI | 块存储 (Managed Disk) | Azure 云原生环境 | 低 |
| GCE Persistent Disk CSI | 块存储 (PD) | GCP 云原生环境 | 低 |
| Longhorn | 块存储 (分布式) | 边缘计算、小规模集群 | 中 |
| Rook-Ceph | 块/文件/对象存储 | Kubernetes 原生 Ceph 部署 | 高 |
2.3.1 Ceph-CSI 驱动架构示例
Ceph-CSI 是社区最成熟的 CSI 驱动之一,支持 RBD(块)和 CephFS(文件)两种存储协议。其架构包含以下组件:
2.3.2 驱动选择建议
- 云原生环境:优先使用云厂商提供的 CSI 驱动(EBS、Azure Disk、GCE PD),部署简单且与云平台深度集成
- 自建数据中心:推荐 Ceph-CSI 或 Longhorn,支持多副本、快照、克隆等企业级特性
- 传统 NAS 迁移:NFS-CSI 是最轻量的选择,但注意 NFS 缺乏数据一致性保证
- 边缘/小规模集群:Longhorn 提供 Web UI 管理界面,运维门槛较低