09. 经验教训汇总

这几天所有踩坑、原则、工具沉淀的一句话清单。 每条都对应实际发生过的事。

配置类

1. Tailscale 在 LXC 三件套

1
2
3
features: nesting=1                                    # 不能是 0
lxc.cgroup2.devices.allow: c 10:200 rwm               # /dev/net/tun
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file

少任何一条 tailscaled 起不来。

2. Syncthing GUI 别绑 127.0.0.1

<address>0.0.0.0:8384</address>default,不是 127.0.0.1

“内网机器,不用这么严格”。

3. Syncthing systemctl 别加 .service

systemctl enable syncthing@syncthing,不是 syncthing@syncthing.service

4. systemd template unit 用户名要对

syncthing@syncthing 第二段是用户名,要先 useradd -r syncthing

5. CT111 /data 不能用 root mkdir

任何给 daemon (syncthing/tailscale/…) 用的目录,必须用 daemon 用户创建,或创建后立刻 chown。

否则 16379 个 permission denied 在等你。

6. ZFS rename 几乎免费

迁移 dataset 用 zfs rename,秒级,0 风险,别用 cp / rsync

28. RustFS 自建 S3 后端 (Kopia 用)

1
2
3
4
5
# CT110 配置
RUSTFS_VOLUMES=/data
RUSTFS_ADDRESS=0.0.0.0:9000
RUSTFS_ACCESS_KEY=admin
RUSTFS_SECRET_KEY=...

Kopia 接 S3 后端:

1
2
3
4
5
6
kopia repository create s3 \
  --bucket=kopia-backup \
  --endpoint=http://192.168.31.128:9000 \
  --access-key=admin \
  --secret-access-key=... \
  --disable-tls

详见 11-RustFS部署与Kopia切换

协议类

7. Syncthing folder XML 结构

1
2
3
4
<folder id="..." label="..." path="...">      ← path 是 attribute
  <device id="..."/>                          ← device 是 child
  ...
</folder>

path 不是 child element,regex 写错位置会匹配不到 device

8. Syncthing 改配置直接改 XML

REST API PUT 经常返回 200 但没生效(字段缺失 / 类型错 / path 不让改)。

改 path / device list 直接 sed/Python 改 XML + restart

9. Syncthing GUI 不让改 path

要改 path,GUI 只能 delete + recreate(数据不丢,但要重新接受介绍)。

XML 流程更快: sed + restart。

调试类

10. 先查本端可观测面,再碰远端磁盘 ⭐

排查 sync 问题,先查 CT111 /rest/events,别先去 mount VM105 磁盘。

详见 08-调试方法论

11. Syncthing 错误不会自我暴露

16379 个 error 静静躺在 /rest/events,Syncthing 不报警。

应对: 监控脚本定期检查 pullErrors

12. 看错误信息要看"具体内容"

1
mkdir /data/工作学习/.obsidian: permission denied

“permission denied” 只是表层,真问题是 owner 是 root,daemon 是 syncthing 用户

13. zfs send 是最后的手段

排查问题时,先用 API / events / logs,别先 zfs send

zfs send 适合确实需要离线分析的场景。

14. 走错路 10 分钟没进展就停

沉没成本不是继续走的理由。

我这次调试 VM105 时,5 步错路就花 12 分钟,该早停。

15. 区分症状 / 问题 / 根因

  • 症状: 数据不 sync
  • 问题: 16379 个 error
  • 根因: 目录 owner 错

一直在查症状,忘了问问题。

工具类

16. qemu-nbd 用 -r,不是 --readonly

1
qemu-nbd -r -c /dev/nbd0 /dev/zdN

17. 看 zdX 映射用 /dev/zvol/<pool>/

1
2
3
ls /dev/zvol/SSD_1TB/
# vm-105-disk-0 -> ../../zd80
# vm-105-disk-1 -> ../../zd32

ls /dev/zd* 直观。

18. Python heredoc + 中文容易炸

f-string 不能有反斜杠,backslashes in expression

复杂逻辑永远写文件 → pct pushpct exec,别用 heredoc + 内嵌 Python。

19. PVE 默认没 smartmontools / lm-sensors

要自己装:

1
2
3
apt install smartmontools lm-sensors
sensors-detect
modprobe k10temp amdgpu

20. PBS datastore 改路径要先停服务

1
2
3
4
systemctl stop proxmox-backup
zfs rename ...
改 /etc/proxmox-backup/datastore.cfg
systemctl start proxmox-backup

决策类

21. 重要迁移要并行观察期,不要一刀切

7 天观察期成本:

  • 多存 500GB 几天(~几分钱)
  • 多跑 1 个 VM (8GB RAM)

收益:

  • 数据安全 +100
  • 心理踏实 +100

7 天观察期必须做

22. CT 跑 Syncthing 比 VM 好

维度VMLXC
启动30s+2s
空闲 RAM1GB50MB
文件系统virtio-scsibind mount (原 FS)
备份qemu snapshotzfs snapshot

Syncthing 这种 IO 重、OS 轻的服务,LXC 完胜

23. 飞牛 NAS 当 Syncthing 节点太重

飞牛 NAS 自带 Syncthing 是 docker,WebUI 经常挂

只为了 Syncthing 装一整套飞牛 NAS,性价比低

LXC + Syncthing + Tailscale 三件套,比 docker-in-VM-in-PVE 简单 10 倍

24. sdc 这种退化盘不要存重要数据

便宜 SSD (Kingston SA400 / GW600) 没 DRAM cache、寿命短。

NAS / 备份盘用企业级(Samsung PM893 / Intel DC S3710)。

系统盘可以便宜。

28. RustFS vs MinIO:资源紧张选 RustFS

RustFS 优势: 内存 ~65MB,启动 <1s,静态链接 RustFS 劣势: preview 版本,有 bug 风险

MinIO 优势: 稳定,生态全 MinIO 劣势: 内存 100-200MB,二进制 ~100MB

家用 PVE 选 RustFS;生产 / 企业选 MinIO。

29. 自建 S3 vs AWS S3

自建AWS
数据控制✅ 自己❌ 在 AWS
月费✅ 无❌ 有
异地高可用❌ 单点✅ 多 region
数据迁移性✅ 数据在 dataset❌ egress 贵

结论: 都做。自建主存储 + 异地 (Backblaze B2 ~¥10/月 500GB) 副本。

备份 / 灾难恢复类 ⭐ 最重要

30. 备份必须 3-2-1 ⭐

3 份数据、2 种介质、1 份异地。

之前 Kopia 仓库在单盘 HHD_3TB 上,metadata 损坏 = 数据丢失,0 备份

原则: 任何"重要数据"必须有异地副本 (Backblaze B2 / 朋友家 NAS / 加密 U 盘寄过去)。

31. 验证恢复,不只是有备份

Kopia 跑了一年从没 kopia restore 验证过能真的解出来。

原则: 每月跑一次恢复演练,确认备份能解。

32. Kopia / Restic / Borg 后端用 S3,别用 local FS

local FS 后端风险:

  • 文件系统 metadata 损坏 → 整个仓库可能不可信
  • 没内置 checksum
  • 单点

原则: 重要备份用 S3 / SFTP / 异地后端。

详见 10-Kopia数据丢失与复盘

硬件 / 电源类

33. PVE 必须配 UPS

sdc GW600 1TB 1655 次开机 / 779 次 power retract,47% 开机伴随突然断电

家用 PVE + 无 UPS = 慢性自杀。

原则: 买 UPS ~¥400 (APC BK650),配 nut / apcupsd 优雅关机。

详见 12-硬盘损坏全程记录

34. 便宜消费级 SSD 不适合 PVE

GW600 1TB (¥300) 用 1.5 年就 DEGRADED。

原则: PVE / NAS 用 Samsung PM893 / Intel D3-S4520 等企业级 SSD,贵的 1.5 倍但寿命 5 倍以上。

35. 单盘 ZFS 池 = 数据裸奔

HHD_3TB 单盘运行到 metadata 永久损坏才意识到,数据抢救困难。

原则: 任何存重要数据的 ZFS pool 必须 mirror

流程类

25. 装新 daemon 前的 4 个问题

任何时候新部署 daemon,问这 4 个问题:

  1. 它跑在哪个 UID? (ps -ef | grep daemon)
  2. 数据目录 owner 是谁? (ls -lad)
  3. 写入路径是否在 UID 可写范围? (sudo -u daemon touch /data/test)
  4. 启动前 daemon 测试可写性

26. 写改动前 5 件事

  1. 备份配置:cp config.xml config.xml.bak
  2. 记录到 memory:关键参数
  3. 想清楚回滚路径
  4. 选非高峰时间
  5. 测试小范围先

27. 改动后 3 件事

  1. 观察一段时间(30 分钟起步)
  2. 看 metrics / errors
  3. 总结到笔记(这次的踩坑 → 经验)

工具沉淀

健康检查脚本

1
2
3
4
5
6
7
8
#!/bin/bash
# /usr/local/bin/syncthing-healthcheck.sh
API_KEY=$(cat /etc/syncthing.api.key)
ERRORS=$(curl -sS -H "X-API-Key: $API_KEY" \
  http://127.0.0.1:8384/rest/db/status?folder=$1 | \
  jq .pullErrors)
[ "$ERRORS" -gt 0 ] && echo "ALERT: $1 has $ERRORS errors" && exit 1
exit 0

CT111 自动重启脚本

1
2
3
4
5
6
7
8
#!/bin/bash
# /usr/local/bin/restart-t11.sh
# 重启 CT111 + 验证 tailscale / syncthing
pct stop 111
pct start 111
sleep 10
pct exec 111 -- systemctl is-active tailscaled syncthing@syncthing
pct exec 111 -- tailscale status | head -5

ZFS 监控脚本

1
2
3
4
5
6
#!/bin/bash
# /usr/local/bin/zfs-healthcheck.sh
# 检查所有池,任何 DEGRADED 立即告警
zpool status | grep -E "DEGRADED|FAULTED|errors:" | grep -v "No known"
[ $? -eq 0 ] && echo "ALERT: ZFS pool has errors" && exit 1
exit 0

SMART 监控

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/bash
# /usr/local/bin/smartd-healthcheck.sh
for d in sda sdb sdc sdd; do
  HEALTH=$(smartctl -H /dev/$d | grep "result:" | awk '{print $NF}')
  if [ "$HEALTH" != "PASSED" ]; then
    echo "ALERT: /dev/$d SMART $HEALTH"
    exit 1
  fi
done
exit 0

Memory 沉淀 (本次)

已存到 jcode memory 的关键事实:

  1. CT111 syncthing 不跑 root,目录必须 chown
  2. Tailscale 在 LXC 三件套
  3. VM105 数据盘是 mdadm RAID,不能直接 mount
  4. qemu-nbd 用 -r 不是 –readonly
  5. VM105 三盘映射(zd80 boot / zd32 data / zd48 extra)
  6. PVE 必须配 UPS
  7. HHD_3TB 单盘有 metadata 永久损坏历史
  8. SSD_1TB 当前 DEGRADED(GW600)

通用原则

一句话

配置改前先备份,问题查前先看本端,踩坑后写笔记。 数据备份必须有异地,验证过能恢复才算数。

三句话

  1. 能 ZFS 不复制(rename 几乎免费)
  2. 能 XML 不 API(Syncthing REST API 不可靠)
  3. 能 CT 不 VM(LXC 更轻更直接)
  4. 能 S3 不 local FS(Kopia 后端用对象存储)
  5. 能 mirror 不单盘(重要数据必须 RAID1)

七句话

  1. 先查本端,再碰远端
  2. 5 分钟没思路,停下来重述
  3. 10 分钟没进展,换路径
  4. 区分症状 / 问题 / 根因
  5. 看错误要看具体内容
  6. 沉没成本不是继续走的理由
  7. 写下来,下次不踩
  8. 3-2-1 备份原则,缺一不可

接下来 7 天

  • [被动] VM105 → CT111 三文件夹跑完
  • [被动] 观察期无异常
  • [主动] 9-09:移除 VM105 设备 → 停 VM105 → 删 VM105 → 释放 1.5TB

中期 (1-3 个月)

  • 买 UPS
  • 买 2× 512G 企业级 SSD
  • 重装 PVE + 数据池 mirror
  • Backblaze B2 异地备份

下一篇

完成。

索引页