mdadm RAID5 硬盘替换实战(无热备盘·关机更换)
上一篇讲了有 hot spare 的自动接管流程。这篇讲没有热备盘的情况——需要关机物理换盘,手动重建。
环境
- 虚拟机:VMware Workstation
- 系统:Ubuntu 22.04
- 阵列:3×20G RAID5,无热备盘(
--spare-devices=0)
- 存储栈:
1 2 3
| sda ─┐ sdb ─┼─ md0 (RAID5, 3盘, 无热备) → vg0 → lv-0 (ext4) → /data (40G) sdc ─┘
|
与有热备的核心区别
|
有热备(上篇) |
无热备/关机换盘(本篇) |
| 停机 |
不停机 |
必须关机 |
| 重建触发 |
热备盘自动接管 |
手动 mdadm --add |
| 开机后阵列状态 |
clean,重建中 |
degraded,新盘闲置 |
| 旧盘记录 |
mdadm 已标记 faulty |
需手动 --remove 清理 |
| 新盘 superblock |
不关心 |
必须 --zero-superblock |
| 冗余窗口 |
重建期间仍有单盘冗余 |
拔盘→重建完成前零冗余 |
完整流程
一、准备阶段
创建测试数据:
1 2 3
| dd if=/dev/urandom of=/data/test_100M.bin bs=1M count=100 echo "重要数据" > /data/important.txt md5sum /data/test_100M.bin /data/important.txt > /root/checksums_before.txt
|
二、关机前操作
这是最容易被忽略但最致命的一步——不做的后果就是重启 emergency mode。
1 2 3 4 5 6 7
| cp /etc/fstab /etc/fstab.bak.$(date +%Y%m%d) sed -i 's|^/dev.* /data |#&|' /etc/fstab
mdadm --detail /dev/md0 | grep -E 'Number|State|sd'
|
三、模拟故障
1 2 3 4 5 6 7 8 9
| mdadm --manage /dev/md0 --fail /dev/sdb
cat /proc/mdstat
shutdown -h now
|
四、物理更换硬盘
在 VMware 中移除故障的 sdb 虚拟磁盘,添加同规格新盘。
五、开机后重建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| lsblk -o NAME,SIZE,TYPE | grep disk
cat /proc/mdstat
mdadm --manage /dev/md0 --remove /dev/sdb
mdadm --zero-superblock /dev/sde
mdadm --manage /dev/md0 --add /dev/sde
cat /proc/mdstat
|
重建完成后的正常状态:
1 2 3 4
| mdadm --detail /dev/md0
|
六、验证数据完整性
1 2 3 4 5 6 7 8 9
| mount /dev/vg0/lv-0 /data df -h /data
cat /data/important.txt ls -lh /data/test_100M.bin
md5sum -c /root/checksums_before.txt
|
七、收尾
1 2 3
| vi /etc/fstab mount -a
|
⚠️ 关键风险:零冗余窗口
从拔掉故障盘到重建完成这段时间,阵列处于降级状态(degraded, 2/3):
1 2 3
| 故障 ─→ 降级 ─→ 关机 ─→ 换盘 ─→ 开机 ─→ 手动 add ─→ 重建中 ─→ clean ↑ ↑ 零冗余开始 零冗余结束
|
这段时间内再坏任意一块盘,数据全丢。 所以:
- 换盘操作要快,开完机立刻
--add
- 如果有条件,换盘前先备份最关键的数据
- 这就是为什么生产环境尽量配 hot spare
踩坑要点
| 编号 |
坑 |
解法 |
| 1 |
关机前忘注释 fstab |
重启必进 emergency mode,参考上篇的修复方法 |
| 2 |
新盘 superblock 未擦除 |
mdadm --add 时报 device or resource busy,必须 --zero-superblock |
| 3 |
旧盘记录未 remove |
新盘加入后显示 spare 而非 active sync,因为旧盘的 slot 还被占着 |
| 4 |
新盘设备名和老盘一样 |
如果新盘插回同一 SCSI 槽位,可能还是 /dev/sdb,直接用就行 |
| 5 |
重建期间性能下降 |
阵列可用但读写性能受影响,等重建完再跑重负载 |
命令速查
| 操作 |
命令 |
| 查看阵列状态 |
cat /proc/mdstat |
| 查看详情 |
mdadm --detail /dev/md0 |
| 标记故障 |
mdadm --manage /dev/md0 --fail /dev/sdX |
| 移除盘 |
mdadm --manage /dev/md0 --remove /dev/sdX |
| 添加盘 |
mdadm --manage /dev/md0 --add /dev/sdX |
| 擦除 superblock |
mdadm --zero-superblock /dev/sdX |
| 关机前注释 fstab |
sed -i 's|^/dev.* /data |#&|' /etc/fstab |
| 查看磁盘列表 |
lsblk -o NAME,SIZE,TYPE | grep disk |
查询命令汇总
日常巡检和排障时快速查看 RAID + LVM + 磁盘 全链路状态。
RAID 阵列
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| cat /proc/mdstat
mdadm --detail /dev/md0
mdadm --detail /dev/md0 | grep -E 'State|Active|Working|Failed|Spare|Rebuild'
mdadm --detail /dev/md0 | grep -A20 'Number.*Major'
mdadm --detail --scan
|
LVM
1 2 3 4 5 6 7 8 9
| pvs && pvdisplay
vgs && vgdisplay vg0
lvs && lvs -a -o name,size,segtype,devices,vg_name lvdisplay /dev/vg0/lv-0
|
磁盘
1 2 3 4 5 6 7 8 9 10 11
| lsblk -o NAME,SIZE,TYPE,MOUNTPOINT
lsblk -o NAME,SIZE,MODEL,SERIAL,TYPE
lsblk -f
fdisk -l /dev/sd[a-z] 2>/dev/null | grep -E 'Disk /dev|Disk model'
|
文件系统
1 2 3 4
| df -hT /data mount | grep /data grep data /etc/fstab blkid /dev/vg0/lv-0
|
故障排查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| dmesg | grep -iE 'sd[a-z]|md|fail|error|DID_NO_CONNECT|I/O error'
smartctl -a /dev/sda | grep -E 'Reallocated|Pending|Uncorrectable|Error'
echo check > /sys/block/md0/md/sync_action && cat /proc/mdstat
cat /sys/block/md0/md/sync_completed cat /sys/block/md0/md/sync_speed
cat /sys/block/md0/md/sync_action
|
一键巡检脚本
保存为 /root/check-storage.sh:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #!/bin/bash echo "===== RAID 状态 =====" cat /proc/mdstat echo "" echo "===== RAID 详情 =====" mdadm --detail /dev/md0 | grep -E 'State|Active|Working|Failed|Spare|Rebuild' echo "" echo "===== LVM =====" pvs && vgs && lvs echo "" echo "===== 磁盘 =====" lsblk -o NAME,SIZE,TYPE,MOUNTPOINT | grep -E 'sd|md|vg|nvme' echo "" echo "===== 挂载 =====" df -hT /data echo "" echo "===== 最近磁盘错误 =====" dmesg | grep -iE 'sd[a-z]|md|fail|error|DID_NO_CONNECT' | tail -10
|