ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Ceph OSD盘符漂移排查与恢复:从/dev/sdX到by-id的加固实践

Ceph OSD盘符漂移排查与恢复:从/dev/sdX到by-id的加固实践 凌晨1点47分监控把我叫醒osd.7 down。登录服务器后ceph -s里确实躺着一条醒目的告警但奇怪的是lsblk里那块SSD明明还在SMART也正常怎么想都不像盘挂了。再查systemd日志一句话点破/dev/sdb: No such file or directory。这不是盘坏了是又一场SSD盘符漂移——重启前还叫/dev/sdb的盘这次变成了/dev/sdc而OSD的挂载单元还在固执地寻找/dev/sdb。这种故障在存储运维里不算罕见但每次出现都足够让人头皮发麻集群里明明有盘OSD却起不来重启节点盘序还可能再洗一次牌要是有人急着ceph osd rm重建数据冗余就会进一步恶化。这篇不写理论空话我把从根因、复现、排障、恢复到加固的完整链路梳理一遍全程基于测试环境的实际操练适合Ceph管理员、存储运维、SRE参考尤其是那些还在用/dev/sdX路径部署OSD的团队。1. 盘符漂移的根因Linux设备名只是内核按扫描顺序发的临时号1.1 盘符是怎么被分配的Linux内核并不关心你的SSD是哪个品牌。系统启动时SCSI子系统会扫描各个HBA/控制器上的设备扫描到一块盘就按顺序给它排一个sdX的设备名sda、sdb、sdc一路排下去。NVMe设备则是nvme0n1、nvme1n1原理类似也是按PCIe枚举顺序来的。这个扫描顺序听起来是确定的实际上并不保证稳定。一台服务器里通常有多个控制器板载SATA控制器、PCIe扩展卡、RAID卡直通模式、NVMe控制器内核模块加载的顺序、PCIe total枚举的时序、设备响应速度的快慢都会影响谁先被内核看到。某块盘在启动瞬间响应慢了几十毫秒就可能被排到后面。再加上热插拔、BIOS盘序设置变化、内核版本升级设备名被打乱也就不奇怪了。拿生活里的场景类比/dev/sdb就像排队时管理员发的临时号码牌先到先得号码可以随时重发但你本人的身份没有变。硬盘真正的身份是设备自身的序列号、WWN、文件系统UUID、LVM的PV UUID而不是这个临时号码牌。1.2 OSD启动流程里哪一环会被盘符漂移卡住Ceph OSD要正常工作需要先把对应的块设备挂载到/var/lib/ceph/osd/ceph-id目录然后由ceph-osd进程检查并读写这个设备。新版Ceph用ceph-volume lvm管理OSD会把物理盘做成LVM PV再创建LVOSD挂载的是LV的设备节点同时LV的UUID、VG名都写在OSD的元数据里。理论上这个机制对盘符漂移是免疫的不管物理盘叫/dev/sdb还是/dev/sdcLVM都能通过UUID找到PV激活VG生成LV节点。但现实里会有几类雷老集群用ceph-disk部署激活逻辑走udev规则依赖设备事件和分区标签某些环节还会引用固定路径手工部署或者脚本部署时为了省事把/dev/sdb这类固定盘符写进了systemd mount unit、ceph.conf、或者容器挂载参数运维在OSD数据盘上单独建了文件系统并写进/etc/fstab挂载项用了/dev/sdX初始化脚本里用parted、mkfs时直接指定了设备名执行前没有校验UUID。只要这些雷存在重启后盘符一漂移OSD的挂载就会失败进程起不来mon超过阈值后就会把它标记为down。有些情况下更危险/dev/sdb漂移后指向了另一块盘而启动脚本没有校验UUID直接把错盘挂上甚至格式化那就从故障升级成事故了。1.3 为什么SSD是高发区机械盘时代盘符漂移一样存在只是大家习惯性觉得盘坏了。到了SSD时代服务器里常常塞着十几块SSD又混着NVMe和SATA/SAS接口和驱动都不一样枚举时序更难预测。NVMe设备名相对稳定但PCIe槽位变化、BIOS开关CSM、内核升级都可能让它重新编号。SATA SSD和SAS SSD则继承了SCSI子系统的扫描逻辑盘序最容易变。所以SSD盘符漂移不是玄学是存储服务器里一个高概率事件尤其当集群还是手工脚本部署、各种路径写死的环境。下表是我平时判断设备命名是否稳定时经常对照的设备类型命名示例稳定性推荐识别方式SATA SSD/dev/sda不稳定/dev/disk/by-id/ata-*、by-uuidSAS SSD/dev/sdb不稳定/dev/disk/by-id/scsi-、wwn-NVMe SSD/dev/nvme0n1相对稳定但会变/dev/disk/by-id/nvme-、by-path/pci-2. 复现实验在虚拟机上折腾出一块找不到家的OSD2.1 实验环境和部署细节我建议用虚拟机做这类实验因为可以随意调整磁盘顺序而不影响生产。一个三节点Ceph测试集群比较理想单节点也能复现但看不到PG迁移和心跳超时的完整过程。我这里搭了一套Ubuntu 22.04 Ceph Quincy的三节点集群其中一个节点挂了4块虚拟盘一块系统盘vda三块SSD数据盘vdb、vdc、vdd控制器用的SCSI类型方便之后模拟扫描顺序变化。先正常部署OSD建议用标准做法ceph-volume lvm batch --bluestore /dev/vdb /dev/vdc /dev/vdd创建完成后记录一下ceph-volume lvm list的输出重点看OSD id、fsid和device信息。这一步非常关键恢复时要靠这些字段确认哪块物理盘属于哪个OSD。然后我故意埋一颗雷把osd.0对应的mount unit里的What从LV的设备节点改成固定盘符/dev/vdb。生产环境没人会刻意这么干但很多老教程、自研脚本、甚至同事的部署习惯里都有类似写法我这里只是把这个问题显性化。如果你用的是标准配置盘符漂移后OSD可能照样起得来那说明当前环境还没踩到雷但隐患就在那里。2.2 三种触发方法按真实度排序方法A在虚拟化平台调整磁盘顺序关机在libvirt/VMware里把磁盘插槽顺序调整一下或者加一块空白盘放到更靠前的槽位再开机。这样内核扫描SCSI设备时盘序会整体后移原来的vdb可能变成vdc或vdd。这最接近真实硬件盘序变化。方法B在系统内删除设备再重新扫描如果你的VM用的是SCSI控制器可以直接在系统内模拟设备消失再出现echo 1 /sys/block/sdb/device/delete重新扫描SCSI总线for host in /sys/class/scsi_host/host*; do echo - - - $host/scan; done设备删除后重新出现内核会重新分配设备号大概率分配一个新的节点名。这个方法不用重启适合快速复现但要注意别在有任何业务IO的机器上试。device/delete的路径只对SCSI设备有效virtio-blk盘没有这个接口用VM平台调整顺序更方便。方法C直接做配置级故障注入不重启、不动设备单纯把mount unit的What指向一个不存在的路径也能看到OSD down。但这样只能验证恢复流程不能体验盘符漂移本身所以我推荐至少做一次A或B。2.3 故障后的现场我用方法A做了一次。重启后系统正常起来lsblk输出里原来三块数据盘的顺序完全变了我提前加进去的空盘成了最前面的vdb原来的三块数据盘顺延为vdc、vdd、vde。此时那个What/dev/vdb的挂载单元找到的不是原来的OSD数据盘而是一块空盘mount直接失败OSD起不来。过了一会ceph -s出现osd.0 down (since 5 minutes)systemctl status ceph-osd0显示Active: failedjournalctl -u ceph-osd0里最关键的一行Mount process exited with code32 mount: /dev/vdb: no such file or directory如果重启后vdb仍然存在只是变成了一块空盘mount报错会变成wrong fs type, bad option, bad superblock。别被报错文字绕晕关键是要确认当前设备名对应的物理盘和OSD元数据里记录的物理盘是不是同一块。3. 排查链路从OSD down到设备名漂移的完整取证3.1 从集群到节点逐层缩小范围遇到OSD down第一件事不是上服务器乱翻而是先看清集群状态ceph -s ceph osd tree ceph health detailosd.0 down的根因可能在节点宕机、网络分区、盘故障、文件系统错误、盘符漂移。挨个排除先看节点是否在线ceph osd find 0能看到OSD所在主机ssh过去看节点活着没再看OSD进程是否在跑systemctl status ceph-osd0。如果进程已经failed就可以把注意力放到本机的启动链路和存储设备上。3.2 日志里找直接原因在OSD节点上执行journalctl -u ceph-osd0 -n 200然后看/var/log/ceph/ceph-osd.0.log最后几十行再配合dmesg | grep -Ei error|failed|I/O。留在报错信息里的设备不存在mount失败block device is read-onlysuperblock on /dev/xxx has bad magic都是有价值的线索。本例中日志直接指向挂载失败且失败的源设备路径是我们写死的/dev/vdb。3.3 用唯一标识确认盘的实际身份这一步是整个排障的核心你要证明原来的OSD数据盘还在机器上只是改了名字。判断方法lsblk -f看各盘的文件系统UUID、LABEL、挂载点。OSD数据盘如果是ceph-volume管理的LVM会显示LVM2_member或者bluestore相关的分区信息ls -l /dev/disk/by-id/ | grep serial用SCSI/NVMe/ATA的序列号去匹配物理盘ceph-volume lvm list这个命令直接告诉你有哪几个OSD、对应哪个LV、fsid是什么。如果它能列出osd.0且device路径是/dev/sdc1之类的新盘符说明LV元数据还在pvs、pvscan看LVM能不能认出PVPV Name现在是/dev/sdc1还是老的/dev/vdb1。比如我的实验里ceph-volume lvm list输出显示osd.0的LV仍然是ceph-uuid/osd-0-fsid物理盘对应的设备路径已经变成/dev/sdc。同时lsblk -f显示/dev/sdc上是LVM PVUUID和之前一致。到这里基本可以确定是盘符漂移而不是盘坏了。3.4 三类常见down原因的区别现象盘符漂移磁盘故障OSD进程崩溃设备路径磁盘还在但名字变了设备消失/IO错误设备名没变日志关键字No such file / mount fail / LVM未激活I/O error、end_request、buffer I/O errorbluefs报错、assert、segfaultsmartctl正常大量Reallocated_Sector/UDMA_CRC错误正常LVM/PV能看到PV Name可能变化PV不见或IO异常正常处理方式修正路径并重新激活更换磁盘排查OSD进程/coredump3.5 最容易被带偏的误区看到OSD down就急着ceph osd rm重建是最常见的惯性动作。但你要知道ceph osd rm会把OSD从CRUSH map里移除PG会进入degraded如果这时候再把盘格式化基本就是主动丢副本。遇到down先问自己盘还在吗数据还完整吗如果盘还在、数据没丢优先恢复而不是重建。另外也别拿着reboot当万金油盘符漂移场景下盲目重启可能把盘序再洗乱一次。4. 恢复步骤让OSD在设备名变化后重新up的实操序列4.1 恢复前必须确认的三件事第一OSD是否还在集群注册表里。ceph osd tree能看到osd.0即使down也没关系说明集群还认这个id。如果连id都没了那是另一套恢复逻辑。第二OSD的fsid和keyring是否还在。通常它们都在/var/lib/ceph/osd/ceph-0/目录下文件名是fsid、keyring和type。第三底层块设备是否被内核识别、LVM是否激活。执行lsblk、pvscan、vgscan确保OSD所在的VG存在LV可以激活。如果pvscan没扫到PV先执行partprobe让内核重新读取分区表如果VG处于inactive状态执行vgchange -ay激活。4.2 先处理掉写死盘符的mount unit如果像我实验里一样之前把mount unit的What写成了/dev/vdb那么先把这个雷拆了。查看现有unitsystemctl cat var-lib-ceph-osd-ceph-0.mount如果What确实是固定盘符把它改成LV设备节点或/dev/disk/by-id/路径。以Ceph LVM标准布局为例What建议用/dev/disk/by-id/ata-serial-part1或者/dev/mapper/ceph--uuid-osd--0--fsid这类稳定路径。改完后systemctl daemon-reload如果这个unit已经被标记failed可以先reset掉systemctl reset-failed var-lib-ceph-osd-ceph-0.mount systemctl reset-failed ceph-osd0.service4.3 标准恢复动作ceph-volume lvm activate确认完以上信息后执行ceph-volume lvm activate 0 fsid0是OSD idfsid用cat /var/lib/ceph/osd/ceph-0/fsid拿到的值替代。activate会做三件事检查并激活对应的LV把LV挂载到/var/lib/ceph/osd/ceph-0然后通知systemd启动ceph-osd0.service。因为这个流程依赖LV的UUID而不是固定盘符所以即使设备的/dev/sdX名字已经变了也能正确找到数据卷。如果节点上的OSD不多也可以ceph-volume lvm activate --all但我建议定点激活单个OSD否则万一同时有多个OSD在激活时出问题排障范围会变大。4.4 当LVM没有自动识别时怎么办有些场景盘符漂移后内核认出了盘但LVM的缓存还是旧的或者PV就是不出来。可以强制刷一下pvscan --cache vgscan --cache partprobe /dev/sdc再看pvs输出确认PV Name是不是/dev/sdc1。如果PV Name变了LVM通常也能自动跟踪但如果VG元数据里记录的设备名和当前不一致可能需要vgcfgbackup vg-name vgreduce --removemissing vg-name vgextend vg-name /dev/sdc1这类操作要非常谨慎只在你确认/dev/sdc1就是原来那块PV时才能做。我的习惯是操作前先把VG元数据备份出来避免误删。4.5 恢复后验证OSD进程起来后还没完。依次检查systemctl status ceph-osd0 ceph -s ceph osd tree等待OSD状态从down变成up再观察PG状态是否从degraded恢复为activeclean。恢复过程中节点上可能短暂出现ceph-osd0重启一两次的现象先别慌观察日志确认是正常重挂还是又报错。如果反复crash去查/var/log/ceph/ceph-osd.0.log和dmesg看是不是还有别的路径引用了旧设备名。如果OSD已经up但权重异常先确认ceph osd tree里的weight是不是0。盘符漂移通常不影响weight除非有人之前执行过ceph osd out。4.6 重建是最后手段什么时候才考虑如果尝试了上面的方法OSD还是起不来并且确认是数据盘真的损坏、文件系统结构损坏无法挂载或者LVM元数据彻底丢失才考虑重建。重建流程也有讲究ceph osd out 0 # 等待所有PG迁出数据重新均衡 ceph osd purge 0 --yes-i-really-mean-it然后找到新盘或者修好后的同一块盘用by-id路径重新创建OSD。注意在osd out到迁移完成的窗口期集群冗余度是降低的如果min_size配置是2手一抖可能连IO都挂了。所以能救就救才是正路。5. 加固方案让部署配置与物理盘绑定而不是与盘符绑定5.1 创建OSD用by-id路径拒绝/dev/sdX从创建OSD这一步开始就避免依赖临时盘符。以前很多人写ceph-volume lvm create --data /dev/sdb这是坏习惯。正确写法ceph-volume lvm batch --bluestore \ /dev/disk/by-id/ata-QEMU_HARDDISK_QM00001 \ /dev/disk/by-id/ata-QEMU_HARDDISK_QM00002 \ /dev/disk/by-id/ata-QEMU_HARDDISK_QM00003如果盘特别多可以用/dev/disk/by-path/pci-0000:00:0a.0-scsi-0:2:0:0这样的路径它绑定物理槽位比盘符稳定。NVMe直接用/dev/disk/by-id/nvme-eui.xxxx。这套路径在服务器重启后依然指向同一块物理盘不会因为扫描顺序变化而改变。5.2 用udev规则给盘起个稳定的别名如果不想记那么长的by-id字符串可以写一条udev规则根据磁盘序列号创建稳定链接# /etc/udev/rules.d/70-osd-disk.rules SUBSYSTEMblock, KERNELsd*, ATTRS{serial}QM00001, SYMLINKdisk/osd-data-0然后重载并触发udevadm control --reload udevadm trigger之后在mount unit、Ansible脚本、监控脚本里统一用/dev/disk/osd-data-0。这样不管它是sdb还是sdc你访问的路径永远指向同一块物理盘。注意serial未必全局唯一有条件优先匹配ID_WWN或ID_SCSI_SERIAL避免同型号多块盘互相冲突。5.3 系统层面减少盘序变化可以从几个层面降低概率BIOS里固定磁盘槽位顺序禁用不必要的热插拔扫描服务器里同一厂商同型号的盘尽量插在同一控制器下避免跨控制器乱序内核升级、BIOS升级后主动检查一次lsblk和/dev/disk/by-id对应关系如果磁盘接了多路径用/dev/mapper/mpathX或WWN路径不要用底层sdX。这些不是强制项但能很大程度减少重启后莫名其妙的设备名变化。至少要做到升级内核或BIOS后第一时间检查集群OSD状态而不是等监控半夜叫你。5.4 监控与自愈的兜底无论怎么加固还是要做好告警。ceph -s里的OSD down是最直观的。更细一层可以写个巡检脚本对比ceph-volume lvm list里的device路径和/dev/disk/by-id的映射如果发现路径对不上自动修正mount unit并daemon-reload。有人给systemd service加Restarton-failure但这只能处理进程崩溃处理不了mount失败——mount失败的unit会直接进入failed状态不会触发service restart。所以自愈只能兜底核心还是要从配置源头根治。5.5 维护checklist都是踩过坑才总结出来的每次重启前把lsblk -o NAME,SERIAL,UUID,LABEL,MOUNTPOINT和ceph-volume lvm list各存一份建立一张OSD id - 磁盘序列号 - 机房槽位的对应表换盘、排查时能省大量时间修改任何systemd unit、fstab、脚本里的设备路径时只允许用UUID/by-id/by-partlabel不要顺手执行rescan、device/delete这类操作除非你知道自己在干什么给关键OSD数据盘做smartctl定时巡检把盘坏了和盘符变了在第一时间分开。我自己的一个小习惯是新接手一个集群第一件事就是把所有节点的/etc/fstab、systemctl list-units | grep ceph和ceph-volume lvm list全都瞟一遍把任何写死的/dev/sdX揪出来改掉。这花不了半小时但能省掉后面无数次凌晨三点被叫醒的麻烦。
返回列表