每台服务器 不限流量、DDoS 防护和 IPMI 全部包含。无开通费,无长期合约。 每台服务器均不限流量 查看价格

指南 · 存储

用 mdadm 在 NVMe 上配置软 RAID 1

在 NVMe 服务器上检查、创建、监控和修复 mdadm RAID 1 与 RAID 10,分步更换故障硬盘,并通过 UEFI 让两块盘都可引导。

  • 阅读 7 分钟
  • 更新于
  • FlexDedi 工程团队

本指南推荐配置

Storage 264

  • AMD EPYC 4565P · 16 核
  • 128 GB DDR5 ECC
  • 12 × 22 TB HDD + 3.84 TB NVMe
  • 25 Gbps,不限流量

$699/月

本页内容

Linux 软 RAID(即由 mdadm 管理的内核 md 驱动)是在独立服务器上为 NVMe 硬盘做镜像的标准方式。它是主线内核的一部分,无需特殊驱动即可引导,只需消耗少量 CPU 时间,省去了 RAID 控制卡。本指南介绍何时选用 RAID 1 或 RAID 10、如何检查和创建阵列、如何监控阵列,以及如何在不影响引导的前提下更换故障的 NVMe 硬盘。

文中命令适用于 Ubuntu 24.04 和 Debian 12/13,均以 root 身份运行。在 AlmaLinux 和 Rocky Linux 上,配置文件为 /etc/mdadm.conf,并使用 dracut -f 重建 initramfs。

RAID 1 还是 RAID 10

硬盘数级别可用容量可容忍的故障FlexDedi 示例
2RAID 1一块硬盘一块硬盘故障Core 16、Core 16X、Pro 32、Pro 48、GPU 服务器
4RAID 10两块硬盘每个镜像对一块硬盘故障Pro 64、Max 96、Max 192

RAID 1 会把每个数据块同时写入两块硬盘,读取时可以从任意一块读取,有利于并行读;写入速度与单块硬盘相当。RAID 10 在两个镜像之间做条带化,因此四块硬盘的可用容量是双盘镜像的两倍,写入吞吐量也更高。校验型 RAID(5 或 6)能提供更多容量,但会增加写入开销,重建时间也很长,所以对于运行在四块 NVMe 硬盘上的数据库和虚拟机,通常选择 RAID 10。

RAID 0 没有冗余,只适合存放临时数据。任何 RAID 级别都不能替代备份:RAID 只能防范硬盘损坏,防不了 rm -rf、软件写入的数据损坏或主机被入侵。

如果你运行的是 Proxmox VE,请改用它自带的 ZFS 镜像,因为 Proxmox 不支持 mdadm;参见在独立服务器上安装 Proxmox VE。

检查安装程序创建的阵列

包括 Debian 和 Ubuntu 在内的安装程序,都可以在安装过程中创建 md 阵列。在做任何更改之前,先弄清楚系统中已有哪些阵列:

bash
cat /proc/mdstat
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS
mdadm --detail /dev/md0

健康的镜像阵列看起来是这样的:

text
Personalities : [raid1]
md0 : active raid1 nvme1n1p2[1] nvme0n1p2[0]
      3749557248 blocks super 1.2 [2/2] [UU]
      bitmap: 1/28 pages [4KB], 65536KB chunk

[2/2] [UU] 表示有两个成员,且都在正常运行。[2/1] 加上 [U_] 或 [_U] 表示阵列已降级,标记为 (F) 的成员已经故障。重建期间,recovery = 这一行会显示进度和预计完成时间。

接着检查服务器的引导方式。UEFI 固件无法读取默认元数据格式的 md 阵列,因此 EFI 系统分区(ESP)位于 RAID 之外。安装程序通常会在每块硬盘上都创建一个 ESP,但只挂载并写入其中一个,挂载点为 /boot/efi:

bash
lsblk -o NAME,SIZE,PARTTYPENAME,MOUNTPOINTS
efibootmgr -v

如果只有一块硬盘上有写入了内容的 ESP 和引导项,那么这块硬盘一旦损坏,服务器就无法启动。下文「让两块硬盘都能引导」一节会解决这个问题。

创建阵列

在新服务器上,最省事的做法是让安装程序创建 RAID 1。如果要自己创建阵列,例如在四盘服务器的两块空闲硬盘上创建数据阵列,请使用 Linux RAID 类型的分区而不是整块磁盘,并在磁盘末尾留出一点空间,这样即使替换硬盘的扇区数略少,也依然放得下:

bash
sgdisk --zap-all /dev/nvme2n1
sgdisk -n 1:0:-100M -t 1:FD00 /dev/nvme2n1
sgdisk --replicate=/dev/nvme3n1 /dev/nvme2n1
sgdisk --randomize-guids /dev/nvme3n1

mdadm --create /dev/md1 --level=1 --raid-devices=2 --bitmap=internal \
  /dev/nvme2n1p1 /dev/nvme3n1p1

对于 RAID 10,用同样的方法为四块硬盘分区,并以四个分区配合 --level=10 --raid-devices=4 创建阵列。写意图位图(write-intent bitmap)让阵列在崩溃或某个成员短暂缺失之后,只需重新同步发生了变化的区域。

创建文件系统,按 UUID 挂载,并记录阵列信息,使其在启动时以相同的名称组装:

bash
mkfs.ext4 /dev/md1
mkdir -p /srv/data
echo "UUID=$(blkid -s UUID -o value /dev/md1) /srv/data ext4 defaults,nofail 0 2" >> /etc/fstab
systemctl daemon-reload && mount /srv/data

mdadm --detail --scan | grep /dev/md1 >> /etc/mdadm/mdadm.conf
update-initramfs -u

阵列创建后即可使用,初始同步会在后台进行;可以用 watch -n 5 cat /proc/mdstat 跟踪进度。

监控阵列

悄无声息降级的镜像,其实就是一块随时可能坏掉的单盘,所以一定要确保有告警能通知到你。

mdadm --monitor

Debian 和 Ubuntu 以 mdmonitor 服务的形式运行 mdadm --monitor。它会把 Fail、DegradedArray 等事件报告给 /etc/mdadm/mdadm.conf 中 MAILADDR 设置的地址,这需要服务器上有可用的邮件传输代理(MTA)。如果服务器无法发送邮件,可以添加一行 PROGRAM,改为运行你指定的可执行程序。mdadm 会把事件名称、阵列以及相关的成员设备(如有)传给它,足以推送到聊天工具或告警呼叫的 Webhook。

text
MAILADDR root
PROGRAM /usr/local/sbin/md-alert

编辑文件后重启服务,然后确认告警确实能够送达。第二条命令会为每个阵列发送一个 TestMessage 事件:

bash
systemctl restart mdmonitor && systemctl status mdmonitor
mdadm --monitor --scan --test --oneshot

定期检查与指标

Debian 和 Ubuntu 还会定期对 md 阵列执行一致性检查。你也可以手动启动一次检查,并在完成后查看结果:

bash
echo check > /sys/block/md0/md/sync_action
cat /sys/block/md0/md/mismatch_cnt

如果你使用 Prometheus,node exporter 的 mdadm 采集器会暴露 node_md_disks{state="failed"} 指标;只要该值大于零就应告警。同时也要监控硬盘本身,因为 smartd 和 nvme smart-log 往往能在硬盘故障之前发出预警。两者在 Linux 安全基线中都有介绍。

更换故障的 NVMe 硬盘

一块硬盘故障后,阵列会依靠剩下的那块继续运行。请尽快更换:在重建完成之前,再坏一块硬盘,数据就会丢失。

1. 通过序列号识别硬盘

nvme0、nvme1 这类 NVMe 设备名是在启动时分配的,可能发生变化,因此要通过序列号识别故障硬盘,绝不能只看设备名:

bash
mdadm --detail /dev/md0             # which member is faulty or removed
nvme list                           # device, model and serial number
ls -l /dev/disk/by-id/ | grep nvme  # serial-based names for each device

2. 将其从所有阵列中移除

如果这块硬盘的分区分属多个阵列(例如根分区和交换分区),要逐一将其标记为故障并移除:

bash
mdadm --manage /dev/md0 --fail /dev/nvme1n1p2 --remove /dev/nvme1n1p2

如果该设备已经消失,用 mdadm /dev/md0 --remove detached 清除失效的条目。

3. 申请更换硬盘

向技术支持提交工单,并注明故障硬盘和健康硬盘的序列号,以免换错硬盘。FlexDedi 在每个机房都备有现场备件。请预留一个维护窗口,以防更换过程中需要断电重启。

4. 将分区表复制到新硬盘

更换完成后,用 lsblk 和 nvme list 确认哪个设备是新的空白硬盘。然后从健康硬盘复制分区布局:

bash
sgdisk --replicate=/dev/nvme1n1 /dev/nvme0n1   # new drive first, healthy drive last
sgdisk --randomize-guids /dev/nvme1n1

5. 重新加入阵列并重建

bash
mdadm --manage /dev/md0 --add /dev/nvme1n1p2
watch -n 5 cat /proc/mdstat

重建速度受 dev.raid.speed_limit_min 和 dev.raid.speed_limit_max 限制,通常分别为 1,000 和 200,000 KB/s;可以用 sysctl dev.raid 查看你的设置。以约 200 MB/s 的速度重建一个 3.84 TB 的镜像,大约需要五个小时(估算:3,840,000 MB ÷ 200 MB/s ≈ 5.3 小时)。NVMe 硬盘的速度可以快得多,因此提高上限能缩短阵列暴露在风险中的时间,代价是会占用运行中业务的一部分 I/O:

bash
sysctl -w dev.raid.speed_limit_max=2000000

6. 让新硬盘可以引导

新硬盘上的 ESP 是空的。请先删除 /etc/fstab 中引用旧 ESP UUID 的条目,再按照下一节的说明重新创建 ESP。

让两块硬盘都能引导

仅仅镜像根文件系统还不够:如果存放活动 ESP 的硬盘损坏,固件必须能在另一块硬盘上找到引导加载程序。在 UEFI 系统上,需要格式化第二个 ESP、复制文件并注册一个引导项。请先查看 /boot/efi/EFI/ 下的目录名,例如 debian 或 ubuntu:

bash
mkfs.vfat -F 32 /dev/nvme1n1p1
mkdir -p /boot/efi2
echo "UUID=$(blkid -s UUID -o value /dev/nvme1n1p1) /boot/efi2 vfat umask=0077,nofail 0 1" >> /etc/fstab
systemctl daemon-reload && mount /boot/efi2
cp -r /boot/efi/. /boot/efi2/
efibootmgr --create --disk /dev/nvme1n1 --part 1 --label "debian disk 2" --loader '\EFI\debian\shimx64.efi'

GRUB 和 shim 更新只会写入第一个 ESP,因此每次更新后都要重新复制。用一个 APT 钩子即可自动完成:

bash
cat > /etc/apt/apt.conf.d/99-sync-esp <<'EOF'
DPkg::Post-Invoke { "if mountpoint -q /boot/efi2; then cp -r /boot/efi/. /boot/efi2/; fi"; };
EOF

在 Ubuntu 上,也可以改用 dpkg-reconfigure grub-efi-amd64 注册多个 ESP,让 GRUB 安装到所有 ESP 上。在传统 BIOS 系统上,dpkg-reconfigure grub-pc 可以让你同时选择两块硬盘。请在维护窗口内通过 KVM 控制台,在固件启动菜单中选择第二块硬盘,测试配置是否生效。

md RAID 上的 TRIM

RAID 1 和 RAID 10 会把 discard(TRIM)请求透传给成员硬盘,有助于 NVMe 保持写入性能并控制磨损。先确认 discard 请求能够到达阵列,然后使用定期运行的 fstrim 定时器,而不要使用 discard 挂载选项,因为后者会在每次删除时都发出 TRIM:

bash
lsblk --discard /dev/md0   # non-zero DISC-GRAN and DISC-MAX mean TRIM works
systemctl enable --now fstrim.timer
fstrim -av

这样做有一个副作用:如果硬盘对已 TRIM 的块不返回全零,之后的一致性检查可能会针对没有任何文件系统使用的空间,报告非零的 mismatch_cnt。nvme id-ns -H /dev/nvme0n1 可以显示硬盘读取已释放块时的行为。TRIM 之后出现少量且稳定的不一致计数,本身并不意味着数据损坏;但如果在繁忙的阵列上该计数持续增长,就值得深入调查。

在 FlexDedi 上运行

FlexDedi 的每台服务器都至少配备两块 NVMe 硬盘,可组建 RAID 1,例如 Core 16($299/月)配备 2 × 1.92 TB Gen4,Pro 32($749/月)配备 2 × 3.84 TB Gen5。如需 RAID 10,Pro 64($1,349/月)配备 4 × 3.84 TB Gen5,可用容量 7.68 TB;Max 96($1,899/月)配备 4 × 7.68 TB,可用容量 15.36 TB。如果更换硬盘后服务器无法启动,可以通过 KVM 控制台和救援模式进行修复,替换硬盘则直接取自现场备件。

更多指南

你的下一台服务器,几分钟后就能上线。

以 $299/月 部署一台 Core 16,或请我们的工程师为你量身规划服务器集群。

  • 无开通费
  • 不限流量
  • 随时取消