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/backup、pkg/archive、pkg/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: true、ttl: 24h0m0s)。这份 JSON 将这些最终生效的配置快照下来,日后无论是排查问题、审计合规,还是理解"当初到底备份了什么",都有一份权威依据。
从实现角度看,这与当前仓库中BackupAPI 类型的序列化逻辑一脉相承。完整字段定义可查阅 pkg/apis/velero/v1/backup.go(BackupSpec、BackupStatus结构体),归档被写入对象存储的流程见 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/apiVersion | Kubernetes API 对象的类型与版本。示例中为 Ark 时代的ark.heptio.com/v1;在后续版本中演进为velero.io/v1 |
metadata.name | 备份名称,与ark backup create指定的名称一致,同时也是.tar.gz文件名 |
metadata.uid/resourceVersion/creationTimestamp | Kubernetes 为对象生成的标准标识与时间戳,用于唯一标识本次备份 |
spec.includedNamespaces | 纳入备份的命名空间列表,"*"表示全部 |
spec.excludedNamespaces | 排除的命名空间列表,null表示不排除 |
spec.includedResources/excludedResources | 纳入/排除的资源类型列表,"*"表示全部资源 |
spec.labelSelector | 按标签选择器过滤备份对象,null表示不过滤 |
spec.snapshotVolumes | 是否对持久卷创建云快照,true表示启用 |
spec.ttl | 备份保留时长(如24h0m0s),超过后会被垃圾回收 |
status.version | 输出文件格式版本号,本示例为1 |
status.expiration | 由ttl计算出的过期时间点 |
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.json的status.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"**四层:
- 顶层固定为
resources/目录; - 其下每个子目录对应一种资源类型(如
persistentvolumes、configmaps、pods、jobs、deployments),目录名采用资源复数名(资源类型小写复数形式); - 每种资源下再按作用域分为两类:
cluster/:存放**集群级别(cluster-scoped)**的资源实例(如PersistentVolume这类不隶属于任何命名空间的资源);namespaces/:存放命名空间级资源,其下再按命名空间分子目录(namespace1/、namespace2/);
- 最底层是每个 Kubernetes 对象序列化后的 JSON 文件,文件名即对象名(如
pv01.json、mypod.json、awesome-job.json)。
这套"资源按类型分目录、集群与命名空间分作用域、命名空间内按对象逐个 JSON 落盘"的设计,使备份内容高度结构化,既可被恢复程序逐对象精准解析,也方便人工用tar -tzf或find快速定位某个对象。
源码与测试的印证
从当前仓库源码看,这套目录常量与解析逻辑被完整保留并演进:
目录名常量定义于 pkg/apis/velero/v1/constants.go:
ResourcesDir = "resources"ClusterScopedDir = "cluster"NamespaceScopedDir = "namespaces"PreferredVersionDir = "-preferredversion"(API 组首选版本目录后缀,见下文)
解析器 pkg/archive/parser.go 的
Parse函数正是按上述规则遍历归档:先检查顶层resources目录,再为每个资源子目录读取cluster与namespaces两类子目录,最终组装出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后缀(如pods、configmaps)。这一格式在 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-preferredversion、v2beta1等按 API 版本划分的子目录,其中-preferredversion后缀标记服务端首选版本。解析逻辑见 pkg/archive/parser.go 的ParseGroupVersions函数——它从目录名提取 API 组与版本,构造metav1.APIGroup结构。 - 解包防护机制:新版解包器 pkg/archive/extractor.go 加入了解压体积上限(默认 16 GiB,见
maxExtractionSize)与路径穿越防护(Zip Slip 防护,sanitizeArchivePath),防止恶意或损坏的归档在解包时耗尽磁盘或逃逸临时目录——这也是在处理不受信任的备份文件时需要了解的安全边界。
实际排查与使用场景速查
基于以上格式知识,你可以通过以下方式直接操作备份产物:
- 列出归档内容,快速确认某对象是否在备份中:
# 下载备份归档后,列出顶层目录与关键对象 tar -tzf backup1234.tar.gz | head -50 tar -tzf backup1234.tar.gz | grep "pods/namespaces/nginx-example/" - 解包并查看某个对象的完整 JSON:
mkdir -p extracted && tar -xzf backup1234.tar.gz -C extracted cat extracted/resources/deployments/namespaces/default/cool-deployment.json - 核对卷快照:读取同目录下的
ark-backup.json(或新版本的velero-backup.json),依据status.volumeBackups.<pvc-name>.snapshotID到云厂商控制台检索对应快照。 - 判断归档格式版本:查看
ark-backup.json的status.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),仅供参考