Velero(Ark)备份输出文件格式深度解析:tar.gz 归档、ark-backup.json 与目录结构全指南
2026/9/17 7:30:01 网站建设 项目流程

Velero(Ark)备份输出文件格式深度解析:tar.gz 归档、ark-backup.json 与目录结构全指南

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

导读:备份文件的组织方式决定了数据能否被可靠地恢复与审计。本文以 Velero(前身 Ark)v0.6.0 的官方文档 output-file-format.md 为骨架,完整讲解备份归档(gzip 压缩的 tar 文件)的命名规则、云端存储目录布局、ark-backup.json清单文件的字段含义,以及归档内部的resources/目录层级;并结合当前仓库源码(pkg/backuppkg/archivepkg/apis/velero/v1)补充格式版本号、元数据目录、API 组版本目录等演进细节。读完你将能手动解包备份、核对快照信息、定位特定资源的 JSON 文件,并对 Velero 备份格式的历史与现状建立完整认知。

备份文件是什么:一个 gzip 压缩的 tar 归档

在 Velero(v0.6.0 时代名为 Ark)中,一次备份最终落盘的产物是一个 gzip 压缩的 tar 文件,其文件名与 Backup API 资源对象(Backup CR)的metadata.name完全一致——即执行ark backup create <NAME>(现在为velero backup create <NAME>)时指定的名称。

也就是说,velero backup create backup1234会在对象存储中生成名为backup1234.tar.gz的归档文件。这种命名约定保证了"备份名字"与"存储文件"的一一对应:你通过命令行创建的每个备份,都能在对象存储的固定位置找到同名文件。

从当前仓库源码看,这一"gzip 压缩 + tar 归档"的写入逻辑至今依然成立。在 pkg/backup/backup.go 的BackupWithResolvers函数中,备份文件首先经过gzip.NewWriter压缩,再交给tar.NewWriter写入:

gzippedData := gzip.NewWriter(backupFile) defer gzippedData.Close() tw := NewTarWriter(tar.NewWriter(gzippedData)) defer tw.Close()

对应的解包逻辑则在 pkg/archive/extractor.go:UnzipAndExtractBackup先用gzip.NewReader解压,再通过tar.NewReader逐个读出归档条目,并解包到本地临时目录。两处代码共同印证:.tar.gz既是备份的物理格式,也是 Velero 恢复时解析备份的标准入口。

对象存储中的目录布局:每个备份一个子目录

备份文件在云端对象存储中并非散落平铺,而是每个备份文件存放于桶(bucket)下的独立子目录中。子目录位于 Ark/Velero 服务端配置所指定的 bucket 之下,其中除了.tar.gz归档外,还额外包含一个名为ark-backup.json(早期版本)或velero-backup.json的清单文件。

整体目录结构形如:

rootBucket/ backup1234/ ark-backup.json backup1234.tar.gz

这一布局的含义是:所有与某次备份相关的"元数据"与"数据本体"被放在同一目录下,便于统一管理、清理与审计。

ark-backup.json:备份的完整历史档案

ark-backup.json明确列出了与本次备份关联的 Backup 资源的全部信息——包括所有被显式或隐式(默认值)使用的配置项,从而形成一份完整的历史记录。它还包含status.version字段,该字段对应备份输出文件的格式版本(下文详述)。

之所以强调"包括默认值",是因为用户创建备份时可能只指定了少量参数,而服务端会填充大量默认值(例如snapshotVolumes: truettl: 24h0m0s)。这份 JSON 将这些最终生效的配置快照下来,日后无论是排查问题、审计合规,还是理解"当初到底备份了什么",都有一份权威依据。

从实现角度看,这与当前仓库中BackupAPI 类型的序列化逻辑一脉相承。完整字段定义可查阅 pkg/apis/velero/v1/backup.go(BackupSpecBackupStatus结构体),归档被写入对象存储的流程见 pkg/controller/backup_controller.go。

一个真实的ark-backup.json示例

{ "kind": "Backup", "apiVersion": "ark.heptio.com/v1", "metadata": { "name": "test-backup", "namespace": "heptio-ark", "selfLink": "/apis/ark.heptio.com/v1/namespaces/heptio-ark/backups/testtest", "uid": "a12345cb-75f5-11e7-b4c2-abcdef123456", "resourceVersion": "337075", "creationTimestamp": "2017-07-31T13:39:15Z" }, "spec": { "includedNamespaces": [ "*" ], "excludedNamespaces": null, "includedResources": [ "*" ], "excludedResources": null, "labelSelector": null, "snapshotVolumes": true, "ttl": "24h0m0s" }, "status": { "version": 1, "expiration": "2017-08-01T13:39:15Z", "phase": "Completed", "volumeBackups": { "pvc-e1e2d345-7583-11e7-b4c2-abcdef123456": { "snapshotID": "snap-04b1a8e11dfb33ab0", "type": "gp2", "iops": 100 } }, "validationErrors": null } }

对关键字段的逐项说明:

字段含义与说明
kind/apiVersionKubernetes API 对象的类型与版本。示例中为 Ark 时代的ark.heptio.com/v1;在后续版本中演进为velero.io/v1
metadata.name备份名称,与ark backup create指定的名称一致,同时也是.tar.gz文件名
metadata.uid/resourceVersion/creationTimestampKubernetes 为对象生成的标准标识与时间戳,用于唯一标识本次备份
spec.includedNamespaces纳入备份的命名空间列表,"*"表示全部
spec.excludedNamespaces排除的命名空间列表,null表示不排除
spec.includedResources/excludedResources纳入/排除的资源类型列表,"*"表示全部资源
spec.labelSelector按标签选择器过滤备份对象,null表示不过滤
spec.snapshotVolumes是否对持久卷创建云快照,true表示启用
spec.ttl备份保留时长(如24h0m0s),超过后会被垃圾回收
status.version输出文件格式版本号,本示例为1
status.expirationttl计算出的过期时间点
status.phase备份所处阶段(如Completed
status.volumeBackups卷快照明细(详见下文)
status.validationErrors校验错误列表,null表示无错误

status.volumeBackups:云控制台核对快照的利器

示例中最值得注意的字段是status.volumeBackups——它以PVC 名称为键,列出每个持久卷对应的云快照信息:

"volumeBackups": { "pvc-e1e2d345-7583-11e7-b4c2-abcdef123456": { "snapshotID": "snap-04b1a8e11dfb33ab0", "type": "gp2", "iops": 100 } }
  • snapshotID:云厂商侧的快照 ID(示例为 AWS 的snap-...格式);
  • type:卷类型(示例为 AWS 的gp2);
  • iops:预置 IOPS 值。

原文档特别提示:如果你想在云厂商的 GUI 控制台中手动核对这些快照,这份文件会非常有用。通过snapshotID可以直接在控制台搜索到对应快照,从而确认快照是否按预期创建、是否与备份一一对应。

文件格式版本:status.version的语义

status.version(示例中为1)对应的就是备份输出文件的格式版本。格式版本的意义在于:当 Velero 未来改变归档内部布局(如新增目录、调整文件名)时,通过版本号可以在不破坏旧备份的前提下安全演进,恢复程序可以依据版本号选择正确的解析路径。

从当前仓库源码看,格式版本机制已经进一步细化。在 pkg/backup/backup.go 中定义了两个版本常量:

// BackupVersion is the current backup major version for Velero. // Deprecated, use BackupFormatVersion const BackupVersion = 1 // BackupFormatVersion is the current backup version for Velero, including major, minor, and patch. const BackupFormatVersion = "1.1.0"
  • BackupVersion:旧的"大版本号"(当前为1),已被标记为 Deprecated;
  • BackupFormatVersion:新的带主版本.次版本.补丁的完整版本号(当前为1.1.0),用于标识备份归档的格式演进。

归档内部还专门有一个版本标记文件。在 pkg/backup/backup.go 的writeBackupVersion函数中,备份开始写入时会先向 tar 中写入metadata/version文件,内容即BackupFormatVersion

func (kb *kubernetesBackupper) writeBackupVersion(tw tarWriter) error { versionFile := filepath.Join(velerov1api.MetadataDir, "version") versionString := fmt.Sprintf("%s\n", BackupFormatVersion) ... }

这说明:"格式版本"不仅记录在ark-backup.jsonstatus.version中,还以独立文件的形式存在于 tar 归档内部metadata/version),双保险地标注了归档格式。metadata目录常量定义于 pkg/apis/velero/v1/constants.go。

解包后的归档内部结构(格式版本 1)

.tar.gz归档被解压后,典型的结构如下(示例文件backup1234.tar.gz):

resources/ persistentvolumes/ cluster/ pv01.json ... configmaps/ namespaces/ namespace1/ myconfigmap.json ... namespace2/ ... pods/ namespaces/ namespace1/ mypod.json ... namespace2/ ... jobs/ namespaces/ namespace1/ awesome-job.json ... namespace2/ ... deployments/ namespaces/ namespace1/ cool-deployment.json ... namespace2/ ... ...

目录层级规则

这一结构的组织规律非常清晰,可以归纳为**"资源类型 → 作用域 → 命名空间 → 单个对象 JSON"**四层:

  1. 顶层固定为resources/目录;
  2. 其下每个子目录对应一种资源类型(如persistentvolumesconfigmapspodsjobsdeployments),目录名采用资源复数名(资源类型小写复数形式);
  3. 每种资源下再按作用域分为两类:
    • cluster/:存放**集群级别(cluster-scoped)**的资源实例(如PersistentVolume这类不隶属于任何命名空间的资源);
    • namespaces/:存放命名空间级资源,其下再按命名空间分子目录(namespace1/namespace2/);
  4. 最底层是每个 Kubernetes 对象序列化后的 JSON 文件,文件名即对象名(如pv01.jsonmypod.jsonawesome-job.json)。

这套"资源按类型分目录、集群与命名空间分作用域、命名空间内按对象逐个 JSON 落盘"的设计,使备份内容高度结构化,既可被恢复程序逐对象精准解析,也方便人工用tar -tzffind快速定位某个对象。

源码与测试的印证

从当前仓库源码看,这套目录常量与解析逻辑被完整保留并演进:

  • 目录名常量定义于 pkg/apis/velero/v1/constants.go:

    • ResourcesDir = "resources"
    • ClusterScopedDir = "cluster"
    • NamespaceScopedDir = "namespaces"
    • PreferredVersionDir = "-preferredversion"(API 组首选版本目录后缀,见下文)
  • 解析器 pkg/archive/parser.go 的Parse函数正是按上述规则遍历归档:先检查顶层resources目录,再为每个资源子目录读取clusternamespaces两类子目录,最终组装出ResourceItems结构(GroupResource+ItemsByNamespace),其中集群级资源以空字符串""作为 namespace 键。

  • 测试用例 pkg/archive/parser_test.go 给出了真实风格的归档文件列表,例如:

    root-dir/resources/widgets.foo/cluster/item-1.json root-dir/resources/widgets.foo/namespaces/ns-1/item-1.json root-dir/resources/widgets.foo/namespaces/ns-2/item-1.json root-dir/resources/dongles.bar/namespaces/ns-3/item-4.json

    注意这里的widgets.foo这种目录名:资源目录名采用resource.group格式,即"资源复数名 + 点号 + API 组名";对于核心(core)API 组则省略.group后缀(如podsconfigmaps)。这一格式在 pkg/archive/parser.go 的extractGroupName中通过SplitN(resourceGroupDir, ".", 2)解析。

版本 1 之后的格式演进(以仓库源码为准)

原文档所述的是"文件格式版本 1"(对应 Ark v0.6.0)。以当前仓库源码为据,格式已经做了若干演进,了解这些有助于你阅读新旧不一的备份归档:

  • 新增metadata/version文件:归档顶层除resources/外,还包含metadata/目录(见 pkg/apis/velero/v1/constants.go 的MetadataDir = "metadata"),内部写入格式版本号(pkg/backup/backup.go)。
  • 资源目录下出现 API 组版本子目录:当启用EnableAPIGroupVersions特性时,resources/<resource.group>/下会出现v1-preferredversionv2beta1按 API 版本划分的子目录,其中-preferredversion后缀标记服务端首选版本。解析逻辑见 pkg/archive/parser.go 的ParseGroupVersions函数——它从目录名提取 API 组与版本,构造metav1.APIGroup结构。
  • 解包防护机制:新版解包器 pkg/archive/extractor.go 加入了解压体积上限(默认 16 GiB,见maxExtractionSize路径穿越防护(Zip Slip 防护,sanitizeArchivePath,防止恶意或损坏的归档在解包时耗尽磁盘或逃逸临时目录——这也是在处理不受信任的备份文件时需要了解的安全边界。

实际排查与使用场景速查

基于以上格式知识,你可以通过以下方式直接操作备份产物:

  1. 列出归档内容,快速确认某对象是否在备份中
    # 下载备份归档后,列出顶层目录与关键对象 tar -tzf backup1234.tar.gz | head -50 tar -tzf backup1234.tar.gz | grep "pods/namespaces/nginx-example/"
  2. 解包并查看某个对象的完整 JSON
    mkdir -p extracted && tar -xzf backup1234.tar.gz -C extracted cat extracted/resources/deployments/namespaces/default/cool-deployment.json
  3. 核对卷快照:读取同目录下的ark-backup.json(或新版本的velero-backup.json),依据status.volumeBackups.<pvc-name>.snapshotID到云厂商控制台检索对应快照。
  4. 判断归档格式版本:查看ark-backup.jsonstatus.version,或直接读取归档内metadata/version文件:
    tar -xOf backup1234.tar.gz metadata/version

总结

备份输出文件格式是 Velero 可靠性与可审计性的基石:<name>.tar.gz以"一备份一子目录"的方式组织于对象存储,配套的ark-backup.json完整记录了 Backup 资源的最终配置(含默认值)、格式版本号(status.version)与卷快照明细(status.volumeBackups);解包后则呈现为resources/<resource.group>/{cluster,namespaces/<ns>}/<object>.json的高度结构化层级。当前仓库源码(pkg/backup/backup.go、pkg/archive/parser.go、pkg/archive/extractor.go)在保留这套核心结构的同时,已演进出版本号文件(metadata/version)、API 组版本目录与安全防护机制。理解这套格式,无论对于备份排障、手工审计还是二次开发,都是扎实的起点。

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

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

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

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

立即咨询