
Velero 插件体系深度解析四种插件类型、命名规范与实现原理【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/veleroVelero即原 Heptio Ark本文讲解的历史版本文档中的 Ark 即其前身通过一套完整的插件架构允许用户在不修改、不重新编译核心二进制的前提下向备份与恢复流程中注入自定义功能。本文将围绕site/content/docs/v0.8.0/plugins.md这篇文档系统讲解插件机制的设计动机、四种核心插件类型、命名与日志规范并结合当前仓库源码pkg/plugin目录剖析插件从注册、发现、拉起进程到 RPC 调用的完整生命周期。读完本文你将掌握如何定义一个合规的 Velero 插件、如何通过 init 容器将其注入 Velero 服务器以及如何在插件中正确使用结构化日志。插件架构概述无需重编译的可扩展设计文档明确阐述了 Velero 插件架构的核心理念用户无需修改或重新编译 Velero 核心二进制即可为备份与恢复添加自定义功能。要做到这一点用户只需完成两件事编写一个独立二进制内部实现 Velero 支持的某一类插件接口下文详述的四种 Plugin Kinds在二进制中加入少量样板代码把插件实现暴露给 Velero。随后这个二进制被打包进一个容器镜像以init 容器的形式挂载到 Velero 服务器 Pod 中将其拷贝到共享的emptyDir卷中供 Velero 服务器访问。文档同时提供了一个功能完整的示例插件仓库作为插件作者的起点示例仓库路径已不再随版本更新维护建议直接参考本仓库pkg/plugin下的实现与测试。这一架构在今天的 Velero 源码中依然一脉相承。服务器侧通过pkg/plugin/framework/server.go的Serve()方法把各类已注册插件暴露给外部客户端侧通过 pkg/plugin/clientmgmt/process/process.go 基于hashicorp/go-plugin拉起插件进程并建立 gRPC 通信。从源码结构看插件进程与 Velero 主进程是独立的操作系统进程二者通过进程间通信协作这正是无需重编译核心二进制的底层保证。四种插件类型Plugin Kinds文档列出了 Ark 时代支持的四种插件类型这也是理解整个插件体系的主干插件类型职责Object Store持久化与检索备份文件、备份日志和恢复日志Block Store备份时创建卷快照、恢复时从快照还原卷Backup Item Action在备份文件中存储单个资源项之前对其执行任意逻辑Restore Item Action在将单个资源项恢复进集群之前对其执行任意逻辑这四类插件在pkg/plugin/framework/common/plugin_kinds.go中以PluginKind常量定义注意源码中的类型名称有所演进Block Store 在源码中被称为VolumeSnapshotter并且在 pkg/plugin/framework/server.go 的Serve()方法中逐一注册了对应的 gRPC Server 实现。Object Store 插件负责与对象存储后端如 S3、GCS、Azure Blob 等交互是备份数据的仓库。其在pkg/plugin/velero/object_store.go中定义的接口包含如下关键方法Init(config map[string]string) error—— 用配置键值对初始化对象存储PutObject(bucket, key string, body io.Reader) error—— 写入对象GetObject(bucket, key string) (io.ReadCloser, error)—— 读取对象ObjectExists(bucket, key string) (bool, error)—— 判断对象是否存在ListCommonPrefixes(bucket, prefix, delimiter string)—— 按分隔符列出公共前缀如模拟目录层级ListObjects(bucket, prefix string)—— 列出前缀下的所有对象键DeleteObject(bucket, key string) error—— 删除对象CreateSignedURL(bucket, key string, ttl time.Duration)—— 生成带有效期的预签名 URL。该接口在 pkg/plugin/framework/object_store.go 中被包装成 go-plugin 的 gRPC 插件ObjectStorePlugin分别通过GRPCClient/GRPCServer桥接客户端与服务端。Block Store卷快照插件对应源码中的VolumeSnapshotter类型承担卷级快照能力备份时为卷创建快照恢复时从快照还原卷。这也是云厂商通常提供原生插件的原因——不同云平台的快照 API 差异巨大通过插件隔离可保持核心逻辑与云平台解耦。Backup Item Action 插件对单个资源项如某个 Pod、PVC、Deployment在写入备份文件之前执行任意逻辑。典型用途包括修改资源清单、补充备份所需信息、根据条件决定是否跳过该项等。它接收待备份的单个资源项作为输入返回处理后的资源项并可附带附加资源列表。当前仓库同时支持 v1 与 v2 两代接口BackupItemAction/BackupItemActionV2定义见 pkg/plugin/velero/backupitemaction/v1 与 pkg/plugin/velero/backupitemaction/v2v2 引入了异步操作等更丰富的语义。Restore Item Action 插件对单个资源项在恢复进集群之前执行任意逻辑典型用途包括改写恢复后的资源如调整 PVC 名称、改写环境变量、声明需要一并恢复的附加资源。其输入输出结构见 pkg/plugin/velero/restore_item_action_shared.go输入包含当前正在恢复的 Item与来自备份的原始 ItemFromBackup以及 Restore 资源本身输出除了UpdatedItem被改写后的资源项和AdditionalItems附加恢复项外还支持SkipRestore跳过恢复该资源以及 v2 引入的OperationID异步操作标识与WaitForAdditionalItems等待附加项就绪后再恢复本项。从实现上看上述四类插件的接口均通过 pkg/plugin/framework 目录中的 gRPC 包装层*_client.go/*_server.go/*.go暴露为 go-plugin 插件对应的 proto 定义位于 pkg/plugin/proto生成的 gRPC 代码位于 pkg/plugin/generated。pkg/plugin/framework/plugin_types_test.go中的TestPluginImplementationsAreGRPCPlugins测试也验证了这些插件实现均满足 go-plugin 的GRPCPlugin接口。插件命名规范Plugin Naming文档强调Velero 依赖命名约定来识别插件。每个插件二进制应命名为ark-plugin-kind-name其中plugin-kind必须是以下之一objectstore、blockstore、backupitemaction、restoreitemactionname在同类插件内必须唯一。在今天的仓库中插件发现的机制演化为启动插件进程后由插件自身上报注册信息。服务端在 pkg/plugin/clientmgmt/process/registry.go 中实现DiscoverPlugins()遍历插件目录默认挂载点/pluginsreadPluginsDir会递归扫描所有可执行文件Linux 下要求文件具有任一执行位Windows 下要求.exe后缀跳过不可执行文件并给出警告日志对每个可执行文件通过listPlugins拉起进程并向其 dispense 一个PluginLister由插件自身调用ListPlugins()上报其注册的所有插件标识Command、Kind、Nameregister会对每个标识做重复注册检查同一kindname不得重复和名称格式校验见下文随后按 kind 建立索引。pkg/plugin/framework/server.go的Serve()方法正是插件侧上报注册信息的实现它把当前二进制中注册的各类插件汇总为PluginIdentifier列表交给NewPluginLister(pluginIdentifiers...)供服务端查询。也就是说现代 Velero 的插件命名不再依赖文件名硬编码而是以插件进程内部注册的kind name为准文件本身只需可执行即可被扫描到。插件名称的格式校验无论插件进程内部如何注册名称名称本身都有严格的格式要求。pkg/plugin/framework/common/server_mux.go 中的ValidatePluginName规定名称必须恰好包含一个/分为两部分两部分均不能为空前缀部分必须是合法的 DNS 子域名DNS-1123 子域名规范若传入已存在名称列表则不允许重复。即合规格式为DNS subdomain/non-empty name。Server接口中各Register*方法的注释也明确写有这一格式要求例如 pkg/plugin/framework/server.go 中RegisterObjectStore的注释Accepted format for the plugin name isDNS subdomain/non-empty name。插件日志规范Plugin Logging文档指出Velero 提供了一个日志器供插件使用使插件能够以结构化方式把日志写入 Velero 主服务器日志或每次备份/恢复各自独立的日志中。在当前源码中该日志器位于 pkg/plugin/framework/logger.go 的newLogger()函数。这里有非常关键的工程细节值得展开绝不能把输出设置到 STDOUTgo-plugin 使用 STDOUT 作为客户端与服务端之间的通信协议通道插件进程的标准输出被协议占用因此日志必须走 stderr使用 JSON 格式化器go-plugin 会解析 stderr 上以 JSON 格式输出的日志并将其转换为结构化日志条目字段映射中消息字段使用 hclog 兼容的message键关闭时间戳Velero 服务器在输出日志时已统一添加时间戳插件内不再重复添加避免日志中出现双重时间戳注册多个日志 Hook包括LogLocationHook以plugin作为 logger name标记日志来源位置、ErrorLocationHook记录错误位置、HcLogLevelHook把warning级别调整为 go-plugin 可解析的warn。插件作者在自己的插件中实例化并使用该日志器即可日志会自动流经 go-plugin 通道最终进入 Velero 主日志或对应备份/恢复的专属日志实现全链路可观测。从源码看插件的完整生命周期将文档中的二进制 init 容器 emptyDir 共享卷描述与源码对照可以勾勒出插件从部署到调用的完整链路部署阶段init 容器注入pkg/install/deployment.go中的WithPlugins(plugins []string)为 Velero 服务器 Deployment 注入一组插件镜像作为 init 容器见pkg/install/deployment_test.go的断言velero-plugin-for-aws:v1.2.0、velero-plugin-for-vsphere:v1.1.1分别成为前两个 init 容器。init 容器把插件二进制拷贝进名为plugins的emptyDir卷主容器将同一卷挂载到/pluginspkg/install/deployment.go 中VolumeMounts的MountPath: /plugins并通过环境变量把该路径交给服务器。发现阶段扫描 上报Velero 服务器启动时Registry.DiscoverPlugins()扫描/plugins下的可执行文件逐一拉起插件进程并请求其PluginLister上报注册的插件标识pkg/plugin/clientmgmt/process/registry.go。通信阶段gRPC 进程间调用pkg/plugin/clientmgmt/process/process.go 中的newProcess为每个插件创建一个独立的 go-pluginClient及对应的exec.Cmddispense方法根据KindAndName从插件进程 dispense 出具体 kind 的 gRPC 客户端实例随后 Velero 的备份/恢复流程即通过该客户端发起远程调用。注意process.go中的removeFeaturesFlag函数会剔除传递给插件进程的--features参数及其值避免特性开关配置干扰插件。备份/恢复阶段动作执行备份时Backup Item Action 在资源项写入备份文件前被执行恢复时Restore Item Action 在资源项写入集群前被执行。v2 接口还支持异步操作OperationID与等待附加项就绪WaitForAdditionalItems等高级语义。结语从 Ark 时代仅四类插件、依赖文件名约定的简单设计到今天pkg/plugin下完整的 go-plugin gRPC 插件框架、PluginLister动态注册机制与 v1/v2 多版本接口并存Velero 的插件体系始终保持了文档所确立的核心理念以独立进程 标准接口实现扩展让核心二进制保持纯净。对于希望为 Velero 贡献自定义能力的开发者建议以本仓库 pkg/plugin/framework 目录下的接口与测试为蓝本实现对应 kind 的接口、通过Server注册并Serve()、再以 init 容器方式交付镜像即可完成一个合规插件。【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考