SeaweedFS CSI 实现原理
Kubernetes CSI(Container Storage Interface)是一套标准化的存储插件接口,用于将第三方存储系统集成到 Kubernetes 中。
本文以 seaweedfs-csi-driver 1.4.5版本讲解下其工作流程和原理
1、Kubernetes CSI 概述
Kubernetes CSI(Container Storage Interface)是一套标准化的存储插件接口,用于将第三方存储系统集成到 Kubernetes 中
1)、CSI 驱动核心组件
Controller plugin:以 Deployment 方式部署,负责集群级存储资源管理,比如 Volume 的创建、删除、扩容、快照等Node plugin:以 DaemonSet 方式部署,处理节点级存储操作,负责在具体的节点上执行 Volume 的挂载和卸载等任务
2)、Kubernetes CSI 核心架构图

3)、核心 CSI Sidecar 容器
为简化 CSI 驱动开发,Kubernetes 提供了一系列标准化的 Sidecar 容器,封装了与 Kubernetes 核心组件的交互逻辑,开发者只需实现 CSI 标准接口即可。核心 Sidecar 容器包括:
external-provisioner:- 监听 PVC 对象变更,结合 PVC 关联的
StorageClass(需指定该 CSI 驱动为 provisioner) - 调用 CSI Controller 服务的
CreateVolume(创建卷)/DeleteVolume(删除卷)接口 - 自动创建 PV 并与 PVC 绑定(创建卷后)或删除 PV(删除卷后)
- 监听 PVC 对象变更,结合 PVC 关联的
node-driver-registrar:- 调用 CSI Node 服务的
NodeGetInfo接口获取驱动信息 - 将驱动注册到节点的
/var/lib/kubelet/plugins_registry/目录(Kubelet 监听该目录) - 完成 Node Plugin 向 Kubelet 的注册,以便 Kubelet 后续调用
- 调用 CSI Node 服务的
external-attacher:- 监听
VolumeAttachment对象,调用 CSI Controller 服务的ControllerPublishVolume(Attach,将卷关联到节点)/ControllerUnpublishVolume(Detach,解除卷与节点的关联)接口 - 区别于 Node 侧的 Mount:Attach 是集群级操作(卷→节点),Mount 是节点级操作(卷→容器目录)
- 对于 SeaweedFS CSI 而言,由于 SeaweedFS 是分布式文件存储(无块设备/物理卷挂载到节点的概念),无需执行卷关联到节点的 Attach/Detach 操作,因此其 CSI 驱动中
ControllerPublishVolume和ControllerUnpublishVolume接口均为空实现,仅返回成功状态以满足 CSI 协议规范
- 监听
external-resizer:监听 PVC 扩容请求,调用 CSI Controller 服务的ControllerExpandVolume接口,完成卷的容量扩容external-snapshotter:监听 VolumeSnapshot 对象,调用 CSI Controller 服务的CreateSnapshot/DeleteSnapshot接口,处理卷快照的创建与删除livenessprobe:通过调用 CSI 驱动的Probe接口,监控 CSI 驱动进程的健康状态,异常时触发重启
4)、CSI 与 Kubernetes 组件的交互逻辑
Controller Plugin:通过 Sidecar 容器(如external-provisioner、external-attacher)与 Kubernetes APIServer 交互,监听 PVC/PV/VolumeAttachment 等资源的变更事件,执行对应的存储资源操作Node Plugin:通过node-driver-registrarSidecar 容器向 Kubelet 完成注册,Kubelet 发现注册信息后,通过 Unix Domain Socket 向 Node Plugin 发起节点级存储操作调用
2、SeaweedFS CSI 工作原理
1)、部署架构
SeaweedFS CSI 驱动部署后包含 1 个 Deployment + 2 个 Daemonset:
1)seaweedfs-controller(Deployment,集群级)
包含 1 个核心业务容器 + 4 个 Sidecar 容器:
- seaweedfs-csi-plugin(核心):实现 CSI Controller 接口,是 SeaweedFS 卷管理的核心逻辑载体:
CreateVolume:调用 SeaweedFS Filer 的接口创建 Volume(指定存储桶、副本策略、容量等参数)DeleteVolume:调用 SeaweedFS Filer 的接口删除对应 Volume,清理存储资源- 额外实现
ControllerExpandVolume(扩容)、CreateSnapshot(快照)等接口
- Sidecar 容器:
csi-provisioner、csi-resizer、csi-attacher、csi-liveness-probe
2)seaweedfs-node(DaemonSet,节点级)
每个节点部署一份,包含 1 个核心业务容器 + 2 个 Sidecar 容器:
- csi-seaweedfs-plugin(核心):实现 CSI Node 接口,负责节点侧卷挂载/卸载:
NodePublishVolume(核心):接收 Kubelet 调用,通过 Unix Domain Socket 调用同节点seaweedfs-mount容器的/mount接口,触发weed mount命令挂载卷NodeUnpublishVolume:调用seaweedfs-mount容器的/unmount接口,执行卸载并清理挂载目录NodeGetInfo:向driver-registrar提供节点信息,完成驱动注册。
- Sidecar 容器:
driver-registrar、csi-liveness-probe
3)seaweedfs-mount(DaemonSet,节点级)
每个节点部署一份,仅包含 seaweedfs-mount 容器:
- 核心职责:通过 Unix Domain Socket 暴露
/mount、/unmountHTTP 接口,接收seaweedfs-node的挂载/卸载请求 - 核心能力:管理
weed mount进程的生命周期(启动/停止),是节点侧卷挂载的实际执行者
2)、使用过程

1)CSI 驱动准备阶段
驱动部署完成后:
seaweedfs-controller中的external-provisioner向 Kubernetes APIServer 注册监听器,监听 PVC、StorageClass 等资源变更seaweedfs-node中的node-driver-registrar向节点 Kubelet 完成驱动注册,Kubelet 记录驱动信息并建立通信通道(Unix Domain Socket)
2)卷的动态配置(PVC → PV → SeaweedFS Volume)
- 集群管理员创建
StorageClass,指定 provisioner 为seaweedfs-csi-driver - 用户创建 PVC,指定上述
StorageClass并声明存储容量 external-provisioner监听到 PVC 创建事件后,向seaweedfs-csi-plugin发起 gRPC 调用CreateVolumeseaweedfs-csi-plugin调用 SeaweedFS Filer 的接口创建对应 Volumeexternal-provisioner自动创建 PV,将 PV 与 PVC 绑定,卷配置完成
3)创建 Pod 并使用卷
用户创建 Pod 并引用已绑定的 PVC,触发节点侧挂载流程:
- Kubernetes 调度器将 Pod 调度到目标节点,节点 Kubelet 发起
NodeStageVolume调用(卷准备):csi-seaweedfs-plugin解析挂载参数(filer 地址、卷路径、挂载选项等)- 通过 Unix Socket(
/var/lib/seaweedfs-mount/seaweedfs-mount.sock)向seaweedfs-mount发送 POST/mount请求 seaweedfs-mount启动weed mount进程(命令:weed mount -filer=<filer地址> <目标挂载路径>),并返回本地通信 Socket 信息
- Kubelet 发起
NodePublishVolume调用(卷发布):csi-seaweedfs-plugin通过bind mount方式,将weed mount挂载的目录绑定到 Pod 的指定路径(如/var/lib/kubelet/pods/<pod-id>/volumes/kubernetes.io~csi/<pvc-name>/mount)
- Pod 启动后,应用程序可直接访问挂载路径,像使用本地文件系统一样操作 SeaweedFS 分布式存储卷
3、SeaweedFS Mount 实现原理
在 SeaweedFS CSI 驱动的节点侧挂载流程中,seaweedfs-mount 容器通过启动 weed mount 进程完成了分布式存储卷到节点本地的挂载,那为什么 weed mount 能让应用像操作本地文件系统一样访问 SeaweedFS 集群呢?
内核态(Kernel):
- FUSE 内核:作为内核态桥接层,与 VFS 交互,表现形式与普通文件系统无异。接到文件操作请求后,不直接处理业务逻辑,而是将请求存入队列并转发给用户空间
用户态(Userspace):
- GO-FUSE:FUSE 内核的通信桥梁。负责与
/dev/fuse设备交互,接收内核队列的请求并转发给 WFS,同时回传结果 - WFS:业务逻辑层。基于 GO-FUSE 实现文件系统接口,实现了GO-FUSE包中定义的文件系统接口,负责与 SeaweedFS 进行交互
完整数据流转流程:
- 应用程序发起
read系统调用,陷入内核 - VFS 识别出 FUSE 挂载点,将请求交由 FUSE 内核处理
- FUSE 内核将请求存入队列,并通过
/dev/fuse转发 - WFS 通过 GO-FUSE 从内核队列中取出请求,进行业务逻辑处理
- WFS 通过 RPC 调用与 SeaweedFS 集群通信完成数据读写,结果沿原路(WFS → GO-FUSE → FUSE 内核 → VFS → Java APP)返回
更多推荐


所有评论(0)