本篇文章,记录搭建备份服务器的过程。
写在前面
今年考虑专门搭建一台用于数据备份的机器,一来今年外出的需求比较多,历史的设备已经用了几年了,需要有更新的设备来“接力”;二来也想验证方案的靠谱程度,解决我接触的一些生产环境的需求以及朋友们的问题。
因为之前已经买过好几台群晖了,加上今年群晖新品的 “CPU 升级” 非常“明智”,于是我决定自建一台。
如果不计算硬盘和内存升级,整机连带 UPS 差不多 2000 块,除了能够充当文件服务器之外,还能运行虚拟机和 Docker 容器,相比群晖性价比还是高不少的。
需求明确
我希望这台设备能够满足以下几个诉求:
- 必须支持 macOS 系统的数据备份(时间机器),如果能够支持 Windows (生产环境中会有)就更好啦。
- 至少有一种靠谱的方案来保障数据写入是正确可靠的。
- 系统稳定可靠,三年五载的不需要额外的维护打理。
- 体积相对小巧,运行起来没有噪音。
- 不包含存储设备(硬盘、内存)成本相对较低,能够支持快速替换硬件来解决可用性问题。
除此之外提供的能力,都是“附加分”。
因为核心诉求其实是软件诉求,所以我们来看看软件方案。
操作系统和软件的选择
我倾向的方案是能够持续稳定运行,不会随意重启的 Linux 系统,或者基于 Linux 系统封装的 NAS 系统,最低的底限是我能够知道“samba”、“afp(netatalk)” 的程序版本,未来能够完成迁移。
本篇文章,我们先使用 Ubuntu 来完成基础的服务搭建。
为什么没有选择“白”或者“黑苹果”
在此之前,我分别使用 Mac 设备,和兼容 Mac 的硬件(包括这台 Elite Desk)运行 macOS,开启文件共享,做了“时间机器”的测试。
相比 Linux 协议兼容的开源软件 netatalk ,确实稳定性高了不少,但是,如果选择使用白苹果,想要限制成本,那么容量就无法满足实际使用;如果选择黑苹果,即使优化配置到 99% 可用,总归觉得还有 1% 的不稳定因素,而我们并不知道这个 1% 的问题什么时候会“触发”,影响有多严重。况且,很有可能不确定性远大于 1%。
为什么没有选择 Windows
因为近几年,我没有主力使用 Windows,对于 Windows 的熟悉程度是不够的。并且,在最近一次的试验中,我发现非服务器版的 Windows 的长时间运行还是有一些问题的(我购入的是专业版的 Licenses)。
11 月末的时候,我入手了一台机器(Dell Optiplex),购入了正版的 Windows 11 ,系统上低负载运行了一款程序。在过去的两个月中,我遇到了跨系统“远程桌面”失效、毫无预兆的“自动”升级和重启,可能作为文件服务器来说,可靠性还需要进一步验证。
硬件方案选择
基于上面的需求,我将硬件选择范围锁定在了 HP EliteDesk 和 Dell Optiplex 两个系列里。经过对比,这次没有选择全新的设备,而是选择了二手市场上供给充沛的 Elite Desk。最终选择了一台 2021 年激活过,因为 2022 “环境变化”退出服役的二手的主机:EliteDesk 800G6 SFF(硬件规格)。
除了机箱有二次喷涂掩盖搬运时的暴力磕碰之外,用酒精擦外壳的时候能够看到喷涂的漆在快速挥发,会有点呛之外,基本没有什么槽点。(不消毒的话,不会触发这个事情,机器本身没气味)
我偷了个懒,选择了搭载 i3-10105T 的机器,成本在 1600 元左右,如果你手头有闲置的 CPU,可以入手 700~800 块左右的准系统。
为什么没有选择新款群晖
我连续购入了前两代的群晖产品 DS918+ 和 DS920+,但是对于 DS 923+,这款“升级到” AMD Ryzen 1600 的产品,实在提不起兴趣。
上文中提到的相对廉价的 i3-10105t CPU 规格可以在 Intel 官网查询到,性价比显然高出不止一头。
为什么没有选择 Apple Time Capsule(时间胶囊)
从外观来说,苹果的时间胶囊(技术规格)还是很好看的。但是,产品在 2018 年停产,如果硬件出现问题,通过购置相同硬件来完成服务恢复其实有点麻烦。加上产品即使停产,现在的价格也是小贵的,换起来心疼。
更关键的是,设备只能插一颗磁盘,设备本身算力也非常有限。
为什么没有选择阵列硬盘盒
如果我们已经有一台设备,并且不介意通过 USB 或者雷电数据线来进行数据交互的话,使用外置阵列硬盘盒未见得不是一个好的方案。这个方案最好的一点是,消费市场中硬盘盒的外观的可选性非常多。
不过,多数硬盘阵列盒不能直接提供服务,需要借助“宿主机”来提供服务,更不能运行一些我们想要运行的软件。而且,既然选择搭建一台设备,并且能够使用更靠谱直连主板的 SATA 线以及更可靠的主机电源,那么硬盘盒的方案的性价比也就不是很高了。何况这类设备的“溢价”非常高。
因为文章开头就“谢绝”了群晖,所以群晖的 “Expansion Unit” 也自然就不在讨论之列了啦。(而且也更贵)
为什么没有选择网络硬盘盒
不论是采用 ARMbian 还是 OpenWRT 的“盒子”,只要硬件靠谱,稳定性都是靠谱的,而且普遍成本低廉,能效比也非常高。
之所以没有选择这个方案,主要的顾虑在硬件可靠性方面,包括三部分:散热、IO能力、供电。
盒子类的设备一般是被动散热,所以如果和硬盘“同处一室”,难以保证有合理的温度,我不想这个备份服务器出现“散装 Style”;盒子类的产品考虑能耗和成本,所以 CPU 相对孱弱,IO 能力自然也就比较弱,跑满硬盘 IO 带宽基本不可能;盒子类的产品供电是带不动多块硬盘的,所以需要独立供电,或者需要和前文提到的能够独立供电的硬盘阵列盒组合使用,容易出现“小马拉大车”的情况。
成品的盒子,几年前我也买过 WD My Cloud 和群晖早些时候的 ARM 产品,就传输效率体验来说,个人体验来说真的不算太好。
准备工作
理论结束,轮到实践啦。
我购置了上面这些硬件素材,分别有:
- 一台搭载了 CPU 的“准系统”,用于到手后测试“开箱即用”的测试主板和 CPU。
- 一台新款的 APC UPS。
- 4 根国产的光威 32G DDR4 内存。
- 2 块 4T 的西数紫盘,用于数据存储和数据校验。
- 一根国产的京造硬盘,用于存放操作系统,以及避免机械硬盘因为有程序运行无法休眠。
- 一些配件:数据线和硬盘螺丝。
成本总计 5000 出头,工作功耗 27 瓦左右,总的来说还是比较爽的。当然,你也可以省掉内存升级和固态硬盘的部分,只选购硬件和 UPS ,只需要 2000 出头。
主板的扩展性还不错,默认支持 3 块 SATA 硬盘和 2 块 NVMe 硬盘,4 根内存条,以及两个 PCI-e 插槽。完整的扩展能力,可以阅读上文中提到的“规格资料”。
BIOS 升级
机器到手后,推荐先做两件事,第一件是进入 BIOS ,重置选项为默认选项。第二件则是给机器插上网线,然后使用 BIOS 中的软件升级工具,将 BIOS 升级到最新,避免软件 BUG 和兼容性问题。
过程中,只有一点注意事项,不要断电,避免造成 BIOS 损坏。
插满内存
考虑到后续想在服务器上运行一些“空间换时间”的程序和虚拟机,我购置了 4 条 32G 的内存,减少分配资源时不必要的“小心翼翼”。
插上之后,进入 BIOS ,能够看到正常识别。不过想要确认硬件正常,只是看信息是不够的,还需要进行硬件测试。
硬件测试
测试硬件需要使用多种方式,如果你的 BIOS 中有测试工具,将能省不少事。
如果你不放心,可以多测试几次,以及使用 PE 或者在完成系统安装之后,使用测试工具进行更持续的测试。
当然,除了一次性测试之外,在使用之前还要进行一些必要的稳定性测试,在实际使用之前,这台设备我通电运行了一周,没有出现意外的异常。
系统的安装和配置
关于基础的系统安装、配置,可以参考这篇文章《在笔记本上搭建高性价比的 Linux 学习环境:基础篇》。
完成系统安装之后,我们还需要一些额外的配置,来让系统性能表现更好。
禁用 Swap
在 Ubuntu 中完全禁用和清理 Swap 需要三步,首先是关闭 Swap 功能:
sudo swapoff -a
接着,编辑分区表文件 /etc/fstab
,去掉 Swap 相关的记录。
然后,重启机器之后,删除掉“残余”文件即可。
rm -rf /swapfile
当你完成上面的动作之后,我们使用 free -g
查看系统资源,就能够看到 Swap 可用量变为零啦:
# free -g
total used free shared buff/cache available
Mem: 125 1 123 0 1 123
Swap: 0 0 0
创建 Raid 1 镜像阵列
先使用 mdadm --examine
来检查机械硬盘的状态,检查两块目标硬盘是否容量一致。
# sudo mdadm --examine /dev/sda /dev/sdb
/dev/sda:
MBR Magic : aa55
Partition[0] : 4294967295 sectors at 1 (type ee)
/dev/sdb:
MBR Magic : aa55
Partition[0] : 4294967295 sectors at 1 (type ee)
接着,使用 sgdisk -R
将两个磁盘的分区表进行一致化处理:
sudo sgdisk /dev/sda -R /dev/sdb
复制完分区表之后,需要对其中一个磁盘的分区 UUID 进行刷新,避免操作系统在使用的时候出现问题。
sudo sgdisk /dev/sdb -G
然后,使用 mdadm --create --level=mirror
创建次盘阵列:
# sudo mdadm --create /dev/md0 --level=mirror --raid-devices=2 /dev/sda /dev/sdb
mdadm: /dev/sda appears to be part of a raid array:
level=raid1 devices=2 ctime=Thu Jan 5 20:47:30 2023
mdadm: partition table exists on /dev/sda but will be lost or
meaningless after creating array
mdadm: Note: this array has metadata at the start and
may not be suitable as a boot device. If you plan to
store '/boot' on this device please ensure that
your boot-loader understands md/v1.x metadata, or use
--metadata=0.90
mdadm: partition table exists on /dev/sdb
mdadm: partition table exists on /dev/sdb but will be lost or
meaningless after creating array
Continue creating array?
Continue creating array? (y/n) y
mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.
创建磁盘阵列需要等待一些时间,完成时间和你够买的磁盘的容量,以及磁盘和主板的数据传输协议,以及你的设备 CPU 算力都有关系。
我们可以随时通过 cat /proc/mdstat
来检查阵列构建进度:
# cat /proc/mdstat
HP-EliteDesk-800-G6-Small-Form-Factor-PC: Thu Jan 5 21:50:56 2023
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md0 : active raid1 sdb[1] sda[0]
3906886464 blocks super 1.2 [2/2] [UU]
[=>...................] resync = 9.6% (375538432/3906886464) finish=325.5min speed=180783K/sec
bitmap: 28/30 pages [112KB], 65536KB chunk
unused devices: <none>
当阵列构建完成,我们再次检查 mdstat
的时候,能够看到类似下面的日志输出:
# sudo cat /proc/mdstat
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md0 : active raid1 sdb[1] sda[0]
3906886464 blocks super 1.2 [2/2] [UU]
bitmap: 0/30 pages [0KB], 65536KB chunk
unused devices: <none>
我们也可以使用 mdadm --detail
来查看阵列的详细信息:
# sudo mdadm --detail /dev/md0
/dev/md0:
Version : 1.2
Creation Time : Thu Jan 5 21:15:24 2023
Raid Level : raid1
Array Size : 3906886464 (3.64 TiB 4.00 TB)
Used Dev Size : 3906886464 (3.64 TiB 4.00 TB)
Raid Devices : 2
Total Devices : 2
Persistence : Superblock is persistent
Intent Bitmap : Internal
Update Time : Fri Jan 6 23:29:38 2023
State : clean
Active Devices : 2
Working Devices : 2
Failed Devices : 0
Spare Devices : 0
Consistency Policy : bitmap
Name : 0
UUID : bd87e586:257740d3:5fd50282:ccc8b145
Events : 6144
Number Major Minor RaidDevice State
0 8 0 0 active sync /dev/sda
1 8 16 1 active sync /dev/sdb
中止阵列创建过程
如果你在构建过程中,因为一些原因,想停止构建,可以使用 idle
来中止构建,或者使用 frozen
来临时暂停任务。
echo idle > /sys/block/md0/md/sync_action
echo frozen > /sys/block/md0/md/sync_action
如果你希望完全重新建立阵列,可以使用下面的命令来恢复阵列前的状态:
sudo mdadm -Esv
sudo mdadm --stop /dev/md*
在系统中使用磁盘阵列
完成阵列构建之后,想要使用磁盘阵列,首先得完成磁盘的挂载和磁盘的初始化(格式化)。
# sudo mkfs.ext4 /dev/md0
mke2fs 1.46.5 (30-Dec-2021)
Discarding device blocks: done
Creating filesystem with 976721616 4k blocks and 244187136 inodes
Filesystem UUID: f7014dd5-b7b1-466c-ae42-2b49c43cbb57
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
102400000, 214990848, 512000000, 550731776, 644972544
Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done
将磁盘手动挂载到 /data
这个路径,我们可以这样做:
sudo mkdir /data
sudo mount /dev/md0 /data
然后使用 df
来检查磁盘是否就绪:
# df -h /data
Filesystem Size Used Avail Use% Mounted on
/dev/md0 3.6T 28K 3.4T 1% /data
实际使用的时候,比如我们在这个分区上创建了一个文件后,磁盘会自动完成文件的镜像动作,提升文件的访问可靠性。
# touch /data/test.go
# sudo mdadm --examine /dev/sda /dev/sdb
/dev/sda:
Magic : a92b4efc
Version : 1.2
Feature Map : 0x1
Array UUID : bd87e586:257740d3:5fd50282:ccc8b145
Name : 0
Creation Time : Thu Jan 5 21:15:24 2023
Raid Level : raid1
Raid Devices : 2
Avail Dev Size : 7813772976 sectors (3.64 TiB 4.00 TB)
Array Size : 3906886464 KiB (3.64 TiB 4.00 TB)
Used Dev Size : 7813772928 sectors (3.64 TiB 4.00 TB)
Data Offset : 264192 sectors
Super Offset : 8 sectors
Unused Space : before=264112 sectors, after=48 sectors
State : clean
Device UUID : da33683e:54478a8b:cd6fd10e:1a19114c
Internal Bitmap : 8 sectors from superblock
Update Time : Fri Jan 6 23:29:14 2023
Bad Block Log : 512 entries available at offset 24 sectors
Checksum : 5ad089e9 - correct
Events : 6144
Device Role : Active device 0
Array State : AA ('A' == active, '.' == missing, 'R' == replacing)
/dev/sdb:
Magic : a92b4efc
Version : 1.2
Feature Map : 0x1
Array UUID : bd87e586:257740d3:5fd50282:ccc8b145
Name : 0
Creation Time : Thu Jan 5 21:15:24 2023
Raid Level : raid1
Raid Devices : 2
Avail Dev Size : 7813772976 sectors (3.64 TiB 4.00 TB)
Array Size : 3906886464 KiB (3.64 TiB 4.00 TB)
Used Dev Size : 7813772928 sectors (3.64 TiB 4.00 TB)
Data Offset : 264192 sectors
Super Offset : 8 sectors
Unused Space : before=264112 sectors, after=48 sectors
State : clean
Device UUID : 577ef05f:fa66ff02:8e4085c0:03d798ec
Internal Bitmap : 8 sectors from superblock
Update Time : Fri Jan 6 23:29:14 2023
Bad Block Log : 512 entries available at offset 24 sectors
Checksum : 460982b8 - correct
Events : 6144
Device Role : Active device 1
Array State : AA ('A' == active, '.' == missing, 'R' == replacing)
不过,上面手动挂载的磁盘,如果设备重启,将自动被释放。需要我们再次手动进行设备挂载。
想要解决这个问题,我们需要调整 fstab
中的内容,而 fstab 需要我们先获取阵列的“UUID”,以及更新 mdadm
的配置:
# sudo mdadm --detail --scan --verbose | sudo tee -a /etc/mdadm/mdadm.conf
ARRAY /dev/md0 level=raid1 num-devices=2 metadata=1.2 name=0 UUID=bd87e586:257740d3:5fd50282:ccc8b145
devices=/dev/sda,/dev/sdb
获取 UUID 需要使用下面的命令,而不能直接使用 mdadm
输出的 ID:
# sudo dumpe2fs /dev/md0 |grep UUID
dumpe2fs 1.46.5 (30-Dec-2021)
Filesystem UUID: f7014dd5-b7b1-466c-ae42-2b49c43cbb57
然后将下面的内容添加到 /etc/fstab
中:
UUID=f7014dd5-b7b1-466c-ae42-2b49c43cbb57 /dev/md0 /mnt/mirror ext4 defaults 0 0
搞定之后,更新 initramfs
,然后重启设备,检查系统是否能够在启动时,正常挂载阵列分区到 /data
路径即可。
# sudo update-initramfs -u
update-initramfs: Generating /boot/initrd.img-5.15.0-57-generic
安装文件服务
安装文件服务的方案有很多种,比如之前文章《装在笔记本里的私有云环境:网络存储篇(中)》提到的 S3 替代品 MinIO 或者 Syncthing、NextCloud。
不过,为了让 Mac 、Windows 设备能够直接“原生”使用服务,并完成备份,我们可以考虑选择使用 samba 或者 netatalk 提供 smb
或 afp
协议的文件访问能力。如果你希望直接使用本地的 samba 或者 netatalk 程序,直接使用 apt install
即可:
sudo apt-get install samba -y
如果你觉得这样做不够环保,使用 docker
版本的 samba 或者 netatalk 也未尝不可。比如,Stanback/alpine-samba。
当然,用户管理(增加、停用、删除、改密)可能比较麻烦,不过基本都是一次性成本,或许还好。(也可能,再单独展开一篇文章更为合适)
当我们完成服务启动之后,就能够再网络中找到这台“存储服务器”了。
以及使用 Samba 协议连接服务器。
接下来,如果你愿意的话,就可以直接使用系统自带的“时间机器”,来备份你的设备数据啦。
最后
因为最近比较忙,本篇文章“战线较长”大概经历了两周左右,过程中可能有一些疏漏,如果你有疑问或者建议,欢迎反馈。
下一篇文章中,我们来聊聊如何解决“管理资源”不方便的问题。
–EOF