公司动态
external-snapshotter Sidecar控制器内幕:CSI CreateSnapshot与DeleteSnapshot调用全流程代码解析
external-snapshotter Sidecar控制器内幕CSI CreateSnapshot与DeleteSnapshot调用全流程代码解析【免费下载链接】external-snapshotterSidecar container that watches Kubernetes Snapshot CRD objects and triggers CreateSnapshot/DeleteSnapshot against a CSI endpoint.项目地址: https://gitcode.com/gh_mirrors/ex/external-snapshotterexternal-snapshotter 是 Kubernetes 官方 CSI 快照组件其核心是一个Sidecar 容器它监听VolumeSnapshotContent自定义资源CRD并自动触发 CSI 驱动的CreateSnapshot / DeleteSnapshotgRPC 调用把云上或本地存储系统的真实快照和 K8s 对象状态双向同步。本文带你完整走一遍这条调用链路帮你彻底搞懂 Kubernetes 卷快照背后的工作机制。一、Sidecar 在整个快照架构中扮演什么角色Kubernetes 卷快照由三类组件协作完成理解分工是读懂源码的前提组件职责部署方式snapshot-controller监听VolumeSnapshot负责动态创建/回收VolumeSnapshotContent每个集群部署一次csi-snapshotterSidecar监听VolumeSnapshotContent通过 CSI socket 调用驱动执行 CreateSnapshot/DeleteSnapshot每个 CSI 驱动部署一份CSI 驱动真正在存储后端创建/删除快照设备与驱动节点/控制器配套关键设计点Sidecar只关心 Content 对象不直接看 VolumeSnapshot。它通过 informer 监视 Content 的创建、更新、删除事件过滤出Driver 本 CSI 驱动名的对象后放入工作队列以指数退避方式处理。这一设计保证不同驱动的快照互不干扰相关入口逻辑见 pkg/sidecar-controller/snapshot_controller_base.go。二、启动链路从 main.go 到控制器运行部署时通常使用 deploy/kubernetes/csi-snapshotter/setup-csi-snapshotter.yaml以 CSI 驱动的 sidecar 容器形式运行。启动入口在 cmd/csi-snapshotter/main.go几个关键命令行参数值得注意-csi-addressCSI 驱动 socket 地址默认/run/csi/socketSidecar 就是连上这个 socket 与驱动对话-snapshot-name-prefix默认snapshot和-snapshot-name-uuid-length用于给快照加前缀并做名称幂等化-extra-create-metadata开启后会把快照的 name/namespace/content 名作为参数附加进 CSI 请求leader election多副本部署时选出一个 leader 执行控制逻辑其余副本热备。启动完成后控制器在 snapshot_controller_base.go 中启动多组 workerRun(workers, ...)→contentWorker→processNextItem不断从队列取出 key 并调用syncContentByKey这是整个控制循环的“心脏”。三、CreateSnapshot 调用全流程解析核心调度函数是syncContent位于 pkg/sidecar-controller/snapshot_controller.go它的判断逻辑非常清晰判断是否需要删除若对象进入删除流程转入 Delete 分支判断是否需要创建当Source.VolumeHandle存在、Status为空、且不属于组快照成员时调用createSnapshot判断是否已就绪ReadyToUse为 true 则跳过避免反复调用 CSI 接口这是重要的性能优化否则轮询状态调用checkandUpdateContentStatus更新快照状态。createSnapshot会先做幂等检查然后进入真正干活函数createSnapshotWrapper流程分五步①getCSISnapshotInput读取VolumeSnapshotClass取出 CSI 参数Parameters与认证信息Secrets ② 打上VolumeSnapshotBeingCreated注解——这是超时保护机制如果请求发出后驱动长时间无响应注解会保留在对象上防止重启后重复创建导致快照泄漏 ③ 调用handler.CreateSnapshot这里最终通过 gRPC 把CreateSnapshotRequest含源卷 ID、快照名、参数、密钥发给 CSI 驱动gRPC 层实现见 pkg/snapshotter/snapshotter.go ④ 成功后调用updateSnapshotContentStatus通过JSON Patch把SnapshotHandle、ReadyToUse、CreationTime、RestoreSize写回 Content 对象的 status 子资源 ⑤ 移除VolumeSnapshotBeingCreated注解宣告一次干净的事务闭环。若驱动返回永久性错误isCSIFinalError同样会移除注解并记录事件让对象进入可重试的错误态。四、状态轮询快照什么时候才“ReadyToUse”CSI 驱动返回“创建成功”不代表快照立即可用例如某些存储后端存在上传/固化阶段。因此checkandUpdateContentStatusOperation会周期性调用GetSnapshotStatus其内部实现pkg/snapshotter/snapshotter.go很有讲究先通过ControllerGetCapabilities探测驱动是否支持ListSnapshots支持则调用ListSnapshots查询快照的ReadyToUse、创建时间、大小不支持则直接假设快照可用保证兼容老驱动。一旦状态变为就绪Sidecar 把ReadyToUsetrue写回 Content上层的 snapshot-controller 随之更新VolumeSnapshot状态用户侧的kubectl get volumesnapshot就能看到快照可用了。五、DeleteSnapshot 调用全流程解析删除分支的入口同样在syncContent触发条件是shouldDelete返回 true对象被删除且删除策略允许。流程如下策略检查仅当DeletionPolicy Delete、SnapshotHandle仍存在说明尚未真正删除、且不属于组快照时才执行 CSI 删除deleteCSISnapshotOperation先取回认证信息再调用handler.DeleteSnapshot发出 gRPCDeleteSnapshotRequest驱动负责在存储后端删除快照设备clearVolumeContentStatus删除成功后从 API Server 拉取最新对象把SnapshotHandle、ReadyToUse、CreationTime、RestoreSize全部清空——清空 handle 是关键的“已删除”信号触发重新入队移除 finalizer队列下一轮同步时Sidecar 移除自己添加的终结器API Server 随即真正删除该 Content 对象。特别注意CSI 删除成功前不会移除 finalizer这确保了即使 Sidecar 崩溃存储后端的快照也不会变成无人认领的泄漏资源。若策略为Retain则跳过 CSI 调用仅移除 finalizer快照保留在存储后端。六、组快照Volume Group Snapshot扩展从 CSI 1.10 / Kubernetes 1.27 alpha 起项目还支持卷组快照。Sidecar 对VolumeGroupSnapshotContent使用完全对称的一套逻辑实现在 pkg/sidecar-controller/groupsnapshot_helper.gosyncGroupSnapshotContent→createGroupSnapshotWrapper→ 调用 CSICreateGroupSnapshot删除走deleteCSIGroupSnapshotOperation。普通快照若作为组快照成员带有组 handle 注解会在syncContent中被排除在单卷 CSI 操作之外避免重复创建/误删。七、关键源码导航清单模块文件看点启动入口cmd/csi-snapshotter/main.go参数解析、leader 选举、控制器装配控制循环pkg/sidecar-controller/snapshot_controller_base.goinformer、workqueue、驱动名过滤核心状态机pkg/sidecar-controller/snapshot_controller.gosyncContent、createSnapshotWrapper、deleteCSISnapshotOperationgRPC 客户端pkg/snapshotter/snapshotter.goCreateSnapshot / DeleteSnapshot / ListSnapshots 调用CSI 请求封装pkg/sidecar-controller/csi_handler.go快照命名、请求上下文构造组快照pkg/sidecar-controller/groupsnapshot_helper.go组快照对称实现类型定义client/apis/volumesnapshot/v1/types.goVolumeSnapshot 系列 CRD 结构CRD 清单client/config/crd/三个 CRD 的完整 YAML 定义八、总结一张图看懂数据流用户创建 VolumeSnapshot │ ▼ snapshot-controller 动态创建 VolumeSnapshotContent │informer 事件 驱动名过滤 ▼ csi-snapshotter Sidecar 工作队列 │ ┌────┴─────────────┐ ▼ ▼ createSnapshot deleteCSISnapshot │ │ ▼ ▼ CSI 驱动 gRPC CSI 驱动 gRPC CreateSnapshot DeleteSnapshot │ │ ▼ ▼ updateStatus 回写 clearStatus 移除 finalizer (ReadyToUse 轮询至就绪)掌握这条CRD 事件 → 工作队列 → CSI gRPC 调用 → 状态回写的主线你就读懂了 external-snapshotter 90% 的核心逻辑。无论是排查快照卡在Creating的问题还是开发自己的 CSI 驱动这套流程都是必修的底层知识。建议配合 pkg/sidecar-controller/ 目录下的单元测试如snapshot_controller_test.go、content_create_test.go边读边跑理解会更扎实。【免费下载链接】external-snapshotterSidecar container that watches Kubernetes Snapshot CRD objects and triggers CreateSnapshot/DeleteSnapshot against a CSI endpoint.项目地址: https://gitcode.com/gh_mirrors/ex/external-snapshotter创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考