NAS数据双保险:从教训到实践的数据保护方案


故障带来的教训

2026年2月5日,我的绿联 NAS 突然故障,所有硬盘报告”已损毁”。虽然最终确认是主板 SATA 控制器问题,数据完好,但这次经历让我深刻认识到一个残酷的现实:

同台 NAS 上的备份,根本救不了 NAS 本身的故障。

之前的想法是:NAS 不同硬盘上备份就行了,毕竟 NAS 整个挂掉的概率不大。

现实是:四个硬盘都没坏,但 SATA 控制器挂了,所有硬盘同时”消失”。同台 NAS 上的 Borgmatic 备份根本救不了。

这次让我重新思考备份策略,开始实践真正的数据双保险。


整体架构

先上一张完整的双保险架构图,后续我将从硬件规划、本地备份环节以及异地备份三个方面详细介绍:

架构图


硬件规划:分槽而治

硬盘槽位设计

槽位类型容量用途
一号SSD512G热数据,应用安装
二号HDD2T闲置
三号HDD4T备份盘,只存放 Borg 备份文件
四号HDD16T主硬盘,存放所有个人数据

设计理念

  • 热数据与冷数据分离:SSD 放应用和频繁访问的数据,HDD 放长期存储
  • 备份独立:第三槽专门用于备份,不混用其他数据
  • 主数据独立:第四槽作为主数据存储,便于管理和维护

IaC 化:让配置可重现

为什么要 IaC

上次 NAS 故障后,我意识到一个问题:如果 NAS 再次挂了,要重新配置所有服务,时间成本太高。

实践内容

完成了绿联服务的 IaC 化:

  • Docker Compose 迁移:将所有的 docker-compose 文件整理并纳入了 Git 版本控制。以 colder-minio(一个用来存放低频归档数据的冷存储对象服务)为例,原本散落在 NAS 里手动配置的映射路径、环境参数现在被完全代码化描述:
    version: '3'
    services:
    minio:
    image: bitnami/minio:2025.4.22
    restart: always
    ports:
    - "9011:9001"
    - "9010:9000"
    environment:
    - MINIO_ROOT_USER=<your_username>
    - MINIO_ROOT_PASSWORD=<your_password>
    - MINIO_BROWSER=on
    volumes:
    - /volume4/AppDataHDD/docker/colder-minio/data:/bitnami/minio/data
    healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
    interval: 30s...
  • Ansible 部署:使用 Ansible 把上面的配置连同服务启动流程,直接通过自动化部署下发到绿联 NAS。
  • 好处:配置不再是一次性的黑盒,即使 NAS 再次挂载异常,我的所有环境挂载逻辑也都在 GitHub 仓库里躺着,即拔即插即用。

Ansible 部署结构与具体流程

目前这套逻辑维护在一个私有 Git 仓库里,使用 Ansible 管理所有应用的上下线:

  1. 统一的 App 目录:在 Ansible 项目下有一个 apps/ 目录,所有的应用以各自目录分类存放对应的 docker-compose.yml 及配置文件。
  2. 通用的部署 Playbook:统一编写了 deploy_app.yml 脚本,以刚刚的 colder-minio 为例,只需执行 ansible-playbook deploy_app.yml -e app_name=colder-minio 就能一键上线该应用。

这是目前正在使用的 deploy_app.yml 核心部分:

---
- name: 部署 Docker 应用
hosts: nas
become: yes
vars:
app_name: "default_app"
app_dir: "{{ docker_data_root }}/{{ app_name }}"
tasks:
- name: 确保应用的配置目录存在
file:
path: "{{ app_dir }}"
state: directory
owner: tomyail
group: admin
mode: '0775'
- name: 同步应用的所有配置数据和 docker-compose 文件到 NAS
copy:
src: "apps/{{ app_name }}/"
dest: "{{ app_dir }}/"
owner: tomyail
group: admin
- name: 启动/更新 Docker 容器 (Docker Compose V2)
command: docker compose up -d --remove-orphans
args:
chdir: "{{ app_dir }}"
register: docker_output

这样一来部署流程就固定下来了:Ansible 连上 NAS 后,会自动新建应用所在的宿主机目录,将所需的配置文件全部从本地 apps/<应用资源> 同步过去(例如同步到 NAS 上的 docker_data_root/...)。检测同步过去的文件无误后,会经由 SSH 远程命令直接触发 docker compose up -d --remove-orphans 让 NAS 完成更新。

这种模式起到了环境版本控制的作用。下次如果再遇到换机器或是主板烧了的情况,只要打通新系统网络,几条命令就能立刻恢复所有服务配置和应用状态。


本地备份:Borgmatic 方案

关于本地备份的具体选型、容灾考量以及使用 Borgmatic 的详细部署方案,在之前的文章中已经做了完整记录:

NAS 数据备份:Borgmatic 与 Docker 的部署实践

简而言之,通过 Borgmatic,我实现了将 SSD(系统及应用配置)和主 HDD(个人数据)的数据定期无感备份到专属的备份 HDD 盘(三号槽位),并接入了监控预警,为数据奠定了第一层保险。


异地备份:rsync 双保险

为什么需要异地备份

volume3 上的备份数据,还要定期备份到其他机器上,避免上次绿联主板挂掉后所有数据拿不出来的问题。

实现方案

在台式机上面启动一个 docker 服务,这个 docker 的目的就是执行 rsync,周期性的把绿联上面的 borg 备份数据同步到台式机。

volume3 (本地备份盘)
↓ rsync 定期同步
台式机 (异地备份)

具体来说,我在异地备份机(台式机 Windows 宿主环境)通过 Docker 部署了一个同步环境。核心的 docker-compose.yml 配置如下:

services:
sync:
image: instrumentisto/rsync-ssh:latest
container_name: nas-rsync-sync
command: sleep infinity
entrypoint: /etc/borgmatic.d/entrypoint.sh
volumes:
# 本地备份终点存放位置(挂载了一块外接硬盘)
- E:/borg:/mnt/local-repository
# Rsync 同步脚本与入口脚本
- ./config/sync-repos.sh:/usr/local/bin/sync-repos
- ./config/entrypoint.sh:/etc/borgmatic.d/entrypoint.sh:ro
# SSH 密钥挂载,实现免密读取远端 NAS
- ./ssh/pi:/mnt/ssh_key:ro
# Rsync 密码文件挂载
- ./config/rsync.pass:/mnt/rsync_pass:ro
# 缓存与配置持久化,加速 Borg 校验
- ./data/borg:/root/.config/borg
- ./data/cache:/root/.cache/borg
environment:
- TZ=Asia/Shanghai
- BORG_PASSPHRASE=<your_borg_password>
restart: unless-stopped

通过这个容器环境,不仅利用 instrumentisto/rsync-ssh 镜像具备了 SSH 与 rsync 的能力,还映射出了单独的外部数据盘(E:/borg),以及解决了自动化所需的免密码 SSH 和 rsync 凭据挂载。

然后利用 Shell 脚本定期执行 rsync 或是触发 Borgmatic 校验任务,确保台式机这里能完整拉取并能打开远端 NAS (volume3)所有的 Borg 归档片段。


工作流总结

完整数据流

  1. 部署服务

    • 根据需求部署 Docker 容器
    • 通过 volume 映射,数据写入 volume1(SSD)或 volume4(HDD)
  2. 本地备份

    • Borg 定义了各种备份任务(如 music.yaml、book.yaml)
    • 定期将 volume1 和 volume4 的数据备份到 volume3
  3. 异地备份

    • volume3 上的备份数据定期备份到其他机器
    • 防止绿联主板故障导致数据丢失
    • 具体实现:在台式机启动 Docker 服务执行 rsync
    • 周期性同步绿联的 Borg 备份到台式机

经验总结

3-2-1 备份原则

3 份副本、2 种介质、1 份异地——这次我算懂了”1 份异地”的份量。

  • 3 份副本:原数据 + 本地备份 + 异地备份
  • 2 种介质:NAS + 台式机
  • 1 份异地:台式机作为异地备份

文件系统的坑

btrfs + 软 RAID 出问题时只能在 Linux 上操作,Mac 和 Windows 没辙。

监控的价值

给关键服务配上心跳监控,能第一时间知情。


相关文章