Velero 仓库维护任务(Repository Maintenance Job)配置详解
【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero
从 v1.14 起,Velero 将备份仓库(BackupRepository)的维护工作从 Velero server 进程中剥离,改为按需在集群内启动独立的 Kubernetes Job 执行;从 v1.15 起,又引入了专门的 ConfigMap(通过--repo-maintenance-job-configmap参数指定)来统一配置这些维护 Job 的资源限制、节点亲和性、优先级类等属性。本文基于仓库内文档与源码,完整介绍该机制的背景、配置模型、ConfigMap 样例、安装参数、维护历史查看方式及继承规则,帮助你在安装 Velero 时一次到位地规划好仓库维护任务。
为什么要把仓库维护从 Velero server 中拆出来
在 v1.14.0 之前,Velero 是在 Velero server 所在的 Pod 内部定期执行备份仓库的维护操作的。仓库维护(repository maintenance)本身是 Kopia 等备份仓库的一项正常后台工作,用于回收不再被引用的数据块、压缩与整理仓库索引,但在某些场景下(例如仓库规模较大、积累了大量已删除备份)它可能消耗显著的 CPU 与内存资源,进而导致 Velero server 进程被 OOM Killer 杀掉,影响备份、恢复等核心能力。
从 v1.14 开始,Velero 改变了这一设计:维护工作被解耦为独立的 Kubernetes Job,按需在 Velero 安装命名空间内启动,由 Job 承载维护过程中的资源消耗,从而避免对 Velero server 造成冲击。这一机制的实现位于 pkg/repository/maintenance/maintenance.go,其中StartNewJob负责根据 BackupRepository 与配置构造并创建维护 Job,WaitJobComplete/WaitAllJobsComplete负责轮询 Job 完成状态并把结果写回 BackupRepository 的状态字段。
从源码看,维护 Job 的容器直接复用 Velero 镜像(/velero可执行文件),以repo-maintenance子命令启动,并携带--repo-name、--repo-type、--backup-storage-location、--log-level、--log-format等参数(见 maintenance.go),Job 本身设置了BackoffLimit: 0(不重试)与RestartPolicy: Never,保证失败可观测、可排查。
维护 Job 的配置入口
两种配置来源与演进
仓库维护 Job 的配置一共有两条来源:
v1.14 引入的
velero install/velero server旧参数,包括:--maintenance-job-cpu-request--maintenance-job-mem-request--maintenance-job-cpu-limit--maintenance-job-mem-limit--keep-latest-maintenance-jobs
这些参数的绑定代码位于 pkg/cmd/cli/install/install.go。它们从 v1.15 起被标记为deprecated,并计划在v1.17 删除,新部署应优先使用 ConfigMap 方式。
v1.15 引入的 ConfigMap 方式:通过
velero server --repo-maintenance-job-configmap=<ConfigMap-Name>指定一个 ConfigMap,集中配置维护 Job 的资源限制(Resource Limitation)与节点亲和性(Node Affinity),此外还支持keepLatestMaintenanceJobs、priorityClassName、podLabels、podAnnotations等字段。该参数同样可以通过安装命令传入:
velero install --repo-maintenance-job-configmap=<ConfigMap-Name>--repo-maintenance-job-configmap在 server 端的注册与说明位于 pkg/cmd/server/config/config.go。
注意:旧参数
--keep-latest-maintenance-jobs与 ConfigMap 中的keepLatestMaintenanceJobs是同一配置的两种载体。从源码看,当repoMaintenanceJobConfig为空(即未指定 ConfigMap)时,GetKeepLatestMaintenanceJobs直接返回默认值 3;当 ConfigMap 存在且含有对应仓库配置时,以 ConfigMap 中的值为准(见 maintenance.go)。
ConfigMap 的内容模型
ConfigMap 的data是一个Map,包含两类 key:
global:全局配置,适用于所有未在 ConfigMap 中找到自身专属配置的 BackupRepository 维护 Job。<namespace>-<backupStorageLocation>-<repositoryType>:仓库专属配置。因为 BackupRepository 的生成是动态的,无法在安装 Velero 时预先得知其名称,所以 Velero 用能够唯一定位一个 BackupRepository 的三个要素组合成 key:- 该 BackupRepository 备份卷数据所在的命名空间(
spec.volumeNamespace); - 该 BackupRepository 引用的 BackupStorageLocation 名称(
spec.backupStorageLocation); - 该 BackupRepository 的类型(
spec.repositoryType,当前支持值为kopia)。
- 该 BackupRepository 备份卷数据所在的命名空间(
key 的拼接规则在源码中有明确实现(maintenance.go):
repoJobConfigKey := repo.Spec.VolumeNamespace + "-" + repo.Spec.BackupStorageLocation + "-" + repo.Spec.RepositoryType匹配优先级是:仓库专属 key 优先,缺失的字段再回退到global配置。具体到JobConfigs结构体(定义于 pkg/types/repo_maintenance.go),回退规则为:podResources、loadAffinity、keepLatestMaintenanceJobs三个字段在仓库专属配置为空时才取global的值;而priorityClassName、podLabels、podAnnotations只从global配置读取(见 maintenance.go)。
例如,一个满足以下条件的 BackupRepository:
- apiVersion: velero.io/v1 kind: BackupRepository metadata: generateName: test-default-kopia- labels: velero.io/repository-type: kopia velero.io/storage-location: default velero.io/volume-namespace: test name: test-default-kopia-kgt6n namespace: velero spec: backupStorageLocation: default maintenanceFrequency: 1h0m0s repositoryType: kopia volumeNamespace: test其对应的 ConfigMap key 应为test-default-kopia(volumeNamespace为test,backupStorageLocation为default,repositoryType为kopia)。
这种"按 key 预配置"的设计最大优势是:管理员可以在 BackupRepository 被创建之前就完成配置,非常适合在 Velero 安装阶段统一规划各命名空间的维护资源。
JobConfigs 支持的全部字段
| 字段 | JSON key | 取值说明 | 作用域 |
|---|---|---|---|
podResources | podResources | CPU / 内存 / 临时存储的 request 与 limit,见下表 | 仓库专属 + global 回退 |
loadAffinity | loadAffinity | 节点亲和性数组,见下文 | 仓库专属 + global 回退 |
keepLatestMaintenanceJobs | keepLatestMaintenanceJobs | 每个仓库保留的最近维护 Job 数量,默认 3 | 仓库专属 + global 回退 |
priorityClassName | priorityClassName | 维护 Job Pod 使用的 PriorityClass 名称 | 仅 global |
podLabels | podLabels | 额外附加到维护 Job Pod 的标签 | 仅 global |
podAnnotations | podAnnotations | 额外附加到维护 Job Pod 的注解 | 仅 global |
podResources内部字段(对应 kube.PodResources 的buildJob实现看,默认情况下维护 Job 不设资源限制(CPU 与内存的 request/limit 默认值均为"0");ephemeralStorageRequest/ephemeralStorageLimit留空时则使用常量默认值,以保持向后兼容。若 ConfigMap 中资源字段为空字符串,也会因可能触发解析错误而被跳过,因此配置时建议显式填写完整。
完整 ConfigMap 示例:资源限制 + 节点亲和性
loadAffinity结构复用了 node-agent 亲和性配置设计 中的LoadAffinity结构。它支持用户把维护 Job 调度到满足条件 A或条件 B 的节点上——例如"运行在指定机器类型上"或"位于 us-central1-x 可用区"——通过在loadAffinity数组中增加多个条目实现。
下面的示例同时演示了global全局配置与kibishii-default-kopia仓库专属配置:
cat <<EOF > repo-maintenance-job-config.yaml apiVersion: v1 kind: ConfigMap metadata: name: repo-maintenance-job-config namespace: velero data: global: | { "podResources": { "cpuRequest": "100m", "cpuLimit": "200m", "ephemeralStorageRequest": "5Gi", "ephemeralStorageLimit": "10Gi", "memoryRequest": "100Mi", "memoryLimit": "200Mi" }, "keepLatestMaintenanceJobs": 1, "loadAffinity": [ { "nodeSelector": { "matchExpressions": [ { "key": "topology.kubernetes.io/zone", "operator": "In", "values": [ "us-central1-a", "us-central1-b", "us-central1-c" ] } ] } } ] } kibishii-default-kopia: | { "podResources": { "cpuRequest": "200m", "cpuLimit": "400m", "ephemeralStorageRequest": "5Gi", "ephemeralStorageLimit": "10Gi", "memoryRequest": "200Mi", "memoryLimit": "400Mi" }, "keepLatestMaintenanceJobs": 2 } EOF说明:
global中的loadAffinity使用matchExpressions表达:维护 Job 只会被调度到topology.kubernetes.io/zone为us-central1-a、us-central1-b、us-central1-c的节点上;kibishii-default-kopia针对kibishii命名空间、defaultBSL、kopia类型的仓库覆盖了更宽裕的资源(200m/400m CPU、200Mi/400Mi 内存)并保留最近 2 个维护 Job;- 其他仓库(没有专属 key)将回退使用
global配置(100m/200m、100Mi/200Mi,保留 1 个 Job)。
需要注意:虽然loadAffinity是数组,Velero 目前只取数组的第一个元素(见 maintenance.go,config.LoadAffinities[0])。数组形态是为了复用既有的LoadAffinity数据结构与设计文档,并非支持多组亲和性叠加。
创建该 ConfigMap:
kubectl apply -f repo-maintenance-job-config.yaml创建后即可在安装 Velero 时引用:
velero install --repo-maintenance-job-configmap=repo-maintenance-job-config日志与继承规则
日志级别
维护 Job继承 Velero server 的日志级别与日志格式设置。如果 Velero server 开启了 debug 日志,维护 Job 也会输出 debug 级别日志。这在buildJob的参数构造中有直接体现:--log-level与--log-format均取自 server 的全局配置(maintenance.go)。
从 Velero deployment 继承的属性
维护 Job 会自动继承 Velero deployment 的以下属性(见 maintenance.go 中对veleroutil.Get*FromVeleroServer系列函数的调用):
- 环境变量(
env)与环境变量来源(envFrom) - 卷与卷挂载(
volumes/volumeMounts),包括云凭证(cloud-credentials) - ServiceAccount
- 镜像(复用 Velero server 镜像)
- 安全上下文(容器级与 Pod 级)
imagePullSecrets- toleration(含 Windows 容忍
os=windows:NoSchedule以保持向后兼容,以及白名单内的第三方容忍,如kubernetes.azure.com/scalesetpriority、CriticalAddonsOnly)
标签与注解的继承限制
与上述"全量继承"不同,维护 Job 并不会继承 Velero deployment 上的所有标签与注解,这是刻意设计,目的是只传播云厂商身份体系(cloud provider identity)所需的少数标签与注解:
标签(Labels):
velero.io/repo-name: <repository-name>—— 自动添加,用于标识该 Job 维护的是哪个仓库;- 仅继承 Velero deployment 上属于第三方白名单的标签,当前白名单只有:
azure.workload.identity/use。
注解(Annotations):
- 仅继承白名单内的第三方注解,当前只有:
iam.amazonaws.com/role。
白名单定义于 pkg/util/third_party.go。此外,如果你在 ConfigMap 的global段配置了podLabels/podAnnotations,这些标签注解会附加到维护 Job Pod 上;其中velero.io/repo-name是保留 key,用户自定义标签若与之冲突会被跳过(见 maintenance.go)。
只读存储位置不执行维护
对于 BackupStorageLocation 被设置为readOnly的备份仓库,不会运行维护 Job。
维护历史查看
维护结束后,结果会写回 BackupRepository CR 的status字段。可通过 describe 查看:
kubectl describe backuprepository <name> -n velero输出示例:
Status: Last Maintenance Time: <timestamp> Recent Maintenance: Complete Timestamp: <timestamp> Result: Succeeded Start Timestamp: <timestamp> Complete Timestamp: <timestamp> Result: Succeeded Start Timestamp: <timestamp> Message: <error message> Result: Failed Start Timestamp: <timestamp>字段含义:
Last Maintenance Time:最近一次成功维护的时间;Recent Maintenance:最近 3 次维护的状态,包含开始时间、结果(succeeded/failed)、完成时间(成功时),以及失败时的错误信息(失败时)。
从源码看,该历史由composeStatusFromJob从 Job 状态组装(成功/失败依据job.Status.Succeeded与job.Status.Failed),错误信息则从容器终止消息中的Repo maintenance error:指示符后解析(maintenance.go 与 maintenance.go)。当一次维护失败时,会立即在对应 BackupRepository 状态中呈现失败结果与错误信息,便于定位问题。
其他安装参数与默认值
保留最近 N 个维护 Job
Velero 为每个仓库保留最近若干个维护 Job(用于历史追溯),默认保留3个。可用安装命令调整:
velero install --keep-latest-maintenance-jobs <NUM>默认维护频率
仓库维护的频率可在安装时指定:
velero install --default-repo-maintain-frequency <DURATION>对应 server 参数为--default-repo-maintain-frequency(见 pkg/cmd/server/config/config.go)。对于 Kopia 仓库,默认维护频率为1 小时(示例 BackupRepository 中的spec.maintenanceFrequency: 1h0m0s即来源于此)。
全量维护间隔定制
Kopia 仓库的全量维护(full maintenance)间隔可通过 backup repository configuration 中描述的 ConfigMap 或spec.repositoryConfig定制:
fullMaintenanceInterval默认跟随 Kopia 的 24 小时默认值;- 可覆盖为
normalGC(24 小时)、fastGC(12 小时)、eagerGC(6 小时),用于加快已删除 Velero 备份对应数据块从 Kopia 仓库中回收的速度。
需要留意:未使用的数据会在全量维护后永久删除,过短的全量维护间隔若使用不当会削弱数据安全性。
优先级类(Priority Class)配置
维护 Job 的优先级类通过 ConfigMap 的global 段配置,且只从 global 段读取——这保证所有维护 Job 无论维护哪个仓库都使用相同的优先级类:
{ "global": { "priorityClassName": "low-priority", "podResources": { "cpuRequest": "100m", "memoryRequest": "128Mi" } } }从源码看,getPriorityClassName会先用 Kubernetes client 校验该 PriorityClass 是否存在于集群中;若不存在会记录告警,但仍把该名称交给 Kubernetes 调度器处理(maintenance.go),因此请确保所引用的 PriorityClass 已提前创建。
使用建议
- 新版本优先用 ConfigMap:
--maintenance-job-*系列旧参数将在 v1.17 移除,请在新部署中直接使用--repo-maintenance-job-configmap,并利用global+ 仓库专属 key 两级配置实现"默认兜底 + 关键仓库差异化"。 - 结合备份数据量规划资源:维护 Job 默认不设资源上限,建议依据目标仓库的数据规模在 ConfigMap 中显式设置 CPU/内存/临时存储的 request 与 limit,避免维护任务在节点上"抢资源",也要防止其因资源不足而失败。
- 维护历史即排障入口:每次维护失败都会在 BackupRepository 的
Recent Maintenance中留下错误信息,结合kubectl describe backuprepository与维护 Job / Pod 的日志(维护 Job 继承 server 的日志级别)即可快速定位 Kopia 仓库侧的维护异常。 - 只读场景自动豁免:对于以只读方式接入的 BackupStorageLocation(如灾备恢复场景),Velero 不会为其启动维护 Job,无需额外配置。
【免费下载链接】veleroBackup and migrate Kubernetes applications and their persistent volumes项目地址: https://gitcode.com/GitHub_Trending/ve/velero
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考