RHEL 8存储管理实战:Stratis与VDO的池化、去重与组合使用
1. 为什么要在RHEL 8上折腾Stratis和VDORHEL 8把存储管理拆成了两条腿走路一条是Stratis面向本地磁盘池的傻瓜式卷管理另一条是VDO面向块设备的压缩去重层。很多人第一次听到这两个词的反应是LVM不香吗我当初也这么想直到一台日志服务器磁盘三天两头爆满、另一台跑虚拟化镜像的机器空间利用率低得可怜才回头认真把这两个东西啃了一遍。先把定位说清楚免得走弯路。Stratis解决的是我有一堆盘想快速建池、建文件系统、做快照、做精简配置但不想背LVM那一长串pvcreate/vgcreate/lvcreate命令的问题。它在底层其实还是LVM和XFS只是把复杂度封装起来了对外暴露的是stratis这一套命令。VDOVirtual 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加一套CLIstratis它管理的是底层的块设备池池上面再切出文件系统。底层用的技术栈是devicemapper负责把多个块设备聚合成一个池做精简配置thin provisioning。XFS每个Stratis文件系统实际就是一个XFS格式化由Stratis自动完成。所以你在Stratis里建一个文件系统本质上是让stratisd在池里切一块thin LV然后mkfs.xfs。理解这一点很重要因为后面排查问题时你既可以用stratis命令看上层也可以下到lvs、dmsetup看底层。Stratis的核心概念只有三个概念说明类比pool块设备池由一个或多个块设备组成相当于LVM的VGfilesystem池上切出的文件系统精简配置相当于LV但自动格式化blockdev加入池的物理设备相当于PV2.2 为什么Stratis适合懒人和快速迭代场景我最初抗拒Stratis的原因是多一层封装就多一层故障点。但用了一段时间后发现它在几个场景下确实比裸LVM省事第一快照和精简配置是默认行为。LVM做快照要手动算COW空间、要lvcreate -sStratis直接stratis filesystem snapshot而且文件系统天生精简不用预先分配。对于需要频繁做测试环境快照的场景这个体验差距很大。第二扩容是自动的。池里加盘文件系统不用手动resizeStratis会自动把新空间纳入。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不是简单的压缩它是三层叠加零块消除写入全零的块直接不落盘只记元数据。这个对预分配的虚拟磁盘镜像特别有效因为镜像里大量是零块。重复数据删除对每个4KB块算哈希默认用SHA-256哈希相同的块只存一份。这是VDO最核心的机制也是它省空间的主力。压缩去重之后剩下的唯一块再用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 --namevdovol \ --device/dev/sdc \ --vdoLogicalSize1.5T \ --vdoSlabSize2G \ --compressionon \ --deduplicationon几个参数要解释--vdoLogicalSize逻辑大小可以大于物理大小这就是overprovision。但不能无限大一般建议不超过物理的1.5-2倍否则写满了会触发只读保护。--vdoSlabSizeVDO把物理空间切成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。演练目标用sdbsdc建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/sddblkid输出为空才算干净。如果还有残留用dd if/dev/zero of/dev/sdX bs1M count100把头部清掉。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 liststratis 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.requiresstratisd.service否则开机时stratisd还没起来挂载会失败。正确的fstab行是UUIDxxxx /mnt/fs01 xfs defaults,x-systemd.requiresstratisd.service 0 0这个坑我踩过重启后文件系统没挂上排查半天才发现是服务依赖顺序问题。4.3 建VDO卷并观察去重效果# 建VDO卷 vdo create --namevdo01 --device/dev/sdd --vdoLogicalSize1.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 bs1M count500 # 拷贝两份到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。排查链路先看stratis pool list发现Used接近Total Physical池满了。池满的原因是thin provisioning超卖文件系统逻辑大小加起来超过了池物理大小实际写入把池撑爆了。底层devicemapper的thin pool满了之后XFS检测到写入失败自动切只读。解决加盘扩容stratis pool add-data然后mount -o remount,rw重新挂载。但已经写入失败的数据可能损坏需要检查。教训Stratis的overprovision是双刃剑生产环境要么监控池使用率要么建文件系统时设--size限制逻辑大小别让它无限超卖。6.2 VDO去重率突然下降现象一个跑了几周的VDO卷vdostats显示去重率从70%掉到20%。排查链路先确认数据模式有没有变。查了写入来源发现新上了一批已经压缩过的归档数据。已压缩数据进去重层哈希不同但内容其实高度相似去重失效压缩层也因为数据已压缩压不动。结论是数据特征变了不是VDO故障。解决把这类已压缩数据挪到普通卷VDO只放未压缩的原始数据。教训VDO不是万能的数据特征决定收益。上线前一定要用真实数据做样本测试别信理论值。6.3 开机挂载顺序导致Stratis文件系统没挂上现象重启后/mnt/fs01是空的mount命令手动执行能挂上。排查链路看systemctl status stratisd服务是active的。看journalctl -b发现挂载单元在stratisd之前执行了找不到设备。确认fstab里没加x-systemd.requiresstratisd.service。解决补上依赖参数systemctl daemon-reload后重启验证。教训Stratis文件系统的设备节点是stratisd动态创建的fstab必须声明服务依赖这是和普通块设备最大的区别。6.4 VDO卷创建时报设备太小现象vdo create报错说设备空间不足以容纳元数据。排查链路查设备大小lsblk显示500G。查VDO元数据需求默认每TB逻辑需要约1.4GB元数据加上VDO自身的固定开销。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再去重意义不大而且两层精简叠加容易出问题。叠加时的容量规划要保守假设物理1TVDO logicalSize设1.2TStratis池就按1.2T算文件系统逻辑大小总和别超过1.2T。这样即使写满VDO还有物理空间兜底。7.3 监控与告警的最小配置不管用哪套监控是必须的。我一般配两个检查# Stratis池使用率 stratis pool list --outputname,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节的排查链路会有更深的体会。