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 软件 RAID
  • parted:创建 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 应为 PASSED
  • Reallocated_Sector_Ct 最好为 0
  • Current_Pending_Sector 应为 0
  • Offline_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文件系统块,结果为128
  • stripe-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,并完成了:

  1. 检查磁盘及 SMART 状态
  2. 清除各分区文件系统签名
  3. 清除整盘 GPT、MBR 分区表
  4. 创建新的 GPT RAID 分区
  5. 使用 mdadm 创建 RAID0
  6. 配置 mdadm 开机自动组装
  7. 创建 ext4 文件系统
  8. 通过文件系统 UUID 挂载到 /data
  9. 验证重启后的自动组装和挂载
  10. 使用 YABS 测试随机混合读写
  11. 使用 fio 测试纯顺序读写

本次阵列顺序读取约883MB/s,顺序写入约881MB/s,符合4块企业级机械硬盘 RAID0 的预期性能。

需要再次强调:RAID0只提升容量和吞吐性能,不提供数据安全保障。任意一块成员盘损坏,都可能导致整个阵列不可用,因此重要数据必须保存在独立设备或远程备份中。


说明

免责声明与版权声明

本文内容由个人发布,仅用于学习、技术研究与经验交流。

文中涉及的软件(包括正版及第三方版本)仅供测试与学习用途,不构成任何形式的分发、破解、商业使用或侵权行为的鼓励。若您需要长期使用或商业部署,请前往官方网站购买或获取正版授权。

作者不对任何软件的使用、修改、传播及由此产生的后果承担法律责任。读者应自行判断、下载与使用软件,并遵守所在地法律法规及相关许可协议。

部分内容参考或摘录自公开资料、官方文档或其他技术文章,均已尽可能注明原作者及来源链接。若原作者或版权方认为本文存在不当引用或侵权内容,请联系作者处理,作者将在核实后及时修改或删除相关内容。


知识共享许可声明

除特别说明外,本文中的原创文字、图片、图表及资料均依据:

CC BY-NC-SA 4.0(署名-非商业性使用-相同方式共享)

许可协议发布。

您可以在遵守本协议的前提下:

  • 复制、转载和分享本文内容;
  • 对本文内容进行修改、改编和二次创作;
  • 将本文内容用于个人学习、研究和非商业用途。

同时必须满足以下条件:

  • 保留原作者署名及原文链接;
  • 明确标注内容来源;
  • 不得将本文及其衍生作品用于任何商业用途;
  • 基于本文进行修改、改编或再创作的作品,必须继续采用相同协议进行发布。

特别声明

未经作者书面授权,禁止以下行为:

  • 将本文原创内容用于商业培训、付费课程、付费社群、收费咨询等商业活动;
  • 将本文原创内容转载至以盈利为目的的网站、平台、出版物或知识付费平台;
  • 将本文原创内容批量采集、镜像、聚合或作为数据库内容进行商业运营;
  • 将本文原创内容用于人工智能模型训练、知识库构建、数据集整理或其他商业化用途;
  • 删除、修改或隐藏原作者署名、原文链接及版权声明。

对于违反上述声明的行为,作者保留依法追究相关责任的权利。


AI 辅助生成声明

本文部分内容在撰写、整理、润色或结构优化过程中使用了 AI 工具进行辅助生成。

AI 生成内容仅作为写作辅助参考,最终内容已由作者进行人工审阅、修改、校对与确认。本文观点、技术步骤、命令示例及相关说明均以作者最终发布版本为准。

读者在参考本文内容进行实际操作前,应结合自身环境进行验证,作者不因 AI 辅助生成内容可能存在的遗漏、错误或不适用情况承担额外责任。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐