Linux RAID 软阵列实战:mdadm 创建、故障替换与数据重建


为什么要在 VPS 上做软 RAID

很多站长以为 RAID 是机房高端硬件才有的东西,其实 Linux 内核自带 md(Multiple Device)驱动,用 mdadm 工具就能把多块云硬盘组成软阵列。对于数据量大、又不想依赖商家快照的 VPS,软 RAID 是性价比最高的冗余方案:两块盘做 RAID1,坏一块不影响服务;三块盘做 RAID5,容量只损失一块盘。软阵列不依赖特定硬件,换机器后只要把盘挂回去用 mdadm 重新组装即可。

本文全程基于 Ubuntu 22.04 / Debian 12 演示,CentOS/RHEL 系命令几乎一致,仅有安装和 initramfs 更新命令不同,文中会单独标注。

RAID 级别怎么选:0 / 1 / 5 / 10

先明确各级别的容量与冗余特性,再动手,避免建错阵列浪费磁盘:

级别   最少盘数   可用容量           冗余能力        典型用途
RAID0  2         N 块之和           无,坏一块全丢    纯性能需求,不建议存数据
RAID1  2         总容量的一半        镜像,坏一块可读   系统盘、数据库数据目录
RAID5  3         (N-1) 块之和       允许坏一块        性价比最高的容量+冗余
RAID10 4         总容量的一半        允许每组坏一块     性能与冗余兼顾,盘多时首选

VPS 上的通用建议:

数据盘数量=2  -> RAID1
数据盘数量=3  -> RAID5
数据盘数量=4+ -> RAID10 或 RAID5 加一块热备盘

需要说明的是,云服务商的"数据盘"通常是虚拟磁盘,单盘 IOPS 有限,RAID 主要解决的是可用性而非性能叠加,写入性能甚至略降,这是正常现象。

环境准备:安装 mdadm 与磁盘规划

先安装工具,Debian/Ubuntu 与 CentOS 命令如下:

# Debian / Ubuntu
apt update && apt install -y mdadm

# CentOS / Rocky / AlmaLinux
dnf install -y mdadm

然后用 lsblk 看清盘符,确认要组阵列的磁盘上没有数据(组阵列会抹掉盘上内容):

lsblk
fdisk -l | grep -E '^Disk /dev'

# 示例输出
# NAME   MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
# sda      8:0    0  40G  0 disk
# sdb      8:16   0  20G  0 disk
# sdc      8:32   0  20G  0 disk

如果磁盘是二手盘或曾经加入过其他阵列,先清掉残留的 superblock 与分区表,否则 mdadm 会报错拒绝创建:

mdadm --zero-superblock /dev/sdb /dev/sdc
wipefs -a /dev/sdb /dev/sdc

创建 RAID1 镜像阵列

以两块 20G 盘 sdb、sdc 组建 RAID1,元数据版本用 1.2(内核可自动识别):

mdadm --create /dev/md0 --level=1 --raid-devices=2 --metadata=1.2 /dev/sdb /dev/sdc

创建完成后立即查看状态,resync 正在后台同步,此时阵列可用但未完成镜像:

cat /proc/mdstat

# Personalities : [raid1]
# md0 : active raid1 sdc[1] sdb[0]
#       20948992 blocks super 1.2 [2/2] [UU]
#       [=>...................]  resync =  7.3% (1540608/20948992) finish=2.1min speed=163000K/sec

[UU] 表示两块盘都正常,resync 完成后即可建文件系统挂载:

mkfs.ext4 /dev/md0
mkdir -p /data
mount /dev/md0 /data
df -h /data

查看阵列详细信息,后面排错经常用到:

mdadm --detail /dev/md0

创建 RAID5 与 RAID10 阵列

三块盘建 RAID5,-c 指定 chunk 大小(典型值 128K,适合大文件与数据库):

mdadm --create /dev/md1 --level=5 --raid-devices=3 --chunk=128 --metadata=1.2 /dev/sdd /dev/sde /dev/sdf

四块盘建 RAID10,外镜像内条带,兼顾性能与容错:

mdadm --create /dev/md2 --level=10 --raid-devices=4 --metadata=1.2 /dev/sdg /dev/sdh /dev/sdi /dev/sdj

建议在创建时顺便指定一个名字并预留热备盘,热备盘平时空转,阵列坏盘时自动顶上:

mdadm --create /dev/md1 --name=raid5_data --level=5 --raid-devices=3 --spare-devices=1 \
  --chunk=128 /dev/sdd /dev/sde /dev/sdf /dev/sdg

# 查看热备盘状态
cat /proc/mdstat

让阵列开机自动组装

软阵列是"按需组装"的,重启后必须告诉内核哪些盘组成哪个阵列。先生成配置:

mdadm --detail --scan

# ARRAY /dev/md0 metadata=1.2 name=xxx:0 UUID=xxxxxxxx:xxxx:xxxx:xxxx

mdadm --detail --scan | tee /etc/mdadm/mdadm.conf

注意 Debian/Ubuntu 配置文件路径是 /etc/mdadm/mdadm.conf,CentOS 是 /etc/mdadm.conf。生成后用 --examine 兜底补充:

mdadm --examine --scan >> /etc/mdadm/mdadm.conf

关键一步:把配置打进 initramfs,否则重启时引导阶段无法识别阵列:

# Debian / Ubuntu
update-initramfs -u

# CentOS / Rocky
dracut --force

最后写 /etc/fstab 开机自动挂载。强烈建议用 UUID 而不是 /dev/mdX,因为 mdX 编号重启后可能变化:

blkid /dev/md0
# /dev/md0: UUID="a1b2c3d4-...." TYPE="ext4"

# /etc/fstab 追加一行
UUID=a1b2c3d4-....  /data  ext4  defaults,noatime  0 2

改完 fstab 后建议用 mount -a 验证语法无误再重启。

模拟磁盘故障:fail / remove / add 热替换

RAID 的价值在故障时体现。模拟 sdc 盘损坏(实际生产中是磁盘硬件告警或 I/O 错误):

# 手动把盘标记为故障
mdadm /dev/md0 --fail /dev/sdc

# 查看状态,出现 [U_] 表示降级运行
cat /proc/mdstat
# md0 : active raid1 sdc[2](F) sdb[0]
#       20948992 blocks super 1.2 [2/1] [U_]

# 从阵列中摘除故障盘
mdadm /dev/md0 --remove /dev/sdc

降级期间阵列只靠 sdb 一块盘撑着,数据读写正常,但任何一块再坏就全丢,应尽快更换。更换新盘后重新加入,自动开始重建:

# 新盘先清理再添加
wipefs -a /dev/sdc
mdadm /dev/md0 --add /dev/sdc

# 观察重建进度
cat /proc/mdstat
# [=>...................]  resync = 15.2% ...

如果创建时配置了热备盘(spare),故障盘被摘除后热备盘会自动接管重建,无需人工干预,这是生产环境的标准姿势。

重建监控与速度调优

重建会占用大量 IO,默认限速可能让重建跑几个小时。可动态调整:

# 调高重建限速(单位 KB/s)
echo 100000 > /proc/sys/dev/raid/speed_limit_min
echo 200000 > /proc/sys/dev/raid/speed_limit_max

实时盯着进度:

watch -n 5 cat /proc/mdstat

也可以一次性查看,等 [UU] 恢复即可:

mdadm --detail /dev/md0 | grep -E 'State|resync'

想要故障第一时间邮件/脚本通知,可用 mdadm 的监控模式常驻:

mdadm --monitor --daemonize --mail=admin@example.com /dev/md0

在线扩容:新增成员盘与 grow

RAID5 扩容非常常用:云控制台加一块新盘后,先加入阵列再扩展成员数,最后扩大文件系统,全程在线:

# 1. 加入新盘
mdadm /dev/md1 --add /dev/sdg

# 2. 把阵列从 3 块盘扩展为 4 块盘(RAID5 自动触发 reshaping)
mdadm --grow /dev/md1 --raid-devices=4

# 3. 扩展文件系统,ext4 在线即可
resize2fs /dev/md1
df -h /dev/md1

RAID1 也可以扩容,方法是先 --grow --raid-devices 增加镜像份数再转换级别(如 RAID1 转 RAID5),操作复杂且耗时,新手建议直接规划好盘数。扩容期间阵列 IO 性能明显下降,业务高峰期别做。

排错手册:常见错误与处理方法

下面是实践中最高频的几个坑,按症状给出处理方案:

1. mdadm: /dev/sdc is busy 或 contains a filesystem
   - 该盘被分区表或旧数据占用:wipefs -a /dev/sdc 后重试
   - 若已被系统挂载:先 umount

2. 创建时报 superblock 残留
   - 旧盘残留 RAID 元数据:mdadm --zero-superblock /dev/sdb /dev/sdc

3. 重启后阵列不自动组装
   - mdadm.conf 未生成或 initramfs 未更新
   - 手动验证:mdadm --detail --scan 与 /etc/mdadm.conf 内容一致
   - Debian 系务必 update-initramfs -u

4. 阵列编号变成 md127
   - 重启后编号漂移属正常,mdadm.conf 里用 name/UUID 固定
   - 手动装配:mdadm --assemble --scan

5. 降级阵列无法启动,提示 not enough devices
   - 少一块盘时用手动装配并指定盘:mdadm --assemble --run /dev/md0 /dev/sdb

6. 重建速度极慢
   - 按上文调高 /proc/sys/dev/raid/speed_limit_min

7. 挂载报 unknown filesystem
   - 先看 cat /proc/mdstat 确认阵列处于 active 而非 degraded 太狠
   - RAID5/RAID10 连续坏盘数超过容错上限时阵列会停止,先换盘重建

最后提醒:RAID 不是备份。阵列冗余只防"盘坏了",不防"手滑删了/商家跑路/机房烧了",重要数据务必配合 mdadm 阵列之上的快照或异地备份,三层防护才睡得着觉。


手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

Linux 硬盘健康检测实战:SMART 体检、坏道排查与数据提前预警

端口转发与SSH隧道实战:Nginx stream、iptables DNAT与内网穿透

评 论
更换验证码