虚拟机中演练RAID与LVM:mdadm建阵列、降级恢复与在线扩容
2026/9/18 4:05:19 网站建设 项目流程

虚拟机里跑RAID这件事,我第一次听到也觉得有点脱裤子放屁——物理磁盘才会坏,镜像才有意义,在虚拟化环境里模拟阵列图啥?这个判断在我带新人、又在生产环境里连续处理过两次阵列降级之后,彻底被推翻了。真正的价值不在于"我能不能把阵列建起来",而在于能不能在没有硬件报废风险、没有业务停机压力的前提下,把RAID0/1/5/10的区别、mdadm的各种报错、LVM叠在阵列之上后的每一步扩容都亲手趟一遍。等你在VMware里把四块虚拟盘从裸盘一路搭到带LVM逻辑卷、能在线扩容、能模拟掉盘重建,再去碰机房里的真机器,心态完全不一样。

这篇就按我自己的操作顺序来:先在虚拟机里把盘挂上,算清楚每种级别需要几块盘、能扛几块坏,再用mdadm把四种阵列各建一遍,最后把LVM压在阵列上走一遍分层设计和在线扩容。中间那些文档里不写、但实际一定会遇到的坑,我尽量写全——包括虚拟机特有的"性能失真"预警,别让你拿虚拟机的测速结果去拍生产环境的容量预算。

1. 为什么我坚持先在虚拟机里把 RAID 跑一遍再碰真机

先讲个挺典型的场景。前两年有个朋友的公司买了两台存储稍好的服务器,四块SAS盘,计划做RAID5。工程师到现场直接开机进阵列卡配置界面,凭感觉选了几块盘、点了确定,结果把系统盘也圈进去了,重做了一遍。第二次又因为没注意条带大小,重建后性能不达标,被要求推倒重来。前后耽误了两天。这类事故里,真正的技术难点其实没有,全是"没练过手"造成的。如果提前在虚拟机里把整个流程走过一遍,这种低级错误基本可以避免。

虚拟机做阵列最大的好处,是把"不可逆操作"变成了"可回滚操作"。物理机上mdadm --create一旦落下,盘上的数据就没了,建错了只能擦掉重来;而在虚拟机里,动手之前给虚拟机拍一个快照,建错了、参数写歪了、把阵列搞成未知状态了,回滚回去接着试。这种近乎零成本的试错空间,是学习阵列和卷管理最宝贵的东西——你可以故意把一块盘标记为故障,看降级的表现,再把它加回去看重建过程,整个过程物理盘一颗没浪费。

还有一个很多人忽略的点:虚拟机让"多盘环境"变得廉价。要做RAID5,至少得凑够三块盘;做RAID10,至少四块,而且最好成对增加。手边要真凑出四块独立物理盘不容易,但在VMware里加四块20G的虚拟盘,五分钟的事。你要测RAID6、测三盘镜像,也就是多加几块盘的功夫。这种"盘不要钱"的便利,让你能把注意力放在阵列逻辑本身,而不是纠结硬件资源。

不过虚拟机的局限也必须说清楚,否则容易误判。虚拟磁盘的底层是宿主机上的一个或几个文件,它的I/O路径多了一层文件系统甚至多层,读写缓存也不是真实的盘缓存。这意味着两件事:第一,延迟和吞吐的绝对值没有参考意义,你别拿虚拟机里的顺序读速去评估真实服务器的性能;第二,缓存刷写行为被宿主层改写,某些掉电一致性的现象你在虚拟机里根本复现不出来。所以我后面在讲性能测试时,会反复强调一点——虚拟机里看趋势可以,看绝对值不行。

这套练习适合谁?我把人群分三类:完全没碰过阵列的运维新人,可以把这里当成从零到一的手册;做过单盘LVM但没和阵列组合过的开发或测试同学,第二、第五节正好补上RAID+LVM叠加那块;还有一类是准备去机房实操、想先彩排一遍的老手,第六节的故障演练和第七节的失真预警,能帮你把预期校准好。不管你属于哪类,我建议全程用一台可以随便折腾的虚拟机,快照多拍几个,别心疼。

2. 四块盘不够分的困局:先算清楚 RAID0/1/5/10 的磁盘账

动手之前必须先算账,这是我见过最多人跳过、也是踩坑最狠的一步。所谓算账,就是搞清楚每种RAID级别最少要几块盘、几块盘能坏、可用容量是总容量的百分之多少。这三件事没算清楚,盘加少了建不起来,盘加错了容量和容错和你预期完全对不上。

先看最小盘数。RAID0至少要两块,少了没意义,因为它就是单纯的条带化,把数据切成块轮流写到多块盘上;RAID1最少两块,互为镜像;RAID5最少三块,因为要有一块盘的容量用来存校验数据,而且是分布在所有盘上的;RAID10最少四块,因为它是先镜像再条带,两层结构决定了它得凑够成对的盘。这四条如果记不住,就记住一句话:0要2、1要2、5要3、10要4

再算容量和容错,我习惯用下面这张表,直接照着对。假设你有四块同样大小的盘,每块记为S:

级别最少盘数可用容量(四块盘)可容忍损坏盘数一句话本质
RAID024S(100%)0只提速,不保命
RAID122S(50%)1(双盘镜像)用一半容量换安全
RAID533S(75%,四盘时)1容量和安全的折中
RAID1042S(50%)视坏盘位置,通常1到2又快又能扛,最费盘

这张表里有几个点特别容易搞错。第一,RAID5的可用容量是(N-1)×S,四块盘就是三块盘的容量,你加第四块盘,容量是增加一块,但容错始终是"任意坏一块"。第二,RAID10的容错不是简单的"坏两块没事",它的容错取决于坏的是哪两块。如果是分属不同镜像组的两块盘,通常没问题,阵列还能跑;如果坏的是同一个镜像对里的两块,那一组就彻底没了。所以严格的RAID10容错,保证的是"每组至少剩一块",真要坏两块还能活,得看你运气。第三,RAID0容量最大但容错为零,任何一块盘挂了,整个阵列的数据全部作废,不是丢一部分,是全部。

算完账再决定盘的大小。这里有个虚拟机特有的做法值得说:四块测试盘不要都建成一样大,至少故意留一块或两块大小不同。为什么?因为真实运维里"给阵列换盘"的场景太常见了,而换进去的盘往往和原来的不完全一样大。阵列重建时,替换盘不能小于故障盘,否则加不进去。你在虚拟机里故意制造一次"盘大小不一致"的对比,就能把这个规则记得死死的。当然,正式演练最重要的四种级别,建议还是用同规格的盘,先把标准流程跑通,再加变量。

最后提一句命名。虚拟机加盘之后,Linux里通常按顺序识别成/dev/sdb/dev/sdc/dev/sdd……但这个顺序不是永恒不变的,插拔、重启、控制器变动都可能让盘符变化。所以从建阵列开始,就要养成用/dev/disk/by-id/下稳定路径的习惯,或者至少每次操作前lsblk确认一遍,别拿着昨天的盘符去建今天的阵列——把系统盘当数据盘干掉的事故,多半都是这么来的。

3. VMware 里挂多块虚拟磁盘的那几个容易踩的设置项

算好盘就动手挂盘。这一步看着简单,但有几个设置项一旦选错,后面要么性能差得离谱,要么阵列行为诡异。我按操作顺序说,边做边解释为什么。

第一步,先关机再加盘。热添加在部分版本和配置下是支持的,但对练习来说没必要冒这个险,关机状态下加盘最干净。打开虚拟机的设置,找到"添加",选"硬盘",然后跟着向导走。关键的分叉点出现在"磁盘类型"和"新虚拟磁盘/现有磁盘"这两处:练习用新虚拟磁盘就行,大小我一般给20G,够建阵列、够格式化、也够做几次扩容演示。

第二步,SCSI控制器的选择。VMware Workstation里,虚拟磁盘默认挂在某个SCSI控制器下,你可以选不同类型的控制器,比如LSI Logic SAS、LSI Logic并行、或半虚拟化控制器。这里的选择会影响Linux里看到的设备名和驱动行为。我自己的习惯是:如果不确定,就用默认的LSI Logic SAS,兼容性最好,Linux各发行版都能直接识别。半虚拟化控制器(PVSCSI)性能更好,但需要系统里装了对应驱动,个别老内核会识别不到盘,反而给自己添堵。这跟真实服务器上"阵列卡需要装驱动"是同一个道理——你选什么卡,系统就得认这个卡。热词里那些"服务器RAID驱动""PERC阵列卡驱动"的困扰,本质上就是控制器和系统驱动没匹配上,虚拟机里虽然简化了,但选控制器的思路是一样的。

第三步,磁盘文件是"单文件"还是"拆分成多个2G文件"。这个选择对练习影响不大,但对性能有一点影响:拆分文件在扩容和移动时更灵活,大文件方式读写略快。练习就选默认。真正要留心的是**"立即分配磁盘空间"和"精简置备"的区别**。如果勾了立即分配,20G会在宿主机上实打实占掉20G;不勾,就是精简置备,你写多少占多少。问题来了,做RAID5、RAID10的时候,你要往盘上写数据、测性能,写满四块20G的盘会让宿主机凭空多出几十G占用,宿主机磁盘空间不足会直接导致虚拟机卡死甚至损坏虚拟磁盘。所以练习前一定看一眼宿主机的剩余空间,别让阵列写到一半把宿主机撑爆。

第四步,加完盘进系统确认。开机后执行lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,你应该能看到新增的sdbsdcsddsde之类,且没有挂载点、没有文件系统。如果看不到,先别急着排查阵列,先看虚拟机设置里盘有没有真的加上、控制器类型对不对、系统日志dmesg | tail有没有识别到新设备。很多"盘加上了但系统看不到"的问题,根源在虚拟机设置那一层,不在Linux里。

这里再给一条实操心得:给每块测试盘做个标记。你可以在一张纸上或笔记里写下"sdX对应虚拟盘几",因为虚拟机设置里的盘顺序和Linux里的盘符顺序不一定一一对应(尤其在你加过、删过盘之后)。建阵列时看着lsblk的输出对一遍再敲命令,能省掉后面的一大堆麻烦。我见过太多人mdadm --create的时候把盘符对的顺序搞错,结果建出来的阵列容量不对,排查了半天才发现是盘放反了。

4. mdadm 建阵列:四条命令背后的分级差异

盘挂好了,进入正题。Linux下做软阵列的核心工具是mdadm,几乎所有发行版都能直接装:Debian/Ubuntu系apt install mdadm,RHEL/CentOS系yum install mdadm。装完之后,先别急着建阵列,用mdadm --examine /dev/sdb之类的命令看一下目标盘,确认它们不是某个已有阵列的成员,也没被别的东西占用。这一步是很多人的盲区——从别的机器上拆下来的盘,可能还带着旧阵列的元数据,直接拿来建新阵列,行为会莫名其妙。

正式建之前,我要说一个绕不开的选择:用整块盘建阵列,还是先分区再建阵列。两种都能用。整盘建是直接mdadm --create /dev/md0 ... /dev/sdb /dev/sdc,简单直接;分区建是先用partedfdisk在每块盘上划一个分区,再用/dev/sdb1这种分区建阵列。分区建的好处是给你留点余量、可以在盘上做别的用途,坏处是多一层管理。练习阶段我推荐直接整盘建,流程最短,也最贴近现在主流的做法。真到了生产,如果阵列卡能直接做硬RAID,你通常也不会用软阵列——软阵列更适合没有阵列卡、或者想用跨盘管理灵活性更强的场景。

下面我按四个级别各写一遍,你要是有四块盘,可以挨个建了删、删了建,把每条都跑通。

RAID0,两块盘,追求速度:

mdadm --create /dev/md0 --level=0 --raid-devices=2 /dev/sdb /dev/sdc

RAID1,两块盘,互为镜像:

mdadm --create /dev/md1 --level=1 --raid-devices=2 /dev/sdd /dev/sde

RAID5,三块盘,一块校验:

mdadm --create /dev/md5 --level=5 --raid-devices=3 /dev/sdb /dev/sdc /dev/sdd

RAID10,四块盘,先镜像再条带:

mdadm --create /dev/md10 --level=10 --raid-devices=4 /dev/sdb /dev/sdc /dev/sdd /dev/sde

这几条命令看下来你应该能发现,除了--level和盘数量,格式完全一样,这就是mdadm设计得好的地方。但有几个参数值得展开,因为它们直接决定性能和重建行为。

第一个是--chunk条带大小,默认512K。它的含义是数据按多大的块切分后轮流写到各盘上。chunk越小,多个盘越像在"同时干活",小文件随机读写时并行度更高;chunk越大,单块盘连续写更顺,适合大文件顺序读写。真实场景要根据你的负载调,虚拟机练习里保持默认就行,知道它是干嘛的即可。这个参数和后面LVM格式化时的stridestripe-width是配套的,第五节再细说。

第二个是--level=10的布局参数。RAID10在mdadm里有nearfaroffset三种布局,默认是near(near=2),意思是相邻的盘两两镜像。不同布局影响的是坏盘容错范围和性能表现,练习阶段用默认即可,但你要知道有这回事,不然看mdadm --detail输出里的布局信息会一头雾水。

第三个是阵列重建的相关参数。阵列建好第一次用之前,有些级别(尤其RAID1/5)mdadm可能会触发一次"初始同步",几GB的盘可能跑几分钟到几十分钟不等。同步期间阵列是可用的,但性能会打折,你可以用cat /proc/mdstat看进度。虚拟机里盘小,一般很快跑完。如果你想跳过同步(比如只是做功能演示),可以加--assume-clean,但千万别在真的存数据的阵列上用这个参数,跳过同步意味着阵列可能带着不一致的数据就开始工作。

阵列建完,还有两件必须做的事,很多人漏掉。第一,保存阵列配置,否则重启后阵列可能识别不到或者编号乱掉:

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

然后在Debian/Ubuntu系上执行update-initramfs -u,RHEL系执行dracut -f,把配置打进initramfs,确保系统启动早期就能组装阵列。第二,格式化阵列设备本身/dev/md0,不是格式化里面的盘。这点新手常错,脑子里总觉得"要格式化盘",其实是把整个md设备当成一块大硬盘来用。格式化我会放到下一节和LVM一起讲,因为更常见的生产架构是"阵列之上再盖LVM",而不是直接在阵列上建文件系统。

5. 把 LVM 压在阵列上:PV、VG、LV 的三层账本怎么分

先回答一个高频疑问:既然阵列已经是一整块大设备了,为什么还要在上面套LVM?我的答案很直接:为了灵活性。阵列解决的是"盘坏了数据还在",LVM解决的是"空间怎么分、怎么改"。阵列一旦建好,它的容量基本就定死了,你想调整大小非常麻烦;而LVM可以让你在一块大设备上划出多个逻辑卷,随时扩容、随时新建、随时迁移。所以生产上最常见的组合是"底层RAID保命,上层LVM保灵活",两层各干各的事。

LVM有三个核心概念,我用记账来类比。物理卷PV,就是把一块存储设备(这里就是我们的/dev/md0)登记成一页可用的"账页";卷组VG,是把一张或多张账页装订成一册"总账",它代表一个可分配的空间池;逻辑卷LV,是从总账里撕下一张纸,写上"这是给数据库的""这是给home的",形成一块可以格式化、可以挂载的设备。这个三层结构看着多,但理解了就一句话:PV是砖,VG是砖堆成的一堵墙,LV是从墙上划出的一块块区域

操作顺序就是pvcreate → vgcreate → lvcreate → 格式化 → 挂载。假设我们在/dev/md0上做:

pvcreate /dev/md0 vgcreate vg_data /dev/md0 lvcreate -L 20G -n lv_home vg_data mkdir -p /data/home mkfs.ext4 /dev/vg_data/lv_home mount /dev/vg_data/lv_home /data/home

这里每个命令的意图都值得说一句。pvcreate会往设备头写入PV的元数据;vgcreate把这块PV加入名为vg_data的卷组,卷组名你自己起,最好能反映用途;lvcreate -L 20G按绝对大小划20G,如果你想划到卷组剩余空间的最大值,用-l 100%FREE-n lv_home是逻辑卷名,格式化后你会在/dev/vg_data/lv_home(或者/dev/mapper/vg_data-lv_home)看到它。

接下来讲格式化时那个容易被忽略的调优参数。因为我们是在阵列上建文件系统,如果能让文件系统的块布局和阵列的条带对齐,性能会更好。以ext4为例:

mkfs.ext4 -E stride=128,stripe-width=384 /dev/vg_data/lv_home

stride是"每块盘一次写多少文件系统块",算法是chunk大小 / 文件系统块大小stripe-width是"整个条带一次覆盖多少块",RAID5是stride × (盘数-1),RAID0是stride × 盘数,RAID10再按镜像对数折算。默认chunk是512K,ext4默认块是4K,那stride = 512K / 4K = 128;如果是四盘的RAID5,stripe-width = 128 × 3 = 384如果你觉得算这个太麻烦,XFS会更省心,它对基于LVM/阵列的自动对齐做得更好,mkfs.xfs通常不需要手动指定这些。这也是为什么现在很多人在阵列+LVM上直接用XFS。

挂载和开机自动挂载这块,我强烈建议用UUID而不是设备路径写/etc/fstab。原因前面提过,/dev/sdX会变,但UUID不会。查UUID用blkid /dev/vg_data/lv_home,然后写进fstab类似这样:

UUID=xxxx-xxxx /data/home ext4 defaults,noatime 0 2

那个noatime是我自己加的习惯,关闭"每次读文件都更新访问时间",能减少不必要的元数据写入,对读多写少的场景有一点好处。注意如果你用的是XFS,fstab里的dump和pass字段写法略有不同,别照抄ext4的。

重头戏是扩容,这也是热词里"LVM扩容home"的典型诉求。假设你的home逻辑卷快满了,先在卷组里看还有没有空间:vgs看卷组剩余,lvs看各逻辑卷大小。如果有剩余,直接扩:

lvextend -L +10G /dev/vg_data/lv_home

注意,lvextend只是把逻辑卷"变大"了,文件系统还没跟着扩,这是新手最容易以为"扩完了"其实没扩的一步。接下来按文件系统类型走:ext4用resize2fs /dev/vg_data/lv_home,XFS用xfs_growfs /data/home。XFS有两点要注意——它只能扩不能缩,而且xfs_growfs后面跟的是挂载点而不是设备名,别写成设备路径,否则会报错。

如果卷组也没空间了,那就得往卷组里加新盘。这才是"RAID+LVM"组合的精髓——你可以加一块新盘建阵列,或者把新阵列以PV形式加进卷组。加PV:pvcreate /dev/md1,然后vgextend vg_data /dev/md1,卷组就变大了一块,接着继续lvextend。整个过程服务不用停,文件系统在线扩容,这就是LVM最值钱的地方。

6. 阵列降级演练:从故障注入到重建的完整链路

阵列建完、LVM挂好,很多人就认为练完了。但我觉得真正能让你在半夜被告警叫醒时心里不慌的,是降级和重建这两步。阵列的价值只有在掉盘的那一刻才体现出来,你必须在虚拟机里主动把盘弄坏一次,看它怎么反应、怎么恢复。

先看健康状态的几个入口。cat /proc/mdstat是最快的,能看到每个md设备的级别、盘数、状态和同步进度;mdadm --detail /dev/md0更详细,包含每块盘的状态(active sync / spare / faulty)、阵列的UUID、chunk大小等。练习之前先把这两个命令的输出记住长什么样,尤其是"正常状态"的模样,因为后面你判断阵列是否健康,靠的就是和这个正常状态对比

故障注入用--fail

mdadm /dev/md0 --fail /dev/sdb

执行完再看cat /proc/mdstat,你会发现/dev/sdb被标成了(F),阵列状态从[UU]变成了[_U]之类,同时如果阵列有冗余(RAID1/5/10),它依然能读写,只是处于降级状态。这时候关键动作是:在降级阵列上试着读文件、写文件。你会发现文件还能正常读写——这正是RAID存在的意义。但注意,降级期间如果另一块盘也坏了,RAID5就彻底报废,RAID10要看坏的是不是同一个镜像对。所以降级不是"没事",是"给你一个窗口去换盘"。

模拟完故障,下一步是恢复。把坏的盘真正移除,再插一块新盘(虚拟机里可以删掉虚拟盘再加一块),然后加回阵列:

mdadm /dev/md0 --remove /dev/sdb mdadm /dev/md0 --add /dev/sdf

加回去之后,cat /proc/mdstat会显示重建进度,阵列进入"恢复中"的状态。重建期间阵列仍然是可用的,但性能会明显下降,因为mdadm在后台一边读所有健康盘的数据、一边把数据重算写进新盘。练习时可以故意在重建没完成的时候拔掉一块健康盘,看阵列怎么彻底崩掉——这个过程虽然残酷,但能让你对"重建窗口期"的风险有切身体会。生产环境里有大量事故就发生在重建期间,第二块盘扛不住压力挂了。

还有几个运维实战里的习惯动作值得带进来。第一,监控。mdadm自带一个守护进程mdmonitor,可以配置邮件告警,阵列一旦降级就通知你。虚拟机里没有邮件服务器,你可以把它配置成写系统日志,或者干脆自己写个脚本定时抓/proc/mdstat,发现状态不是全U就告警。第二,scrub(校验扫描)。对RAID5/10这种有冗余的阵列,定期做一次echo check > /sys/block/md0/md/sync_action可以让它全盘校验一遍,提前发现潜在坏块。第三,不要用RAID0存任何你还想找回的东西。前面说过,RAID0没有冗余,一块盘坏全盘丢。练习时把RAID0当纯粹的"性能演示",别拿它当"阵列"来理解容错,两者不是一回事。

7. 性能对比与虚拟机环境的"失真"预警

把四种阵列都建好之后,很多人第一件事就是想测速度,看RAID0是不是真的最快、RAID5是不是比单盘强。测可以测,但虚拟机里的测速结果必须带着"失真"两个字来看,否则你会得出完全错误的结论。

先说怎么测。顺序写用dd最简单:

dd if=/dev/zero of=/data/testfile bs=1M count=2048 oflag=direct

关键在那个oflag=direct,它绕过页缓存,让测试更接近真实的盘写入,而不是写进内存就返回。如果你想更专业一点,用fio做混合读写和随机读测试,能更贴近数据库、Web这类真实负载,但参数比较多,练习阶段先用dd感受一下差异就够了。

现在说失真从哪来。第一,虚拟磁盘底层是宿主机上的文件,宿主机文件系统和它自己的缓存层,会把你以为"落到盘上"的写入,其实先落到宿主机的内存里,所以虚拟机的写入延迟整体偏低、吞吐偏高。第二,宿主机的磁盘可能被多个虚拟机共享,你测速的时候隔壁虚拟机在跑备份,你的结果就飘了。第三,快照、精简置备、宿主机内存压力这些因素都会干扰测速。所以虚拟机里能看趋势——比如同样的条件下,RAID0顺序读比RAID1快、RAID5写入因为要算校验所以比RAID1慢——但绝对数字不能拿去给生产选型。

既然这样,那些真实环境里才需要关心的指标,就只能靠理论理解补上。RAID5和RAID10最核心的差异在写性能上:RAID5每次写入都要读旧数据、算校验、再写回数据盘和校验盘,这叫"写惩罚",小随机写场景下性能会比较吃力;RAID10是镜像加条带,写入时直接写到两个镜像组,没有校验计算,写性能更好,代价是只有50%容量。所以给数据库用RAID10的多,给大容量、写少读多的存储用RAID5/6的多,这个选型逻辑只看阵列本身就能推出来,不用靠虚拟机测速。

最后把所有容易踩的坑收成一张清单,方便你实操时对照。盘符漂移:操作前先lsblk确认,fstab用UUID;盘放反:建阵列前对一遍盘和用途;精简置备撑爆宿主机:练习前查宿主机剩余空间;漏了mdadm.conf和initramfs:重启后阵列找不到或编号乱;以为lvextend就扩完了:别忘了resize2fs/xfs_growfs;XFS用了缩容命令:XFS只能扩不能缩,别搞反;在RAID0上存重要数据:没有冗余,一块坏全丢;重建期间又动盘:重建窗口期是最脆弱的时段,能不动就不动。这些东西文档里往往一句带过,但真正让你在机房里手忙脚乱、在告警面前发懵的,恰恰就是它们。

我自己这几年的体会是,RAID和LVM这套东西,看十遍教程不如在虚拟机里亲手建删一遍。你把四种级别各建一次、故意弄坏两块盘看它怎么反应、再把LVM叠上去扩容一次、最后回滚快照重来,这一整套走完,你对"底层保命、上层保灵活"这句话的理解,就不只是字面意思了。下次真服务器摆在你面前,多半也能稳着来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询