☰
RHEL 8存储管理实战:Stratis与VDO的池化、去重与组合使用
2026/10/15 11:45:21 网站建设 项目流程

1. 为什么要在RHEL 8上折腾Stratis和VDO

RHEL 8把存储管理拆成了两条腿走路:一条是Stratis,面向本地磁盘池的"傻瓜式"卷管理;另一条是VDO,面向块设备的"压缩+去重"层。很多人第一次听到这两个词的反应是"LVM不香吗",我当初也这么想,直到一台日志服务器磁盘三天两头爆满、另一台跑虚拟化镜像的机器空间利用率低得可怜,才回头认真把这两个东西啃了一遍。

先把定位说清楚,免得走弯路。Stratis解决的是"我有一堆盘,想快速建池、建文件系统、做快照、做精简配置,但不想背LVM那一长串pvcreate/vgcreate/lvcreate命令"的问题。它在底层其实还是LVM和XFS,只是把复杂度封装起来了,对外暴露的是stratis这一套命令。VDO(Virtual Data Optimizer)解决的是另一个维度的问题:同一块物理盘,怎么塞进更多的逻辑数据。它通过零块消除、重复数据删除、压缩三层机制,把实际写入的物理空间压下来,特别适合备份、日志、虚拟化镜像这类重复率高的场景。

这两个东西不是互斥的,实际生产里经常叠着用:底层用VDO做一层空间优化,上面再跑Stratis做池化管理。但叠之前你得先搞清楚每一层在干什么,否则出了问题根本不知道是哪一层背锅。这篇就把我踩过的坑、验证过的参数、以及一套能直接照着敲的演练流程完整写出来,适合刚接触RHEL 8存储、或者想从LVM迁移到新方案的朋友。

提示:本文所有操作基于RHEL 8.x,命令在CentOS Stream 8/9、Rocky Linux 8上基本通用,但VDO在RHEL 9之后被移出了主线,如果你用的是9,需要额外装vdo和kmod-kvdo包,这点后面会单独说。

2. Stratis的底层逻辑与池化设计思路

2.1 Stratis到底封装了什么

很多人以为Stratis是个全新的文件系统,其实不是。Stratis是一个存储管理守护进程(stratisd)加一套CLI(stratis),它管理的是底层的块设备池,池上面再切出文件系统。底层用的技术栈是:

  • devicemapper:负责把多个块设备聚合成一个池,做精简配置(thin provisioning)。
  • XFS:每个Stratis文件系统实际就是一个XFS,格式化由Stratis自动完成。

所以你在Stratis里建一个文件系统,本质上是让stratisd在池里切一块thin LV,然后mkfs.xfs。理解这一点很重要,因为后面排查问题时,你既可以用stratis命令看上层,也可以下到lvs、dmsetup看底层。

Stratis的核心概念只有三个:

概念说明类比
pool块设备池,由一个或多个块设备组成相当于LVM的VG
filesystem池上切出的文件系统,精简配置相当于LV,但自动格式化
blockdev加入池的物理设备相当于PV

2.2 为什么Stratis适合"懒人"和快速迭代场景

我最初抗拒Stratis的原因是"多一层封装就多一层故障点"。但用了一段时间后发现,它在几个场景下确实比裸LVM省事:

第一,快照和精简配置是默认行为。LVM做快照要手动算COW空间、要lvcreate -s,Stratis直接stratis filesystem snapshot,而且文件系统天生精简,不用预先分配。对于需要频繁做测试环境快照的场景,这个体验差距很大。

第二,扩容是自动的。池里加盘,文件系统不用手动resize,Stratis会自动把新空间纳入。LVM里你得vgextend再lvextend再xfs_growfs三步,Stratis一步stratis pool add-data搞定。

第三,overprovisioning是内建的。你可以建一个比池实际容量大的文件系统,写满了再扩池。这在开发测试环境里很实用,不用一开始就规划死容量。

但代价也要说清楚:Stratis不支持缩小文件系统,不支持RAID(它把冗余交给底层硬件或mdraid),快照不能单独挂载到别的机器。所以它定位很明确——单机、本地盘、快速迭代,不是企业级共享存储的替代品。

2.3 池的创建与设备选择的一个关键细节

建池的时候有个坑我踩过:Stratis默认会把加入池的设备整个吃掉,包括分区表。如果你拿一块已经有分区的盘直接stratis pool create,它会报错或者把分区表清掉。正确做法是先用wipefs -a把设备清干净。

# 确认设备没有挂载、没有分区表 lsblk /dev/sdb wipefs -a /dev/sdb # 建池 stratis pool create mypool /dev/sdb # 查看池 stratis pool list

另一个细节:池的设备大小最好一致。Stratis底层是thin pool,如果混用不同大小的盘,devicemapper的元数据分配会按最大设备算,小盘的空间利用率会打折。我一般建议同型号同容量一起加,扩容时也尽量成对加。

3. VDO的空间优化机制与参数计算

3.1 VDO的三层优化到底怎么工作

VDO不是简单的压缩,它是三层叠加:

  1. 零块消除:写入全零的块直接不落盘,只记元数据。这个对预分配的虚拟磁盘镜像特别有效,因为镜像里大量是零块。
  2. 重复数据删除:对每个4KB块算哈希(默认用SHA-256),哈希相同的块只存一份。这是VDO最核心的机制,也是它省空间的主力。
  3. 压缩:去重之后剩下的唯一块,再用LZ4压缩。LZ4的特点是快,压缩比一般,但对在线场景友好。

这三层的顺序不能乱:先去重再压缩。因为如果先压缩,相同内容的块压缩后可能因为元数据差异导致哈希不同,去重就失效了。

VDO的元数据本身也占空间,默认每1TB逻辑空间需要约1.4GB元数据(实际配置时按物理空间算,比例类似)。所以你不能把整块盘都给VDO用,得留出元数据空间。vdo create的时候它会自动算,但你要心里有数。

3.2 去重效果到底能到多少

这是所有人最关心的问题。我实测过几类场景:

场景去重+压缩后空间占用说明
虚拟机镜像(同模板多实例)原始10%-20%同模板重复率极高
日志文件(结构化重复)原始30%-50%重复行多,压缩也有效
备份归档(增量)原始20%-40%取决于增量重复度
随机二进制数据原始90%-100%基本没效果

关键结论:VDO的收益完全取决于数据重复率。如果你的数据是加密后的、已经压缩过的、或者本身就是随机数据,VDO不但不省空间,还会因为元数据开销和CPU消耗拖慢性能。我见过有人给已经用LUKS加密的盘再套VDO,结果空间没省、IO延迟翻倍,这就是典型的用错场景。

3.3 创建VDO卷时的参数取舍

# 安装 dnf install vdo kmod-kvdo # 创建VDO卷,逻辑大小设为物理的1.5倍(overprovision) vdo create --name=vdovol \ --device=/dev/sdc \ --vdoLogicalSize=1.5T \ --vdoSlabSize=2G \ --compression=on \ --deduplication=on

几个参数要解释:

  • --vdoLogicalSize:逻辑大小,可以大于物理大小,这就是overprovision。但不能无限大,一般建议不超过物理的1.5-2倍,否则写满了会触发只读保护。
  • --vdoSlabSize:VDO把物理空间切成slab管理,默认2G。slab太小元数据多,太大分配不灵活。2G是经验值,除非有特殊需求不用改。
  • --compression和--deduplication:默认都开。如果数据已经压缩过,建议关掉compression省CPU。

创建完用vdostats --human-readable看状态,重点看Used、Available、1K-blocks这几个字段。

注意:VDO卷创建后不能直接改逻辑大小,要改得先停掉、用vdo growLogical,而且只能增不能减。所以规划时宁可保守一点。

4. 从裸盘到可用文件系统的完整演练

4.1 环境准备与设备清理

假设你有一台RHEL 8,挂了三块盘:/dev/sdb、/dev/sdc、/dev/sdd。演练目标:用sdb+sdc建Stratis池,sdd建VDO卷,最后在VDO上再建Stratis池,体验叠加。

第一步永远是清理设备:

# 确认没有挂载 mount | grep -E 'sdb|sdc|sdd' # 清分区表和文件系统签名 wipefs -a /dev/sdb wipefs -a /dev/sdc wipefs -a /dev/sdd # 确认干净 blkid /dev/sdb /dev/sdc /dev/sdd

blkid输出为空才算干净。如果还有残留,用dd if=/dev/zero of=/dev/sdX bs=1M count=100把头部清掉。

4.2 建Stratis池并切文件系统

# 装包 dnf install stratisd stratis-cli # 启动服务 systemctl enable --now stratisd # 建池 stratis pool create pool01 /dev/sdb /dev/sdc # 看池状态 stratis pool list # 建文件系统 stratis filesystem create pool01 fs01 # 看文件系统 stratis filesystem list

stratis filesystem list会输出文件系统的设备路径,类似/dev/stratis/pool01/fs01。这个路径可以直接挂载:

mkdir -p /mnt/fs01 mount /dev/stratis/pool01/fs01 /mnt/fs01 # 写进fstab,注意用UUID echo "UUID=$(blkid -s UUID -o value /dev/stratis/pool01/fs01) /mnt/fs01 xfs defaults 0 0" >> /etc/fstab

这里有个必须注意的点:Stratis文件系统在fstab里要用xfs类型,而且必须加x-systemd.requires=stratisd.service,否则开机时stratisd还没起来,挂载会失败。正确的fstab行是:

UUID=xxxx /mnt/fs01 xfs defaults,x-systemd.requires=stratisd.service 0 0

这个坑我踩过,重启后文件系统没挂上,排查半天才发现是服务依赖顺序问题。

4.3 建VDO卷并观察去重效果

# 建VDO卷 vdo create --name=vdo01 --device=/dev/sdd --vdoLogicalSize=1.5T # 格式化并挂载 mkfs.xfs /dev/mapper/vdo01 mkdir -p /mnt/vdo01 mount /dev/mapper/vdo01 /mnt/vdo01 # 看初始状态 vdostats --human-readable

现在做个去重实验。往/mnt/vdo01里写两份完全相同的大文件:

# 生成一个500M的随机文件 dd if=/dev/urandom of=/tmp/base.img bs=1M count=500 # 拷贝两份到VDO cp /tmp/base.img /mnt/vdo01/copy1.img cp /tmp/base.img /mnt/vdo01/copy2.img # 看VDO统计 vdostats --human-readable

你会看到Used大概只增加了500M左右,而不是1G,因为第二份被去重了。vdostats里的Deduplication和Compression字段会显示节省的比例。这个实验能让你直观感受到VDO在干什么。

4.4 在VDO上叠加Stratis

这是进阶玩法。VDO卷本身是个块设备/dev/mapper/vdo01,可以当Stratis的底层设备用:

# 先卸载VDO上的XFS(如果之前格式化过) umount /mnt/vdo01 wipefs -a /dev/mapper/vdo01 # 把VDO卷加入Stratis池 stratis pool create pool02 /dev/mapper/vdo01 stratis filesystem create pool02 fs02 mount /dev/stratis/pool02/fs02 /mnt/fs02

这样数据先经过Stratis的thin层,再经过VDO的去重压缩层。但要注意:Stratis的thin provisioning和VDO的overprovision会叠加,空间超卖的风险翻倍。我一般在这种叠加场景下把VDO的logicalSize设得保守些,比如物理的1.2倍,避免写爆。

5. 快照、扩容与日常维护的实操细节

5.1 Stratis快照的正确用法

Stratis快照是瞬间完成的,因为它底层是thin snapshot,不复制数据。命令很简单:

stratis filesystem snapshot pool01 fs01 fs01-snap

但有几个细节文档里不会强调:

第一,快照和原文件系统共享池空间。快照本身不占空间,但原文件系统后续的写入会触发COW,占用池空间。如果池满了,快照和原文件系统都会出问题。所以要监控池的Used比例。

第二,快照可以单独挂载,但挂载后是只读还是可写取决于你怎么挂。默认挂载是可写的,但写快照会加速空间消耗。测试场景我一般挂成只读:

mount -o ro /dev/stratis/pool01/fs01-snap /mnt/snap

第三,删除快照要确认没有挂载,否则会报设备忙。

5.2 池扩容与文件系统自动增长

池扩容分两种情况:加新盘、扩已有盘。

# 加新盘 stratis pool add-data pool01 /dev/sde # 扩已有盘(比如盘做了分区,扩分区后) stratis pool add-data pool01 /dev/sdb

加完之后,池的Total Physical会变大,池上的所有文件系统自动获得新空间,不需要手动resize。这是Stratis比LVM省事的地方。但注意:文件系统的逻辑大小不会自动变,如果你之前建的文件系统设了固定大小,得手动stratis filesystem set-size。默认建的文件系统是精简的,会跟着池走。

5.3 VDO的监控与调优

VDO的日常监控主要看vdostats:

# 简洁模式 vdostats --human-readable # 详细模式,看每个卷 vdostats --verbose

重点关注的字段:

  • Used:物理已用空间。接近物理大小时会触发只读。
  • Available:物理剩余。
  • Logical Size:逻辑大小。
  • Write Amplification:写放大,正常应该接近1,如果远大于1说明去重效果差或者元数据开销大。

如果发现Used快满了,有两个选择:加物理盘(vdo growPhysical)或者扩逻辑(vdo growLogical,但物理不够时没用)。我一般设置监控告警在Used达到85%时触发,留出处理时间。

提示:VDO卷写满后会进入只读模式,此时写入全部失败,但读还能用。恢复方法是扩物理空间或者删数据。这个只读保护是VDO的安全机制,别以为是故障。

6. 踩过的坑与排查链路实录

6.1 Stratis池满了导致文件系统只读

现象:某台测试机的Stratis文件系统突然变成只读,dmesg里有XFS: filesystem has become read-only。

排查链路:

  1. 先看stratis pool list,发现Used接近Total Physical,池满了。
  2. 池满的原因是thin provisioning超卖,文件系统逻辑大小加起来超过了池物理大小,实际写入把池撑爆了。
  3. 底层devicemapper的thin pool满了之后,XFS检测到写入失败,自动切只读。

解决:加盘扩容stratis pool add-data,然后mount -o remount,rw重新挂载。但已经写入失败的数据可能损坏,需要检查。

教训:Stratis的overprovision是双刃剑,生产环境要么监控池使用率,要么建文件系统时设--size限制逻辑大小,别让它无限超卖。

6.2 VDO去重率突然下降

现象:一个跑了几周的VDO卷,vdostats显示去重率从70%掉到20%。

排查链路:

  1. 先确认数据模式有没有变。查了写入来源,发现新上了一批已经压缩过的归档数据。
  2. 已压缩数据进去重层,哈希不同但内容其实高度相似,去重失效;压缩层也因为数据已压缩,压不动。
  3. 结论是数据特征变了,不是VDO故障。

解决:把这类已压缩数据挪到普通卷,VDO只放未压缩的原始数据。

教训:VDO不是万能的,数据特征决定收益。上线前一定要用真实数据做样本测试,别信理论值。

6.3 开机挂载顺序导致Stratis文件系统没挂上

现象:重启后/mnt/fs01是空的,mount命令手动执行能挂上。

排查链路:

  1. 看systemctl status stratisd,服务是active的。
  2. 看journalctl -b,发现挂载单元在stratisd之前执行了,找不到设备。
  3. 确认fstab里没加x-systemd.requires=stratisd.service。

解决:补上依赖参数,systemctl daemon-reload后重启验证。

教训:Stratis文件系统的设备节点是stratisd动态创建的,fstab必须声明服务依赖,这是和普通块设备最大的区别。

6.4 VDO卷创建时报"设备太小"

现象:vdo create报错,说设备空间不足以容纳元数据。

排查链路:

  1. 查设备大小,lsblk显示500G。
  2. 查VDO元数据需求,默认每TB逻辑需要约1.4GB元数据,加上VDO自身的固定开销。
  3. 500G设备如果logicalSize设得太大,元数据空间不够。

解决:要么减小--vdoLogicalSize,要么换更大的设备。我一般建议VDO底层设备至少100G起步,太小没意义。

教训:VDO有最小空间要求,规划时把元数据开销算进去,别把设备空间用满。

7. 两套方案怎么选与组合使用建议

7.1 选型对照表

维度StratisVDO
核心目标池化管理、快照、精简配置空间优化(去重+压缩)
底层技术LVM thin + XFS块设备层 + UDS + LZ4
适用场景本地多盘管理、测试环境快照备份、日志、虚拟化镜像
不适用需要RAID、需要缩容已压缩/加密/随机数据
性能影响小,thin层开销低中,去重消耗CPU和内存
扩容方式add-data,自动增长growPhysical/growLogical
缩容不支持不支持

7.2 组合使用的正确姿势

如果你的场景既需要池化管理又需要空间优化,可以叠加,但顺序有讲究:

推荐顺序:VDO在下,Stratis在上。因为VDO是块设备层的优化,应该尽量贴近物理设备;Stratis的thin层在上面做逻辑管理。这样VDO能对Stratis写入的所有数据做去重,包括快照产生的COW数据。

不推荐:Stratis在下,VDO在上。因为Stratis的thin设备本身是精简的,VDO再去重意义不大,而且两层精简叠加容易出问题。

叠加时的容量规划要保守:假设物理1T,VDO logicalSize设1.2T,Stratis池就按1.2T算,文件系统逻辑大小总和别超过1.2T。这样即使写满,VDO还有物理空间兜底。

7.3 监控与告警的最小配置

不管用哪套,监控是必须的。我一般配两个检查:

# Stratis池使用率 stratis pool list --output=name,total-physical,used-physical # VDO使用率 vdostats --human-readable | awk '{print $1, $5, $6}'

把这两个输出接到监控系统,阈值设85%。Stratis池满了会导致文件系统只读,VDO满了也会只读,都是影响业务的。

注意:RHEL 9之后VDO不再默认安装,需要从AppStream单独装。如果你在规划长期方案,要评估这个变化。Stratis在RHEL 9/10里还是主线,可以放心用。

8. 一些不写在文档里的经验

最后分享几个我实际用下来觉得值得记的点。

Stratis的stratis filesystem list输出里有个Size字段,那是逻辑大小,不是实际占用。实际占用要看池的Used。很多人看文件系统Size以为空间还多,结果池早满了。这个认知差是新手最容易踩的。

VDO的--vdoSlabSize改起来很麻烦,创建后基本不能改,要改得重建。所以创建时想清楚,2G对绝大多数场景够用,除非你的数据块特别大或者特别小。

Stratis快照不要留太多。每个快照都会让原文件系统的COW开销累积,快照越多,原文件系统写入越慢、空间消耗越快。我一般只保留最近2-3个快照,旧的及时删。

VDO的CPU开销在去重开启时比较明显,尤其是写入密集场景。如果机器CPU核数少,建议先测一下,或者关掉去重只留压缩。压缩用LZ4,开销比去重小得多。

两套方案都不支持缩容,这是设计上的取舍,不是bug。规划时宁可从小开始慢慢加,也别一次给太大后面想缩。我见过有人给Stratis文件系统设了10T逻辑大小,结果池只有2T,写了一点就满了,想缩还缩不了,只能重建。

演练环境里随便折腾,生产环境先做容量规划。Stratis和VDO的很多行为(thin超卖、VDO只读保护)在测试环境不容易触发,因为测试数据量小。上线前一定要用接近真实的数据量和写入模式压一遍,把边界摸清楚。

这套东西我前后在几台机器上跑了小半年,从最初的"这什么鬼"到现在的"真香",中间踩的坑基本都写在这了。如果你刚开始接触,建议先按第4节的演练走一遍,把命令敲熟,再回头看第6节的排查链路,会有更深的体会。

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

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

立即咨询