[!warning] 敏感信息说明 本文涉及的真实密码 (
<your-password>) 与用户名 (<kopiauser@host>) 已脱敏。阅读时按你的实际部署替换占位符。
10. Kopia 数据丢失与复盘
⚠️ 本文涉及真实数据丢失事件。 Kopia 仓库 (57GB 备份) 在 2026 年 8 月因 ZFS 池损坏事件受损。 阅读时请注意:不是所有备份都救回了。
时间线
| |
Kopia 原本是什么
Kopia 是一个开源的、加密的、增量备份工具,支持多种后端 (filesystem / S3 / SFTP / B2 等)。
主要特点:
- 全局去重: 跨文件、跨设备、跨时间的 block-level dedup
- 端到端加密: 数据上传前加密,服务端无法读
- 增量: 只传变更的 block
- 多平台: Windows / Linux / macOS 都支持
我当初用它是想做"统一备份服务器":
- 所有 PC (公司电脑 / 家里的电脑 / redmi-pad-se) 都把数据推到一个中心仓库
- 利用 dedup 节省空间 (跨设备 dedup)
- 加密保证数据安全
Kopia 部署历史
Phase 1: 初始部署 (2026-05-30)
| |
服务跑在 51515 端口。
Phase 2: 加 TLS + 用户认证 (2026-05-31)
| |
Phase 3: 最终方案 (2026-06-09)
经过一系列参数调优(KOPIA_CONTENT_CACHE_SIZE_MB、KOPIA_METADATA_CACHE_SIZE_MB、–log-level=warning 等):
| |
最终成果 (2026-06-09):
- 逻辑数据: 274.4 GB (4 个备份源)
- 物理占用: 30 GB (89% 去重率)
- 系统盘: 563M / 8G
- 服务: 稳定自启
Kopia 当时是我对备份的"银弹":单点加密、去重、自动调度、跨设备。
灾变: 2026-08-30 的发现
起因
我在 2026-08-30 做 PVE 硬件体检时,跑 zpool status 发现:
| |
永久错误 + 元数据损坏。
风险评估
HHD_3TB 池上有什么?
| |
两个关键数据都在这个单盘无冗余的坏池上。
Kopia 仓库的影响
Kopia 仓库 (/KopiaRepo) 在 /HHD_3TB/subvol-102-disk-0/(CT102 的 rootfs subvol)。
元数据损坏的位置是 <metadata>:<0x0> 和 <metadata>:<0x3d>:
- Kopia 仓库的核心是它的索引文件 (
kopia.repository),里面记录所有 block 的 manifest - 如果这些索引所在的 block 在坏池的 metadata 损坏范围内,kopia 可能完全无法验证或恢复数据
紧急救援 (2026-08-30)
| |
抢救结果 (推测):
- ✅ 大部分文件复制成功
- ⚠️ 部分块可能在 metadata 损坏区,rsync 可能报错或跳过
- ⚠️ 即使复制成功,kopia 仓库完整性也无法保证
数据丢失的实际范围
诚实声明: 我没有逐个验证每个备份是否完整恢复。 以下是我推断的数据丢失范围:
| 备份源 | 原始大小 | 状态 |
|---|---|---|
| D 盘 工作学习 | ~16 GB | ⚠️ 部分丢失 (具体量未知) |
| D 盘 服务物资对账单 | ~40 GB | ⚠️ 部分丢失 |
| E 盘 工作学习 | ~16 GB | ⚠️ 部分丢失 |
| E 盘 服务物资对账单 | ~40 GB | ⚠️ 部分丢失 |
实际可恢复的备份量:未知。
Kopia 的 dedup 特性让"丢失多少数据"难以准确评估 — 一个丢失的 manifest 块可能让几十个快照的部分数据全部失效。
为什么这次事故严重
1. 单盘无冗余
HHD_3TB 池只有一块 Seagate ST3000NM0053 3TB HDD,没有 mirror / RAID。
任何 metadata 损坏都无法自动恢复。
2. 元数据损坏是最严重类型
ZFS 数据损坏有几种:
- Data block: 文件内容损坏 (还能 mount)
- Metadata block: 文件系统结构损坏 (mount 失败或静默错)
- Metadata 永久损坏: 无法自愈
我这次是 metadata 永久损坏。整个池理论上仍能 mount,但元数据不可信。
3. 没做异地备份
Kopia 仓库本身就是备份,但只在一个本地磁盘。
3-2-1 备份原则 (3 份副本、2 种介质、1 份异地) 我一条都没做到。
4. 监控盲区
我之前没装 smartmontools,也不知道池里 errors 在积累。
SMART 在 daily 跑是事件触发,我没主动设监控。
复盘: 一开始哪里可以做得不同
❶ 异地备份
应该一开始就把 Kopia 推到异地 (云 S3 / 朋友家 NAS / 加密 U 盘寄过去)。
代价: 几毛钱/月的 S3 存储费 收益: 这次事故完全避免
❷ ZFS mirror (RAID1)
应该一开始就用两块盘做 mirror。
代价: 多买一块 SSD (~¥150) 收益: 自动 failover,metadata 损坏自动修复
❸ 监控 + 告警
应该一开始就装 smartmontools + 定期 zpool status 自动检查 + email/push 告警。
❹ 验证恢复
应该定期 kopia repository validate-provider + 实际恢复一个文件验证。
Kopia 仓库完整性 ≠ 数据可恢复。我从来没真正"打开"过一个备份看看是不是能解出来。
❺ 备份分层
应该:
- Tier 1 (snapshot): ZFS snapshot 频繁做 (分钟级)
- Tier 2 (版本): Kopia 每天一次
- Tier 3 (异地): Kopia 推异地
不要把"备份"all-in-one。
修复路径: 从这次事故学到
短期 (2026-08-30 当晚)
| |
中期 (2026-09-01 部署 RustFS)
意识到 local FS 后端的脆弱性,改用 S3 后端:
| |
S3 后端好处:
- object storage 通常有内部 checksum + 多副本
- 即使本地磁盘坏,数据在 S3 内是冗余的
- 跨进程锁更可靠(避免本地 FS race)
长期 (规划中)
- 异地 S3 (Backblaze B2 / 阿里云 OSS, ~¥10/月 500GB)
- Kopia snapshot 定期 validate
- 每月实际恢复一个文件验证
- ZFS mirror 重构 (参见 12-硬盘损坏全程记录)
- 自动监控 zpool status + email 告警
教训
教训 1: 备份不上异地等于没备份 ⭐
“本地备份"不是"真备份”。
单盘挂了 / 误操作 / 火灾 / 失窃 = 本地副本全没。
原则: 任何"重要数据"必须有异地副本。
教训 2: ZFS 不会自我救 metadata
ZFS scrub 能修数据 checksum 错,但 metadata 损坏不会自动修复(如果单盘无冗余)。
scrub 完了告诉我: “repaired 0B with 0 errors”。但前面 errors: 4 data errors 是历史遗留。
原则: scrub 之前先看 zpool status 的 errors: 行,有问题立即查。
教训 3: Kopia dedup 是双刃剑
dedup 让 274GB 逻辑数据只占 30GB 物理,省空间。
但一个关键 block 损坏 = 引用它的所有快照都失效,放大损失。
原则: dedup 后端必须配异地 + 多副本,不能本地单盘。
教训 4: 不验证就不是备份
Kopia 跑了一年,服务正常,客户端能 push 数据,但我从没验证过能真正恢复。
原则: 每月跑一次 kopia restore 到临时目录,确认文件能解开。
教训 5: 备份系统的"3-2-1"原则
3 份数据、2 种介质、1 份异地。
我之前 3-2-1 一个都没做到(只有 1 份本地)。
原则: 评估备份方案时,先列 3-2-1 是否满足,再谈别的。
关键命令清单
| |
数据现状 (2026-09-02)
| |
心理感受 (诚实记一笔)
这次事故让我意识到:我以为我做了备份,但实际上没有。
Kopia 跑了一年,GUI 看着一切正常,数据"已上传"的安心感很足。但后台的 ZFS 池已经悄悄坏了几个月,我毫不知情。
不是 Kopia 的问题,是我没验证过能不能恢复。
这件事是个教训,也是一个礼物 — 让我重新认真对待备份这件事。