Velero 多标签选择器(OrLabelSelectors)备份与恢复设计解读
【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero
本文以 Velero 官方设计文档 design/Implemented/multiple-label-selectors_design.md 为骨架,结合当前仓库源码,完整讲解
OrLabelSelectors的设计动机、API 结构、实现原理与使用限制,帮助读者掌握如何用一份 Backup/Restore 配置完成"多标签 OR 逻辑"的资源筛选。
导读
Kubernetes 的 label selector 原生只支持 AND 逻辑(多个键值对同时匹配),而现实中很多应用以多套标签体系标记同一批资源(如app=gdpr、app=wpa、app=ccpa),按任意一个标签命中就要纳入备份。Velero 通过新增OrLabelSelectors字段,让一个备份或恢复请求可以指定一组 label selector,资源只要命中其中任意一个即被选中。读完本文,你将理解该字段的 API 定义、与原有LabelSelector的互斥关系、备份与恢复两侧的底层实现调用链,以及直接使用 YAML 配置该功能的方法。
一、背景:单标签筛选的局限
Velero 的 Backup / Restore API 原本只有一个LabelSelector字段(*metav1.LabelSelector),用于在备份/恢复请求级别按标签过滤资源。例如指定labelSelector: {matchLabels: {data-protection-app: "true"}},Velero 只会把带该标签的资源纳入备份。
LabelSelector的匹配语义来自 Kubernetes 本身:多个标签键值对之间是 AND 关系,即必须同时满足全部条件。这带来两个问题:
- 无法表达"标签集合中任意命中一个"(OR 逻辑);
- 用户若想按 OR 规则备份,只能针对每个标签分别创建一份 Backup,规模一大就非常繁琐。
设计文档中给出的典型场景是:用户想备份一批 Secret,但这些 Secret 的标签并不统一,只要命中app=gdpr、app=wpa、app=ccpa中任意一个就要备份。在旧方案下必须创建 3 份 Backup,每份对应一个标签规则。相关讨论见 Velero 仓库 issue #1508(对应设计文档内的 Related Issue 链接)。
二、设计目标与总体思路
该特性的核心目标是:
- 支持在单个 Backup 配置中按多标签 OR 逻辑筛选资源;
- 支持在单个 Restore 配置中按多标签 OR 逻辑筛选资源;
- 不改变现有
LabelSelector的任何行为,二者作为相互独立的 API 功能并存。
关键设计决定是新增独立的OrLabelSelectors字段,而不是扩展LabelSelector的语义。设计文档同时明确了二者共存时的优先级规则:若同时指定两者(现实中不常见),OrLabelSelectors优先;LabelSelector仅在未指定OrLabelSelectors时生效。
三、API 设计:BackupSpec 与 RestoreSpec 的新字段
3.1 结构定义
设计文档给出的原型为:BackupSpec 与 RestoreSpec 各自新增OrLabelSelectors []*metav1.LabelSelector,语义为"资源命中集合中任意一个 label selector 即被纳入"。当前仓库中的落地实现位于 pkg/apis/velero/v1/backup_types.go,并已带有明确的互斥注释:
// OrLabelSelectors is list of metav1.LabelSelector to filter with // when adding individual objects to the backup. If multiple provided // they will be joined by the OR operator. LabelSelector as well as // OrLabelSelectors cannot co-exist in backup request, only one of them // can be used. // +optional // +nullable OrLabelSelectors []*metav1.LabelSelector `json:"orLabelSelectors,omitempty"`RestoreSpec 的对应字段定义在 pkg/apis/velero/v1/restore_types.go 中,语义为"从备份中恢复时,对象命中任意一个 selector 即被恢复"。
3.2 字段互斥校验
设计文档强调LabelSelector与OrLabelSelectors被视作两种独立功能,不应混用。这一约束在控制器层有强制校验:备份控制器在 pkg/controller/backup_controller.go 中,若发现请求同时携带两个字段,会向request.Status.ValidationErrors追加错误信息:
"encountered labelSelector as well as orLabelSelectors in backup spec, only one can be specified"
恢复侧同样遵循"二者不能共存,只能指定其一"的约束(见 pkg/restore/restore.go 的注释说明)。
四、YAML 使用示例
4.1 仅使用OrLabelSelectors(推荐方式)
下面的配置来自设计文档的用例:命名空间test内的资源只要命中app=gdpr、app=wpa、app=ccpa中任意一个标签即被备份:
apiVersion: velero.io/v1 kind: Backup metadata: name: backup-101 namespace: openshift-adp spec: includedNamespaces: - test storageLocation: velero-sample-1 ttl: 720h0m0s orLabelSelectors: - matchLabels: app: gdpr - matchLabels: app: wpa - matchLabels: app: ccpa注意:
orLabelSelectors的每一项都是一个完整的metav1.LabelSelector,因此不仅可以使用matchLabels,也可以使用matchExpressions(如In/NotIn/Exists操作符)来表达更复杂的匹配条件,并可与原LabelSelector一样与 namespace 过滤、resource 过滤配合使用。
4.2 仅使用LabelSelector(原有行为)
apiVersion: velero.io/v1 kind: Backup metadata: name: backup-101 namespace: openshift-adp spec: includedNamespaces: - test storageLocation: velero-sample-1 ttl: 720h0m0s labelSelector: matchLabels: app: gdpr此例仍保持原有语义:只匹配app=gdpr这一个标签。
4.3 语义对比小结
| 配置方式 | 匹配语义 | 命中条件 |
|---|---|---|
仅labelSelector | AND | 资源必须满足该 selector 的全部条件 |
仅orLabelSelectors | OR | 资源满足集合中任意一个 selector 即命中 |
| 两者同时指定 | 非法 | 控制器校验报错,只允许其一 |
Restore 的用法与 Backup 完全一致,只需将同样的字段写到kind: Restore的spec下即可实现"按多标签 OR 逻辑恢复对象"。
五、源码级实现剖析
5.1 备份侧:item_collector 的双路查询
设计文档指出备份侧的改动集中在pkg/backup/item_collector.go。当前实现的核心逻辑在listResourceByLabelsPerNamespace函数(pkg/backup/item_collector.go),其处理流程如下:
- 初始化全局选择器:遍历
backupRequest.Spec.OrLabelSelectors,用metav1.FormatLabelSelector逐个格式化为字符串并放入orLabelSelectors切片;若存在Spec.LabelSelector则格式化为labelSelector字符串(pkg/backup/item_collector.go)。 - 细粒度过滤覆盖:当配置了基于资源类型的细粒度过滤器(如 ResourcePolicies 的 per-kind filter)时,会用 filter 中携带的
LabelSelector/OrLabelSelectors覆盖全局选择器(pkg/backup/item_collector.go),保证更精细的过滤策略优先。 - OR 列表优先查询:只要
orLabelSelectors非空,就对其中每个 selector 分别执行一次 list 查询并合并结果(listItemsForLabel),实现"多次查询、结果取并集"的 OR 效果(pkg/backup/item_collector.go)。 - 仅当 OR 列表为空时才走单 label 查询:若
len(orLabelSelectors) == 0,则回退到原来的labelSelector单次查询,完全保留旧行为(pkg/backup/item_collector.go)。
此外,在设计文档提到的collectResource路径上,命名空间对象同样会经过 label 选择器检查(见 pkg/backup/item_collector.go 附近关于 namespace 过滤的注释),而资源对象也会在写入备份前按 OR 集合做逐项判定(pkg/backup/item_collector.go),与 API Server 端的选择器查询形成双重保险。
备份请求中的选择器还会被转换为labels.Selector形式,用于 namespace 追踪器(nsTracker)的初始化(pkg/backup/item_collector.go),确保按 OR 规则选中的资源所在 namespace 也能被正确记录与处理。
5.2 恢复侧:restore.go 的逐对象判定
设计文档指出的恢复侧改动位于pkg/restore/restore.go。当前实现包含两处关键逻辑:
- 选择器准备:在恢复流程入口,若
req.Restore.Spec.OrLabelSelectors非空,则逐个通过metav1.LabelSelectorAsSelector转换为labels.Selector列表OrSelectors;同时将LabelSelector(为空时用空 selector 兜底,即匹配全部)转换为selector(pkg/restore/restore.go)。 - 逐对象 OR 判定:恢复每个对象时,先按原有
selector判断,再遍历ctx.OrSelectors:只要对象标签与任意一个OR selector 匹配,就保留该对象;若与全部 OR selector 都不匹配,则跳过(pkg/restore/restore.go)。
这样恢复侧就实现了"命中集合中任意一个标签即恢复,全部不命中则跳过"的语义,与备份侧完全对齐。
5.3 细粒度过滤(ResourcePolicies)中的 OR 支持
除了 Backup/Restore 顶层字段,OrLabelSelectors还被引入到细粒度资源过滤体系:在备份的资源策略过滤与恢复的资源策略过滤中,均可为某个资源类型配置LabelSelector或OrLabelSelectors(相关判定见 pkg/backup/item_collector.go 与 pkg/restore/restore.go),使多标签 OR 逻辑不仅能用于整份备份/恢复请求,还能用于对特定资源类型做精细控制。
六、CLI 支持情况与使用边界
设计文档明确说明:该特性不会通过 Velero CLI 暴露。从当前仓库看,虽然 pkg/cmd/util/flag/orlabelselector.go 提供了一个 Cobra 兼容的OrLabelSelectorflag 包装器(支持以or分隔解析多个 selector,例如app=gdpr or app=wpa),并且 pkg/cmd/cli/backup/create.go、pkg/cmd/cli/restore/create.go、pkg/cmd/cli/schedule/create.go 等 CLI 代码中都有OrLabelSelectors相关引用,但作为 API 层字段,它最稳定、最推荐的使用方式是直接编写 Backup / Restore 的 YAML 清单提交给集群,通过kubectl apply或velero backup create --from-backup等清单化方式使用。
使用时请注意以下几点边界:
labelSelector与orLabelSelectors互斥,二者同时出现会被控制器校验拒绝;orLabelSelectors中每一项都是独立的metav1.LabelSelector,单项内部仍是 AND 语义,多项之间才是 OR 语义;- 该字段同时适用于 Backup 与 Restore,也适用于 Schedule 触发的备份(底层仍是 Backup 资源);
- 字段可选(
+optional)、可空(+nullable),为空或 nil 时行为等同于不筛选,即所有对象纳入。
七、测试与验证
仓库为这一特性提供了完整的单元测试覆盖,可作为理解语义的补充证据:
- 备份侧:
pkg/backup/backup_test.go与pkg/backup/item_collector.go相关的 OR 选择器测试,验证多 selector 合并查询与逐项判定逻辑; - 恢复侧:
pkg/restore/restore_test.go中覆盖了OrLabelSelectors场景的恢复筛选测试; - 构建器与 CLI:
pkg/builder/backup_builder.go、pkg/builder/restore_builder.go提供了在测试或代码中构造OrLabelSelectors的便捷方式,pkg/cmd/util/flag/orlabelselector_test.go验证了 flag 解析行为。
八、总结
OrLabelSelectors以"新增独立字段、不改旧行为、二者互斥、OR 优先"为原则,解决了 Kubernetes 标签选择器只支持 AND 语义的天然限制,让 Velero 用户可以:
- 用一份 Backup 配置覆盖"多套标签中的任意一套";
- 用一份 Restore 配置按同样规则恢复对象;
- 将多标签 OR 逻辑扩展到细粒度的 ResourcePolicies 过滤场景。
从实现上看,备份侧通过"每个 selector 分别 list、结果取并集"实现 OR 查询,恢复侧通过"逐对象遍历 OR selector 集合、全部不命中才跳过"实现 OR 判定,二者语义一致、边界清晰。若你需要对一批标签不统一但"命中任一标签即需保护"的资源做备份与恢复,可以直接参考本文第四节 YAML 示例,将orLabelSelectors写入 Backup / Restore 清单投入使用。
【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考