LVM 和多路径过滤字符串

LVM 配置 - 过滤器参数

主要的 LVM 配置文件是 /etc/lvm/lvm.conf 。
该文件由多个部分组成,每个部分都包含各种参数/值。
本文特别关注设备部分中的过滤器参数。

以下是一个示例 lvm.conf 文件:

devices {
    dir = "/dev"
    scan = [ "/dev" ]
    obtain_device_list_from_udev = 1
    preferred_names = [ ]
    filter = [ "a/.*/" ]
    cache_dir = "/etc/lvm/cache"
    cache_file_prefix = ""
    write_cache_state = 1
    sysfs_scan = 1
    multipath_component_detection = 1
    md_component_detection = 1
    md_chunk_alignment = 1
    default_data_alignment = 0
    data_alignment_detection = 1
    data_alignment = 0
    data_alignment_offset_detection = 1
    ignore_suspended_devices = 0
    disable_after_error_count = 0
    require_restorefile_with_uuid = 1
    pv_min_size = 2048
    issue_discards = 0
}
log {
    verbose = 0
    syslog = 1
    overwrite = 0
    level = 0
    indent = 1
    command_names = 0
    prefix = "  "
}
backup {
    backup = 1
    backup_dir = "/etc/lvm/backup"
    archive = 1
    archive_dir = "/etc/lvm/archive"
    retain_min = 10
    retain_days = 30
}
shell {
    history_size = 100
}
global {
    umask = 077
    test = 0
    units = "h"
    si_unit_consistency = 0
    activation = 1
    proc = "/proc"
    locking_type = 1
    wait_for_locks = 1
    fallback_to_clustered_locking = 1
    fallback_to_local_locking = 1
    locking_dir = "/var/lock/lvm"
    prioritise_write_locks = 1
    abort_on_internal_errors = 0
    detect_internal_vg_cache_corruption = 0
    metadata_read_only = 0
}
activation {
    checks = 0
    udev_sync = 1
    udev_rules = 1
    verify_udev_operations = 0
    missing_stripe_filler = "error"
    reserved_stack = 256
    reserved_memory = 8192
    process_priority = -18
    mirror_region_size = 512
    readahead = "auto"
    mirror_log_fault_policy = "allocate"
    mirror_image_fault_policy = "remove"
    snapshot_autoextend_threshold = 100
    snapshot_autoextend_percent = 20
    use_mlockall = 0
    monitoring = 1
    polling_interval = 15
}
dmeventd {
    mirror_library = "libdevmapper-event-lvm2mirror.so"
    snapshot_library = "libdevmapper-event-lvm2snapshot.so"
}

默认情况下,在系统启动时,LVM 会扫描由 filter 参数定义的设备以发现 LVM 设备。
使用上面的默认过滤器字符串 (filter = [ "a/.*/" ] ),LVM 扫描系统上所有可用的设备。
随着 PV 被发现,VG 被组装,LV 被激活,然后文件系统(如果存在)随后被挂载。

对于连接了大量存储设备 (LUN) 的系统,LVM 可能不需要或者不需要扫描每个可用设备。
在这种情况下,可以修改(优化)LVM 过滤器字符串以扫描用户指定的一组设备。

LVM 和多路径

除了本地存储,用户通常在 SAN 存储上创建 LVM 设备。
此外,对 SAN 存储的访问通常是多路径的,例如:系统上存在指向同一 SAN LUN 的多条路径。
在 device-mapper-multipath(原生 Oracle Linux 多路径解决方案)的情况下,可能存在以下所有引用相同 SAN LUN 的设备:

/dev/mapper/mpath1
/dev/dm-1
/dev/sda
/dev/sdb

EMC PowerPath 的多路径实施有所不同,可能存在以下所有引用相同 SAN LUN 的设备:

/dev/emcpowera
/dev/sda
/dev/sdb

如前所述,默认的 lvm.conf 过滤器字符串值指示 LVM 扫描所有连接/可用的设备。
不幸的是,这在将 LVM 与多路径结合使用时可能会出现问题。
根据设备(路径)发现顺序,LVM 最终可能会使用单路径设备,例如/dev/sd[a,b] 来构建 VG 而不是使用预期的多路径设备,例如/dev/mapper/mpath1.如果发生这种情况,LVM 设备将无法获得多路径的好处,例如:路径丢失冗余、高可用性等。
同样的问题同样适用于配置了从 SAN 引导的系统。

当使用多路径的 LVM 系统没有最佳配置以排除单路径设备时,通常会观察到如下消息:

# pvs
  Found duplicate PV Yvq85ssLqAXeBvZpVtAqBIbm44KU8cd5: using /dev/dm-1 not /dev/sda
  Found duplicate PV Yvq85ssLqAXeBvZpVtAqBIbm44KU8cd5: using /dev/mapper/mpath1 not /dev/dm-1
  Found duplicate PV Yvq85ssLqAXeBvZpVtAqBIbm44KU8cd5: using /dev/sdb not /dev/mapper/mpath1
  PV                  VG         Fmt  Attr PSize  PFree
  /dev/sdb            VolGroup01 lvm2 a--   1.00G 1.00G
  /dev/cciss/c0d0p2   VolGroup00 lvm2 a--  48.81G    0

 

上面,LVM 错误地使用了单路径设备 /dev/sdb 而不是多路径设备 /dev/mapper/mpath1.
为确保 LVM 使用预期的存储设备/路径,请自定义 LVM 过滤器字符串以明确包括和/或者排除想要和/或者不需要的设备。
由于可用的本地和 SAN 存储的范围和种类繁多,没有一种 LVM 文件配置一定适合所有可能的部署。
因此,必须为各个系统/存储组合自定义 LVM 过滤器字符串。

示例 LVM 过滤器字符串

本节提供了不完整范围的示例 LVM 过滤器字符串值。
请注意,LVM 接受过滤字符串值的正则表达式语法的各种组合。
以下示例表示一种这样的变体,但是,也接受其他变体/组合。
但是,LVM 会在出现重大语法错误时很容易地抱怨。

接受(a) 过滤器

Filter Meaning
filter = [ "a/.*/" ] 所有设备
filter = [ "a|^/dev/sd*|" ] All SCSI devices only
filter = [ "a|^/dev/sda|" ] SCSI device /dev/sda
filter = [ "a|^/dev/sda[1-9]$|" ] All partitions on SCSI device /dev/sda only
filter = [ "a|^/dev/cciss/*|" ] HP SmartArray controlled devices (cciss) only
filter = [ "a|^/dev/loop*|" ] All loop devices - /dev/loop*
filter = [ "a|^/dev/loop1[0-2]$|" ] Loop devices 10, 11, 12 only - /dev/loop1[0-2]
filter = [ "a|^/dev/hda1$|" ] Partition 1 on IDE device /dev/hda
filter = [ "a|^/dev/mapper/*|" ] device mapper multipath devices
filter = [ "a|^/dev/emcpower*|" ] All EMC PowerPath devices
filter = [ "a|^/dev/vpath[a-z]*|" ] All IBM Subsystem Device Driver (SDD) devices
filter = [ "a|^/dev/sddlm*|" ] All Hitachi Dynamic Link Manager (HDLM) devices

拒绝(r)过滤器

Filter Meaning
filter = [ "r|^/dev/*|" ] 所有设备
filter = [ "r|^/dev/cdrom|" ] CD/DVD 设备 /dev/cdrom
filter = [ "r|^/dev/hdc|" ] 仅 IDE 设备 /dev/hdc

LVM 过滤器字符串可以根据需要单独指定或者结合使用多个值。
为避免歧义或者意外的设备扫描/使用,应定义任何预期的设备 (a),然后紧跟明确的排除字符串 (r) 以防止扫描/使用任何其他设备。

LVM 过滤器字符串的工作示例

在本地 SCSI 存储和设备映射器多路径 SAN 存储上具有 LVM 设备的系统可能定义:

filter = [ "a|^/dev/sda[1-9]$|", "a|^/dev/mapper/*|", "r|^/dev/*|" ]

在本地 Smart Array 存储和远程 EMC PowerPath SAN 存储上具有 LVM 设备的 HP 系统可能定义:

filter = [ "a|^/dev/cciss/*|", "a|^/dev/emcpower*|", "r|^/dev/*|" ]

在本地 SCSI 存储和 IBM 子系统设备驱动程序 SAN 存储上具有 LVM 设备的系统可能定义:

filter = [ "a|^/dev/sda[1-9]$|", "a|^/dev/vpath[a-z]*|", "r|^/dev/*|" ]

验证候选 LVM 过滤器字符串

在设计和测试 LVM 过滤器字符串时,确保 LVM 发现/使用所有(且仅)预期设备,并且不会扫描/使用其他非预期设备。
验证过程应包括以下内容:

  • 备份原来的/etc/lvm/lvm.conf文件
  • 可选择使用 lvmpdump 来备份整个 LVM 配置
  • 根据需要自定义 LVM 过滤器字符串,例如:/etc/lvm/lvm.conf: filter = [...]
  • 删除 LVM 缓存文件,例如# /bin/rm /etc/lvm/cache/.cache
  • 重新扫描 LVM 设备,例如# /sbin/pvscan -vv

pvscan 输出的“遍历所有物理卷”部分中列出的设备表示 LVM 扫描了哪些设备。
pvscan 输出的结尾分列出了发现的任何/所有 PV 设备。
请注意,不正确或者未优化配置的 LVM 过滤器字符串可能会导致:

  • 使用非预期设备,例如单路径而不是多路径
  • 不必要的 LVM 设备扫描,导致系统启动时间延长
  • 未能发现预期的 LVM 设备,导致设备/文件系统不可用
  • 无法启动系统,例如:内核崩溃等。

以下系统控制台输出表示系统无法找到包含根文件系统的 LVM 设备时的典型引导时间消息:

root (hd0,0)
Filesystem type is ext2fs, partition type 0x83
kernel /vmlinuz-2.6.18-348.el5 ro root=/dev/VolGroup00/root 3 crashkernel=128@16M elevator=deadline
 [Linux-bzImage, setup=0x1e00, size=0x1fd6fc]
initrd /initrd-2.6.18-348.el5.img
 [Linux-initrd @ 0x37a7c000, 0x57396d bytes]
Warning: pci_mmcfg_init marking 256MB space uncacheable.
Red Hat nash version 5.1.19.6 starting.
lpfc 0000:06:00.0 0:1303 Link Up Event x1 received Data : x1 xf7 x10 x9 x0 x0 0
lpfc 0000:06:00.1 1:1303 Link Up Event x1 received Data : x1 xf7 x10 x9 x0 x0 0
Unable to access resume device (/dev/VolGroup00/swap)
mount: could not find filesystem '/dev/root'
setuproot: moving /dev failed: No such file or directory
setuproot: error mounting /proc: No such file or directory
setuproot: error mounting /sys: No such file or directory
switchroot: mount failed: No such file or directory
Kernel panic - not syncing: Attempted to kill init!

实施 LVM 配置更改

lvm.conf 文件的副本存储在系统启动期间使用的系统初始 ram 磁盘 (initrd) 文件中。
因此,LVM 配置更改保证了 initrd 的重建,以使更改在引导时生效。
定义/验证适当的 LVM 过滤器后,执行以下操作:

  1. 删除 LVM 缓存文件,例如
# rm /etc/lvm/cache/.cache
  1. 重建初始ramdisk(initrd)如下

请注意,使用错误配置的 LVM 过滤器重建 initrd 文件可能会导致系统启动完全失败。
因此,提供以下替代方法来帮助防止此类故障。

选项 1(推荐)

此选项涉及定义新的 GRUB 内核引导条目,以便在不覆盖当前 initrd 的情况下测试 LVM 更改。

# cd /boot
# mkinitrd -v -f /boot/initrd-`uname -r`.LVM.img `uname -r`
Creating initramfs
...
# ls -lart
...
-rw-------  1 root root 3805700 Nov  1 16:40 initrd-2.6.18-348.el5.LVM.img

接下来,查看 GRUB 配置文件 /boot/grub/grub.conf。
以标题开头的 GRUB 内核引导项一个接一个地列出。
default 参数的值定义了当前的默认引导内核。
GRUB 引导条目编号从零 (0) 开始,因此:

default=0 指的是第一个列出的 GRUB 内核引导条目。

default=3 是指列出的第四个 GRUB 内核引导条目。

复制默认内核启动项下面的所有行。
修改新内核引导项的 initrd 行以反映新创建的 initrd 文件的名称。
修改默认参数的值以反映新创建的 GRUB 内核引导项。
如果原始默认参数值为 0 并且在其正下方创建了新的 GRUB 条目,请将默认参数值修改为 1,例如:

# cat /etc/grub/grub.conf
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE:  You have a /boot partition.  This means that
#          all kernel and initrd paths are relative to /boot/, eg.
#          root (hd0,0)
#          kernel /vmlinuz-version ro root=/dev/VolGroup00/LogVol00
#          initrd /initrd-version.img
#boot=/dev/sda
#default=0
default=1
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title Oracle Linux Server (2.6.18-348.el5)
        root (hd0,0)
        kernel /vmlinuz-2.6.18-348.el5 ro root=/dev/VolGroup00/LogVol00 crashkernel=128M@32 numa=off
        initrd /initrd-2.6.18-348.el5.img
title Oracle Linux Server (2.6.18-348.el5) LVM
        root (hd0,0)
        kernel /vmlinuz-2.6.18-348.el5 ro root=/dev/VolGroup00/LogVol00 crashkernel=128M@32 numa=off
        initrd /initrd-2.6.18-348.el5.LVM.img
...

重新启动后,系统将使用新创建的 GRUB 引导项进行引导,包括新创建的 initrd。
如果出现任何问题,请重新引导系统,中断引导过程以访问 GRUB 菜单并选择使用原始引导条目引导系统。

选项 2(专家)

此选项涉及覆盖现有的默认 GRUB 内核引导项并覆盖当前的 initrd。

# cd /boot
# mv initrd-`uname -r`.img initrd-`uname -r`.img.orig
# mkinitrd -v -f /boot/initrd-`uname -r`.img `uname -r`
Creating initramfs
...

重新启动后,系统将使用现有的 GRUB 引导但使用新重建的 initrd。

  1. 重新启动后,确认所有 LVM 设备(PV、VG、LV)都存在并且正在使用预期的物理和/或者多路径设备。
    对任何进一步的 LVM 过滤器配置优化或者在进一步的 LVM/存储更改/重组需要重新配置时重复上述操作。

 

 

 

 

 

 

 

 

 

 

 

 

THE END