Ubuntu 26.04 使用 mdadm 组建四盘软件 RAID0(软 RAID)完整实战:磁盘清理、ext4 格式化、UUID 自动挂载及 YABS/fio 性能测试
Ubuntu 26.04 使用 mdadm 组建四盘 RAID0:UUID 自动挂载与 fio 性能测试
本文记录在 Ubuntu 26.04 LTS 中,使用4块4TB机械硬盘创建软件 RAID0 的完整过程,包括:
- 检查磁盘及 SMART 状态
- 清除各分区的文件系统签名
- 清除整盘分区表
- 创建 GPT 分区和 RAID0
- 格式化为 ext4
- 使用文件系统 UUID 自动挂载到
/data - 配置 mdadm 开机自动组装
- 使用 YABS 测试混合读写性能
- 使用 fio 手动测试顺序读写性能
一、环境说明
服务器磁盘情况如下:
NAME SIZE MODEL 用途
sda 3.6T HGST HUS726T4TAL RAID0成员盘
sdb 3.6T HGST HUS726T4TAL RAID0成员盘
sdc 3.6T HGST HUS726T4TAL RAID0成员盘
sdd 3.6T HGST HUS726T4TAL RAID0成员盘
nvme0n1 476.9G WDC CL SN720 SDAQNTW-512G-2000 系统盘
最终配置:
RAID设备:/dev/md0
RAID级别:RAID0
成员数量:4
条带大小:512KiB
文件系统:ext4
挂载目录:/data
阵列容量:14.55TiB,约16TB
RAID0没有任何数据冗余。任意一块成员盘损坏,都可能导致整个阵列的数据丢失。重要数据必须另行备份。
本文中的清除和格式化命令会破坏目标磁盘上的原有文件,执行前必须确认磁盘名称,避免误操作系统盘。
二、安装所需工具
apt update
apt install -y mdadm parted smartmontools fio curl sysstat
主要工具作用如下:
mdadm:创建和管理 Linux 软件 RAIDparted:创建 GPT 分区表和磁盘分区smartmontools:读取硬盘 SMART 健康信息fio:测试磁盘 I/O 性能curl:下载 YABS 脚本sysstat:提供iostat等磁盘监控命令
三、确认目标磁盘
首先查看磁盘型号、容量和序列号:
lsblk -d -o NAME,SIZE,MODEL,SERIAL
本次确认的4块成员盘为:
/dev/sda V6HE7H9S
/dev/sdb V6GP92NS
/dev/sdc V6GN81KS
/dev/sdd V6H483LS
系统盘为:
/dev/nvme0n1
后续任何清除、分区和 RAID 创建命令都不能包含系统盘。
继续查看磁盘原有文件系统和挂载状态:
lsblk -o NAME,SIZE,TYPE,FSTYPE,UUID,MOUNTPOINTS
如果目标磁盘原来有分区处于挂载状态,需要先停止使用并卸载。例如:
umount /dev/sda1
如果提示设备正忙,可以查看占用进程:
fuser -vm /dev/sda1
如果磁盘原来属于其他 RAID、LVM、LUKS 或被用作 Swap,也必须先停止或停用对应设备。
四、检查机械硬盘 SMART 状态
创建 RAID0 前,建议先检查成员盘健康状态:
for disk in /dev/sda /dev/sdb /dev/sdc /dev/sdd; do
echo "===== $disk ====="
smartctl -H "$disk"
smartctl -A "$disk" |
grep -E 'Reallocated_Sector|Current_Pending_Sector|Offline_Uncorrectable|Power_On_Hours'
done
重点关注:
SMART overall-health应为PASSEDReallocated_Sector_Ct最好为0Current_Pending_Sector应为0Offline_Uncorrectable应为0
本次4块硬盘以上关键项目均为0,SMART总体状态为 PASSED。
SMART正常不代表硬盘绝对不会损坏,特别是 RAID0 没有容错,因此仍然需要独立备份。
五、清除原文件系统签名和整盘分区表
这里采用的是“快速逻辑清空”,不会对整块硬盘执行全盘写零。
它会清除:
- 文件系统签名
- 旧 RAID 签名
- LVM、LUKS 等可识别签名
- GPT、MBR 分区表
原来的文件将无法正常访问,但未被新数据覆盖前,仍可能被专业工具恢复。
5.1 清除各分区的文件系统签名
先自动找出4块磁盘上的现有分区,再清除分区签名:
for disk in /dev/sda /dev/sdb /dev/sdc /dev/sdd; do
while read -r part; do
echo "清除分区签名:$part"
wipefs -a "$part"
done < <(
lsblk -lnpo NAME,TYPE "$disk" |
awk '$2 == "part" {print $1}'
)
done
wipefs -a 只清除文件系统、RAID、LVM等结构的识别签名,不会像全盘写零一样覆盖所有数据扇区。
如果磁盘没有分区,这一步不会产生实际操作。
5.2 清除整盘分区表
接着清除整盘上的 GPT、MBR 等分区表签名:
for disk in /dev/sda /dev/sdb /dev/sdc /dev/sdd; do
echo "清除整盘分区表:$disk"
wipefs -a "$disk"
done
让内核重新读取磁盘状态:
partprobe
udevadm settle
检查:
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS
此时4块硬盘应当没有分区、文件系统和挂载点。
还可以使用只读方式检查是否存在可识别签名:
for disk in /dev/sda /dev/sdb /dev/sdc /dev/sdd; do
echo "===== $disk ====="
wipefs -n "$disk"
done
wipefs -n 只检查,不执行修改。
六、创建 GPT 分区
为每块硬盘创建 GPT 分区表,并建立一个占满整盘的 RAID 分区:
for disk in /dev/sda /dev/sdb /dev/sdc /dev/sdd; do
parted -s "$disk" mklabel gpt
parted -s "$disk" mkpart primary 1MiB 100%
parted -s "$disk" set 1 raid on
done
从 1MiB 开始分区可以保证常见硬盘扇区和 RAID 条带对齐。
重新读取分区表:
partprobe
udevadm settle
检查结果:
lsblk -o NAME,SIZE,TYPE,FSTYPE,PARTTYPENAME
预期结构如下:
sda
└─sda1 Linux RAID
sdb
└─sdb1 Linux RAID
sdc
└─sdc1 Linux RAID
sdd
└─sdd1 Linux RAID
七、创建 RAID0
使用4个分区创建 /dev/md0,条带大小设置为512KiB:
mdadm --create /dev/md0 \
--level=0 \
--raid-devices=4 \
--chunk=512K \
/dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1
参数说明:
--level=0:创建 RAID0--raid-devices=4:使用4个成员设备--chunk=512K:单盘条带块大小为512KiB/dev/sda1~/dev/sdd1:阵列成员分区
如果出现确认提示,确认设备无误后输入:
yes
RAID0不需要像 RAID1、RAID5 那样执行数据同步,因此创建后即可使用。
检查阵列:
cat /proc/mdstat
mdadm --detail /dev/md0
正常状态应包含:
Raid Level : raid0
State : clean
Active Devices : 4
Working Devices : 4
Failed Devices : 0
Chunk Size : 512K
本次创建后的容量为:
14.55TiB,约16.00TB
八、配置 mdadm 开机自动组装
先查看阵列扫描结果:
mdadm --detail --scan
输出类似:
ARRAY /dev/md0 metadata=1.2 UUID=b035c5fe:8a7777ad:d579eb19:364caa63
备份现有配置:
cp -a /etc/mdadm/mdadm.conf \
/etc/mdadm/mdadm.conf.bak.$(date +%Y%m%d-%H%M%S)
将 /dev/md0 的阵列信息写入配置,并避免重复添加:
ARRAY_LINE="$(mdadm --detail --scan | grep '^ARRAY /dev/md0 ')"
grep -qxF "$ARRAY_LINE" /etc/mdadm/mdadm.conf ||
printf '%s\n' "$ARRAY_LINE" >> /etc/mdadm/mdadm.conf
检查:
cat /etc/mdadm/mdadm.conf
更新 initramfs,使系统启动阶段能够读取最新的 mdadm 配置:
update-initramfs -u
九、格式化为 ext4
将 /dev/md0 格式化为 ext4:
mkfs.ext4 \
-L data \
-m 0 \
-E stride=128,stripe-width=512 \
/dev/md0
参数说明:
-L data:设置文件系统标签为data-m 0:不为 root 预留默认的5%空间stride=128:512KiB条带除以4KiB文件系统块,结果为128stripe-width=512:128乘以4块成员盘,结果为512
对于约16TB的数据盘,如果保留默认5%,会占用大量空间,因此这里设置为0。该参数更适合专用数据盘,不建议直接套用到系统根分区。
格式化完成后检查:
lsblk -f /dev/md0
blkid /dev/md0
这里会生成一个新的 ext4 文件系统 UUID。它与 mdadm --detail 中显示的 RAID UUID不是同一个 UUID。
十、使用 UUID 挂载到 /data
创建挂载目录:
mkdir -p /data
获取 ext4 文件系统 UUID:
blkid -s UUID -o value /dev/md0
备份 /etc/fstab:
cp -a /etc/fstab \
/etc/fstab.bak.$(date +%Y%m%d-%H%M%S)
编辑:
nano /etc/fstab
在文件末尾添加:
UUID=实际的文件系统UUID /data ext4 defaults,nofail,x-systemd.device-timeout=30s 0 2
参数说明:
defaults:使用默认挂载参数nofail:阵列异常时允许系统继续启动,适合远程服务器x-systemd.device-timeout=30s:启动时最多等待设备30秒0 2:关闭 dump,并将文件系统检查顺序设置为2
检查配置语法:
findmnt --verify --verbose
重新加载 systemd 并测试挂载:
systemctl daemon-reload
mount -a
确认挂载结果:
findmnt /data
df -hT /data
lsblk -f
正常情况下应看到:
TARGET SOURCE FSTYPE OPTIONS
/data /dev/md0 ext4 rw,relatime,stripe=512
容量信息类似:
Filesystem Type Size Used Avail Use% Mounted on
/dev/md0 ext4 15T 2.1M 15T 1% /data
如果应用程序不是以 root 用户运行,需要根据实际服务调整目录所有者。例如交给 ubuntu 用户使用:
chown ubuntu:ubuntu /data
chmod 755 /data
不建议直接使用 chmod 777。
十一、重启验证
确认 mount -a 没有报错后重启:
reboot
重启后检查:
cat /proc/mdstat
mdadm --detail /dev/md0
findmnt /data
df -hT /data
如果阵列状态为 clean,4块成员盘均为 active sync,并且 /data 已挂载到 /dev/md0,说明自动组装和 UUID 自动挂载均已生效。
十二、使用 YABS 测试 RAID0
YABS 项目地址:
https://github.com/masonr/yet-another-bench-script
YABS 会在“当前工作目录”创建临时测试文件,因此必须确保脚本运行目录位于 /data。
如果直接在 /root 或用户家目录运行,测试到的会是系统盘,而不是 RAID0。
12.1 下载脚本
根据服务器访问 GitHub 的情况,从下面两种方式中选择一种即可。
方式一:不使用代理
服务器可以正常访问 GitHub Raw 时,直接下载:
curl -fL \
"https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/yabs.sh" \
-o /tmp/yabs.sh
chmod +x /tmp/yabs.sh
方式二:使用 gh-proxy.com 代理
如果服务器访问 GitHub Raw 较慢或无法连接,可以通过 gh-proxy.com 下载:
curl -fL \
"https://gh-proxy.com/https://raw.githubusercontent.com/masonr/yet-another-bench-script/master/yabs.sh" \
-o /tmp/yabs-gh-proxy.sh
下载完成后,将脚本内部可能访问的 GitHub Raw 地址也替换为代理地址:
sed -i \
's#https://raw.githubusercontent.com/#https://gh-proxy.com/https://raw.githubusercontent.com/#g' \
/tmp/yabs-gh-proxy.sh
chmod +x /tmp/yabs-gh-proxy.sh
这不仅通过代理下载 YABS 脚本,也可以让脚本运行过程中可能发生的 GitHub Raw 文件下载经过代理。
由于前面已经安装了 Ubuntu 软件仓库中的 fio,YABS通常会直接使用本机的 fio,不再下载预编译版本。不过代理方式仍然保留了脚本内部 GitHub Raw 地址的加速处理。
12.2 执行 RAID0 磁盘测试
YABS会在当前工作目录中创建临时测试文件,因此必须先进入 /data。根据前面选择的下载方式,执行对应命令。
方式一:不使用代理测试
如果下载的是无代理版本,执行:
(
cd /data &&
echo "测试目录:$PWD" &&
findmnt -T . &&
/tmp/yabs.sh -ign
) | tee /root/yabs-raid0-$(date +%Y%m%d-%H%M%S).log
方式二:使用代理测试
如果下载的是代理版本,执行:
(
cd /data &&
echo "测试目录:$PWD" &&
findmnt -T . &&
/tmp/yabs-gh-proxy.sh -ign
) | tee /root/yabs-raid0-$(date +%Y%m%d-%H%M%S).log
此时运行的是已经将内部 GitHub Raw 地址替换为 gh-proxy.com 的代理版本。
参数说明:
-i:跳过 iperf3 网络测试-g:跳过 Geekbench-n:跳过公网网络信息查询tee:在终端显示结果,同时保存到/root下的日志文件
不要使用 -f 或 -d,因为这两个参数会关闭 fio 磁盘测试。
无论是否使用代理,测试结果标题都必须显示:
fio Disk Speed Tests (Mixed R/W 50/50) (Partition /dev/md0):
如果显示:
Partition /dev/nvme0n1p3
说明脚本是在系统盘目录下运行,测试到的是 NVMe 系统盘,而不是挂载在 /data 的 RAID0。
12.3 本次 YABS 测试结果
Block Size | 4k (IOPS) | 64k (IOPS)
Read | 6.32 MB/s (1.5k) | 68.53 MB/s (1.0k)
Write | 6.31 MB/s (1.5k) | 68.91 MB/s (1.0k)
Total | 12.64 MB/s (3.0k) | 137.44 MB/s (2.0k)
Block Size | 512k (IOPS) | 1m (IOPS)
Read | 243.78 MB/s (464) | 274.32 MB/s (261)
Write | 256.73 MB/s (489) | 292.59 MB/s (279)
Total | 500.52 MB/s (953) | 566.91 MB/s (540)
YABS采用50%读取、50%写入的随机混合测试,因此结果不能直接等同于纯顺序读写峰值。
对于机械硬盘:
- 4K随机读写较低属于正常现象
- 512K和1M大块混合读写更能体现 RAID0 的并行吞吐能力
- YABS使用较高队列深度和较小测试文件,不能代表所有实际业务负载
测试期间可以在另一个 SSH 窗口观察成员盘负载:
iostat -dx 1 /dev/sda /dev/sdb /dev/sdc /dev/sdd /dev/md0
十三、使用 fio 手动测试顺序性能
为了测试 RAID0 的纯顺序读写性能,在 /data 中创建一个64GiB测试文件。
测试文件大于服务器的15.5GiB内存,同时使用 direct=1 绕过系统页缓存,可以减少内存缓存对结果的影响。
13.1 顺序写入测试
fio \
--name=seq-write \
--filename=/data/fio-seq-test.bin \
--size=64G \
--rw=write \
--bs=1M \
--ioengine=libaio \
--iodepth=32 \
--direct=1 \
--numjobs=1 \
--group_reporting
主要参数:
--size=64G:测试文件大小为64GiB--rw=write:顺序写入--bs=1M:单次I/O块大小为1MiB--iodepth=32:同时保持32个I/O请求--direct=1:使用Direct I/O,减少页缓存影响--group_reporting:合并显示测试结果
本次顺序写入结果:
WRITE: bw=840MiB/s (881MB/s)
io=64.0GiB
run=78005msec
err=0
13.2 顺序读取测试
写入完成后,使用同一个文件测试读取:
fio \
--name=seq-read \
--filename=/data/fio-seq-test.bin \
--size=64G \
--rw=read \
--bs=1M \
--ioengine=libaio \
--iodepth=32 \
--direct=1 \
--numjobs=1 \
--group_reporting
本次顺序读取结果:
READ: bw=842MiB/s (883MB/s)
io=64.0GiB
run=77789msec
err=0
顺序读写结果汇总:
| 测试项目 | 阵列速度 | 平均到单盘 |
|---|---|---|
| 顺序写入 | 840MiB/s,约881MB/s | 约210MiB/s |
| 顺序读取 | 842MiB/s,约883MB/s | 约210MiB/s |
4块成员盘的读写量基本一致,测试中没有出现 I/O 错误、短读写或请求丢失,说明阵列负载分配正常。
当前阵列几乎为空,64GiB文件大概率位于机械盘外圈,因此测试结果接近最佳状态。随着磁盘逐渐写满,机械盘内圈的顺序速度通常会有所下降。
13.3 删除测试文件
测试完成后删除64GiB文件:
rm -f /data/fio-seq-test.bin
sync
df -hT /data
不要将 fio 的 --filename 设置为 /dev/md0。直接对 /dev/md0 进行写测试会破坏 ext4 文件系统和现有数据。
十四、日常检查命令
查看 RAID 状态:
cat /proc/mdstat
mdadm --detail /dev/md0
查看挂载情况:
findmnt /data
df -hT /data
查看磁盘 SMART 状态:
for disk in /dev/sda /dev/sdb /dev/sdc /dev/sdd; do
echo "===== $disk ====="
smartctl -H "$disk"
done
查看实时磁盘负载:
iostat -dx 1 /dev/sda /dev/sdb /dev/sdc /dev/sdd /dev/md0
十五、总结
本文在 Ubuntu 26.04 LTS 中使用4块4TB机械硬盘创建了一个约14.55TiB的 RAID0,并完成了:
- 检查磁盘及 SMART 状态
- 清除各分区文件系统签名
- 清除整盘 GPT、MBR 分区表
- 创建新的 GPT RAID 分区
- 使用 mdadm 创建 RAID0
- 配置 mdadm 开机自动组装
- 创建 ext4 文件系统
- 通过文件系统 UUID 挂载到
/data - 验证重启后的自动组装和挂载
- 使用 YABS 测试随机混合读写
- 使用 fio 测试纯顺序读写
本次阵列顺序读取约883MB/s,顺序写入约881MB/s,符合4块企业级机械硬盘 RAID0 的预期性能。
需要再次强调:RAID0只提升容量和吞吐性能,不提供数据安全保障。任意一块成员盘损坏,都可能导致整个阵列不可用,因此重要数据必须保存在独立设备或远程备份中。
说明
免责声明与版权声明
本文内容由个人发布,仅用于学习、技术研究与经验交流。
文中涉及的软件(包括正版及第三方版本)仅供测试与学习用途,不构成任何形式的分发、破解、商业使用或侵权行为的鼓励。若您需要长期使用或商业部署,请前往官方网站购买或获取正版授权。
作者不对任何软件的使用、修改、传播及由此产生的后果承担法律责任。读者应自行判断、下载与使用软件,并遵守所在地法律法规及相关许可协议。
部分内容参考或摘录自公开资料、官方文档或其他技术文章,均已尽可能注明原作者及来源链接。若原作者或版权方认为本文存在不当引用或侵权内容,请联系作者处理,作者将在核实后及时修改或删除相关内容。
知识共享许可声明
除特别说明外,本文中的原创文字、图片、图表及资料均依据:
CC BY-NC-SA 4.0(署名-非商业性使用-相同方式共享)
许可协议发布。
您可以在遵守本协议的前提下:
- 复制、转载和分享本文内容;
- 对本文内容进行修改、改编和二次创作;
- 将本文内容用于个人学习、研究和非商业用途。
同时必须满足以下条件:
- 保留原作者署名及原文链接;
- 明确标注内容来源;
- 不得将本文及其衍生作品用于任何商业用途;
- 基于本文进行修改、改编或再创作的作品,必须继续采用相同协议进行发布。
特别声明
未经作者书面授权,禁止以下行为:
- 将本文原创内容用于商业培训、付费课程、付费社群、收费咨询等商业活动;
- 将本文原创内容转载至以盈利为目的的网站、平台、出版物或知识付费平台;
- 将本文原创内容批量采集、镜像、聚合或作为数据库内容进行商业运营;
- 将本文原创内容用于人工智能模型训练、知识库构建、数据集整理或其他商业化用途;
- 删除、修改或隐藏原作者署名、原文链接及版权声明。
对于违反上述声明的行为,作者保留依法追究相关责任的权利。
AI 辅助生成声明
本文部分内容在撰写、整理、润色或结构优化过程中使用了 AI 工具进行辅助生成。
AI 生成内容仅作为写作辅助参考,最终内容已由作者进行人工审阅、修改、校对与确认。本文观点、技术步骤、命令示例及相关说明均以作者最终发布版本为准。
读者在参考本文内容进行实际操作前,应结合自身环境进行验证,作者不因 AI 辅助生成内容可能存在的遗漏、错误或不适用情况承担额外责任。
更多推荐
所有评论(0)