Velero 插件架构实战指南:无需重编译即可扩展 Kubernetes 备份与恢复能力
2026/9/16 15:11:11 网站建设 项目流程

Velero 插件架构实战指南:无需重编译即可扩展 Kubernetes 备份与恢复能力

【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero

导读:本文以 Velero 官方文档《Plugins》为骨架,结合仓库pkg/plugin下的真实源码,系统讲解 Velero 的插件化架构——如何在不修改、不重新编译 Velero 核心二进制的前提下,通过自定义插件扩展对象存储、卷快照、备份/恢复时的资源处理等能力。读完本文,你将掌握 Velero 四类核心插件的职责划分、接口定义与注册方式,理解插件二进制的分发机制(init container + emptyDir),并学会利用插件日志体系进行结构化排障。

Velero 为什么需要插件架构

Velero 的核心职责是“备份并迁移 Kubernetes 应用及其持久化卷”。然而,不同用户对接的对象存储后端(AWS S3、Azure Blob、GCS、MinIO 等)、云厂商快照服务(EBS、Azure Managed Disks 等)以及应用自身的备份/恢复语义千差万别。如果把这些能力全部硬编码进 Velero 主二进制,任何新需求都意味着一次完整重编译与重新发布。

Velero 给出的答案是插件(Plugin)架构:用户创建自己的二进制文件,在其中实现 Velero 定义的若干种插件接口,再用少量样板代码把实现“暴露”给 Velero。正如原文档所述,这样的设计使得自定义功能的接入无需修改或重新编译 Velero 核心二进制(见 site/content/docs/v0.11.0/plugins.md)。

从源码看,插件体系建立在 HashiCorp 的 go-plugin(ObjectStore.protoVolumeSnapshotter.protoBackupItemAction.protoRestoreItemAction.protoDeleteItemAction.protoPluginLister.protoShared.proto),生成代码位于 pkg/plugin/generated。

插件如何分发与加载:init container + emptyDir

原文档描述了一种典型的插件分发机制:

  1. 插件作者把实现了插件接口的二进制打进一个容器镜像
  2. 该镜像以init container的形式加入 Velero server Pod;
  3. init container 将插件二进制拷贝到与 Velero 主容器共享的 emptyDir 卷
  4. Velero server 启动时从该共享卷发现并加载插件。

这种做法的好处是显而易见的:Velero 的官方镜像保持精简,而每个存储后端/云厂商的快照能力都作为独立镜像发布与迭代,互不影响。同一个二进制可以同时实现多个插件、多种类型(例如同时实现 ObjectStore 与 VolumeSnapshotter),原文档对此有明确说明。

插件类型(Plugin Kinds)详解

原文档列出了 Velero 支持的四种核心插件类型。结合当前仓库 pkg/plugin/framework/common/plugin_kinds.go 中的PluginKind常量,实际可实现的类型还包括 v2 版本与若干扩展类型:

PluginKind(源码常量)职责
ObjectStore持久化与检索备份文件、备份日志、恢复日志
VolumeSnapshotter(即文档中的 Block Store)备份时创建卷快照、恢复时从快照重建卷
BackupItemAction/BackupItemActionV2备份时对单个资源条目执行自定义逻辑
RestoreItemAction/RestoreItemActionV2恢复时对单个资源条目执行自定义逻辑
DeleteItemAction删除备份时对备份中的资源条目执行清理逻辑
ItemBlockAction对备份中的“块(block)”执行自定义逻辑

其中BackupItemActionV2RestoreItemActionV2与 v1 之间存在版本适配:PluginKindsAdaptableTo映射声明了 v1 实现可以被自动适配为 v2 插件使用,老插件无需改动即可在新版本 Velero 中继续运行。

Object Store:对接任意对象存储后端

Object Store 插件负责 Velero 与对象存储之间的全部底层交互。接口定义在 pkg/plugin/velero/object_store.go,核心方法包括:

  • Init(config map[string]string) error:用配置键值对初始化存储后端,如 bucket、region、endpoint、凭证等;
  • PutObject(bucket, key string, body io.Reader) error:写入对象;
  • ObjectExists(bucket, key string) (bool, error):判断对象是否存在;
  • GetObject(bucket, key string) (io.ReadCloser, error):读取对象;
  • ListCommonPrefixes(bucket, prefix, delimiter string) ([]string, error):按分隔符列出公共前缀(源码注释给出了清晰的示例:bucket 内存在a-prefix/foo-1/bara-prefix/foo-2/baz等键时,以a-prefix/为前缀、/为分隔符会返回a-prefix/foo-1/a-prefix/foo-2/);
  • ListObjects(bucket, prefix string) ([]string, error):列出指定前缀下的全部键;
  • DeleteObject(bucket, key string) error:删除对象;
  • CreateSignedURL(bucket, key string, ttl time.Duration) (string, error):生成带 TTL 的预签名 URL(用于下载备份文件等场景)。

gRPC 服务端注册逻辑见 pkg/plugin/framework/object_store.go 中的ObjectStorePlugin:其GRPCServer通过proto.RegisterObjectStoreServer将实现注册到 gRPC server,GRPCClient则通过common.NewClientDispenser向 Velero 主进程分发客户端。

Block Store(VolumeSnapshotter):云厂商快照能力

原文档中的 “Block Store” 在当前源码中对应VolumeSnapshotter。接口定义见 pkg/plugin/velero/volumesnapshotter/v1/volume_snapshotter.go:

  • Init(config map[string]string) error:按配置初始化快照服务;
  • CreateVolumeFromSnapshot(snapshotID, volumeType, volumeAZ string, iops *int64) (volumeID string, err error):在指定可用区从快照创建新卷,支持指定卷类型与预置 IOPS;
  • GetVolumeID(pv runtime.Unstructured) (string, error)SetVolumeID(pv runtime.Unstructured, volumeID string):读写 PersistentVolume 的云厂商 ID;
  • GetVolumeInfo(volumeID, volumeAZ string) (string, *int64, error):查询卷的类型与 IOPS;
  • CreateSnapshot(volumeID, volumeAZ string, tags map[string]string) (snapshotID string, err error):为指定卷创建快照并打标签;
  • DeleteSnapshot(snapshotID string) error:删除快照。

其 gRPC 封装见 pkg/plugin/framework/volume_snapshotter.go 中的VolumeSnapshotterPlugin。正是因为该接口的存在,AWS EBS、Azure Managed Disks 等不同云厂商的快照能力才能以插件形式独立演进。

Backup Item Action:备份时改造单个资源

BackupItemAction接口(pkg/plugin/velero/backupitemaction/v1/backup_item_action.go)在备份过程中、资源条目被写入备份文件之前被调用,用于对单个资源执行任意逻辑,甚至可以修改资源本身。接口仅有两个方法:

  • AppliesTo() (velero.ResourceSelector, error):声明该动作作用于哪些资源。只有当待备份条目匹配返回的 selector 时,Execute才会被触发;零值 ResourceSelector 表示匹配所有资源
  • Execute(item runtime.Unstructured, backup *api.Backup) (runtime.Unstructured, []velero.ResourceIdentifier, error):对条目执行逻辑并返回(修改前或修改后的)条目,同时可返回一组ResourceIdentifier指定额外需要一并备份的关联资源

典型使用场景包括:备份前为 Secret 注入临时令牌、剔除敏感字段、为自定义 CRD 关联的依赖资源打标记等。

Restore Item Action:恢复时改造单个资源

RestoreItemAction接口(pkg/plugin/velero/restoreitemaction/v1/restore_item_action.go)在恢复过程中、资源条目被写入集群之前被调用,语义与 BackupItemAction 对称:

  • AppliesTo():声明作用于哪些资源;
  • Execute(input *velero.RestoreItemActionExecuteInput) (*velero.RestoreItemActionExecuteOutput, error):执行自定义逻辑,返回输出中包含可选的附加关联资源warning(记录日志但不阻止恢复)或error(记录日志且阻止该资源恢复)。

插件如何声明自己:Names() 与 PluginLister

任何插件实现都要继承 go-plugin 的Plugin接口并实现Names() []string(见 pkg/plugin/framework/interface.go),返回该插件注册的全部实现名称(例如 BackupItemAction 插件可能同时注册podpvc等多个具名实现)。PluginLister插件类型则由 Velero 与插件库代码内部处理,开发者无需实现(见AllPluginKinds()的注释说明)。

编写插件:从接口到二进制

综合上述源码,编写一个插件通常遵循以下流程:

  1. 实现接口:依据目标类型实现ObjectStoreVolumeSnapshotterBackupItemActionRestoreItemAction等接口的全部方法;
  2. 编写样板代码:创建自己的main包,使用框架提供的ObjectStorePluginVolumeSnapshotterPluginBackupItemActionPluginRestoreItemActionPlugin等类型(位于 pkg/plugin/framework),把实现注册进 server,并调用框架的启动入口(server.Serve,见 pkg/plugin/framework/server.go);
  3. 构建二进制并打镜像:将二进制放入容器镜像,作为 init container 挂载到 Velero server Pod 的共享 emptyDir 卷;
  4. 部署启用:重新部署 Velero server,使其从共享卷加载新插件。

需要注意,一个二进制可以同时实现并注册多个插件、多个类型,通过Names()返回多个实现名称,从而用单个镜像覆盖多种扩展需求。

插件日志:结构化的排障入口

插件运行在独立进程中,其日志需要回传给 Velero 主进程统一输出。原文档强调 Velero 提供了专门的 logger 供插件使用。当前仓库的实现位于 pkg/plugin/framework/logger.go,其关键设计值得留意:

  • 绝不能将日志输出到 stdout:go-plugin 用 stdout 承载客户端与服务端之间的通信协议,插件日志一律走stderr,再由 Velero server 转发到统一日志;
  • 使用logrus JSONFormatter,并把消息字段映射为 go-plugin 可解析的@message,从而让插件日志融入主日志流形成结构化条目;
  • 关闭时间戳(Velero server 已统一添加),并通过多个 hook(LogLocationHookErrorLocationHookHcLogLevelHook)完成日志位置记录、错误位置记录与warningwarn级别字符串的兼容转换。

这意味着插件作者可以直接复用该 logger,将结构化信息写入 Velero server 主日志或每个 backup/restore 各自的日志中,与 Velero 自身的日志体系无缝衔接。

版本演进:v1 与 v2 的兼容性

从 pkg/plugin/framework/common/plugin_kinds.go 可以看到,插件接口存在v1 与 v2 两个世代BackupItemAction(v1)与BackupItemActionV2RestoreItemAction(v1)与RestoreItemActionV2均有对应的 gRPC 封装(见 pkg/plugin/framework/backupitemaction/v2 与 pkg/plugin/framework/restoreitemaction/v2)。PluginKindsAdaptableTo映射保证 v1 插件可被自动适配为 v2 使用——这是 Velero 在插件生态演进中对既有第三方插件的兼容性承诺。

进一步探索

  • 原文档与接口定义:site/content/docs/v0.11.0/plugins.md
  • 插件类型常量与版本适配:pkg/plugin/framework/common/plugin_kinds.go
  • 四类核心接口:pkg/plugin/velero/object_store.go、pkg/plugin/velero/volumesnapshotter/v1/volume_snapshotter.go、pkg/plugin/velero/backupitemaction/v1/backup_item_action.go、pkg/plugin/velero/restoreitemaction/v1/restore_item_action.go
  • gRPC 协议定义与生成代码:pkg/plugin/proto、pkg/plugin/generated
  • 客户端进程管理与重启动态加载:pkg/plugin/clientmgmt/process/process.go、pkg/plugin/clientmgmt/manager.go

说明:原文档中提到的示例插件仓库与 logger 链接为外部地址,本文不予引用;仓库内 pkg/plugin/framework/doc.go 明确说明framework包是插件作者与 Velero 核心共同需要 import 的公共包,可作为插件开发的第一手起点。

【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询