广告位 · 页头(后台-模块管理-新建模块后替换此区域)

如何为Oracle RAC集群编写可靠的udev规则?

在Linux平台部署Oracle RAC集群时,共享存储设备的管理方式直接影响整个集群的稳定性。许多生产环境中的ASM磁盘故障并非硬件损坏,而是由于udev规则缺失或写错,导致设备重启后权限被重置、符号链接丢失、设备名漂移。这类问题往往在首次重启或计划内维护后才暴露出来,排查耗时且容易误判为存储链路故障。因此,理解udev在Oracle RAC环境中的匹配逻辑并编写正确的规则文件,是每个RAC管理员必须掌握的基础技能。

如何为Oracle RAC集群编写可靠的udev规则?

udev在Oracle RAC中的角色与常见故障

udev是Linux内核的设备管理器,负责在设备插入或系统启动时动态创建/dev目录下的设备节点。对于普通本地磁盘,系统默认的规则会根据总线枚举顺序生成类似/dev/sda、/dev/sdb这样的名称,但顺序并不固定。Oracle RAC使用ASM管理共享磁盘时,需要所有节点对同一块磁盘拥有一致的路径和权限。如果直接使用/dev/sdb这种内核命名,当服务器增加一块新盘或者HBA卡初始化顺序变化时,原有的设备名就可能指向另一块物理磁盘,导致ASM无法找到正确的磁盘组成员。

另一个常见问题是权限。默认情况下,块设备的属主通常是root:disk,权限为0640或0660,普通用户grid无法直接读写。如果依赖系统启动脚本手动chown,不仅容易遗漏,而且在设备热插拔或udev重新触发时权限会被恢复。曾经有用户反映,在给RAC节点添加一块新硬盘后,所有ASM磁盘的属主全部变回root:disk,直接导致OCR磁盘组无法挂载,数据库实例批量宕机。这个问题的根源就是udev没有持久化的权限绑定规则。

相比之下,ASMLib虽然可以简化设备管理,但需要额外安装内核模块,且在部分新内核上支持不理想。直接使用udev规则绑定设备标识和权限,是更通用、更轻量的方案,官方文档也推荐这种做法。udev规则的核心思路是:通过磁盘的WWID、序列号或UUID等硬件唯一标识,匹配到具体的块设备,然后强制指定属主、组、权限,并创建带有固定名称的符号链接。这样无论内核如何枚举设备,ASM始终可以通过固定链接访问到同一块物理磁盘。

编写udev规则的完整示例与逐行解析

要编写有效的udev规则,首先需要获取磁盘的唯一标识。在Linux中,最常用的命令是scsi_id,它可以读取SCSI磁盘的WWID。执行以下命令可以查看单个磁盘的标识:

# 获取/dev/sdb的WWID
/usr/lib/udev/scsi_id -g -u -d /dev/sdb

返回的字符串通常是一长串十六进制数字,例如360060e80164c210000014c2100000d0f7。这个值在同一块磁盘在所有节点上是一致的,非常适合作为udev规则的匹配依据。需要注意的是,不同Linux发行版中scsi_id的路径可能不同,有的位于/sbin/scsi_id或/lib/udev/scsi_id,可以通过which scsi_id确认。

获取到所有ASM磁盘的WWID后,就可以创建规则文件。建议将规则文件放在/etc/udev/rules.d/目录下,文件名以99-oracle-asm.rules命名,数字越大优先级越高,确保自定义规则能覆盖系统默认规则。下面是一个完整的规则文件示例,适用于四块ASM磁盘,分别对应OCR、VOTE和数据磁盘组:

# /etc/udev/rules.d/99-oracle-asm.rules
KERNEL=="sd*", SUBSYSTEM=="block", ENV{ID_SERIAL}=="360060e80164c210000014c2100000d0f7", OWNER="grid", GROUP="asmadmin", MODE="0660", SYMLINK+="asmdisk/ocr1"
KERNEL=="sd*", SUBSYSTEM=="block", ENV{ID_SERIAL}=="360060e80164c210000014c2100000d0f8", OWNER="grid", GROUP="asmadmin", MODE="0660", SYMLINK+="asmdisk/ocr2"
KERNEL=="sd*", SUBSYSTEM=="block", ENV{ID_SERIAL}=="360060e80164c210000014c2100000d0f9", OWNER="grid", GROUP="asmadmin", MODE="0660", SYMLINK+="asmdisk/vote1"
KERNEL=="sd*", SUBSYSTEM=="block", ENV{ID_SERIAL}=="360060e80164c210000014c2100000d0fa", OWNER="grid", GROUP="asmadmin", MODE="0660", SYMLINK+="asmdisk/data01"

逐行解析一下这些键的含义。KERNEL=="sd*"表示只匹配内核设备名以sd开头的块设备,也就是SCSI/SATA磁盘。SUBSYSTEM=="block"进一步限定为块设备子系统,避免匹配到字符设备。ENV{ID_SERIAL}==后面的值就是之前用scsi_id获取的WWID,这个环境变量由udev在设备初始化时从sysfs中读取并填充,用于唯一标识磁盘硬件。OWNER和GROUP指定设备节点的属主和属组,这里分别是grid用户和asmadmin组,需要和Oracle Grid Infrastructure安装时使用的用户和组保持一致。MODE="0660"将权限设置为属主和同组用户可读写,其他用户无权限,这是ASM设备推荐的安全权限。SYMLINK+="asmdisk/ocr1"会在/dev目录下创建一个名为asmdisk/ocr1的符号链接,指向实际的内核设备节点。ASM磁盘发现路径可以配置为/dev/asmdisk/*,这样就能避免设备名漂移问题。

如果环境中使用了多路径软件如multipath,则应该匹配的是多路径设备而不是底层的sd设备。此时规则中的KERNEL可以改为dm-*,并且ENV{DM_UUID}作为多路径设备的唯一标识。例如:

KERNEL=="dm-*", SUBSYSTEM=="block", ENV{DM_UUID}=="mpath-360060e80164c210000014c2100000d0f7", OWNER="grid", GROUP="asmadmin", MODE="0660", SYMLINK+="asmdisk/ocr1"

这种规则的匹配精度更高,因为多路径屏蔽了底层路径切换的细节,节点上看到的设备始终是稳定聚合后的dm设备。但要注意,多路径设备在udev中的DM_UUID通常带有mpath前缀,需要结合multipath -ll的输出确认具体值。

验证、排错与生产实践建议

编写完规则文件后,需要重新加载udev规则并触发设备重新应用规则。使用以下命令:

udevadm control --reload-rules
udevadm trigger --subsystem-match=block --action=change

第一条命令让udev守护进程重新读取所有规则文件,第二条命令通知内核重新触发块设备的change事件,使新规则立即生效。之后可以检查设备节点和符号链接是否生成正确:

ls -l /dev/asmdisk/
ls -l /dev/sdb

如果符号链接没有出现,或者权限没有变化,可以使用以下命令进行深入排查。首先查看目标设备的所有udev属性:

udevadm info -a -n /dev/sdb

该命令会输出设备链上每个父设备的所有属性键值对,重点确认ID_SERIAL是否存在,以及值是否与规则文件中的一致。如果ID_SERIAL缺失,可能是因为scsi_id工具没有正确集成到udev规则中,需要检查/lib/udev/rules.d/60-persistent-storage.rules是否正常工作。

还可以使用udevadm test命令模拟一次设备事件,查看规则匹配过程:

udevadm test /dev/block/8:16

其中8:16是设备的主次设备号,可以通过lsblk或stat /dev/sdb获取。该命令会打印出所有被匹配的规则以及最终设置的属性,帮助定位是哪一条规则没有命中,或者哪个键值写错了。

在生产实践中,有几个细节值得注意。第一,规则的赋值操作符分为=和+=。对于OWNER、GROUP这类只能出现一次的值,使用=赋值即可;对于SYMLINK,使用+=可以在多个规则中追加链接,避免覆盖其他规则创建的链接。第二,如果磁盘经过重新分区或者更换了控制器,其WWID可能发生变化,此时需要重新收集并更新规则文件。第三,在所有节点上必须保持一致,包括规则文件内容、grid用户的UID和GID,否则即使路径相同,权限检查也会失败。第四,建议在测试环境充分验证重启后的设备状态,并编写自动化检查脚本,在每次重启后对比/dev/asmdisk/下的符号链接与实际设备WWID是否匹配。

广告位 · 文章底部(后台-模块管理替换此区域)