Proxmox Backup Server 维护三剑客:Prune、GC 与 Verify 详解

文章目录

摘要: Proxmox Backup Server(PBS)采用创新的 Chunk 全局去重备份架构,彻底告别传统备份链的脆弱性。它将数据切割为固定大小的 Chunk,通过哈希算法实现跨虚拟机、跨备份的全局去重,显著降低存储占用。每个快照都是独立的完整恢复点,无需依赖备份链,实现快速、可靠的恢复。结合增量备份和压缩技术,PBS 在保证数据完整性的同时,大幅提升备份效率和存储利用率,是企业级虚拟化环境备份的理想解决方案。

延伸阅读

如果想进一步了解 PBS 的其他内容,可以参考以下文章:


PBS 维护操作:Prune、GC 与 Verify

PBS 的 Chunk 全局去重架构带来了显著的存储效率优势,但也引入了新的维护需求:如何清理不再被引用的 Chunk?如何验证备份数据的完整性?这就是 GC(垃圾回收)和 Verify(验证)任务的作用。

一、Prune:管理备份保留策略

Prune(修剪)是 PBS 中用于自动删除过期备份快照 的功能。它根据用户定义的保留策略(如"保留最近7天每日备份,保留最近4周每周备份"),在备份任务运行时自动清理旧的、不再需要的快照索引。Prune 是触发 GC 释放物理空间的关键前置步骤。

例如:

假设 VM 101 有一块磁盘,按每天备份,keep-weekly=2

bash 复制代码
vm/101/
├── 2026-05-10T22:30:00Z/    ← 第1周的备份,保留
│   └── drive-scsi0.img.fidx
│
├── 2026-05-17T22:30:00Z/    ← 第2周的备份,保留
│   └── drive-scsi0.img.fidx
│
├── 2026-05-03T22:30:00Z/    ← 第3周的备份,被 Prune 删除
│   └── drive-scsi0.img.fidx
│
└── 2026-04-26T22:30:00Z/    ← 第4周的备份,被 Prune 删除
    └── drive-scsi0.img.fidx

原理

Prune 操作本身只删除备份快照的索引文件 (如 .fidx, .didx, .img.fidx 等),这些文件存储在快照目录下,体积很小。删除索引意味着该快照从 PBS 的目录视图中消失,无法再用于恢复。

然而,该快照所引用的实际数据块(Chunk)仍然保留在 .chunks/ 目录中,因为其他快照可能还在共享这些 Chunk。这些"失去引用"的 Chunk 就成为了 GC 的清理目标。

简单来说:Prune 负责"逻辑删除"(标记快照过期),GC 负责"物理清理"(回收无引用的数据块)。

配置备份保留策略

Prune 保留策略的配置入口

实际上有两个地方可以配置备份保留策略,侧重点不同:
1. PVE 端(Datacenter → Backup)

在备份任务中直接配置 Prune 策略,备份任务成功完成后立即触发 ,由 PVE 负责执行。策略作用范围是该备份任务覆盖的 VM,适合针对不同 VM 设置差异化的保留策略。
2. PBS 端(Datastore → Prune & GC Jobs)

在 PBS 上独立配置 Prune Job,按照独立的 schedule 定时触发,与备份任务完全解耦。策略作用范围是整个 Datastore 或指定的 VM群组,适合集中统一管理所有 VM 的保留策略。


两者的核心区别:

PVE 端 PBS 端
触发时机 备份任务完成后立即执行 独立 schedule 定时执行
作用范围 单个备份任务覆盖的 VM 整个 Datastore 或指定 VM
管理方式 分散在各个备份任务中 集中在 PBS 统一管理
适用场景 各 VM 保留策略不同 统一策略,集中管理

重要提示 :两端策略若同时配置且不一致,最终生效的是更严格(保留更少)的那一端 ,

可能导致备份被意外删除。建议只在一端配置 Prune 策略,

大多数企业环境推荐统一在 PBS 端管理,PVE 端不设 Prune。

PVE 端(Datacenter → Backup)配置备份保留策略
  1. 在备份任务中配置 :创建或编辑备份任务时,可以在"保留"选项卡中设置 Prune 策略。

  2. 策略说明:

    • `keep-last:保持未设置
    • keep-daily=7: 保留最近7天的每日备份。
    • keep-weekly=4:保留最近4周的每周备份(通常指每周日的备份)。
    • keep-monthly=3:保留最近3个月的每月备份(每月第一天的备份)。
    • keep-yearly=1:保留最近1年的每年备份。
  3. 触发时机 :Prune 会在备份任务成功完成后自动执行,根据设定的策略清理该任务历史中的旧快照。

keep-last与keep-daily区别 :

keep-daily比较宽松,例如,keep-daily=7 的结果:

周五、周四、周三、周二、周一、上周日、上周六 ← 周六空缺

而keep-last更严格,例如,keep-last=7 的结果:强制保留最近 7 个,不管哪天,绝对有 7 个

PBS 端配置备份保留策略

PBS Web UI 中 Datastore → Prune & GC Jobs → Add Prune Job 的配置界面:

** 基本设置**

字段 值 说明
Datastore test_pbs_backup 这个 Prune Job 作用的 Datastore
Prune Schedule 21:30 每天晚上 21:30 自动执行
Enabled 已勾选 代表当前启用
Namespace Root 作用于根命名空间
Max. Depth Full 递归处理所有子命名空间
Comment 空 可填写备注,方便在列表中识别用途
Job ID Autogenerate PBS 自动生成唯一 Job ID,也可手动指定

保留策略

保留策略部分,其实与PVE端的设置是一样,不再详细说明

字段 值 说明
Keep Last 未设置 没有备份强制保留
Keep Hourly 未设置 不按小时粒度保留
Keep Daily 7 最近 7 天内每天保留 1 个
Keep Weekly 4 最近 4 周内每周保留 1 个
Keep Monthly 3 最近 3 个月内每月保留 1 个
Keep Yearly 1 最近 1 年内每年保留 1 个

另外,除了PBS Web UI中配置外,PBS也提供了CLI界面:

bash 复制代码
root@pbs:~#  proxmox-backup-manager help prune 
Usage:

prune-job create <id> --schedule <calendar-event> --store <string> [OPTIONS]
prune-job list [OPTIONS]
prune-job remove <id> [OPTIONS]
prune-job run <id> [OPTIONS]
prune-job show <id> [OPTIONS]
prune-job update <id> [OPTIONS]

以下命令与上方 Web UI 配置等效,通过命令行创建相同策略的 Prune Job:

bash 复制代码
proxmox-backup-manager prune-job create prune-nightly \
  --store test-pbs_backup \
  --schedule "21:30" \
  --keep-daily 7 \
  --keep-weekly 4 \
  --keep-monthly 3 \
  --keep-yearly 1
查看 Prune 后的效果

Prune 完成后,在 Web UI 的"备份"内容中,对应的旧快照会消失。但通过 proxmox-backup-manager garbage-collection status 命令查看,会发现 pending-bytes 和 pending-chunks 可能增加了(如果刚运行完 Prune),这些就是等待 GC 安全窗口过后清理的数据。

与 GC 的协同

  1. 顺序:先有 Prune 删除快照(逻辑),后有 GC 回收空间(物理)。
  2. 时间差:Prune 立即生效(快照不可见),但对应的 Chunk 要等到 GC 运行且安全窗口(默认24小时5分钟)过后才会被删除,空间才真正释放。
  3. 监控 :定期检查 GC 状态中的 pending-bytes,可以了解因 Prune 而产生的、即将被释放的空间量。

最佳实践建议

  • 制定清晰的保留策略:根据业务恢复点目标(RPO)和数据重要性制定,平衡存储成本与恢复灵活性。
  • 策略不宜过紧 :避免 keep-daily=1 这样激进的策略,至少保留几天的备份以应对误操作。
  • 理解延迟释放:删除大量历史备份后,不要立即期望看到存储空间大幅下降,需要等待 GC 运行。
  • 结合 GC 调度:将 GC 任务安排在 Prune 可能发生的时间点之后(例如,每日备份任务完成后的几小时)。

二、GC(垃圾回收):释放无用空间

原理

当备份快照被删除(手动删除或按保留策略自动清理)时,PBS 只会删除快照目录下的索引文件(.fidx、.blob 等),而不会立即删除 .chunks/ 目录中对应的 Chunk 文件。这是因为同一个 Chunk 可能被多个备份共享,贸然删除会导致其他备份损坏。

GC 任务会扫描所有存活的备份快照,统计每个 Chunk 的引用计数。引用计数为 0 的 Chunk 表示没有任何备份在使用它,这些 Chunk 会被安全删除,从而释放磁盘空间。

触发方式

  1. 手动触发:通过 Web UI 或命令行手动运行 GC
  2. 自动调度:配置定期 GC 任务(建议每周一次)
  3. 空间阈值触发:当 Datastore 空间使用率达到阈值时自动触发

对存储空间的影响

  • 立即删除快照不会立即释放空间:只有运行 GC 后,空间才会真正释放
  • GC 运行期间性能影响:GC 需要扫描所有 Chunk 的引用关系,会消耗一定的 CPU 和 I/O 资源,建议在业务低峰期运行
  • 空间回收延迟:从删除快照到空间释放,中间存在 GC 运行间隔

命令行操作示例

查看 GC 状态
bash 复制代码
# 查看 Datastore 的 GC 状态
root@PBS01-P:~# proxmox-backup-manager garbage-collection status RS4021XS-02

输出:

复制代码
┌──────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────
│ Name             │ Value                                                                                                
╞══════════════════╪══════════════════════════════════════════════════════════════════════════════════════════════════════
│ store            │ RS4021XS-02                                                                                      
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ disk-bytes       │ 253565643854   # 当前实际占用磁盘空间(已去重)                                                                                      
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ disk-chunks      │ 184190         #当前磁盘上的 chunk 数量                                                                                             
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ index-data-bytes │ 4880156590080    # 所有索引文件引用的 chunks 总大小(原始逻辑数据量 ≈ 4.54 TiB)                                                                                    
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ index-file-count │ 68             #当前 datastore 中所有索引文件(.fidx 和 .didx)的总数量。                                                                                                  
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ pending-bytes    │ 0   # 待删除(Pending Removal)字节数                                                                                               
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ pending-chunks   │ 0     # 待删除 chunk 数量                                                                                                
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ removed-bad      │ 0     # 本次 GC 删除的损坏 chunk 数                                                                                               
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ removed-bytes    │ 12694985831    # 本次 GC 已释放的字节数                                                                                      
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ removed-chunks   │ 35710   # 本次 GC 已删除的 chunk 数量                                                                                            
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ still-bad        │ 0       # 仍存在的损坏 chunk 数                                                                                             
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ duration         │ 7      # 上次 GC 耗时(秒)                                                                                              
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ last-run-endtime │ 1778983207  # 上次 GC 结束时间(Unix 时间戳)                                                                                         
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ last-run-state   │ OK     # 上次 GC 运行状态                                                                                              
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ next-run         │ 1779588000       # 下次计划运行时间(Unix 时间戳)                                                                                    
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ schedule         │ sun 09:00    # GC 计划任务(每周日 09:00)                                                                                        
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ cache-stats      │ {"hits":979330,"misses":184190}    # GC 缓存命中统计                                                                  
├──────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────
│ upid             │ UPID:PBS01-P:000003A1:00000A9C:00000137:6A092120:garbage_collection:x2dRS4021XS\x2d02:root@pam # 任务唯一 ID
└──────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────
root@PBS01-P:~# 

关键字段解释

字段 含义说明
disk-bytes 当前 datastore 在磁盘上实际占用的空间(去重后)
disk-chunks 当前存储的 chunk 总数
pending-bytes/pending-chunks 已经"不再被任何备份引用",但因为 GC 的安全窗口(grace period,默认 24 小时 5 分钟)尚未到期,所以暂时不能删除的 chunk。
removed-bytes removed-chunks,上次 GC 实际释放的空间和 chunk 数量
last-run-state OK 表示上次 GC 正常完成
next-run 下一次计划执行的时间

为何设置GC 的安全窗口(grace period,默认 24 小时 5 分钟)?

主要基于如下场景:

某些 chunk 原本被某个 backup snapshot 引用。

后来可能:

  • prune 删除了 snapshot
  • 手工删了 backup
  • retention policy 生效
  • namespace 删除
  • VM backup 被删
    这些行为会导致这些对应的chunk 已经没人引用。
    GC 在扫描时会发现:这些chunk处于"unused chunk" 状态
    为避免一下可能的情形,PBS 不会立刻删这些已经没有被引用的chunk,而是设置了一个安全窗口期(grace period)来暂时保留这些已经没有人引用的chunk
  • backup 任务刚完成
  • index 尚未同步
  • datastore metadata 尚未稳定
  • replication 尚未完成

这些 chunk 会在 GC(Garbage Collection)阶段被识别,但不会立即删除。PBS 默认会保留约24 小时 5 分钟的安全保护期(Grace Period),对应 PBS WebUI 中的:

PBS节点--->datastore--->datastore name--->Options--->Tunning Options--->GC Access-Time Cutoff(如下图)

手动运行 GC
复制代码
root@PBS01-P:~# proxmox-backup-manager garbage-collection start RS4021XS-02 

输出:

复制代码
starting garbage collection on store RS4021XS-02
Access time update check successful, proceeding with GC.
Using access time cutoff 1d 5m, minimum access time is 2026-05-23T01:54:37Z
Start GC phase1 (mark used chunks)
marked 1% (1 of 71 index files)
marked 2% (2 of 71 index files)
marked 4% (3 of 71 index files)
marked 5% (4 of 71 index files)
marked 7% (5 of 71 index files)
marked 8% (6 of 71 index files)
marked 9% (7 of 71 index files)
marked 11% (8 of 71 index files)
marked 12% (9 of 71 index files)
marked 14% (10 of 71 index files)
marked 15% (11 of 71 index files)
marked 16% (12 of 71 index files)
marked 18% (13 of 71 index files)
marked 19% (14 of 71 index files)
marked 21% (15 of 71 index files)
marked 22% (16 of 71 index files)
marked 23% (17 of 71 index files)
marked 25% (18 of 71 index files)
marked 26% (19 of 71 index files)
marked 28% (20 of 71 index files)
marked 29% (21 of 71 index files)
marked 30% (22 of 71 index files)
marked 32% (23 of 71 index files)
marked 33% (24 of 71 index files)
marked 35% (25 of 71 index files)
marked 36% (26 of 71 index files)
marked 38% (27 of 71 index files)
marked 39% (28 of 71 index files)
marked 40% (29 of 71 index files)
marked 42% (30 of 71 index files)
marked 43% (31 of 71 index files)
marked 45% (32 of 71 index files)
marked 46% (33 of 71 index files)
marked 47% (34 of 71 index files)
marked 49% (35 of 71 index files)
marked 50% (36 of 71 index files)
marked 52% (37 of 71 index files)
marked 53% (38 of 71 index files)
marked 54% (39 of 71 index files)
marked 56% (40 of 71 index files)
marked 57% (41 of 71 index files)
marked 59% (42 of 71 index files)
marked 60% (43 of 71 index files)
marked 61% (44 of 71 index files)
marked 63% (45 of 71 index files)
marked 64% (46 of 71 index files)
marked 66% (47 of 71 index files)
marked 67% (48 of 71 index files)
marked 69% (49 of 71 index files)
marked 70% (50 of 71 index files)
marked 71% (51 of 71 index files)
marked 73% (52 of 71 index files)
marked 74% (53 of 71 index files)
marked 76% (54 of 71 index files)
marked 77% (55 of 71 index files)
marked 78% (56 of 71 index files)
marked 80% (57 of 71 index files)
marked 81% (58 of 71 index files)
marked 83% (59 of 71 index files)
marked 84% (60 of 71 index files)
marked 85% (61 of 71 index files)
marked 87% (62 of 71 index files)
marked 88% (63 of 71 index files)
marked 90% (64 of 71 index files)
marked 91% (65 of 71 index files)
marked 92% (66 of 71 index files)
marked 94% (67 of 71 index files)
marked 95% (68 of 71 index files)
marked 97% (69 of 71 index files)
marked 98% (70 of 71 index files)
marked 100% (71 of 71 index files)
Start GC phase2 (sweep unused chunks)
processed 1% (2260 chunks)
processed 2% (4564 chunks)
processed 3% (6679 chunks)
processed 4% (8948 chunks)
processed 5% (11246 chunks)
processed 6% (13480 chunks)
processed 7% (15738 chunks)
processed 8% (17980 chunks)
processed 9% (20159 chunks)
processed 10% (22390 chunks)
processed 11% (24659 chunks)
processed 12% (26967 chunks)
processed 13% (29208 chunks)
processed 14% (31612 chunks)
processed 15% (33892 chunks)
processed 16% (36163 chunks)
processed 17% (38455 chunks)
processed 18% (40736 chunks)
processed 19% (43053 chunks)
processed 20% (45367 chunks)
processed 21% (47702 chunks)
processed 22% (49983 chunks)
processed 23% (52337 chunks)
processed 24% (54657 chunks)
processed 25% (56922 chunks)
processed 26% (59150 chunks)
processed 27% (61515 chunks)
processed 28% (63690 chunks)
processed 29% (65963 chunks)
processed 30% (68248 chunks)
processed 31% (70561 chunks)
processed 32% (72901 chunks)
processed 33% (75088 chunks)
processed 34% (77362 chunks)
processed 35% (79669 chunks)
processed 36% (81955 chunks)
processed 37% (84220 chunks)
processed 38% (86495 chunks)
processed 39% (88842 chunks)
processed 40% (91068 chunks)
processed 41% (93386 chunks)
processed 42% (95721 chunks)
processed 43% (98053 chunks)
processed 44% (100338 chunks)
processed 45% (102671 chunks)
processed 46% (105038 chunks)
processed 47% (107294 chunks)
processed 48% (109629 chunks)
processed 49% (111992 chunks)
processed 50% (114259 chunks)
processed 51% (116469 chunks)
processed 52% (118725 chunks)
processed 53% (121020 chunks)
processed 54% (123253 chunks)
processed 55% (125608 chunks)
processed 56% (127923 chunks)
processed 57% (130134 chunks)
processed 58% (132495 chunks)
processed 59% (134720 chunks)
processed 60% (136945 chunks)
processed 61% (139195 chunks)
processed 62% (141388 chunks)
processed 63% (143686 chunks)
processed 64% (145973 chunks)
processed 65% (148264 chunks)
processed 66% (150609 chunks)
processed 67% (152919 chunks)
processed 68% (155222 chunks)
processed 69% (157490 chunks)
processed 70% (159753 chunks)
processed 71% (162045 chunks)
processed 72% (164420 chunks)
processed 73% (166700 chunks)
processed 74% (169052 chunks)
processed 75% (171321 chunks)
processed 76% (173719 chunks)
processed 77% (176054 chunks)
processed 78% (178352 chunks)
processed 79% (180640 chunks)
processed 80% (182953 chunks)
processed 81% (185191 chunks)
processed 82% (187500 chunks)
processed 83% (189803 chunks)
processed 84% (192095 chunks)
processed 85% (194334 chunks)
processed 86% (196608 chunks)
processed 87% (198949 chunks)
processed 88% (201215 chunks)
processed 89% (203496 chunks)
processed 90% (205763 chunks)
processed 91% (208091 chunks)
processed 92% (210407 chunks)
processed 93% (212689 chunks)
processed 94% (215091 chunks)
processed 95% (217449 chunks)
processed 96% (219685 chunks)
processed 97% (221994 chunks)
processed 98% (224203 chunks)
processed 99% (226435 chunks)
Chunk cache: hits 1015866, misses 195014 (hit ratio 83.89%)
Removed garbage: 14.082 GiB
Removed chunks: 33731
Original data usage: 4.619 TiB
On-Disk usage: 244.023 GiB (5.16%)
On-Disk chunks: 195014
Deduplication factor: 19.38
Average chunk size: 1.281 MiB
queued notification (id=2497e0b5-e091-439d-9363-701a0a6a5e3a)
TASK OK

运行GC后,会持续输出处理的进度,处理完成后输出了一组关键统计数据:

bash 复制代码
Chunk cache: hits 1015866, misses 195014 (hit ratio 83.89%)
Removed garbage: 14.082 GiB
Removed chunks:  33731
Original data usage: 4.619 TiB
On-Disk usage:       244.023 GiB (5.16%)
On-Disk chunks:      195014
Deduplication factor: 19.38
Average chunk size:   1.281 MiB
字段 值 说明
Chunk cache hit ratio 83.89% GC 标记阶段的内存缓存命中率,说明大量 Chunk 被多个快照重复引用
Removed garbage 14.082 GiB 本次 GC 释放的磁盘空间,来自 Prune 删除的过期快照遗留的无引用 Chunk
Removed chunks 33731 本次删除的无引用 Chunk 数量
Original data usage 4.619 TiB 所有快照的原始数据总量(未去重)
On-Disk usage 244.023 GiB (5.16%) 实际占用的磁盘空间,仅为原始数据的 5.16%
On-Disk chunks 195014 当前 Datastore 中存活的 Chunk 总数
Deduplication factor 19.38 去重倍数,原始数据是实际存储空间的 19.38 倍
Average chunk size 1.281 MiB Chunk 平均大小,低于 4MB 目标值,因全零稀疏块拉低了平均值

其中最值得关注的是 Deduplication factor: 19.38------4.619 TiB 的原始数据实际只用了 244GB 存储,这正是 PBS 全局去重在多台 VM 长期备份场景下的真实效果。

查看 GC 历史记录
bash 复制代码
# 查看 .gc-status 文件内容
root@PBS01-P:~# cat /mnt/RS4021XS-02/.gc-status | jq
bash 复制代码
{
  "upid": "UPID:PBS01-P:000003A1:00000A9C:000001CA:6A125BA0:garbage_collection:x2dRS4021XS\\x2d02:root@pam:",
  "index-file-count": 71,
  "index-data-bytes": 5078798827520,
  "disk-bytes": 262018056164,
  "disk-chunks": 195014,
  "removed-bytes": 0,
  "removed-chunks": 0,
  "pending-bytes": 0,
  "pending-chunks": 0,
  "removed-bad": 0,
  "still-bad": 0,
  "cache-stats": {
    "hits": 1015866,
    "misses": 195014
  }
}

字段说明如下:

字段 当前值 说明 当前状态
upid UPID:PBS01-P:... 本次 GC(Garbage Collection)任务的唯一任务 ID 正常
index-file-count 71 当前 datastore 中的 Backup Index 文件数量 正常
index-data-bytes 5078798827520 所有 Backup Snapshot 逻辑引用的数据总量(约 5.08 TB) 逻辑备份容量正常
disk-bytes 262018056164 Chunk 实际占用的物理磁盘空间(约 262 GB) 磁盘利用率非常高
disk-chunks 195014 当前 datastore 中的 chunk 数量 正常
removed-bytes 0 本次 GC 实际删除的数据量 本次无垃圾数据可删除
removed-chunks 0 本次 GC 删除的 chunk 数量 本次无垃圾 Chunk
pending-bytes 0 已失去引用、但仍处于 Grace Period 的数据量 无 Pending Garbage
pending-chunks 0 已失去引用、但尚未实际删除的 chunk 数量 无待删除 Chunk
removed-bad 0 本次 GC 已移除的损坏 chunk 数量 无损坏 Chunk
still-bad 0 GC 完成后仍存在的损坏 chunk 数量 Datastore 健康
cache-stats.hits 1015866 GC Chunk Cache 命中次数 1015866/(1015866+195014 Cache)=83.9%, 命中率优秀
cache-stats.misses 195014 GC Chunk Cache 未命中次数 正常

总的来说:

  • 无损坏的chunk
  • 命中率优秀
  • Dedup Ratio(去重率)极高,约约 19 : 1:
    Dedup Ratio = index-data-bytes ÷ disk-bytes,本例5078798827520 ÷ 262018056164 ≈ 19.38

整体属于一个状态非常健康的 PBS datastore。

GC 调度策略

自定义GC 任务排程

默认,PBS自带一个Garbage Collect jobs:

我们能通过点击图中的"Edit",根据需要调整排程时间

手工运行GC Job:

除了排程运行外,我们也能手工运行GC Job:

复制代码
root@pbs:~# proxmox-backup-manager garbage-collection start test_pbs_backup

输出:

bash 复制代码
starting garbage collection on store test_pbs_backup
Access time update check successful, proceeding with GC.
Using access time cutoff 1d 5m, minimum access time is 2026-05-25T03:19:25Z
Start GC phase1 (mark used chunks)
Start GC phase2 (sweep unused chunks)
processed 73% (0 chunks)
Removed garbage: 0 B
Removed chunks: 0
Original data usage: 0 B
On-Disk chunks: 1
Deduplication factor: 0.00
Average chunk size: 159 B
queued notification (id=ef476961-ad1d-4e7b-8685-87b232ea81d1)
TASK OK
列出GC Job:
bash 复制代码
root@pbs:~# proxmox-backup-manager garbage-collection list

输出

复制代码
root@pbs:~# proxmox-backup-manager garbage-collection list
┌─────────────────┬──────────────────────────┬──────────┬───────────────┬───────────────┬────────────────┬──────────┬──────────────────────────┐
│ store           │ last-run-endtime         │ duration │ removed-bytes │ pending-bytes │ last-run-state │ schedule │ next-run                 │
╞═════════════════╪══════════════════════════╪══════════╪═══════════════╪═══════════════╪════════════════╪══════════╪══════════════════════════╡
│ test_pbs_backup │ Tue May 26 00:01:28 2026 │ 1m 28s   │ 0 B           │ 0 B           │ OK             │ daily    │ Wed May 27 00:00:00 2026 │
└─────────────────┴──────────────────────────┴──────────┴───────────────┴───────────────┴────────────────┴──────────┴──────────────────────────┘

输出说明如下:

字段 值 说明
store test_pbs_backup 这个 GC 任务所属的 Datastore
last-run-endtime Tue May 26 00:01:28 2026 上次 GC 于今天凌晨 0:01 完成
duration 1m 28s 本次 GC 耗时 1 分 28 秒
removed-bytes 0 B 本次没有清理任何空间,说明没有无引用的孤立 Chunk
pending-bytes 0 B 当前仍无待清理空间,Datastore 状态干净
last-run-state OK 上次 GC 执行成功,无错误
schedule daily 已配置每天自动执行一次 GC
next-run Wed May 27 00:00:00 2026 下次执行时间是明天凌晨 0 点

三、Verify:确保备份完整性

原理

Verify 任务会读取每个备份快照的 .fidx 索引文件,获取该快照引用的所有 Chunk 哈希列表,然后:

  1. 根据哈希值在 .chunks/ 目录中查找对应的 Chunk 文件
  2. 重新计算 Chunk 文件的 SHA-256 哈希
  3. 将计算出的哈希与文件名(即原始哈希)进行比对
  4. 如果哈希不匹配,说明 Chunk 文件已损坏,任务会记录错误

与 index.json.blob 中 csum 的区别

  • csum:验证索引文件(.fidx、.blob)本身的完整性
  • Verify:验证索引文件指向的实际 Chunk 数据的完整性

两者共同构成 PBS 备份完整性的双重保障。

触发方式

  1. 手动触发:通过 Web UI 或命令行手动运行 Verify
  2. 自动调度:配置定期 Verify 任务(建议每月一次)
  3. 恢复前验证:在重要恢复操作前手动运行 Verify

对备份完整性的影响

  • 主动发现损坏:在数据真正丢失前发现损坏的 Chunk
  • 修复机制 :如果 Verify 发现损坏,可以:
    • 从其他 PBS 副本同步(如果配置了同步)
    • 重新备份受影响的 VM
    • 删除损坏的快照(作为最后手段)

命令行操作示例

验证整个datastore
bash 复制代码
# 验证特定 VM 的特定快照
proxmox-backup-manager verify RS4021XS-02 \
  --ignore-verified true \
  --outdated-after 30 \
  --read-threads 2 \
  --verify-threads 4

输出:

bash 复制代码
verify datastore RS4021XS-02
found 19 groups
using 1 read and 4 verify thread(s)
verify group RS4021XS-02:vm/101 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/101/2026-05-23T15:00:05Z (recently verified)
percentage done: 2.63% (0/19 groups, 1/2 snapshots in group #1)
SKIPPED: verify RS4021XS-02:vm/101/2026-05-17T15:30:08Z (recently verified)
percentage done: 5.26% (1/19 groups)
verify group RS4021XS-02:vm/102 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/102/2026-05-23T15:00:12Z (recently verified)
percentage done: 7.89% (1/19 groups, 1/2 snapshots in group #2)
SKIPPED: verify RS4021XS-02:vm/102/2026-05-17T15:30:14Z (recently verified)
percentage done: 10.53% (2/19 groups)
verify group RS4021XS-02:vm/103 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/103/2026-05-23T16:59:06Z (recently verified)
percentage done: 13.16% (2/19 groups, 1/2 snapshots in group #3)
SKIPPED: verify RS4021XS-02:vm/103/2026-05-16T19:00:02Z (recently verified)
percentage done: 15.79% (3/19 groups)
verify group RS4021XS-02:vm/104 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/104/2026-05-23T15:00:18Z (recently verified)
percentage done: 18.42% (3/19 groups, 1/2 snapshots in group #4)
SKIPPED: verify RS4021XS-02:vm/104/2026-05-17T15:30:20Z (recently verified)
percentage done: 21.05% (4/19 groups)
verify group RS4021XS-02:vm/105 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/105/2026-05-23T15:01:35Z (recently verified)
percentage done: 23.68% (4/19 groups, 1/2 snapshots in group #5)
SKIPPED: verify RS4021XS-02:vm/105/2026-05-17T15:30:47Z (recently verified)
percentage done: 26.32% (5/19 groups)
verify group RS4021XS-02:vm/106 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/106/2026-05-23T15:01:41Z (recently verified)
percentage done: 28.95% (5/19 groups, 1/2 snapshots in group #6)
SKIPPED: verify RS4021XS-02:vm/106/2026-05-17T15:30:53Z (recently verified)
percentage done: 31.58% (6/19 groups)
verify group RS4021XS-02:vm/107 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/107/2026-05-23T17:00:41Z (recently verified)
percentage done: 34.21% (6/19 groups, 1/2 snapshots in group #7)
SKIPPED: verify RS4021XS-02:vm/107/2026-05-16T19:00:42Z (recently verified)
percentage done: 36.84% (7/19 groups)
verify group RS4021XS-02:vm/108 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/108/2026-05-23T17:00:49Z (recently verified)
percentage done: 39.47% (7/19 groups, 1/2 snapshots in group #8)
SKIPPED: verify RS4021XS-02:vm/108/2026-05-16T19:00:48Z (recently verified)
percentage done: 42.11% (8/19 groups)
verify group RS4021XS-02:vm/109 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/109/2026-05-23T17:01:02Z (recently verified)
percentage done: 44.74% (8/19 groups, 1/2 snapshots in group #9)
SKIPPED: verify RS4021XS-02:vm/109/2026-05-16T19:00:56Z (recently verified)
percentage done: 47.37% (9/19 groups)
verify group RS4021XS-02:vm/110 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/110/2026-05-23T17:01:08Z (recently verified)
percentage done: 50.00% (9/19 groups, 1/2 snapshots in group #10)
SKIPPED: verify RS4021XS-02:vm/110/2026-05-16T19:01:02Z (recently verified)
percentage done: 52.63% (10/19 groups)
verify group RS4021XS-02:vm/111 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/111/2026-05-23T17:01:15Z (recently verified)
percentage done: 55.26% (10/19 groups, 1/2 snapshots in group #11)
SKIPPED: verify RS4021XS-02:vm/111/2026-05-16T19:01:09Z (recently verified)
percentage done: 57.89% (11/19 groups)
verify group RS4021XS-02:vm/112 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/112/2026-05-23T15:01:49Z (recently verified)
percentage done: 60.53% (11/19 groups, 1/2 snapshots in group #12)
SKIPPED: verify RS4021XS-02:vm/112/2026-05-17T15:31:00Z (recently verified)
percentage done: 63.16% (12/19 groups)
verify group RS4021XS-02:vm/113 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/113/2026-05-23T15:02:04Z (recently verified)
percentage done: 65.79% (12/19 groups, 1/2 snapshots in group #13)
SKIPPED: verify RS4021XS-02:vm/113/2026-05-17T15:31:07Z (recently verified)
percentage done: 68.42% (13/19 groups)
verify group RS4021XS-02:vm/114 (1 snapshots)
SKIPPED: verify RS4021XS-02:vm/114/2026-05-07T07:25:56Z (recently verified)
percentage done: 73.68% (14/19 groups)
verify group RS4021XS-02:vm/115 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/115/2026-05-23T17:01:32Z (recently verified)
percentage done: 76.32% (14/19 groups, 1/2 snapshots in group #15)
SKIPPED: verify RS4021XS-02:vm/115/2026-05-16T19:01:19Z (recently verified)
percentage done: 78.95% (15/19 groups)
verify group RS4021XS-02:vm/116 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/116/2026-05-23T17:02:02Z (recently verified)
percentage done: 81.58% (15/19 groups, 1/2 snapshots in group #16)
SKIPPED: verify RS4021XS-02:vm/116/2026-05-16T19:01:27Z (recently verified)
percentage done: 84.21% (16/19 groups)
verify group RS4021XS-02:vm/117 (1 snapshots)
SKIPPED: verify RS4021XS-02:vm/117/2026-05-08T14:00:07Z (recently verified)
percentage done: 89.47% (17/19 groups)
verify group RS4021XS-02:vm/120 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/120/2026-05-23T15:02:15Z (recently verified)
percentage done: 92.11% (17/19 groups, 1/2 snapshots in group #18)
SKIPPED: verify RS4021XS-02:vm/120/2026-05-17T15:31:13Z (recently verified)
percentage done: 94.74% (18/19 groups)
verify group RS4021XS-02:vm/122 (2 snapshots)
SKIPPED: verify RS4021XS-02:vm/122/2026-05-23T15:02:37Z (recently verified)
percentage done: 97.37% (18/19 groups, 1/2 snapshots in group #19)
SKIPPED: verify RS4021XS-02:vm/122/2026-05-17T15:31:22Z (recently verified)
percentage done: 100.00% (19/19 groups)
TASK OK

重点其实看末尾出现:

bash 复制代码
TASK OK

表示:

Verify 完成

没发现损坏 Chunk

Backup 完整性正常

参数说明:

参数 默认值 说明
<store> 必填 指定要验证的 Datastore 名称,例如 RS4021XS-02
--ignore-verified true 跳过已验证且未过期的快照,避免重复验证浪费时间,配合 --outdated-after 使用
--outdated-after 无 如果一个快照已经验证过,就跳过它,不重复验证。而 Re-Verify After: 30 days,一次验证完成后,经过多少天就视为"已过期",是对这个跳过规则的补充限制:即使已经验证过,但如果距离上次验证已经超过 30 天,就被视为"异过期",重新验证一次。这个设计的目的是在性能和安全之间取得平衡------不需要每次都对所有快照全量验证(耗时很长),但也不允许一个快照永远只验证一次就再也不管,30 天后强制复查,确保数据在存储过程中没有发生静默损坏。
--read-threads 1 读取 Chunk 的线程数,范围 1-32。适当调大可提升验证速度,但会增加磁盘 I/O
--verify-threads 4 验证 Chunk 哈希的线程数,范围 1-32,CPU 密集型操作,调大可加快校验速度
--output-format text 输出格式,可选 text、json、json-pretty,json 格式适合脚本解析结果

也能透过webui进行验证:

验证单个VM

进入PBS Node--->Datastore--->Datastore Name--->Contents,选中目标VM后右键选择Verify

输出:

Verify 调度策略

自定义Verify Job

创建每月第一天的晚上21 点运行的 Verify 任务

bash 复制代码
proxmox-backup-manager verify-job create verify-nightly \
  --store test_pbs_backup \
  --schedule "21:00" \
  --ignore-verified true \
  --outdated-after 30 \
  --read-threads 2 \
  --verify-threads 4 \
  --comment "每晚9点定期验证备份完整性"

参数说明:

参数 值 说明
verify-nightly Job ID 这个 Verify Job 的唯一识别名称
--store RS4021XS-02 要验证的 Datastore
--schedule 21:00 每晚 9 点执行
--ignore-verified true 跳过已验证且未过期的快照
--outdated-after 30 超过 30 天未验证的快照强制重新验证
--read-threads 2 读取 Chunk 的线程数
--verify-threads 4 验证哈希的线程数
--comment 备注 方便在 Web UI 识别这个 Job 的用途

列出Verify Job:

bash 复制代码
root@PBS01-P:~# proxmox-backup-manager verify-job list

输出

bash 复制代码
root@pbs:~#  proxmox-backup-manager verify-job list
┌────────────────┬─────────────────┬──────────┬─────────────────┬────────────────┬───────────────────────────┐
│ id             │ store           │ schedule │ ignore-verified │ outdated-after │ comment                   │
╞════════════════╪═════════════════╪══════════╪═════════════════╪════════════════╪═══════════════════════════╡
│ verify-nightly │ test_pbs_backup │ 21:00    │               1 │             30 │ 每晚9点定期验证备份完整性 │
└────────────────┴─────────────────┴──────────┴─────────────────┴────────────────┴───────────────────────────┘

其他更多操作,可查看命令行帮助:

bash 复制代码
root@pbs:~#  proxmox-backup-manager help verify-job 
Usage:

verify-job create <id> --store <string> [OPTIONS]
verify-job list [OPTIONS]
verify-job remove <id> [OPTIONS]
verify-job run <id> [OPTIONS]
verify-job show <id> [OPTIONS]
verify-job update <id> [OPTIONS]

也能透过webui,更直观方便:

四、监控与告警

  1. 监控 Prune 运行结果 :定期检查 Prune Job 的执行记录,确认过期快照已按策略清理,
    关注是否有快照数量异常增长的情况。可通过以下命令查看:
bash 复制代码
   proxmox-backup-manager prune-job list
  1. 监控 GC 运行结果 :检查 .gc-status 文件中的 last-run 时间和释放空间大小,
    确认 GC 在 Prune 之后正常运行并回收了预期的磁盘空间:
bash 复制代码
   proxmox-backup-manager garbage-collection list
  1. 监控 Verify 结果 :定期检查验证日志,关注 ERROR 或 WARNING 级别的消息,
    任何 Chunk 哈希不一致都应立即排查底层存储是否发生静默数据损坏:
bash 复制代码
   proxmox-backup-manager verify-job list
  1. 设置空间告警 :当 Datastore 使用率超过 80% 时触发告警,优先检查 Prune 策略是否

    过于宽松,或 GC 是否长时间未运行导致孤儿 Chunk 堆积。

  2. 验证频率 :生产环境建议每月全量验证一次,重要备份在恢复前额外验证。

    Prune 策略建议在 PVE 端和 PBS 端统一配置,避免两端策略冲突导致备份被意外删除。


五、实际案例:GC 运行效果

查看 GC 运行前后的空间变化:

bash 复制代码
# GC 运行前
root@PBS01-P:~# df -h /mnt/RS4021XS-02/
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdb1       10T   8.2T  1.8T  83% /mnt/RS4021XS-02

# 运行 GC
root@PBS01-P:~# proxmox-backup-manager garbage-collection run RS4021XS-02 --verbose
...
[INFO] removed 12457 unused chunks, freed 48.7 GiB
[INFO] garbage collection finished successfully

# GC 运行后
root@PBS01-P:~# df -h /mnt/RS4021XS-02/
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdb1       10T   8.1T  1.9T  82% /mnt/RS4021XS-02

在这个例子中,GC 清理了 12457 个不再被引用的 Chunk,释放了 48.7GB 的存储空间。


六、总结

Prune、GC 和 Verify 是 PBS 日常维护中不可或缺的三个核心操作,三者分工明确,缺一不可:

  • Prune 负责按照保留策略清理过期快照,删除不再需要的 .fidx 索引文件,决定哪些备份时间点需要保留,哪些可以淘汰。Prune 不会立即释放磁盘空间,需配合 GC 使用。
  • GC 负责清理被 Prune 删除后无人引用的"孤儿"Chunk,真正回收磁盘空间,确保去重机制不会导致空间持续增长。
  • Verify 负责主动校验备份数据的完整性,逐一验证 Chunk 的哈希是否与文件名一致,确保在需要恢复时数据真实可用,而不是等到恢复时才发现数据已损坏。

三者的执行顺序也有依赖关系:Prune 先行,GC 紧随,Verify 定期执行。Prune 不运行,GC 就没有可回收的 Chunk;GC 不运行,Prune 后的磁盘空间就无法释放;Verify 不运行,备份数据的完整性就得不到主动保障。

合理配置三项任务的调度策略,并建立相应的监控告警机制,是保障 PBS 备份系统长期稳定运行的关键。虽然 PBS 的架构设计大大简化了备份管理,但定期的维护操作仍然是保证数据安全的重要环节。

相关推荐
锅巴编程22 分钟前
nginx-413-client-max-body-size
运维·nginx
蓝速科技41 分钟前
仓储盘点移动终端选型与蓝速科技 K10 实战方案
运维·数据库·人工智能·科技·材质
溜达的大象1 小时前
极空间部署Traggo时间追踪工具:Docker安装、标签管理与cpolar远程访问
运维·docker·容器
wjjzhbb1 小时前
Jenkins到ArgoCD——GitOps持续交付实践
运维·缓存·jenkins·argocd
智商网输送线配件1 小时前
流水线全套配件直供化落地的三个实操切入维度
大数据·运维·自动化·智商网·流水线设备配件
硅基手札1 小时前
【linux内核专栏01】Linux 内核心智模型与设计哲学
linux·运维·驱动开发·开源软件
脏脏a1 小时前
极空间部署 Dashlet:Docker 搭建私人导航仪表盘,再配置固定公网访问
运维·docker·容器
中电金信2 小时前
中电金信参编的团体标准《商业银行应用程序接口治理能力要求》正式发布
大数据·运维·人工智能
码完就睡2 小时前
Linux——socket网络编程
linux·运维·网络
道尔柯南2 小时前
【Linux】网络基础概念
linux·运维·网络