ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Velero v1.3 版本深度解析:CRD 备份恢复体系重构、多架构镜像与关键缺陷修复

2026/9/15 16:35:48 拓冰建站 浏览量
Velero v1.3 版本深度解析:CRD 备份恢复体系重构、多架构镜像与关键缺陷修复 Velero v1.3 版本深度解析CRD 备份恢复体系重构、多架构镜像与关键缺陷修复【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero本文以 Velero 仓库的 changelogs/CHANGELOG-1.3.md 为骨架系统梳理 v1.3.0 / v1.3.1 / v1.3.2 三个版本引入的核心能力CRDCustom Resource Definition备份与恢复的多项结构性改进、基于 Docker manifest list 的多架构镜像发布以及 restic、调度恢复、并发安全等领域的大量缺陷修复。读完本文你将理解 Velero 是如何在 v1 与 v1beta1 两代 CRD API 之间做出兼容处理的并能从当前仓库源码中定位到这些能力的真实实现与测试用例为自己的备份方案升级与排障提供依据。一、v1.3 版本概览与定位v1.3 是 Velero 在 2020 年 3 月前后发布的一个功能型版本共包含三个补丁版本版本发布日期容器镜像版本主题v1.3.02020-03-02velero/velero:v1.3.0CRD 备份恢复大改进、多架构镜像v1.3.12020-03-10velero/velero:v1.3.1修复 CRD 整数字段备份失败v1.3.22020-04-03velero/velero:v1.3.2支持plugins/目录、restic 空值修复从变更清单看这一版本的核心工作量集中在两个方向一是围绕 CRD 及其实例的备份/恢复正确性做了系统性的修补与重构二是将镜像构建升级为多架构发布。此外还包含 restic 集成、恢复流程并发安全、指标恢复、资源恢复优先级等一系列工程化改进。二、CRD 备份与恢复的系统性改进v1.3.0 核心这一节是 v1.3.0 的 Highlights 主体Changelog 明确列出了三类问题与两项流程改进全部围绕“让 CRD 与其实例能跨 Kubernetes 版本无缝备份与恢复”展开。1. 背景v1beta1 与 v1 两代 CRD API 的兼容困境Kubernetes 在 1.16 中将 CRD 从apiextensions.k8s.io/v1beta1提升为apiextensions.k8s.io/v1两个版本之间存在结构性差异v1 API 要求 CRD 必须具备结构化的 OpenAPIv3 schema并且不允许spec.preserveUnknownFields为truev1beta1 时代的 CRD 常常没有结构化 schema或依赖preserveUnknownFields: true来保留未知字段从 v1beta1 静默升级到 v1 的 CRD其versions条目常常缺少 schema 信息。这意味着用 v1beta1 API 创建的 CRD直接按 v1 写入 1.16 集群会报错或被剪裁字段。Velero v1.3 需要在备份与恢复两端分别处理这类对象。2. 改进一PreserveUnknownFields的迁移转换Changelog 描述的第一类问题PreserveUnknownFields为true的 CRD 无法恢复到 1.16 集群因为 v1 CRD API 禁止该字段为true。Velero 的解决方案是恢复时将该字段置为false同时把保留语义迁移到 OpenAPIv3 结构化 schema 中的x-kubernetes-preserve-unknown-fields: true这正是 Kubernetes 官方建议的迁移路径。该逻辑在 pkg/restore/actions/crd_v1_preserve_unknown_fields_action.go 中有完整实现核心步骤为通过AppliesTo()将动作限定在customresourcedefinition.apiextensions.k8s.io资源上只处理apiVersion apiextensions.k8s.io/v1的 CRDv1beta1 对象直接放行第 63-68 行若crd.Spec.PreserveUnknownFields为真先置为false再遍历crd.Spec.Versions为每个非空 schema 设置v.Schema.OpenAPIV3Schema.XPreserveUnknownFields preserve第 79-98 行。需要留意的是注释指出这里刻意避开了runtime.DefaultUnstructuredConverter.FromUnstructured因为它在浮点字段中出现整数时会引入转换 bug见 第 70-73 行而是通过 JSON 中转完成结构化转换——这也是 v1.3.1 补丁修复整数字段问题的根源所在。该动作的注册位置可参见 pkg/cmd/server/plugin/plugin.go。3. 改进二无结构化 schema 的 CRD 强制走 v1beta1 APIChangelog 描述的第二类问题没有结构化 schema 的 CRD 必须通过 v1beta1 API 备份/恢复因为通过 v1 API 创建的 CRD 一律要求结构化 schema。在备份侧pkg/backup/actions/remap_crd_version_action.go 中的RemapCRDVersionAction负责判断一个从 v1 端点取回的 CRD 是否“骨子里还是 v1beta1”并决定是否改为抓取 v1beta1 版本进行备份。判断依据是Execute中的 switch 分支第 110-119 行hasSingleVersion(crd)CRD 只有一个版本且该版本无 schema——这是 v1beta1 CRD 被静默升级后的典型形态所有 v1beta1 版本共享同一 schema而 v1 则允许每个版本有独立 schemahasNonStructuralSchema(crd)CRD 状态中存在NonStructuralSchema条件第 151-161 行hasPreserveUnknownFields(crd)spec.preserveUnknownFields为true第 146-149 行。命中任一条件时插件会通过 v1beta1 typed client 重新拉取该 CRDfetchV1beta1CRD并显式补回Kind与APIVersion后返回给备份流程第 124-144 行。此外该动作还会先探测目标集群是否仍支持 v1beta1 CRD API不支持则直接放行第 75-90 行避免不必要的降级。4. 改进三恢复 CRD 后等待就绪并刷新 API 缓存Changelog 描述的第三类痛点用户此前需要执行两次 restore——第一次恢复 CRD第二次恢复 CRD 实例。根因有二Velero 不等待 CRD 被 API Server 完全接受并进入可服务状态恢复 CRD 后没有刷新目标集群的已发现 API 列表因此不认识新恢复的 CRD 类型。v1.3 的修复在 pkg/restore/restore.go 中均有落地等待 CRD 就绪在restoreItem的收尾阶段当恢复的资源是 CRD 时会调用ctx.crdAvailable(...)进行轮询等待第 2143-2152 行。crdAvailable以 1 秒为间隔、在ctx.resourceTimeout超时窗口内持续查询直至kube.IsCRDReady返回可用第 1260-1289 行。就绪判定由 pkg/util/kube/utils.go 的IsCRDReady完成它会根据 CRD 的 apiVersion 分派到 v1 或 v1beta1 的判定逻辑核心是Established条件成立且 name 被接受。刷新 API 列表恢复主流程中CRD 被单独收集进crdResourceCollection并优先处理当检测到有 CRD 被创建或更新后立即调用ctx.discoveryHelper.Refresh()重新发现集群 API第 833-863 行使后续迭代能够解析并恢复这些 CRD 的实例。从代码结构看这一“先 CRD、刷新、再实例”的顺序编排正是单次 restore 完成 CRD 与实例恢复的关键。5. 配套修复多 API 版本处理与备份侧版本选择除上述三项外v1.3 还修复了恢复代码无法处理同一资源类型多 API 版本备份的问题以及一个备份侧的重要行为修正备份服务器偏好server-preferred版本的 CRD而不是一律备份 v1beta1 版本PR #2230。后者的意义在于对本身就是结构化 v1 CRD 的对象不再做无谓的降级从而保持备份数据的现代性与最小差异。在 pkg/backup/actions/remap_crd_version_action_test.go 中可以看到相应测试用例例如Spec.PreserveUnknownFields为true时返回 v1beta1 版本集群只支持 v1 CRD 时即使输入带PreserveUnknownFieldstrue也返回 v1 版本对应 issue 4080 的后续演进。这些用例印证了“先探测集群能力、再决定版本”的实现边界。三、多架构 Docker 镜像v1.3.0v1.3.0 通过 Docker manifest list 实现了多架构镜像发布社区成员 Prajyot-Parab 与 shaneutt 是主要贡献者。当前支持并发布的架构包括linux/amd64linux/arm64linux/armlinux/ppc64leChangelog 明确说明用户无需做任何配置变更只需更新镜像 tag。由于 v1.3 镜像以 manifest list 形式发布Docker 会根据运行主机的架构自动拉取对应架构的镜像层。从该版本开始ARM树莓派类设备与 ppc64le 等平台也能直接使用官方velero/velero镜像而不必自行交叉编译。需要说明的是多架构支持依赖 Docker Registry v2 的 manifest list 规范因此要求使用的镜像仓库实现该规范Docker Hub、多数自建 Harbor/Registry 均满足。四、restic 集成改进v1.3.0 / v1.3.2restic 是 Velero 卷级备份的底层工具v1.3 系列围绕 restic 做了多项修补支持私有仓库自定义端口的 restic restore helper 镜像PR #1999此前 restic 恢复辅助镜像的地址拼接假定仓库无自定义端口v1.3 修正后配置了registry:port形式的私有仓库也能正常拉取 helper 镜像这在离线环境与私有化部署中非常关键。使用 BackupStorageLocation 中的 AWS profile 调用 resticPR #2096当集群中存在多个 s3 兼容的 BackupStorageLocation 且需要不同 AWS 凭证时Velero 会根据当前位置切换AWS_PROFILE环境变量而不是一律使用默认凭证。升级 restic 至 0.9.6PR #2210解决非 AWS 标准 region 场景下的一些问题。v1.3.2 的空值修复PR #2200 / #2315velero restic repo get在LastMaintenanceTime为nil时不再 panic。该修复同时覆盖了ResticRepository.duesForMaintenance中对nil的判空对应代码位于 pkg/repository 下的仓库维护逻辑中。五、恢复流程的缺陷修复与可用性增强v1.3.0 还修复了一批直接影响恢复正确性的缺陷修复恢复流程中的内存泄漏与竞态条件PR #2201此前存在“restic 恢复已失败但 restore 却成功”的竞态v1.3 保证 restore 的最终结果与 restic 恢复结果一致。支持从其他集群的 schedule 恢复PR #2218恢复时不再要求 schedule 对象存在而是校验是否存在带有该 schedule 名称标签的备份。这使得从已删除的 schedule、甚至其他集群创建的 schedule 发起恢复成为可能。修复replicasets的恢复优先级PR #2120 / #2157同时恢复replicasets.apps与replicasets.extensions且均先于deployments恢复同时不再错误地把replicasets.extensions纳入优先名单。修复集群级资源的误恢复PR #2118当按命名空间恢复且IncludeClusterResources为nil时不再错误恢复集群级资源。修复备份标签的深拷贝问题PR #2075构造快照标签时深拷贝备份的 labels避免 PV 名称被当作 label 误加到 backup 上。支持 PV 重命名场景的 SetVolumeIDPR #2216恢复过程中若 PV 被重命名使用 volume snapshotter 返回的 PV 名进行关联。可用性方面还包括重启后重新填充各 schedule 的backup_last_successful_timestamp指标PR #2196无法找到集群配置时给出更清晰的错误提示覆盖--kubeconfig、$KUBECONFIG、in-cluster 三种途径PR #2057将示例应用 nginx 中废弃的fsfreeze-pause镜像替换为ubuntu:bionicPR #2068相关示例见 examples/nginx-app/base.yaml 与 examples/nginx-app/with-pv.yaml。六、v1.3.1 与 v1.3.2 补丁要点v1.3.12020-03-10整数字段修复v1.3.1 唯一的功能改动是修复 CRD 备份失败的问题PR #2322当 CRD 数值字段中含有整数whole number时runtime.DefaultUnstructuredConverter.FromUnstructured的已知缺陷会导致转换失败。正如第二节所述v1.3.0 中的两个 CRD 动作已经通过“JSON 中转”规避了该问题v1.3.1 将该修复补齐到备份流程的其他转换路径保证任意含整数的 CRD 都能稳定备份。v1.3.22020-04-03plugins/目录与空值防护v1.3.2 引入了一个面向插件作者的能力允许plugins/作为 BackupStorageLocation 下的合法顶层目录。该目录用于存放插件所需的任意数据官方建议插件在plugins/下再建一个专属子目录例如plugins/my-plugin-data/以避免与其他插件的数据冲突。这为插件生态提供了标准化的数据落地位置。同时修复了velero restic repo get在仓库最后维护时间为nil时 panic 的问题已在第四节详述。七、升级到 v1.3 的注意事项结合 Changelog 给出的升级入口upgrade-to-1.3文档位于 Velero 官方文档站仓库内对应历史文档可从 site/content 目录检索与上文分析升级前建议确认以下几点镜像 tag 更新v1.3.0 起镜像为多架构 manifest list升级只需更新 tag无需按架构选择镜像目标集群版本CRD 相关修复面向 1.16 集群恢复 v1beta1 时代 CRD 时 Velero 会自动完成字段迁移与版本重映射但备份数据本身仍保留原始结构私有仓库配置若 restic helper 镜像来自带自定义端口的私有仓库升级后可正常拉取多 BackupStorageLocation 凭证使用多个 s3 兼容位置且凭证不同的环境升级后 restic 会按位置自动切换AWS_PROFILE。八、结论从 v1.3 看 Velero 的 CRD 兼容哲学v1.3 是 Velero 在 CRD 备份恢复领域的一次“补课式”重构备份侧通过RemapCRDVersionAction智能判断对象是否需要降级为 v1beta1恢复侧通过CRDV1PreserveUnknownFieldsAction完成字段语义迁移再配合“等待就绪 刷新发现”的编排让 CRD 与其实例的单次恢复成为可能。这些动作在今天的主干代码中依然存在并可被直接阅读备份动作、恢复动作、就绪判定说明其设计经受住了后续版本的考验——它确立的不只是几个 bug 修复而是一套“按目标集群能力自适应、保留原始语义、尊重版本差异”的兼容策略这也是 Velero 能长期支撑跨版本 Kubernetes 备份迁移的基础。【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考