Linux 软件 RAID:从 mdadm 创建阵列到磁盘故障自动重建
本文要点
- 软件 RAID 由内核
md模块实现,命令行入口是mdadm,把多块磁盘组合成一个块设备(如/dev/md0),对上层应用完全透明 - RAID1 即"镜像",最少 2 块盘、每块都保留完整副本,成本是容量减半;查看实时状态统一读
/proc/mdstat - 创建命令
mdadm --create --level=1 --raid-devices=2 --spare-devices=1可以先配好热备盘,趁盘没坏先"备"一手 - 磁盘损坏时用
mdadm --fail标记故障,热备盘会自动顶替并在后台重建数据,期间阵列降级但服务不中断、数据依然可读写 - 换新盘走
mdadm --remove移除故障盘 +mdadm --add加入新盘;把mdadm --detail --scan的结果写入/etc/mdadm.conf即可实现开机自动装配
单块磁盘上的数据,总是怕两件事:盘坏(高可用)和容量不够(扩容)。RAID(独立磁盘冗余阵列)把多块物理盘组合成一个逻辑设备,从而换来信赖:某个盘坏了,数据不丢,系统照跑——这就是本文要演示的软件 RAID。它不需要专用 RAID 卡,用的只是 Linux 内核自带的 md 模块和 mdadm 这个命令。
这里在一台演示机上完整跑一遍 RAID1 的生命周期:从准备磁盘、创建阵列,到格式化挂载、模拟坏盘、热备自动重建,再到换新盘收尾。全程使用镜像文件 + loop 设备模拟真实磁盘,任何一台 Linux 机器上都能照着复现,不会碰你真正的数据盘。
一、软 RAID 与 mdadm 是什么
Linux 的软件 RAID 分两层:
- 内核
md模块:负责真正的数据冗余计算与分发,把多块磁盘(成员盘)虚拟成一个块设备,比如/dev/md0。应用和文件系统只会看到/dev/md0这一个设备,完全不知道底下有好几块盘。 - 用户态
mdadm:管理工具,负责创建阵列、增减成员盘、标记故障、查询状态等一切运维操作。
选择软件 RAID 的理由很实在:零硬件成本(免去专用 RAID 卡)、任意 Linux 都能用、可以用 loop 设备/分区把任意多块盘组合起来。代价是 RAID0/5/6 这类带校验计算会占用少量 CPU,但对现代 CPU 来说几乎可以忽略。
先看一下系统里支持哪些 RAID 级别。装好 mdadm 后,/proc/mdstat 顶部的 personalities(模式)那行会列出来:
$ apt install -y mdadm
$ cat /proc/mdstat
Personalities : [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
md0 : ....raid0 / raid1 / raid6 / raid5 / raid4 / raid10 就是内核支持的全部类型。这几年最常打交道的四种,先建个直觉:
| 级别 | 冗余能力 | 最少盘数 | 可用容量 | 一句话说明 |
|---|---|---|---|---|
| RAID0 | 无 | 2 块 | 全部 | 条带化,追求速度与容量,坏一块全没 |
| RAID1 | 坏 1 块 | 2 块 | 一半 | 镜像,每块盘都有完整副本,最稳 |
| RAID5 | 坏 1 块 | 3 块 | N-1 | 分布式校验,容量与冗余的平衡 |
| RAID6 | 坏 2 块 | 4 块 | N-2 | 双校验,专治大容量/重建期二次故障 |
| RAID10 | 每对镜像坏 1 块 | 4 块 | 一半 | 镜像 + 条带,性能与冗余兼得 |
本文实操的 RAID1 是个人/小服务器最常用的方案:两块镜像盘,任何一块坏了读出数据都完整。
二、准备工作:用镜像文件模拟磁盘
真实机房里有的是物理磁盘,演示机只有一块系统盘,不能真拿它去组阵列。好在 md 支持任意块设备,我们可以用"文件"配合 loop 设备模拟出三块大小一样的"磁盘"——这也是整个实验可以安全复现的关键。
# 建立实验目录
mkdir -p /root/raidlab
# 生成 3 个 2G 的镜像文件,分别扮演 disk1/disk2/disk3
for i in 1 2 3; do
dd if=/dev/zero of=/root/raidlab/disk$i.img bs=1M count=2048 status=none
l=$(losetup -f) # 找到下一个空闲的 loop 设备
losetup "$l" /root/raidlab/disk$i.img
echo "$l -> disk$i.img"
done执行后会看到三个 /dev/loop12/13/14 依次出现:
/dev/loop12 -> disk1.img
/dev/loop13 -> disk2.img
/dev/loop14 -> disk3.img
total 6.1G
-rw-r--r-- 1 root root 2.0G Aug 26 08:03 disk1.img
-rw-r--r-- 1 root root 2.0G Aug 26 08:03 disk2.img
-rw-r--r-- 1 root root 2.0G Aug 26 08:03 disk3.imglosetup -f 会自动挑选未被占用的 loop 设备号,losetup 设备 文件 把文件关联成块设备。到这一步,/dev/loop12、/dev/loop13、/dev/loop14 就等价于三块 2GB 的"裸盘",可以直接交给 md。
真实环境没有这一步:把上面的/dev/loop12/13/14替换成你的真实磁盘名(如/dev/sdb /dev/sdc /dev/sdd)即可,其余命令基本一字不改。
三、创建 RAID1 阵列
mdadm 创建阵列用 --create。关键参数:--level=1 指 RAID1,--raid-devices=2 指 2 块数据成员盘,--spare-devices=1 指额外配 1 块热备盘(平时闲置,哪块盘坏了立刻顶上)。三个盘位正好对应我们准备好的三块"磁盘":
echo y | mdadm --create /dev/md0 \
--level=1 --raid-devices=2 --spare-devices=1 \
/dev/loop12 /dev/loop13 /dev/loop14输出里有几行需要解释:
mdadm: Note: this array has metadata at the start and
may not be suitable as a boot device. ...
Continue creating array? mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.Continue creating array?是创建前的交互确认,我们用了echo y |自动应答;Defaulting to version 1.2 metadata:mdadm 在磁盘上写元数据(superblock)记录阵列信息,默认 1.2 版本(写在磁盘开头)。后面的警告只是提醒"带 1.2 元数据的盘不适合作/boot引导盘",对你的数据盘没有影响。
阵列启动后,内核会立刻在成员盘之间做一次初次同步(resync),把 RAID1 的两块盘内容对齐。此时 cat /proc/mdstat 能看到同步进度:
md0 : active raid1 loop14[2](S) loop13[1] loop12[0]
2094080 blocks super 1.2 [2/2] [UU]
[=>...................] resync = 6.2% (130944/2094080) finish=0.2min speed=130944K/secmd0 : active raid1 说明阵列已激活;loop14[2](S) 里 (S) 是 spare(热备)标记;[2/2] [UU] 表示 2 块成员盘中 2 块在线(U=Up,_=Down/Failed)。resync 完成后 [UU] 前会变成空。
初次同步一般只需要数十秒,用 mdadm --wait /dev/md0 阻塞等待它跑完。之后用 mdadm --detail 查看阵列的完整信息:
mdadm --wait /dev/md0
mdadm --detail /dev/md0
图中值得读的几行:
Raid Level : raid1、Array Size : 2094080(约 2045 MiB):2 块 2G 盘组成的镜像阵列,总容量 2045 MiB —— RAID1 的容量 = 单块盘容量;Raid Devices : 2、Total Devices : 3:阵列由 2 块数据盘 + 1 块热备盘构成;State : active、Active Devices : 2、Failed Devices : 0、Spare Devices : 1:健康状态,2 正常 + 1 热备;- 最下面的盘位表看得更直白:
loop12、loop13是active sync(在线同步中),loop14是spare。
四、格式化、挂载、写入数据
阵列创建好后就是一个普普通通的块设备,接下来和用一块新硬盘没有任何区别:格式化文件系统 → 挂载 → 读写。
mkfs.ext4 /dev/md0
mkdir -p /mnt/raid
mount /dev/md0 /mnt/raid
# 写入一个测试文件,作为"珍贵数据"
echo "hello-from-raid1 $(date)" > /mnt/raid/test.txt
cat /mnt/raid/test.txt
df -h /mnt/raid输出确认文件系统可用:
/dev/md0 2.0G 28K 1.9G 1% /mnt/raid这个 test.txt 会一直放在里面,等会儿制造故障时它就是检验"数据有没有丢"的试金石。
五、模拟磁盘故障:热备盘自动顶替
真实的 RAID1 价值体现在坏盘那一刻。我们把 loop13(第二块数据盘)模拟成"突然损坏",用 mdadm --fail 标记故障:
mdadm --fail /dev/md0 /dev/loop13 && cat /proc/mdstat标记磁盘故障后阵列立即降级为 [2/1](https://blog.astarry.cn/usr/uploads/2026/08/354642304.png)
两处关键变化:
md0 : active raid1 loop14[2](S) loop13[1](F) loop12[0],loop13[1](F)中(F)= Failed,故障盘被标记;[2/1] [U_]中[2/1]表示"2 块数据盘配额、当前 1 块在线",[U_]中_就是坏掉的那块盘的位置。阵列状态为 degraded(降级)。
心跳到顶点:RAID1 现在只剩 loop12 一块好盘在扛,但这正是它设计上的容错时刻——降级不是宕机,数据仍在分毫不差。此时验证一下测试文件:
$ cat /mnt/raid/test.txt
hello-from-raid1 Wed Aug 26 08:04:21 CST 2026数据完好。更妙的是,这不是故事的终点:阵列里还躺着一块闲置的 loop14 热备盘,内核检测到成员盘故障后,会自动把热备盘拉起来顶替,然后把 loop12 上的数据镜像到 loop14 上。整个过程不需要任何人干预。观察 /proc/mdstat:
cat /proc/mdstat
此时 loop14[2] 已经不再是 (S)(spare),它变成了活动成员,正在执行 recovery:
md0 : active raid1 loop14[2] loop13[1](F) loop12[0]
2094080 blocks super 1.2 [2/2] [UU]
[=============>.......] recovery = 68.7% (1440384/2094080)recovery = 68.7%、finish=0.0min、speed=130944K/sec:热备盘正在以约 128MB/s 的速度后台同步,同步完成后阵列自动回到 [UU] 全绿状态。一次磁盘故障,全程零数据丢失、零人工介入——这就是 RAID1 配热备的核心价值。
重建期间阵列仍处于降级状态。对 RAID5/6 来说,这个窗口期是风险最高的时刻(再坏一块就整个阵列报废),所以盘坏了要尽快换新盘。
六、更换新盘:移除故障盘、加入新盘
热备盘虽然顶上了,但阵列的冗余储备用光了。正确做法是:把故障盘从阵列里正式移除,再用一块新盘补充进去,恢复"2 块数据盘 + 1 块热备"的完整配置。
# 1) 把故障盘从阵列中移除
mdadm --remove /dev/md0 /dev/loop13
# 2) 准备一块新的"磁盘"(真实环境这里是一块插进服务器的新物理盘)
dd if=/dev/zero of=/root/raidlab/disk4.img bs=1M count=2048 status=none
l=$(losetup -f)
losetup "$l" /root/raidlab/disk4.img
# 3) 把新盘加入阵列,它会被自动安排为热备
mdadm --add /dev/md0 "$l"移除与加入的输出都很干净:
mdadm: hot removed /dev/loop13 from /dev/md0
mdadm: added /dev/loop15mdadm --remove 把 loop13 温柔地逐出;mdadm --add 把新盘 loop15 加进阵列。再次查看阵列详情确认台账:
mdadm --detail /dev/md0
最终状态图说明一切:
State : clean:阵列完全健康;Active Devices : 2:两块数据盘在线(loop12、loop14,后者正是刚才从热备转正的盘);Spare Devices : 1:新加入的loop15重新成为热备,冗余储备已回满。
至此,一次完整的 RAID1 "损坏 → 自愈 → 换新"生命周期闭环了。数据从头到尾没掉过一根汗毛。
七、开机自动装配与其它常用管理命令
阵列不是魔法,重启后内核需要重新认识它。要想开机自动把成员盘重新合成 /dev/md0,两步:
# 1) 把阵列定义写入 mdadm 的配置文件
mdadm --detail --scan | tee -a /etc/mdadm.conf
# 2) 顺便把挂载写进 fstab,开机自动挂载(用 UUID 更稳)
# /dev/md0 /mnt/raid ext4 defaults 0 2mdadm --detail --scan 输出的就是一条 ARRAY 记录,包含元数据版本、设备名和 UUID,mdadm 靠它在机器重启后凭 UUID 认领成员盘并恢复阵列。/etc/mdadm.conf 里的样子大致是:
ARRAY /dev/md0 metadata=1.2 name=demo:0 UUID=6dd9a1d1:a7b390c3:f7423365:... 常用管理命令再汇总一张速查表:
| 命令 | 作用 |
|---|---|
mdadm --detail /dev/md0 | 查看阵列完整状态(成员盘、健康度、容量) |
cat /proc/mdstat | 快速瞄一眼阵列状态与重建进度 |
mdadm --fail /dev/md0 /dev/sdX | 标记某块盘故障,触发热备顶替 |
mdadm --remove /dev/md0 /dev/sdX | 把(故障)盘从阵列移除 |
mdadm --add /dev/md0 /dev/sdX | 加入一块新盘(自动成为热备) |
mdadm --stop /dev/md0 | 停用阵列(先 umount 挂载点) |
mdadm --zero-superblock /dev/sdX | 抹掉盘上的 md 元数据,归还为普通盘 |
八、小结
把这一趟实验串起来看:mdadm --create 建阵列 → mkfs/mount 当普通盘用 → mdadm --fail 模拟坏盘 → 热备自动顶替并 recovery → mdadm --remove/--add 换新盘。RAID1 的关键设计就一句话:任何时候都保留一份完整的镜像副本,系统级的故障由一块热备盘在后台悄悄修复,而你的应用程序毫无感知。
选型上给个简单结论:只要你能接受容量减半,RAID1 是最划算的默认选择,两块盘保平安;追求大容量和低成本用 RAID5(3 块起),数据更重要就上 RAID6 或 RAID10。对大多数单机小服务,一片由 mdadm 拉的 RAID1,比一块裸盘踏实得多。
进一步阅读:
评论 (0)
暂无评论,快来抢沙发吧!