配置 GFS2 文件系统

Red Hat Enterprise Linux 9

在高可用性集群中规划、管理、故障排除和配置 GFS2 文件系统

Red Hat Customer Content Services

摘要

Red Hat Enterprise Linux (RHEL) Resilient Storage 附加组件提供 Red Hat Global File System 2 (GFS2),一个管理共享一个通用块设备的多个节点间一致性的集群文件系统。这个标题提供有关规划 GFS2 文件系统部署的信息,以及配置、故障排除和调优 GFS2 文件系统的流程。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。详情请查看 CTO Chris Wright 的信息

对红帽文档提供反馈

我们感谢您对我们文档的反馈。让我们了解如何改进它。

通过 Jira 提交反馈(需要帐户)

  1. 登录到 Jira 网站。
  2. 在顶部导航栏中点 Create
  3. Summary 字段中输入描述性标题。
  4. Description 字段中输入您对改进的建议。包括文档相关部分的链接。
  5. 点对话框底部的 Create

第 1 章 规划 GFS2 文件系统部署

Red Hat Global File System 2 (GFS2) 是一个 64 位对称集群文件系统,它提供了一个共享名称空间,并管理共享一个常见块设备的多个节点间的一致性。GFS2 文件系统旨在提供尽量与本地文件系统类似的功能,同时在节点间强制实施完整集群一致性。为达到此目的,节点在文件系统资源中使用集群范围的锁定方案。这个锁定方案使用 TCP/IP 等通讯协议来交换锁定信息。

在某些情况下,Linux 文件系统 API 不允许具有集群特性的 GFS2 完全透明。例如,在 GFS2 中使用 POSIX 锁定的程序应该避免使用 GETLK 功能,因为在集群的环境中,该进程 ID 可能用于集群中的不同节点。然而,多数情况下 GFS2 文件系统的功能和本地文件系统的功能是一样的。

Red Hat Enterprise Linux (RHEL) Resilient Storage Add-On提供 GFS2,它依赖于 RHEL High Availability 附加组件来提供 GFS2 所需的集群管理功能。

gfs2.ko 内核模块实现 GFS2 文件系统,并加载在 GFS2 集群节点上。

要获得最佳 GFS2 性能,请务必考虑基础设计中给出的性能注意事项。和本地文件系统一样,GFS2 依赖于页面缓存以便通过本地缓存来提高经常使用数据的性能。为了在集群中的节点间保持一致性,缓存控制由 glock 状态机器提供。

重要

请确定您部署的 Red Hat High Availability Add-On红 满足您的需要并可支持。部署前请咨询权威红帽代表确认您的配置。

1.1. GFS2 文件系统格式版本 1802

从 Red Hat Enterprise Linux 9 开始,使用格式 1802 创建 GFS2 文件系统。

格式版本 1802 启用以下功能:

  • trusted 命名空间的扩展属性 ("trusted.* xattrs") 可被 gfs2gfs2-utils 识别。
  • rgrplvb 选项默认为活动状态。这允许 allowgfs2 将更新的资源组数据附加到 DLM 锁定请求,因此获取锁定的节点不需要从磁盘更新资源组信息。这在某些情况下提高了性能。

使用新格式版本创建的文件系统将无法安装在较早的 RHEL 版本下,并且较旧版本的 fsck.gfs2 实用程序将无法检查它们。

用户可以运行带有 -o format=1801 选项的 mkfs.gfs2 命令,创建采用较旧版本的文件系统。

用户可以在卸载的文件系统中通过运行 tunegfs2 -r 1802 device 来升级旧文件系统的格式版本。不支持降级格式版本。

1.2. 要决定的主要 GFS2 参数

在安装和配置 GFS2 文件系统前,您应该规划多个关键 GFS2 参数。

GFS2 节点
决定集群中的哪些节点将挂载 GFS2 文件系统。
文件系统的数量
决定初始创建多少个 GFS2 文件系统。之后,可以添加更多文件系统。
文件系统名称
每个 GFS2 文件系统都应该有一个唯一的名称。这个名称通常与 LVM 逻辑卷名称相同,在挂载 GFS2 文件系统时可作为 DLM 锁定表名称使用。例如,本指南在一些示例中使用文件系统名 mydata1mydata2
Journals(日志)
决定 GFS2 文件系统的日志数。GFS2 需要集群中的每个需要挂载文件系统的日志的节点都具有一个日志。例如,如果您有一个 16 个节点的集群,但只需要从两个节点挂载文件系统,则只需要两个日志。通过 GFS2,您可以将 gfs2_jadd 实用程序动态添加日志作为附加服务器挂载文件系统。
存储设备和分区
确定用于在文件系统中创建逻辑卷(使用 lvmlockd)的存储设备和分区。
时间协议

请确定 GFS2 节点中的时钟是同步的。推荐使用 Precision Time Protocol (PTP),或在如果需要,使用由您的 Red Hat Enterprise Linux 系统提供的 Network Time Protocol (NTP) 软件。

不同 GFS2 节点间的系统时钟必须保持在几分钟内,以防止不必要的内节点(inode)时间戳更新。不必要的内节点时间戳更新会严重影响集群的性能。

注意

当同时在同一目录中执行多个生成和删除操作时,GFS2 可能会出现性能问题。如果在系统中造成性能问题,您应该将节点创建和删除的文件本地到特定于该节点的目录。

1.3. GFS2 支持注意事项

要有资格获得红帽对运行 GFS2 文件系统的集群的支持,您必须考虑 GFS2 文件系统的支持政策。

1.3.1. 最大文件系统和集群大小

下表总结了当前的最大文件系统大小以及 GFS2 支持的节点数量。

表 1.1. GFS2 支持限制

参数最大值

节点数

16(X86, PowerVM 中的 Power8)

4(z/VM 中的 s390x)

文件系统大小

所有支持的构架都为 100TB

GFS2 是基于 64 位构架,理论上可提供 8 EB 文件系统。如果您的系统需要比目前支持的更大的 GFS2 文件系统,请联络您的红帽服务代表,

在决定文件系统大小时,您应该考虑您的恢复需求。在大型文件系统中运行 fsck.gfs2 命令需要很长时间且消耗大量内存。另外,当磁盘或者磁盘子系统失败时,恢复时间受您的备份介质速度的限制。有关 fsck.gfs2 命令需要的内存量的信息,请参阅 确定运行 fsck.gfs2 所需的内存

1.3.2. 最小集群大小

虽然 GFS2 文件系统可在独立系统或作为集群配置的一部分实现,但红帽不支持将 GFS2 作为单节点文件系统使用,但以下情况除外:

  • 例如,为了备份,红帽支持挂载集群文件系统快照的单节点 GFS2 文件系统。
  • 对于辅助站点灾难恢复(DR)节点,支持挂载 GFS2 文件系统(使用 DLM)的单节点集群。这个例外仅用于 DR 目的,不适用于将主集群工作负载转移到二级站点。

    例如,在主站点离线的情况下,支持复制辅助站点挂载的文件系统的数据。但是,不支持将工作负载从主站点直接迁移到单节点集群次要站点。如果需要将完整工作负载迁移到单节点次要站点,则次要站点的大小必须与主站点相同。

    红帽建议当您在单节点集群中挂载 GFS2 文件系统时,您可以指定 errors=panic 挂载选项,以便在 GFS2 撤回发生时单一节点集群会出现 panic,因为单节点集群在遇到文件系统错误时将无法隔离自己。

红帽支持很多为单一节点优化的高性能单节点文件系统,因此开销通常比集群文件系统的低。红帽建议您在只需要单节点挂载文件系统的情况下首选使用这些文件系统,而不是 GFS2。有关 Red Hat Enterprise Linux 9 支持的文件系统的详情,请参考 管理文件系统

1.3.3. 共享存储注意事项

当在 LVM 之外使用 GFS2 文件系统时,红帽只支持在共享 LVM 逻辑卷中创建的 GFS2 文件系统。

当您将 GFS2 文件系统配置为集群文件系统时,您必须确定集群中的所有节点都可访问共享存储。不支持非对称集群配置(集群中有些节点可访问共享存储而其他节点不能访问共享存储)。这并不需要所有节点都确实挂载到 GFS2 文件系统中。

1.4. GFS2 格式化注意事项

要格式化 GFS2 文件系统以优化性能,您应该考虑这些建议。

重要

请确定您部署的 Red Hat High Availability Add-On红 满足您的需要并可支持。部署前请咨询权威红帽代表确认您的配置。

文件系统大小:较小越好

GFS2 是基于 64 位构架,理论上可提供 8 EB 文件系统。但是,目前支持的 64 位硬件的最大 GFS2 文件系统为 100TB。

注:虽然有可能使用 GFS2 大文件系统,但并不意味着推荐使用它们。GFS2 的一般原则是容量越小越好:最好使用 10 个 1TB 文件系统而不是使用一个 10TB 文件系统。

尽量保持 GFS2 文件系统较小的原因是:

  • 备份每个文件系统需要较少的时间。
  • 如果您需要使用 fsck.gfs2 命令检查文件系统,则需要较少的时间。
  • 如果您需要使用 fsck.gfs2 命令检查文件系统,则需要较少的内存。

另外,需要较少的资源组来保持更好的性能。

当然,如果您的 GFS2 文件系统太小,可能没有足够空间,这本身就会产生一定后果。在决定大小之前,您应该考虑您自己的具体用例。

块大小:默认(4K)块首选

mkfs.gfs2 命令会尝试根据设备拓扑估算最佳块大小。通常, 4K 块是首选块大小,因为 4K 是 Red Hat Enterprise Linux 的默认页面大小(内存)。与其他一些文件系统不同,GFS2 使用 4K 内核缓冲进行大多数操作。如果您的块大小是 4K,那么内核会在操作缓冲区时进行较少的工作。

建议您使用默认块大小,这样可获得最好的性能。只有在需要有效存储许多小文件时才可能需要使用不同的块大小。

日志大小:默认(128MB)通常是最佳设置

当您运行 mkfs.gfs2 命令创建 GFS2 文件系统时,可以指定日志的大小。如果您没有指定大小,则默认为 128MB,这应该适用于大多数应用程序。

有些系统管理员可能会认为 128MB 过大,并尝试将日志大小降低为最小的 8MB 或者更传统的 32MB。虽然这样可能会正常工作,但可能会严重影响性能。与很多日志记录文件系统类似,GFS2 每次写入元数据时,会在日志发出前将其提交到日志中。这样可确保系统崩溃或断电,当日志在挂载时自动重新显示时,您将恢复所有元数据。但是,它没有太多文件系统活动来填充 8MB 日志,当日志满时,性能会慢,因为 GFS2 必须等待写入存储。

通常建议您使用默认的 128MB 的日志大小。如果您的文件系统非常小(例如 5GB),拥有 128MB 日志可能不太现实。如果您有一个大的文件系统并且可以获得更多的存储空间,则使用 256MB 日志可能会提高性能。

资源组的大小和数目

使用 mkfs.gfs2 命令创建 GFS2 文件系统时,它会将存储划分为统一的分片,称为资源组。它试图估算一个最佳资源组群大小(从 32MB 到 2GB)。您可以使用 mkfs.gfs2 命令的 -r 选项覆盖默认设置。

您的最佳资源组群大小取决于您的文件系统如何使用。考虑它的使用情况,以及是否产生大量碎片。

您应该使用不同的资源组大小进行测试,以了解哪些配置具有最佳性能。最好在将 GFS2 部署到完整产品前测试测试集群。

如果您的文件系统有太多资源组,则每个资源组太小,块分配可能会浪费大量时间为空闲块搜索成千上万的资源组。更加完整的文件系统、将搜索更多资源组,其中每个组都需要一个集群范围的锁定。这会导致性能下降。

然而,,果您的文件系统资源组太少,且每个资源组太大,块分配可能会更频繁地影响到同一资源组锁定,这也会影响到性能。例如:如果您有一个 10GB 文件系统被分为 5 个 2GB 资源组,则集群中的节点会比相同的文件系统被分成 320 个 32MB 的资源组更频繁竞争使用这 5 个资源组。如果您的文件系统计划已被完全占用,则这个问题会更加严重,因为每个块分配可能需要查看多个资源组才能找到可用块。GFS2 尝试以两种方式缓解这个问题:

  • 首先,当资源组完全满时,它会记住,并尝试避免在将来分配时检查它们,直到块从中释放。如果您从不删除文件,则这个问题并不严重。但是,如果您的应用程序正在持续删除块并在文件系统中分配最多完全的新块,则竞争会非常高,并且会对性能有严重影响。
  • 其次,当在现有文件中添加新块时,GFS2 将尝试将新块分组到与该文件相同的资源组群中。这么做的目的是为了提高性能:在旋转磁盘中,如果存储在物理位置上接近,则操作需要较少的时间。

最糟糕的情况是,当存在所有节点创建文件的中央目录时,因为所有节点都会持续努力锁定同一资源组。

1.5. 集群中 GFS2 的注意事项

在决定您系统包含的节点数量时,请注意高可用性和性能之间有一个利弊关系。在有大量节点时,更难以扩展工作负载。因此,红帽不支持将 GFS2 用于部署超过 16 个节点的集群文件系统。

部署集群文件系统不是单一节点部署的"拖放"替换。红帽建议您预留约 8-12 周的时间测试新的安装,以便测试该系统并确保其在所需性能水平正常工作。在此阶段,可解决所有性能和功能问题,且所有查询都可提交红帽支持团队。

红帽建议考虑部署集群的用户在部署前由红帽支持审核其配置,以避免以后出现可能的支持问题。

1.6. 硬件注意事项

在部署 GFS2 文件系统时,请考虑以下硬件注意事项。

  • 使用更高质量的存储选项

    GFS2 可以在更便宜的共享存储选项上运行,如 iSCSI 或以太网光纤通道(FCoE),但如果您购买具有更大的缓存容量的质量存储,您将会获得更好的性能。红帽通过光纤通道互连对 SAN 存储执行最高质量的、健全性和性能测试。作为常规规则,最好先部署已经测试的对象。

  • 在部署前测试网络设备

    高质量的、更快的网络设备可使集群和 GFS2 速度更快,且更可靠。然而,您并不要一定要买最昂贵的硬件。某些最昂贵的网络交换机通过多播数据包传递问题,它们用于传递 fcntl 锁定(flocks),而更便宜的商用网络交换机有时会更可靠。红帽建议您在将其部署到生产环境中前,对设备进行全面测试。

第 2 章 关于 GFS2 使用的建议

在部署 GFS2 文件系统时,您应该考虑各种常规建议。

2.1. 配置 atime 更新

每个文件内节点和目录内节点都有三个与之关联的时间戳:

  • ctime - 最后一次内节点(inode)状态发生变化的时间
  • mtime - 修改文件(或目录)数据最后一次的时间
  • atime - 最后一次访问文件(或目录)数据的时间

如果默认在 GFS2 和其他 Linux 文件系统上启用了 atime 更新,那么每次读取文件时都需要更新其内节点。

因为有些应用程序使用由 atime 提供的信息,因此这些更新可能需要大量不必要的写入流量和文件锁定流量。该流量可能会降低性能,因此最好关闭或降低 atime 更新的频率。

以下是减少 atime 更新影响的方法:

  • 使用 relatime (相对 atime)挂载,如果以前的 atime 更新比 mtimectime 更新早,则更新 atime。这是 GFS2 文件系统的默认挂载选项。
  • 带有 noatimenodiratime 的挂载。使用 noatime 挂载时会禁用在那个文件系统上的文件和目录的 atime 更新;使用 nodiratime 挂载会禁用那个文件系统上的目录的 atime 更新。通常建议尽可能将 GFS2 文件系统挂载为使用 noatimenodiratime 挂载选项,而在允许的情况下首选使用 noatime。有关这些参数对 GFS2 文件系统性能的影响的更多信息,请参阅 GFS2 节点锁定

使用以下命令使用 noatime Linux 挂载选项挂载 GFS2 文件系统。

mount BlockDevice MountPoint -o noatime
BlockDevice
指定 GFS2 文件系统所在的块设备。
MountPoint
指定要挂载 GFS2 文件系统的目录。

在这个示例中,GFS2 文件系统位于 /dev/vg01/lvol0 上,并挂载到目录 /mygfs2 中,atime 更新被关闭。

# mount /dev/vg01/lvol0 /mygfs2 -o noatime

2.2. VFS 调整选项:研究和实验

和所有 Linux 文件系统一样,GFS2 位于名为虚拟文件系统(VFS)的层上。VFS 为大多数工作负载的缓存设置提供了很好的默认值,多数情况下不需要修改。但是,您有一个无法高效运行的工作负载(例如,缓存太大或太小),那么您可以使用 sysctl (8)命令来调整 /proc/sys/vm 目录中的 sysctl 文件的值。有关这些文件的文档可在内核源树文档 /sysctl/vm.txt 中找到。

例如,根据具体情况,可以调整 dirty_background_ratiovfs_cache_pressure 的值。要获取当前值,请使用以下命令:

# sysctl -n vm.dirty_background_ratio
# sysctl -n vm.vfs_cache_pressure

以下命令调整值:

# sysctl -w vm.dirty_background_ratio=20
# sysctl -w vm.vfs_cache_pressure=500

您可以通过编辑 /etc/sysctl.conf 文件来永久更改这些参数的值。

要找到您的使用案例的最佳值,请在部署到完整产品前检查各种 VFS 选项并在测试集群中进行实验。

2.3. GFS2 中的 SELinux

在 GFS2 中使用 Security Enhanced Linux(SELinux)会导致性能小。为了避免这种性能损失,您可能会选择在 GFS2 中不使用 SELinux,即使其所在的系统中的 SELinux 处于 enforcing 模式。挂载 GFS2 文件系统时,您可以使用 context 选项(如 mount(8)man page 所述)确定 SELinux 不会尝试读每个文件系统项中的 seclabel 元素。SELinux 会假设文件系统中的所有内容都被 context 挂载选项提供的 seclabel 元素进行标记。这也将加快处理速度,因为它避免了可能包含 seclabel 元素的扩展属性块的另一个磁盘。

例如:在采用 enforcing 模式的 SELinux 的系统中,如果文件系统将要包含 Apache 内容,您可以使用以下 mount 命令挂载 GFS2 文件系统。这个标签将应用于整个文件系统,它会保留在内存中,不会被写入磁盘。

# mount -t gfs2 -o context=system_u:object_r:httpd_sys_content_t:s0 /dev/mapper/xyz/mnt/gfs2

如果您不确定文件系统是否包含 Apache 内容,您可以使用标签 public_content_rw_tpublic_content_t,或者定义一个新标签并为其定义策略。

请注意,在一个 Pacemaker 集群中,应该一直使用 Pacemaker 管理 GFS2 文件系统。您可在创建 GFS2 文件系统资源时指定挂载选项。

2.4. 使用 GFS2 设置 NFS

由于 GFS2 锁定子系统及其集群性质增加了复杂性,因此通过 GFS2 设置 NFS 需要花费很多问题。

警告

如果导入了 GFS2 文件系统,则必须使用 localflocks 选项挂载文件系统。因为使用 localflocks 选项可防止您从多个位置安全地访问 GFS2 文件系统,因此无法同时从多个节点导出 GFS2。在使用此配置时,在同一时间只在一个节点上挂载 GFS2 文件系统是被支持的条件。这样做预期的效果是将每个服务器的 POSIX 锁定强制为本地:非集群,相互独立。这是因为 GFS2 试图在集群节点间从 NFS 部署 POSIX 锁定会有很多问题。对于在 NFS 客户端中运行的应用程序,如果两个客户端从不同的服务器挂载,本地化 POSIX 锁定意味着两个客户端可同时拥有相同的锁定,从而导致数据崩溃。如果所有客户端都从一个服务器中挂载 NFS,那么不同服务器单独赋予同一锁定的问题就不存在。如果您不确定是否使用 localflocks 选项挂载文件系统,则不应使用这个选项。立即联系红帽支持,讨论适当的配置以避免数据丢失。我们不推荐通过 NFS 导出 GFS2,但在某些情况下并不支持。

对于所有其他(非 NFS)GFS2 应用程序,不要使用 localflocks 挂载文件系统,因此 GFS2 将管理集群中的所有节点之间的 POSIX 锁定和 flocks。如果您指定了 localflocks 且不使用 NFS,集群中的其它节点将不知道其他节点的 POSIX 锁定和 flock,因此它们在一个集群的环境中不安全

除锁定注意事项外,您应该在通过 GFS2 文件系统配置 NFS 时考虑以下问题。

  • 红帽只支持使用带主动/被动锁定的 NFSv3 进行红帽高可用性附加组件配置,并具有以下特征。此配置为文件系统提供高可用性(HA),并减少系统停机,因为故障的节点在 NFS 服务器故障到另一个节点时不需要执行 fsck 命令。

    • 后端文件系统是在 2 到 16 个节点集群中运行的 GFS2 文件系统。
    • NFSv3 服务器的定义是一次从单一集群节点中导出整个 GFS2 文件系统的服务。
    • NFS 服务器可以从一个集群节点故障切换到另外一个节点(主动/被动配置)。
    • 不允许访问 GFS2 文件系统, 除非 通过 NFS 服务器。这包括本地 GFS2 文件系统访问以及通过 Samba 或者集群的 Samba 访问。通过挂载该文件系统的集群节点在本地访问文件系统可能会导致数据崩溃。
    • 在该系统中不支持 NFS 配额。
  • 对于 GFS2 的 NFS 导出,需要 fsid= NFS 选项。
  • 如果您的集群出现问题(例如,群集变得不连续且隔离不成功),则集群逻辑卷和 GFS2 文件系统将变得冻结,且在集群被仲裁前可能无法访问。在确定一个简单的故障切换解决方案时,您应该考虑这一点,比如选择在这个过程中定义的最适合您的系统的解决方案。

2.5. 使用 GFS2 提供 Samba(SMB 或者 Windows)文件

您可以使用由 CTDB 提供的 GFS2 文件系统提供的 Samba(SMB 或者 Windows)文件,该文件允许主动/主动配置。

不支持从 Samba 以外同时访问 Samba 共享的数据。目前不支持 GFS2 集群租期,这可延迟 Samba 文件服务。有关 Samba 支持政策的更多信息,请参阅 RHEL Resilient Storage 的支持策略 - ctdb 常规策略RHEL Resilient Storage 的支持策略 - 通过其他协议导出 gfs2 内容

2.6. 为 GFS2 配置虚拟机

当在虚拟机中使用 GFS2 文件系统时,务必要正确配置每个节点中的虚拟机存储设置,以便强制关闭缓存。例如:在 libvirt 域中包括 cacheio 的这些设置应该允许 GFS2 的行为如预期。

<driver name='qemu' type='raw' cache='none' io='native'/>

另外,您可以在 device 元素中配置 shareable 的属性。这表示在域间应该共享该设备(只要虚拟机监控程序支持和操作系统支持)。如果使用 shareable,则 cache='no' 应该为该设备使用。

2.7. 块分配

尽管只写数据的应用程序通常无法无需了解如何或在哪里分配块,但了解块分配如何工作可帮助您优化性能。

2.7.1. 在文件系统中保留空闲空间

当 GFS2 文件系统接近满时,块分配程序在分配新块时会比较困难。因此,所有分配器给出的块往往会被限制在资源组的末尾,或者更有可能将大量文件碎片处理。该文件的碎片可能会导致性能问题。另外,当 GFS2 文件系统接近满时,GFS2 块分配程序会通过多个资源组花费较长时间搜索,同时添加了锁定竞争,且不一定在该文件系统中有足够剩余空间。这也可能导致性能问题。

由于这些原因,建议您不要运行一个超过 85% 的文件系统,但这个数字会根据工作负载的不同而有所不同。

2.7.2. 在可能的情况下,每个节点分配自己的文件

当为 GFS2 文件系统开发应用程序时,建议您在可能的情况下为每个节点分配它自己的文件。由于分布式锁管理器(DLM)的工作方式,如果所有文件都被一个节点分配,则有更多锁定竞争,而其他节点则需要向这些文件添加块。

过去,术语"锁 master"过去用于表示当前锁定请求的协调者,这些请求源自于本地或来自集群中的远程节点。锁定请求协调器的术语稍具误导,因为它实际上是一个资源(在 DLM 术语中),与锁定请求是排队、拒绝或拒绝的关系。在 DLM 中使用术语的意义上,应该使用 "first among equals",因为 DLM 是一个 peer-to-peer 系统。

在 Linux 内核 DLM 实现中,首先使用锁定的节点会成为锁定请求的协调器,此后它不会变化。这是 Linux 内核 DLM 的实现详情,而不是一般的 DLM 属性。将来的更新可能会允许协调特定锁定的锁定请求,以便在节点间移动。

协调锁定请求的位置对锁定请求的启动器是透明的,但对请求延迟的影响除外。当前实现的一个结果是,如果对初始工作负载造成不平衡的情况(例如,在其他人执行任何 I/O 命令前,通过整个文件系统进行一次节点扫描)可能会导致集群中其他节点的锁定延迟与执行文件系统初始扫描的节点进行比较。

与很多文件系统一样,GFS2 分配程序会尝试在同一文件中让块保持接近,以减少磁盘头的移动并提升性能。将块分配给文件的节点可能需要为新块使用和锁定同一资源组(除非该资源组中的所有块都被使用)。如果包含文件的资源组的锁定请求协调器分配其数据块(让首先打开该文件的节点更快)时,文件系统将更快运行。

2.7.3. 如果可能,预先分配

如果文件预先分配,可以完全避免块分配,且该文件系统可以更有效地运行。GFS2 包含 fallocate(1) 系统调用,您可以使用它预先分配数据块。

第 3 章 管理 GFS2 文件系统

您可以使用各种命令和选项来创建、挂载、增加和管理 GFS2 文件系统。

3.1. GFS2 文件系统创建

您可以使用 mkfs.gfs2 命令创建 GFS2 文件系统。文件系统是在活跃的 LVM 卷中创建的。

3.1.1. GFS2 mkfs 命令

运行 mkfs.gfs2 命令需要以下信息来创建集群的 GFS2 文件系统:

  • 锁定协议/模块名称,即集群的 lock_dlm
  • 集群名称
  • 日志数(每个可能挂载文件系统的节点都需要一个日志)
注意

当您使用 mkfs.gfs2 命令创建 GFS2 文件系统后,您就无法缩小该文件系统的大小。但是您可以使用 gfs2_grow 命令增加现有文件系统的大小。

创建集群 GFS2 文件系统的格式如下。请注意,红帽不支持将 GFS2 作为单节点文件系统使用。

mkfs.gfs2 -p lock_dlm -t ClusterName:FSName -j NumberJournals BlockDevice

如果您愿意,您可以使用 mkfs 命令并使用 -t 参数指定类型为 gfs2 的文件系统,再加上 GFS2 文件系统选项来创建 GFS2 文件系统。

mkfs -t gfs2 -p lock_dlm -t ClusterName:FSName -j NumberJournals BlockDevice
警告

不正确的指定 ClusterName:FSName 参数可能会导致文件系统或者锁定空间崩溃。

ClusterName
创建 GFS2 文件系统的集群名称。
FSName
文件系统名称,长度为 1-16 个字符。所有 lock_dlm 文件系统的名称必须是唯一的。
NumberJournals
指定由 mkfs.gfs2 命令创建的日志数。每个挂载文件系统的节点都需要一个日志。对于 GFS2 文件系统来说,以后可以添加更多的日志而不会增大文件系统。
BlockDevice
指定逻辑设备或其他块设备

下表描述了 mkfs.gfs2 命令选项(标签和参数)。

表 3.1. 命令选项: mkfs.gfs2

标记参数描述

-c

Megabytes

将每个日志的配额更改文件的初始大小设定为 Megabytes

-D

 

启用调试输出。

-h

 

帮助信息。显示可用选项。

-J

Megabytes

以 MB 为单位指定日志大小。默认日志大小为 128MB,最小值为 32MB。最小值为 8MB。较大的日志提高了性能,虽然它们使用的内存超过较小的日志。

-j

Number

指定由 mkfs.gfs2 命令创建的日志数。每个挂载文件系统的节点都需要一个日志。如果没有指定这个选项,则会生成一个日志。对于 GFS2 文件系统,您可以稍后添加附加日志而不会增大文件系统。

-O

 

防止 mkfs.gfs2 命令在编写文件系统之前进行确认。

-p

LockProtoName

* 指定要使用的锁定协议名称。可以使用的锁定协议包括:

* lock_dlm - 集群文件系统所需的标准锁定模块。

* lock_nolock - 当 GFS2 作为本地文件系统使用时(只有一个节点)。

-q

 

静默。不要显示任何结果。

-r

Megabytes

以 MB 为单位指定资源组群大小。资源组群最小值为 32MB。资源组群最大值为 2048MB。在大型的文件系统中,大的资源组群可能会提高性能。如果没有指定,mkfs.gfs2 会根据文件系统的大小选择资源组群大小: 平均大小的文件系统将会有 256MB 字节资源组,而较大的文件系统会有一个较大的 RG 来提高性能。

-t

LockTableName

*在使用 lock_dlm 协议时指定 lock table 字段的唯一标识符; lock_nolock 协议不使用这个参数。

* 这个参数有两个部分使用冒号(无空格),如下所示:ClusterName:FSName.

* clusterName 是创建 GFS2 文件系统的集群名称,只有集群成员可以使用这个文件系统。

* FSName,文件系统名称,长度可在 1-16 个字符之间,且该名称在集群的所有文件系统中必须是唯一的。

-V

 

显示命令版本信息。

3.1.2. 创建 GFS2 文件系统

以下示例创建两个 GFS2 文件系统。对于这两个文件系统,lock_dlm' 是文件系统使用的锁定协议,因为这是一个集群的文件系统。这两个文件系统都可以在名为 alpha 的集群中使用。

对于第一个文件系统,文件系统名称为 mydata1。它包含八个日志,在 /dev/vg01/lvol0 上创建。对于第二个文件系统,文件系统名称为 mydata2。它包含八个日志,在 /dev/vg01/lvol1 上创建。

# mkfs.gfs2 -p lock_dlm -t alpha:mydata1 -j 8 /dev/vg01/lvol0
# mkfs.gfs2 -p lock_dlm -t alpha:mydata2 -j 8 /dev/vg01/lvol1

3.2. 挂载 GFS2 文件系统

在您挂载 GFS2 文件系统前,该文件系统必须存在,文件系统所在的卷必须被激活,且必须启动支持的集群和锁定系统。满足这些要求后,您可以将 GFS2 文件系统挂载到任意 Linux 文件系统中。

注意

您应该在生产环境中使用 Pacemaker 管理 GFS2 文件系统,而不是使用 mount 命令手动挂载文件系统,因为这可能会导致系统关闭时出现问题。

要操作文件 ACL,您必须使用 -o acl 挂载选项挂载文件系统。如果在不使用 -o acl 挂载选项的情况下挂载文件系统,则用户可以查看 ACL(使用 getfacl),但不允许设置它们(使用 setfacl)。

3.2.1. 在没有指定选项的情况下挂载 GFS2 文件系统

在这个示例中,/dev/vg01/lvol0 上的 GFS2 文件系统被挂载到 /mygfs2 目录。

# mount /dev/vg01/lvol0 /mygfs2

3.2.2. 挂载指定挂载选项的 GFS2 文件系统

以下是挂载指定挂载选项的 GFS2 文件系统的命令格式。

mount BlockDevice MountPoint -o option
BlockDevice
指定 GFS2 文件系统所在的块设备。
MountPoint
指定要挂载 GFS2 文件系统的目录。

-o option 参数包括 GFS2 特定选项或可接受的标准 Linux mount -o 选项,或者两者的组合。多个 option 参数用逗号分开,没有空格。

注意

mount 命令是一个 Linux system 命令。除了使用这些特定于 GFS2 的选项外,您还可以使用其它标准的 mount 命令选项(例如 -r)。有关其他 Linux mount 命令选项的详情,请查看 Linux mount man page。

下表描述了挂载时可传递给 GFS2 的可用的针对 GFS2 的 -o option 值。

注意

这个表格包含了只用于本地文件系统选项的描述。但请注意,红帽不支持将 GFS2 作为单节点文件系统使用。红帽将继续支持单节点 GFS2 文件系统来挂载集群文件系统的快照(例如用于备份目的)。

表 3.2. GFS2 特定挂载选项

选项描述

acl

允许控制文件 ACL。如果在没有使用 acl 挂载选项的情况下挂载文件系统,则用户可以查看 ACL(使用 getfacl),但不允许设置它们(使用 setfacl)。

data=[ordered|writeback]

当设置了 data=ordered 时,被交易修改的用户数据会在交易被提交到磁盘前被写入磁盘。这样可让用户在崩溃后的文件中看到未初始化的块。当设置了 data=writeback 模式时,用户数据会在变“脏”后的任何时间写入磁盘;它不能提供和 ordered 模式一样的一致性保证,但对某些工作负载应该速度稍快。默认值为 ordered 模式。

ignore_local_fs

注意:当共享 GFS2 文件系统时,不应该使用这个选项。

强制 GFS2 将文件系统视为多主机文件系统。默认情况下,使用 lock_nolock 会自动打开 localflocks 标记。

localflocks

注意:当共享 GFS2 文件系统时,不应该使用这个选项。

告诉 GFS2 让 VFS(虚拟文件系统)层完成所有 flock 和 fcntl 操作。localflocks 标志由 lock_nolock 自动打开。

lockproto=LockModuleName

允许用户指定文件系统要使用的锁定协议。如果没有指定 LockModuleName,则从文件系统超级块中读取锁定协议名称。

locktable=LockTableName

允许用户指定文件系统要使用的锁定表。

quota=[off/account/on]

为文件系统打开或者关闭配额。将配额设定为 account 状态可让文件系统正确维护每个 UID/GID 使用量统计,忽略限制和警告值。默认值为 off

errors=panic|withdraw

当指定 error=panic 时,文件系统错误会导致内核 panic。当指定 error=withdraw 时(这是默认行为),文件系统错误会导致系统从文件系统中撤回,并使其无法访问直到下一次重启为止 ; 在某些情况下,系统可能会继续运行。

discard/nodiscard

导致 GFS2 为释放的块生成 "discard" I/O 请求。它们可供合适的硬件用来实施精简配置和类似方案。

barrier/nobarrier

导致 GFS2 在清除日志时发送 I/O 屏蔽。默认值为 on。如果基础设备不支持 I/O 屏蔽,则会自动关闭这个选项。强烈推荐在 GFS2 中使用 I/O 障碍,除非需要使用块设备。这可以避免丢失写缓存的内容(例如,如果它连接了 UPS,或者没有写入缓存)。

quota_quantum=sec

在将更改的配额信息写入配额文件前将其保存在某个节点的秒数。这是设置此参数的首选方法。该数值是一个大于零的整数。默认为 60 秒。设定为较短的间隔会让配额信息更快地更新,且降低了用户超过其配额的情况出现。较长的间隔可让文件系统操作更迅速有效地包括配额。

statfs_quantum=secs

设置 statfs 较慢版本的首选是将 statfs_quantum 设置为 0 是。默认值为 30 secs,它设置 statfs 更改将同步到主 statfs 文件前的最大时间段。可将该值调整为更迅速、不准确的 statfs 值或者更慢的准确值。当此选项设置为 0 时,statfs 始终会报告 true 值。

statfs_percent=value

在同步回主 statfs 文件之前,在 statfs 信息中提供有关本地基础的最大百分比更改的绑定,即使时间段尚未过期。如果 statfs_quantum 设置为 0,则忽略此设置。

3.2.3. 卸载 GFS2 文件系统

在系统关闭时卸载文件系统时,系统将无法了解手动挂载而不是通过 Pacemaker 自动挂载的 GFS2 文件系统。因此,GFS2 资源代理将不会卸载 GFS2 文件系统。关闭 GFS2 资源代理后,标准关闭进程会杀死所有剩余的用户进程,包括集群基础结构,并尝试卸载该文件系统。没有集群基础结构则卸载将失败,同时该系统会挂起。

要防止卸载 GFS2 文件系统时系统停滞,您应该进行以下操作之一:

  • 总是使用 Pacemaker 管理 GFS2 文件系统。
  • 如果使用 mount 命令手动挂载了 GFS2 文件系统,请确定在重启或关闭系统前,使用 umount 命令手动卸载该文件系统。

如果在这些情况下关闭系统的过程中卸载文件系统时停滞,请执行硬件重启。这不太会出现丢失任何数据的情况,因为文件系统在关闭进程早期是同步的。

可使用 umount 命令卸载 GFS2 文件系统。

注意

umount 命令是一个 Linux 系统命令。有关此命令的信息,请参阅 Linux umount 命令 man page。

使用

umount MountPoint
MountPoint
指定当前挂载 GFS2 文件系统的目录。

3.3. 备份 GFS2 文件系统

无论您的文件系统大小如何,在出现紧急事件时常规备份 GFS2 文件系统是很重要的。很多系统管理员会觉得很安全,因为他们使用了 RAID、多路径、镜像、快照和其它冗余形式对系统进行保护。但是,这些安全措施并不一定是完全足够的。

创建备份的过程可能会有问题,因为备份节点或节点集合通常涉及按顺序读取整个文件系统。如果从单一节点完成此操作,该节点将在缓存中保留所有信息,直到群集里的其他节点开始请求锁定为止。在集群运行时运行这种备份程序会对性能造成负面影响。

完成备份后丢弃缓存可减少其他节点重新拥有其集群锁定/缓存所需的时间。但这不是个理想情况,因为其他节点在备份过程开始前已停止缓存它们缓存的数据。您可以在备份完成后使用以下命令丢弃缓存:

echo -n 3 > /proc/sys/vm/drop_caches

如果集群中的每个节点都备份自己的文件,则速度会较快,任务会在节点之间进行分割。您可以使用对特定于节点的目录使用 rsync 命令的脚本完成此操作。

红帽建议通过在 SAN 中创建硬件快照生成 GFS2 备份,向另一个系统中显示快照并进行备份。备份系统应该使用 -o lockproto=lock_nolock 挂载快照,因为它不会位于集群中。

3.4. 在 GFS2 文件系统中挂起动作

您可以使用 dmsetup suspend 命令挂起对文件系统的写入操作。暂停写活动允许使用基于硬件的设备快照捕获处于一致状态的文件系统。dmsetup resume 命令终止挂起。

在 GFS2 文件系统中暂停动作的命令格式如下。

dmsetup suspend MountPoint

本示例会挂起对文件系统 /mygfs2 的写入操作。

# dmsetup suspend /mygfs2

GFS2 文件系统中终止活动的命令格式如下。

dmsetup resume MountPoint

这个示例终止了对文件系统 /mygfs2 的写入操作。

# dmsetup resume /mygfs2

3.5. 增大 GFS2 文件系统

gfs2_grow 命令用于在扩展文件系统所在设备后扩展 GFS2 文件系统。在现有 GFS2 文件系统上运行 gfs2_grow 命令,使用新初始化的 GFS2 文件系统扩展在文件系统当前末尾和设备末尾占占所有备用空间。然后,集群中的所有节点都可以使用添加的额外存储空间。

注意

您不能缩小 GFS2 文件系统的大小。

gfs2_grow 命令必须在挂载的文件系统上运行。下面的步骤会增加在逻辑卷 shared_vg/shared_lv1 上挂载的 GFS2 文件系统的大小,其挂载点为 /mnt/gfs2

步骤

  1. 对文件系统中的数据进行备份。
  2. 如果您不知道要扩展的文件系统所使用的逻辑卷,您可以运行 df mountpoint 命令来确定这一点。这将以以下格式显示该设备名称:

    /dev/mapper/vg-lv

    例如,设备名称 /dev/mapper/shared_vg-shared_lv1 表示逻辑卷是 shared_vg/shared_lv1

  3. 在集群的一个节点上,使用 lvextend 命令扩展基础集群卷。

    # lvextend -L+1G shared_vg/shared_lv1
    Size of logical volume shared_vg/shared_lv1 changed from 5.00 GiB (1280 extents) to 6.00 GiB (1536 extents).
    WARNING: extending LV with a shared lock, other hosts may require LV refresh.
    Logical volume shared_vg/shared_lv1 successfully resized.
  4. 一个集群节点,增大 GFS2 文件系统的大小。如果没有在所有节点中刷新逻辑卷,则不要扩展该文件系统,否则该文件系统数据可能会在集群中不可用。

    # gfs2_grow /mnt/gfs2
    FS: Mount point:             /mnt/gfs2
    FS: Device:                  /dev/mapper/shared_vg-shared_lv1
    FS: Size:                    1310719 (0x13ffff)
    DEV: Length:                 1572864 (0x180000)
    The file system will grow by 1024MB.
    gfs2_grow complete.
  5. 在所有节点上运行 df 命令,以检查新空间现在是否可在文件系统中可用。请注意,所有节点上的 df 命令最多可能需要 30 秒才能显示相同的文件系统大小

    # df -h /mnt/gfs2]
    Filesystem                        Size  Used Avail Use% Mounted on
    /dev/mapper/shared_vg-shared_lv1  6.0G  4.5G  1.6G  75% /mnt/gfs2

3.6. 在 GFS2 文件系统中添加日志

GFS2 需要为集群中需要挂载该文件系统的每个节点生成一个日志。如果在集群中添加附加节点,您可以使用 gfs2_jadd 命令将日志添加到 GFS2 文件系统。您可以在任意点动态在 GFS2 文件系统中添加日志,而不扩展基础逻辑卷。gfs2_jadd 命令必须在挂载的文件系统上运行,但只需要在集群中的一个节点上运行。其它节点可以了解到扩展的发生。

注意

如果 GFS2 文件系统已满,则 gfs2_jadd 命令将失败,即使逻辑卷已经扩展并大于文件系统。这是因为在 GFS2 文件系统中,日志是纯文本文件而不是嵌入的元数据,因此只是扩展基础逻辑卷不会为日志提供空间。

在向 GFS2 文件系统添加日志前,您可以找出 GFS2 文件系统当前包含的日志数量与 gfs2_edit -p jindex 命令,如下例所示:

# gfs2_edit -p jindex /dev/sasdrives/scratch|grep journal
   3/3 [fc7745eb] 4/25 (0x4/0x19): File    journal0
   4/4 [8b70757d] 5/32859 (0x5/0x805b): File    journal1
   5/5 [127924c7] 6/65701 (0x6/0x100a5): File    journal2

在 GFS2 文件系统中添加日志的基本命令格式如下。

gfs2_jadd -j Number MountPoint
Number
指定要添加的新日志数目。
MountPoint
指定要挂载 GFS2 文件系统的目录。

在本例中,将一个日志添加到 /mygfs2 目录的文件系统中。

# gfs2_jadd -j 1 /mygfs2

第 4 章 GFS2 配额管理

文件系统配额是用来限制某个用户或者组群使用的文件系统空间。在设置前用户或组群没有配额限制。当使用 quota=onquota=account 选项挂载 GFS2 文件系统时,GFS2 会跟踪每个用户和组群使用的空间,即使没有设定限制也是如此。GFS2 以互动的方式更新配额信息,因此系统崩溃并不需要重建配额使用。

为防止性能下降,GFS2 节点只会定期同步配额文件更新。模糊配额核算可让用户或组群稍微超过其设定的限制。为最小化这种情况,GFS2 会在接近硬配额限制时动态缩短同步周期。

注意

GFS2 支持标准 Linux 配额工具。要使用这个功能,您需要安装 quota RPM。这是在 GFS2 中管理配额的首选方法,应该在所有使用配额的 GFS2 新部署中使用。

有关磁盘配额的详情,请查看以下命令的man 页:

  • quotacheck
  • edquota
  • repquota
  • quota

4.1. 配置 GFS2 磁盘配额

要为 GFS2 文件系统实现磁盘配额,请执行三个步骤:

实现磁盘配额的步骤如下:

  1. 使用强制模式或者计数(accounting)模式设置配额。
  2. 使用当前块使用信息初始化配额数据库文件。
  3. 分配配额策略。(在计数模式中不强制这些策略。)

在以下小节中会详细讨论这些步骤的具体内容。

4.1.1. 在强制或者计数模式下设置配额

在 GFS2 文件系统中,默认会禁用配额。要为文件系统启用配额,请使用指定的 quota=on 选项挂载文件系统。

要挂载启用配额的文件系统,在集群中创建 GFS2 文件系统资源时,为 options 参数指定 quota=on。例如:以下命令指定正在创建的 GFS2 Filesystem 资源将使用启用配额挂载。

# pcs resource create gfs2mount Filesystem options="quota=on" device=BLOCKDEVICE directory=MOUNTPOINT fstype=gfs2 clone

可以跟踪磁盘用量,并在不强制限制和警告值的情况下为每个用户和组群保持配额核算。为此,请使用指定的 quota=account 选项挂载文件系统。

要挂载禁用配额的文件系统,在集群中创建 GFS2 文件系统资源时,为 options 参数指定 quota=off

4.1.2. 创建配额数据库文件

挂载每个启用了配额的文件系统后,该系统就可以使用磁盘配额。但是,文件系统本身尚未准备好支持配额。在下一步中运行 quotacheck 命令。

quotacheck 命令检查启用了配额的文件系统,并为每个文件系统构建一个当前磁盘使用情况的表。该表被用于更新磁盘用量的操作系统副本。另外,还会更新文件系统的磁盘配额文件。

要在文件系统上创建配额文件,请使用 quotacheck 命令的 -u-g 选项;必须指定这两个选项以便初始化用户和组配额。例如,如果为 /home 文件系统启用配额,请在 /home 目录中创建文件:

# quotacheck -ug /home

4.1.3. 为每个用户分配配额

最后一步是使用 edquota 命令分配磁盘配额。请注意,如果您以计数模式挂载文件系统(指定了 quota=account 选项),则不强制配额。

要为一个用户配置配额,在 shell 提示符中以 root 用户执行以下命令:

# edquota username

为每个需要配额的用户执行这个步骤。例如,如果为 /home 分区(以下示例中的 /dev/VolGroup00/LogVol02)启用了配额,并且执行了命令 edquota testuser,则在编辑中显示为系统默认设置:

Disk quotas for user testuser (uid 501):
Filesystem                blocks     soft     hard    inodes   soft   hard
/dev/VolGroup00/LogVol02  440436        0        0
注意

edquota 使用由 EDITOR 环境变量定义的文本编辑器。要更改编辑器,请将 ~/.bash_profile 文件中的 EDITOR 环境变量设为您选择的编辑器的完整路径。

第一列是启用了配额的文件系统的名称。第二列显示目前该用户使用的块数。下面的两列是为该用户在文件系统中设定软限制和硬限制。

软块限制定义可以使用的最大磁盘空间量。

硬块限制是用户或者组群可以使用的绝对最大磁盘空间量。达到这个限制后,就无法再使用其他磁盘空间。

GFS2 文件系统并不为内节点维护配额,因此这些列不适用于 GFS2 文件系统,并为空。

如果值为 0,则代表没有设定那个限制。在文本编辑器中更改限制。例如:

Disk quotas for user testuser (uid 501):
Filesystem                blocks     soft     hard    inodes   soft   hard
/dev/VolGroup00/LogVol02  440436   500000   550000

要验证是否为该用户设定了配额,使用以下命令:

# quota testuser

您也可以使用 setquota 命令从命令行设置配额。有关 setquota 命令的详情,请查看 setquota(8)手册页。

4.1.4. 为每个组群分配配额

配额可以针对单独组群进行分配。请注意:如果您使用计数模式挂载文件系统(指定 account=on 选项),则不强制配额。

要为 devel 组设置组配额(在设置组群配额前必须存在组配额),请使用以下命令:

# edquota -g devel

这个命令在文本编辑器中显示该组群的现有配额:

Disk quotas for group devel (gid 505):
Filesystem                blocks    soft     hard    inodes   soft   hard
/dev/VolGroup00/LogVol02  440400       0        0

GFS2 文件系统并不为内节点维护配额,因此这些列不适用于 GFS2 文件系统,并为空。修改限制后保存文件。

要验证是否设定了组群配额,使用以下命令:

$ quota -g devel

4.2. 管理 GFS2 磁盘配额

如果使用了配额,则需要对其进行维护。大部分是查看是否超过了配额,并确定配额是准确的。

如果用户重复超过配额,或者持续达到其软限制,系统管理员可根据用户类型以及影响其工作的空间数量而决定一些选择。管理员可帮助用户决定如何使用较少的磁盘空间,或者增加用户的磁盘配额。

您可以通过运行 repquota 实用程序创建磁盘用量报告。例如,命令 repquota /home 生成此输出:

*** Report for user quotas on device /dev/mapper/VolGroup00-LogVol02
Block grace time: 7days; Inode grace time: 7days
			Block limits			File limits
User		used	soft	hard	grace	used	soft	hard	grace
----------------------------------------------------------------------
root      --      36       0       0              4     0     0
kristin   --     540       0       0            125     0     0
testuser  --  440400  500000  550000          37418     0     0

要查看所有启用了配额的文件系统的磁盘使用情况报告(选项 -a),请使用命令:

# repquota -a

每个用户后显示 --,可让您迅速确定是否超过块限制。如果超过了块的软限制,在输出中的第一个 - 的位置将出现 +。第二个 - 表示内节点限制,但 GFS2 文件系统不支持内节点限制,因此该字符将保留为 -。GFS2 文件系统不支持宽限期,因此 grace 栏将保持空白。

请注意,repquota 命令不支持通过 NFS(底层文件系统无关)的支持。

4.3. 使用 quotacheck 命令准确保留 GFS2 磁盘配额

如果您在使用配额禁用后在文件系统中启用配额,您应该运行 quotacheck 命令以创建、检查和修复配额文件。另外,如果您认为配额文件可能不准确(因为系统崩溃后没有完全卸载文件系统),可能需要运行 quotacheck 命令。

有关 quotacheck 命令的详情,请查看 quotacheck(8) man page。

注意

当文件系统在所有节点中都相对闲置时运行 quotacheck,因为磁盘的操作可能会影响计算的配额值。

4.4. 使用 quotasync 命令同步配额

GFS2 在其磁盘的内部文件中保存所有配额信息。GFS2 节点不会在每次写入文件系统时更新这个配额文件,默认情况下它每 60 秒更新一次配额文件。这是避免节点间在写入配额文件时出现竞争所必需的,这会导致性能下降。

随着用户或组群接近其配额限制,GFS2 会动态减少更新配额文件的时间间隔以避免超过限制。配额同步之间的正常时间周期是一个可调整的参数 quota_quantum。您可以使用 quota_quantum= 挂载选项更改默认值 60 秒,如 挂载指定挂载选项的 GFS2 文件系统 中"GFS2-Specific Mount Options"表中所描述的。

必须在每个节点上设置 quota_quantum 参数,并且每次挂载文件系统时都必须设置。卸载后不会保留对 quota_quantum 参数的更改。您可以使用 mount -o remount 来更新 quota_quantum 值。

您可以使用 quotasync 命令在 GFS2 执行自动更新时将节点的配额信息与磁盘上的配额文件同步。使用 同步配额信息

quotasync [-ug] -a|mountpoint...
u
同步用户配额文件。
g
同步组配额文件
a
同步所有当前启用配额并支持同步的文件系统。当没有 -a 时,应该指定一个文件系统挂载点。
mountpoint
指定要执行操作的 GFS2 文件系统。

您可以通过指定 quota-quantum 挂载选项来调整同步之间的时间。

# mount -o quota_quantum=secs,remount BlockDevice MountPoint
MountPoint
指定要执行操作的 GFS2 文件系统。
secs
指定 GFS2 对常规配额文件进行同步之间的新时间周期。数值越小,竞争越高,性能会下降。

以下示例为文件系统 /mnt/mygfs2 在运行的节点上把缓存的“脏配额”与磁盘中的配额文件进行同步。

# quotasync -ug /mnt/mygfs2

这个示例在逻辑卷 /dev/volgroup/logical_volume 中重新挂载文件系统时,在 /mnt/mygfs2 中将常规配额文件更新的默认时间周期改为一小时(3600 秒)。

# mount -o quota_quantum=3600,remount /dev/volgroup/logical_volume /mnt/mygfs2

第 5 章 GFS2 文件系统修复

当挂载文件系统的节点失败时,文件系统日志允许快速恢复。但是,如果存储设备断电或者断开物理连接,则会发生文件系统崩溃。(无法使用日志进行存储子系统失败修复。) 当这种崩溃发生时,您可以使用 fsck.gfs2 命令恢复 GFS2 文件系统。

重要

只能在从所有节点中卸载的文件系统上运行 fsck.gfs2 命令。当文件系统作为 Pacemaker 集群资源进行管理时,您可以禁用文件系统资源,这会卸载文件系统。运行 fsck.gfs2 命令后,您可以重新启用该文件系统资源。使用 pcs resource disable--wait 选项指定的 timeout 值是一个以秒为单位的值。

pcs resource disable --wait=timeoutvalue resource_id
[fsck.gfs2]
pcs resource enable resource_id

请注意,即使文件系统是资源组的一部分,如在加密文件系统部署中那样,您只需要禁用文件系统资源才能在文件系统上运行 fsck 命令。您不能禁用整个资源组。

为确保启动时 fsck.gfs2 命令不会在 GFS2 文件系统上运行,您可以在在集群中创建 GFS2 文件系统资源时设置 options 参数的 run_fsck 参数。指定 "run_fsck=no" 代表您不应运行 fsck 命令。

5.1. 确定运行 fsck.gfs2 所需的内存

运行 fsck.gfs2 命令可能需要系统内存高于操作系统和内核所使用的内存。较大的文件系统可能需要额外内存才能运行这个命令。

下表显示了在 GFS2 文件系统中运行 fsck.gfs2 文件系统所需内存的近似值,它们大小为 1TB、10TB 和 100TB,块大小为 4K。

GFS2 文件系统大小运行 fsck.gfs2 所需的大约内存

1 TB

0.16 GB

10 TB

1.6 GB

100 TB

16 GB

请注意,如果文件系统的块大小较小,则需要更大的内存。例如:块大小为 1K 的 GFS2 文件系统需要这个表所示的内存量的四倍。

5.2. 修复 gfs2 文件系统

修复 GFS2 文件系统的 fsck.gfs2 命令格式如下:

fsck.gfs2 -y BlockDevice
-y
使用 -y 标志会对所有问题回答 yes。指定 -y 标志后,fsck.gfs2 命令不会在进行更改前提示您找到答案。
BlockDevice
指定 GFS2 文件系统所在的块设备。

在这个示例中修复了位于块设备 /dev/testvg/testlv 上的 GFS2 文件系统。所有关于修复查询的回答都自动使用 yes

# fsck.gfs2 -y /dev/testvg/testlv
Initializing fsck
Validating Resource Group index.
Level 1 RG check.
(level 1 passed)
Clearing journals (this may take a while)...
Journals cleared.
Starting pass1
Pass1 complete
Starting pass1b
Pass1b complete
Starting pass1c
Pass1c complete
Starting pass2
Pass2 complete
Starting pass3
Pass3 complete
Starting pass4
Pass4 complete
Starting pass5
Pass5 complete
Writing changes to disk
fsck.gfs2 complete

第 6 章 提高 GFS2 性能

您可以分析 GFS2 配置来改进文件系统性能。

有关使用高可用性附加组件和 Red Hat Global File System 2 (GFS2) 部署和升级 Red Hat Enterprise Linux 集群的常规建议,请查看红帽客户门户网站中的相应文章 Red Hat Enterprise Linux Cluster, High Availability, and GFS Deployment Best Practices

6.1. GFS2 文件系统进行碎片整理

虽然 Red Hat Enterprise Linux 上没有 GFS2 的碎片工具,但您可以使用 filefrag 工具标识单个文件,将其复制到临时文件,并将临时文件重命名为临时文件以替换原始文件。

6.2. GFS2 节点锁定

要获得最佳 GFS2 文件系统性能,了解其操作的基本原理非常重要。单一节点文件系统带有一个缓存,其目的是在频繁使用时减少磁盘访问所造成的访问延迟。在 Linux 中,页面缓存(以及过去的缓冲缓存)提供了这个缓存功能。

使用 GFS2 时,每个节点都有其自身的页面缓存,该缓存中可能包含部分磁盘数据。GFS2 使用一个称为 glocks (发音为 gee-locks)的锁定机制,用于维护节点间缓存的完整性。glock 子系统提供了一个缓存管理功能,它使用 分布式锁管理器(DLM)作为底层通信层。

glocks 在每个内节点中为缓存提供保护,因此在每个内节点中都有一个锁定用来控制缓存层。如果该 glock 被赋予共享模式(DLM 锁定模式:然后,那个 glock 下的数据会同时被缓存在一个或多个节点上,以便所有节点都可以对数据进行本地访问。

如果 glock 被赋予专用模式(DLM 锁定模式:EX)然后,只有一个节点可以缓存那个 glock 下的数据。此模式供需要修改数据(如 write 系统调用)的所有操作使用。

如果另一个节点请求 glock 但无法立即获得,那么 DLM 会向该节点发送一条信息,或者向目前使用 glock 阻止新请求的节点发送一条信息,要求它们释放其锁定。释放 glock 可能需要较长时间(与大多数文件系统操作相比)。释放一个共享的 glock 只需要将缓存设置为无效,它的速度比较快,并与缓存数据的数量相对应。

释放一个专用 glock 需要清除日志,并将所有更改的数据写入磁盘,然后象共享 glock 一样使缓存失效。

单一节点文件系统与 GFS2 之间的区别在于,单一节点文件系统只有一个缓存,GFS2 在每个节点中都有单独的缓存。在这两种情况下,访问缓存的数据的延迟程度类似,但如果另一个节点之前缓冲了同样的数据,GFS2 对未缓存的数据访问的时间延迟要大得多。

诸如 read (buffered)、statreaddir 等操作只需要共享 glock。write (buffered)、mkdirrmdirunlink 等操作需要一个专用的 glock。如果写入需要分配,则直接 I/O 读写操作需要延迟 glock,如果写入需要分配,则需要延迟 glock(即扩展该文件或填充)。

这有两个主要的性能注意事项。首先,只读操作可在集群中并行化,因为它们可以在每个节点中独立运行。其次,如果有多个节点可以访问同一内节点,则需要一个专用 glock 的操作可以降低性能。因此,在每个节点上考虑工作集是 GFS2 文件系统性能的重要因素,例如您执行文件系统备份时,如备份 GFS2 文件系统所述

另外,我们建议您尽可能在 GFS2 中使用 noatimenodiratime 挂载选项,在应用程序允许的情况下首选 noatime。这可防止读取需要专用锁定来更新 atime 时间戳。

对于关注工作集合或缓存效率的用户,GFS2 提供可让您监控 GFS2 文件系统性能的工具:Performance Co-Pilot 和 GFS2 追踪点。

注意

由于采用 GFS2 缓存的方法,在出现以下任意情况之一时都会获得最佳性能:

  • 在所有节点上以只读方式使用内节点。
  • 只在单一节点中写入或修改内节点。

请注意,在创建和删除文件的过程中插入和删除目录条目计算为写入目录内节点。

有可能会打破这个规则,但并不常发生。过度忽略这个规则会对性能有严重影响。

如果您对在带有一个读写映射的 GFS2 的一个文件执行 mmap(),但只从中进行读取操作,则只被看作为一个读操作。

如果您没有设置 noatime mount 参数,则读取还将会导致更新文件时间戳的写操作。我们建议所有 GFS2 用户都不应该使用 noatime 挂载,除非它们对 atime 有具体要求。

6.3. Posix 锁定的问题

当使用 Posix 锁定时,您应该考虑以下问题:

  • 使用 Flocks 比使用 Posix 锁要快。
  • 在 GFS2 中使用 Posix 锁定的程序应该避免在集群环境中使用 GETLK 功能,进程 ID 可能用于集群中的不同节点。

6.4. 使用 GFS2 的性能调整

通常可以更改有问题的应用程序保存其数据的方法,以便获得显著的性能优势。

典型的问题程序示例为电子邮件服务器。通常使用含有每个用户的文件的 spool 目录(mbox),或者为每个用户指定一个目录,其中包含每个邮件的文件(maildir)。当请求到达 IMAP 时,理想的情况是为每个用户赋予一个与特定节点的亲和性。这样一来,他们查看和删除电子邮件信息的请求就会从那个节点的缓存中提供。如果那个节点失败,则可以在不同节点中重启该会话。

当邮件通过 SMTP 方法到达时,那么独立的节点可以再次设置,在默认情况下把特定用户的邮件发送到一个特定的节点。如果默认节点没有启动,则信息可以通过接收节点直接保存到用户的邮件 spool 中。同样,这个设计的目的是在通常情况下只在一个节点中保留缓存的文件集合,但在节点失败时允许直接访问。

这个设置可以最佳地使用 GFS2 的页面缓存,并使用故障对应用程序透明(imapsmtp)。

备份通常是另一个值得关注的地方。如果可能最好直接从节点备份每个节点的工作组件,这样可缓存具体的内节点组。如果您有一个在特定时间点定期运行的备份脚本,且发现会因为 GFS2 中运行的其他应用程序而造成反应延迟时,则通常代表没有有效地使用页面缓存。

如果您可以在运行备份脚本时停止运行应用程序,则这就不是一个问题。相反,如果备份脚本只从一个节点中执行备份,则完成后大部分的文件系统内容会在那个节点中被缓存,这会对以后从其他节点访问有一定的性能损失。通过以下命令在备份完成后丢弃备份节点上的 VFS 页面缓存可将此影响缓解到一定程度:

echo -n 3 >/proc/sys/vm/drop_caches

然而,这并非是一个好的解决方案,因为它要保证每个节点中的工作集合是共享的,或多数操作是集群的只读操作,或大量操作是从一个单一节点进行访问的。

6.5. 使用 GFS2 锁定转储对 GFS2 性能进行故障排除

如果由于使用 GFS2 缓存而导致集群性能增加,您可能会看到大量和增长的 I/O 等待时间。您可以使用 GFS2 的锁定转储信息来确定问题的原因。

GFS2 锁定转储信息可以从 debugfs 文件中收集,该文件可在以下路径名称中找到,假设 debugfs 被挂载到 /sys/kernel/debug/ 中:

/sys/kernel/debug/gfs2/fsname/glocks

文件的内容是一系列行。每行以 G: 表示一个 glock,下面一行使用单个空格缩进,代表在文件中立即与 glock 相关的信息项目。

使用 debugfs 文件的最佳方法是,在应用程序遇到问题时,使用 cat 命令获取文件内容副本(如果您有大量 RAM 和大量缓存的内节点,可能需要很长时间),然后在以后查看得到的数据。

注意

debugfs 文件创建两个副本会很有用,一次需要几秒钟甚至一两分钟。通过比较与同一 glock 号相关的两个 trace 的拥有者信息,您可以告诉工作负载是否进行进度(只是缓慢)或者它是否被卡住(始终是一个程序错误,应该立即报告给红帽支持)。

debugfs 文件中的行以 H:(拥有者)代表赋予或等待被授予的锁定请求。拥有者行 f 中的 flags 字段显示:'W' 标志指的是等待的请求,"H"标记指的是授予的请求。有大量等待请求的 glock 可能是遇到特定争用的请求。

下表显示了 glock 标记和 glock 拥有者标记的含义。

表 6.1. Glock 标记

标志名称含义

b

Blocking

在设置 locked 标记时有效,并指示从 DLM 请求的操作可能会被阻断。对于演示操作和"try"锁定,这个标记会被清除。这个标志的目的是允许收集 DLM 响应时间的统计数据,与其他节点与降级锁无关。

d

Pending demote

推迟(远程)降级请求

D

Demote

降级请求(本地或者远程)

f

Log flush

释放这个 glock 前需要提交该日志

F

Frozen

回复忽略的远程节点 -- 恢复正在进行。这个标志与文件系统冻结无关,它使用不同的机制,但仅在恢复中使用。

i

Invalidate in progress

这个 glock 下无效页面的进程中

I

Initial

设定何时将 DLM 锁定与这个 glock 关联

l

Locked

这个 glock 处于更改状态中

L

LRU

glock 出现在 LRU 列表中时设置

o

Object

设置 glock 何时与对象关联(即类型为 2 glocks 的内节点,以及类型为 3 的 glock 的资源组)

p

Demote in progress

glock 正在响应降级请求

q

Queued

设定当拥有者排队到 glock 时,并在 glock 保留时清除,但没有剩余所有者。作为算法的一部分使用,计算 glock 的最小保留时间。

r

Reply pending

从远程节点接收的回复正在等待过程中

y

Dirty

释放这个 glock 前需要冲刷到磁盘中的数据

表 6.2. Glock 拥有者标记

标志名称含义

a

Async

不要等待 glock 结果(以后轮询结果)

A

Any

接受任意兼容锁定模式

c

No cache

取消锁定时,立即降级 DLM 锁定

e

No expire

忽略随后的锁定取消请求

E

exact

必须有准确的锁定模式

F

First

设定赋予这个锁定的第一个拥有者

H

Holder

表示赋予请求的锁定

p

Priority

在队列头启用 ENQUEUE 拥有者

t

Try

"try" 锁定

T

Try 1CB

发送回调的 "try" 锁定

W

Wait

等待请求完成的设置

在确定会导致问题的 glock 后,下一步就是找出它所相关的内节点。glock 号 (n: on the G: line) 表示这个值。它是格式 type/number,如果 type 为 2,则 glock 是一个内节点 glock,number 是一个内节点号。要跟踪内节点,运行 find -inum number,其中 number 是从 glocks 文件中的十六进制格式转换为十进制格式的索引节点编号。

警告

如果您在有锁定冲突的文件系统中运行 find 命令,可能会让问题更加严重。当您查找冲突的内节点时,最好在运行 find 命令前停止应用程序。

下表显示了不同 glock 类型的含义。

表 6.3. Glock 类型

类型号锁定类型使用

1

Trans

事务锁定

2

Inode

内节点元数据和数据

3

Rgrp

源组群元数据

4

Meta

超级块

5

Iopen

内节点最近探测

6

Flock

flock(2)syscall

8

Quota

配额操作

9

Journal

Journal mutex

如果识别出的 glock 是不同的类型,那么最可能是类型 3(资源组)。如果您在正常负载时看到大量进程正在等待其它 glock 类型,请向红帽支持提交报告。

如果您看到在资源组锁定中排队了大量等待的请求,,那么可能有很多原因。一个原因可能是,在文件系统中,相对于资源组有大量的节点。另一个可能的原因是,文件系统可能接近完全被使用(平均来讲,需要较长的搜索时间)可以通过添加更多存储并使用 gfs2_grow 命令来扩展文件系统来提高这种情况。

6.6. 启用数据日志

通常 GFS2 只将元数据写入其日志中。文件内容会随后由内核定期进行的同步(同步会清除文件系统缓冲)写入磁盘。对一个文件的 fsync() 调用会导致将文件数据立即写入磁盘。当磁盘报告所有数据被安全写入时,调用会返回。

对于非常小的文件,数据日志可缩短 fsync() 时间,因为除元数据外,文件数据也会写入日志。随着文件的增大,这个优势会明显降低。在启用数据日志的情况下,对中等和较大文件的写操作会较慢。

对于依赖于 fsync() 同步文件数据的应用程序,启用数据日志会提高性能。在标记的目录及其所有子目录中创建的 GFS2 文件可自动启用数据日志。现有的长度为零的文件也可以打开或者关闭数据日志。

在一个目录上启动数据日志会把目录设定为 "inherit jdata",这代表以后所有在这个目录中生成的文件和目录都会进行日志。您可以使用 chattr 命令在文件中启用和禁用数据日志。

以下命令在 /mnt/gfs2/gfs2_dir/newfile 文件中启用数据日志,然后检查是否正确设定了标志。

# chattr +j /mnt/gfs2/gfs2_dir/newfile
# lsattr /mnt/gfs2/gfs2_dir
---------j--- /mnt/gfs2/gfs2_dir/newfile

以下命令在 /mnt/gfs2/gfs2_dir/newfile 文件中禁用数据日志,然后检查是否正确设定了标志。

# chattr -j /mnt/gfs2/gfs2_dir/newfile
# lsattr /mnt/gfs2/gfs2_dir
------------- /mnt/gfs2/gfs2_dir/newfile

您还可以使用 chattr 命令在目录中设置 j 标志。当您为某个目录设定此标记时,以后在那个目录中生成的所有文件和目录都会进行日志操作。以下命令在 gfs2_dir 目录上设置 j 标志,然后检查是否正确设定了标志。之后,命令会在 /mnt/gfs2/gfs2_dir 目录中创建一个名为 newfile 的新文件,然后检查是否为该文件设置了 j 标志。因为为该目录设置了 j 标志,因此 newfile 也应启用日志功能。

# chattr -j /mnt/gfs2/gfs2_dir
# lsattr /mnt/gfs2
---------j--- /mnt/gfs2/gfs2_dir
# touch /mnt/gfs2/gfs2_dir/newfile
# lsattr /mnt/gfs2/gfs2_dir
---------j--- /mnt/gfs2/gfs2_dir/newfile

第 7 章 诊断并修正 GFS2 文件系统的问题

以下流程描述了一些常见的 GFS2 问题,并提供了有关如何解决它们的信息。

7.1. 在节点无法使用 GFS2 文件系统(GFS2 撤回功能)

GFS2 withdraw 功能是 GFS2 文件系统的数据完整性功能,可防止因为硬件或者内核软件造成潜在的文件系统损坏。如果 GFS2 内核模块在任何指定集群节点中使用 GFS2 文件系统时检测到不一致的情况,它会从该文件系统中撤回(withdraw),并使它在相应的节点上不可用,直到卸载并重新挂载该节点(或者被探测到有问题的机器被重启)。所有其他挂载的 GFS2 文件系统在那个节点中仍能完全正常工作。(GFS2 撤回功能没有内核的 panic 严重,内核 panic 会导致该节点被隔离。)

可能导致 GFS2 撤回的主要原因:

  • 内节点一致性错误
  • 资源组一致性错误
  • 日志一致性错误
  • Magic number 元数据一致性错误
  • 元数据类型一致性错误

因为不一致性导致 GFS2 撤回的一个示例是,文件内节点的不正确的块计数。当 GFS2 删除一个文件时,它会系统性地删除该文件引用的所有数据和元数据块。在完成后,它会检查内节点的块计数。如果块计数不是 1(1 代表所有剩下的都是磁盘内节点),这表示文件系统不一致,因为内节点的块数量与该文件使用的实际块不匹配。

在很多情况下,问题可能是由硬件故障造成的(内存、主板、HBA、磁盘驱动器、电缆等出问题)。也可能是由内核的程序漏洞(另一个内核模块意外覆盖 GFS2 内存)或者实际文件系统损坏(由 GFS2 错误导致)造成的。

在大多数情况下,从 GFS2 文件系统中恢复的最佳方法是重新引导或者隔离该节点。撤回的 GFS2 文件系统将给您一个将服务重新定位到集群的另一个节点的机会。重新定位服务后,您可以重新引导节点或使用这个命令强制进行隔离。

pcs stonith fence node
警告

不要尝试使用 umountmount 命令手动卸载并重新挂载文件系统。您必须使用 pcs 命令,否则 Pacemaker 会检测到文件系统服务已消失并保护该节点。

导致撤回的一致性问题可能会导致无法停止文件系统服务,因为它可能导致系统挂起。

如果重新挂载后问题仍然存在,应该停止该文件系统服务以从集群中的所有节点卸载该文件系统,然后按照以下步骤使用 fsck.gfs2 命令执行文件系统检查。

  1. 重新引导受影响的节点。
  2. 在 Pacemaker 中禁用非克隆的文件系统服务,从集群中的每个节点卸载该文件系统。

    # pcs resource disable --wait=100 mydata_fs
  3. 在集群的一个节点中,在文件系统设备上运行 fsck.gfs2 命令来检查并修复文件系统损坏。

    # fsck.gfs2 -y /dev/vg_mydata/mydata > /tmp/fsck.out
  4. 通过重新启用文件系统服务从所有节点中重新挂载 GFS2 文件系统:

    # pcs resource enable --wait=100 mydata_fs

您可以使用文件系统服务中指定的 -o error=panic 选项挂载文件系统来覆盖 GFS2 撤回功能。

# pcs resource update mydata_fs “options=noatime,errors=panic”

当指定这个选项时,所有会导致系统撤回的错误都是强制造成一个内核 panic。这样可停止节点的通讯,从而可以隔离该节点。这对于长期保持无人值守的集群特别有用,而无需监控或干预。

GFS2 撤回的内部工作原理是,断开锁定协议以确保以后所有的文件系统操作都会出现 I/O 错误。因此,当发生撤回时,通常会在系统日志中看到来自设备映射器的 I/O 错误。

7.2. GFS2 文件系统挂起,需要重启一个节点

如果您的 GFS2 文件系统挂起且没有返回针对它运行的命令,但重启一个特定节点会使系统恢复正常,这可能表示有锁定问题或者存在程序漏洞。如果出现这种情况,在出现这个问题时收集 GFS2 数据并创建一个红帽支持问题单,如收集 GFS2 数据进行故障排除所述。

7.3. GFS2 文件系统挂起,需要重启所有节点

如果您的 GFS2 文件系统挂起且不会返回针对它运行的命令,并需要您重启集群中的所有节点才可以使用它,检查以下问题。

  • 您可能有一个失败的隔离(fence)。GFS2 文件系统将停滞,以保证在出现隔离失败时的数据完整性。检查信息日志,查看在挂起时是否有失败的隔离。确定正确配置了隔离。
  • GFS2 文件系统可能已经撤回。检查信息日志中的 withdraw ,检查所有来自 GFS2 的信息并调用显示已经撤回的文件系统的信息。撤回通常代表文件系统崩溃、存储失败或存在程序漏洞。根据具体情况,尽早进行以下操作来卸载文件系统:

    1. 重启发生撤回的节点。

      # /sbin/reboot
    2. 停止该文件系统资源在所有节点中卸载 GFS2 文件系统。

      # pcs resource disable --wait=100 mydata_fs
    3. 捕获元数据 gfs2_edit savemeta…​ 命令所需的文件。您应该确定有足够的空间来容纳该文件,在某些情况下,所需空间可能比较大。在本例中,元数据被保存到 /root 目录中的一个文件中。

      # gfs2_edit savemeta /dev/vg_mydata/mydata /root/gfs2metadata.gz
    4. 更新 gfs2-utils 软件包。

      # sudo dnf update gfs2-utils
    5. 在一个节点上,在文件系统中运行 fsck.gfs2 命令以确保文件系统的完整性并修复任何损坏。

      # fsck.gfs2 -y /dev/vg_mydata/mydata > /tmp/fsck.out
    6. fsck.gfs2 命令完成后,重新启用该文件系统资源使其返回服务:

      # pcs resource enable --wait=100 mydata_fs
    7. 创建一个红帽支持问题单。告知您遇到 GFS2 撤回问题,并提供 sosreportsgfs2_edit savemeta 命令生成的日志和调试信息。

      在 GFS2 撤回的某些情况下,试图访问文件系统或其块设备的命令可能会挂起。在这些情况下,需要一个“硬”重启来重启集群。

      有关 GFS2 撤回功能的详情,请参考 GFS2 文件系统对节点不可用(GFS2 撤回功能)。

  • 这个出错信息表示可能有锁定问题或者程序漏洞。在出现这个问题时收集 GFS2 数据并创建一个红帽支持问题单,如收集 GFS2 数据进行故障排除所述。

7.4. GFS2 文件系统不会挂载到新添加的集群节点中

如果您在集群中添加新节点,且发现您无法在那个节点中挂载 GFS2 文件系统,则 GFS2 文件系统中的日志可能比尝试访问 GFS2 文件系统的节点要少。对于用来挂载文件系统的 GFS2 主机,每个 GFS 2 主机都需要有一个日志(除通过 spectator 挂载选项集挂载的 GFS2 文件系统除外,因为这不需要日志)。您可以使用 gfs2_jadd 命令在 GFS2 文件系统中添加日志,如在 GFS2 文件系统中添加日志所述。

7.5. 在空文件系统中的空间被标记为已被使用

如果您有一个空 GFS2 文件系统,df 命令将显示有可用空间。这是因为 GFS2 文件系统日志会占用磁盘空间(日志数乘以日志大小)。如果您创建了有大量日志的 GFS2 文件系统,或者指定大的日志大小,那么在执行 df 命令时,您将看到(日志数乘以日志大小)已要使用的。即使您没有设置大量日志或者大的日志,小 GFS2 文件系统(1GB 或者更小)也会显示部分空间被使用(默认 GFS2 日志大小)。

7.6. 为故障排除收集 GFS2 数据

如果您的 GFS2 文件系统挂起,且不会返回针对它运行的命令,您应该收集以下数据并创建一个红帽支持问题单:

  • 每个节点中的文件系统的 GFS2 锁定转储数据:

    cat /sys/kernel/debug/gfs2/fsname/glocks >glocks.fsname.nodename
  • 每个节点上的文件系统的 DLM 锁定转储数据:您可以使用 dlm_tool 获取此信息:

    dlm_tool lockdebug -sv lsname

    在这个命令中,lsname 是有问题的文件系统中 DLM 使用的锁定空间名称。您可以在 group_tool 命令的输出中找到这个值。

  • sysrq -t 命令的输出。
  • /var/log/messages 文件的内容。

收集到这些数据后,创建一个红帽支持问题单。

第 8 章 集群中的 GFS2 文件系统

使用以下管理流程在红帽高可用性集群中配置 GFS2 文件系统。

8.1. 在集群中配置 GFS2 文件系统

您可以按照以下流程设置包含 GFS2 文件系统的 Pacemaker 集群。在这个示例中,您在双节点集群的三个逻辑卷上创建三个 GFS2 文件系统。

先决条件

  • 在集群节点上安装并启动集群软件,并创建一个基本的双节点集群。
  • 为集群配置隔离。

有关创建 Pacemaker 集群并为集群配置隔离的详情,请参考 使用 Pacemaker 创建红帽高可用性集群

步骤

  1. 在集群中的两个节点上,启用与您的系统架构对应的弹性存储存储库。例如,要为 x86_64 系统启用 Resilient Storage 仓库,您可以输入以下 subscription-manager 命令:

    # subscription-manager repos --enable=rhel-9-for-x86_64-resilientstorage-rpms

    请注意,弹性存储存储库是高可用性存储库的超集。如果启用弹性存储存储库,则不需要启用高可用性存储库。

  2. 在集群的两个节点上安装 lvm2-lockdgfs2-utilsdlm 软件包。要支持这些软件包,您必须订阅 AppStream 频道和 Resilient Storage 频道。

    # dnf install lvm2-lockd gfs2-utils dlm
  3. 在集群的两个节点上,将 /etc/lvm/lvm.conf 文件中的 use_lvmlockd 配置选项设置为 use_lvmlockd=1

    ...
    use_lvmlockd = 1
    ...
  4. 将全局 Pacemaker 参数 no-quorum-policy 设置为 freeze

    注意

    默认情况下,将 no-quorum-policy 的值设置为 stop,表示一旦仲裁丢失,剩余分区上的所有资源都会立即停止。通常,这个默认行为是最安全、最优的选项,但与大多数资源不同,GFS2 要求使用 quorum 才可以正常工作。当使用 GFS2 挂载的应用程序和 GFS2 挂载都丢失时,就无法正确停止 GFS2 挂载。任何在没有 quorum 的情况下停止这些资源的尝试都会失败,并最终会在每次 quorum 都丢失时保护整个集群。

    要解决这个问题,请在使用 GFS2 时将 no-quorum-policy 设置为 freeze。这意味着,当 quorum 丢失时,剩余的分区将不会进行任何操作,直到 quorum 功能被恢复。

    [root@z1 ~]# pcs property set no-quorum-policy=freeze
  5. 设置 dlm 资源。这是在集群中配置 GFS2 文件系统所需的依赖软件包。这个示例创建 dlm 资源作为名为 locking 的资源组的一部分。

    [root@z1 ~]# pcs resource create dlm --group locking ocf:pacemaker:controld op monitor interval=30s on-fail=fence
  6. 克隆 locking 资源组,以便资源组可以在集群的两个节点上都活跃。

    [root@z1 ~]# pcs resource clone locking interleave=true
  7. 建立 lvmlockd 资源,来作为 locking 资源组的一部分。

    [root@z1 ~]# pcs resource create lvmlockd --group locking ocf:heartbeat:lvmlockd op monitor interval=30s on-fail=fence
  8. 检查集群的状态,以确保在集群的两个节点上启动了 locking 资源组。

    [root@z1 ~]# pcs status --full
    Cluster name: my_cluster
    [...]
    
    Online: [ z1.example.com (1) z2.example.com (2) ]
    
    Full list of resources:
    
     smoke-apc      (stonith:fence_apc):    Started z1.example.com
     Clone Set: locking-clone [locking]
         Resource Group: locking:0
             dlm    (ocf::pacemaker:controld):      Started z1.example.com
             lvmlockd       (ocf::heartbeat:lvmlockd):      Started z1.example.com
         Resource Group: locking:1
             dlm    (ocf::pacemaker:controld):      Started z2.example.com
             lvmlockd       (ocf::heartbeat:lvmlockd):      Started z2.example.com
         Started: [ z1.example.com z2.example.com ]
  9. 在集群的一个节点中,创建两个共享卷组。一个卷组将包含两个 GFS2 文件系统,另一个卷组将包含一个 GFS2 文件系统。

    注意

    如果您的 LVM 卷组包含一个或多个位于远程块存储上的物理卷,如 iSCSI 目标,红帽建议您确保服务在 Pacemaker 启动前启动。有关为 Pacemaker 集群使用的远程物理卷配置启动顺序的详情,请参考 为不由 Pacemaker 管理的资源依赖项配置启动顺序

    以下命令在 /dev/vdb 上创建共享卷组 shared_vg1

    [root@z1 ~]# vgcreate --shared shared_vg1 /dev/vdb
      Physical volume "/dev/vdb" successfully created.
      Volume group "shared_vg1" successfully created
      VG shared_vg1 starting dlm lockspace
      Starting locking.  Waiting until locks are ready...

    以下命令在 /dev/vdc 上创建共享卷组 shared_vg2

    [root@z1 ~]# vgcreate --shared shared_vg2 /dev/vdc
      Physical volume "/dev/vdc" successfully created.
      Volume group "shared_vg2" successfully created
      VG shared_vg2 starting dlm lockspace
      Starting locking.  Waiting until locks are ready...
  10. 在集群的第二个节点上:

    1. 如果设备文件的使用是通过 lvm.conf 文件中的 use_devicesfile = 1 参数启用的,请将共享设备添加到设备文件中,此功能默认启用。

      [root@z2 ~]# lvmdevices --adddev /dev/vdb
      [root@z2 ~]# lvmdevices --adddev /dev/vdc
    2. 为每个共享卷组启动锁定管理器。

      [root@z2 ~]# vgchange --lockstart shared_vg1
        VG shared_vg1 starting dlm lockspace
        Starting locking.  Waiting until locks are ready...
      [root@z2 ~]# vgchange --lockstart shared_vg2
        VG shared_vg2 starting dlm lockspace
        Starting locking.  Waiting until locks are ready...
  11. 在集群的一个节点中,创建共享逻辑卷并使用 GFS2 文件系统格式化卷。每个挂载文件系统的节点都需要一个日志。确保为集群中的每个节点创建足够日志。锁表名称的格式为 ClusterName:FSName,其中 ClusterName 是创建 GFS2 文件系统的集群名称,FSName 是文件系统名称,它必须在集群中所有 lock_dlm 文件系统是唯一的。

    [root@z1 ~]# lvcreate --activate sy -L5G -n shared_lv1 shared_vg1
      Logical volume "shared_lv1" created.
    [root@z1 ~]# lvcreate --activate sy -L5G -n shared_lv2 shared_vg1
      Logical volume "shared_lv2" created.
    [root@z1 ~]# lvcreate --activate sy -L5G -n shared_lv1 shared_vg2
      Logical volume "shared_lv1" created.
    
    [root@z1 ~]# mkfs.gfs2 -j2 -p lock_dlm -t my_cluster:gfs2-demo1 /dev/shared_vg1/shared_lv1
    [root@z1 ~]# mkfs.gfs2 -j2 -p lock_dlm -t my_cluster:gfs2-demo2 /dev/shared_vg1/shared_lv2
    [root@z1 ~]# mkfs.gfs2 -j2 -p lock_dlm -t my_cluster:gfs2-demo3 /dev/shared_vg2/shared_lv1
  12. 为每个逻辑卷创建一个 LVM-activate 资源,以便在所有节点中自动激活该逻辑卷。

    1. 为卷组 shared_vg1 中的逻辑卷 shared_lv1 创建名为 sharedlv1LVM-activate 资源。此命令还会创建包含该资源的资源组 shared_vg1。在这个示例中,资源组的名称与包含逻辑卷的共享卷组的名称相同。

      [root@z1 ~]# pcs resource create sharedlv1 --group shared_vg1 ocf:heartbeat:LVM-activate lvname=shared_lv1 vgname=shared_vg1 activation_mode=shared vg_access_mode=lvmlockd
    2. 为卷组 shared_vg1 中的逻辑卷 shared_lv2 创建名为 sharedlv2LVM-activate 资源。此资源也是资源组 shared_vg1 的一部分。

      [root@z1 ~]# pcs resource create sharedlv2 --group shared_vg1 ocf:heartbeat:LVM-activate lvname=shared_lv2 vgname=shared_vg1 activation_mode=shared vg_access_mode=lvmlockd
    3. 为卷组 shared_vg2 中的逻辑卷 shared_lv1 创建名为 sharedlv3LVM-activate 资源。此命令还会创建包含该资源的资源组 shared_vg2

      [root@z1 ~]# pcs resource create sharedlv3 --group shared_vg2 ocf:heartbeat:LVM-activate lvname=shared_lv1 vgname=shared_vg2 activation_mode=shared vg_access_mode=lvmlockd
  13. 克隆两个新资源组。

    [root@z1 ~]# pcs resource clone shared_vg1 interleave=true
    [root@z1 ~]# pcs resource clone shared_vg2 interleave=true
  14. 配置排序限制,以确保首先启动包含 dlmlvmlockd 资源的 locking 资源组。

    [root@z1 ~]# pcs constraint order start locking-clone then shared_vg1-clone
    Adding locking-clone shared_vg1-clone (kind: Mandatory) (Options: first-action=start then-action=start)
    [root@z1 ~]# pcs constraint order start locking-clone then shared_vg2-clone
    Adding locking-clone shared_vg2-clone (kind: Mandatory) (Options: first-action=start then-action=start)
  15. 配置共存限制,以确保 vg1vg2 资源组在与 locking 资源组相同的节点上启动。

    [root@z1 ~]# pcs constraint colocation add shared_vg1-clone with locking-clone
    [root@z1 ~]# pcs constraint colocation add shared_vg2-clone with locking-clone
  16. 在集群中的两个节点中,验证逻辑卷是否活跃。这可能会延迟几秒钟。

    [root@z1 ~]# lvs
      LV         VG          Attr       LSize
      shared_lv1 shared_vg1  -wi-a----- 5.00g
      shared_lv2 shared_vg1  -wi-a----- 5.00g
      shared_lv1 shared_vg2  -wi-a----- 5.00g
    
    [root@z2 ~]# lvs
      LV         VG          Attr       LSize
      shared_lv1 shared_vg1  -wi-a----- 5.00g
      shared_lv2 shared_vg1  -wi-a----- 5.00g
      shared_lv1 shared_vg2  -wi-a----- 5.00g
  17. 创建文件系统资源在所有节点中自动挂载每个 GFS2 文件系统。

    您不应该将文件系统添加到 /etc/fstab 文件,因为它将作为 Pacemaker 集群资源进行管理。可以通过 options=options 将挂载选项指定为资源配置的一部分。运行 pcs resource describe Filesystem 命令显示完整的配置选项。

    以下命令可创建文件系统资源。这些命令在包含该文件系统逻辑卷资源的资源组中添加每个资源。

    [root@z1 ~]# pcs resource create sharedfs1 --group shared_vg1 ocf:heartbeat:Filesystem device="/dev/shared_vg1/shared_lv1" directory="/mnt/gfs1" fstype="gfs2" options=noatime op monitor interval=10s on-fail=fence
    [root@z1 ~]# pcs resource create sharedfs2 --group shared_vg1 ocf:heartbeat:Filesystem device="/dev/shared_vg1/shared_lv2" directory="/mnt/gfs2" fstype="gfs2" options=noatime op monitor interval=10s on-fail=fence
    [root@z1 ~]# pcs resource create sharedfs3 --group shared_vg2 ocf:heartbeat:Filesystem device="/dev/shared_vg2/shared_lv1" directory="/mnt/gfs3" fstype="gfs2" options=noatime op monitor interval=10s on-fail=fence

验证步骤

  1. 验证 GFS2 文件系统是否挂载到集群的两个节点中。

    [root@z1 ~]# mount | grep gfs2
    /dev/mapper/shared_vg1-shared_lv1 on /mnt/gfs1 type gfs2 (rw,noatime,seclabel)
    /dev/mapper/shared_vg1-shared_lv2 on /mnt/gfs2 type gfs2 (rw,noatime,seclabel)
    /dev/mapper/shared_vg2-shared_lv1 on /mnt/gfs3 type gfs2 (rw,noatime,seclabel)
    
    [root@z2 ~]# mount | grep gfs2
    /dev/mapper/shared_vg1-shared_lv1 on /mnt/gfs1 type gfs2 (rw,noatime,seclabel)
    /dev/mapper/shared_vg1-shared_lv2 on /mnt/gfs2 type gfs2 (rw,noatime,seclabel)
    /dev/mapper/shared_vg2-shared_lv1 on /mnt/gfs3 type gfs2 (rw,noatime,seclabel)
  2. 检查集群的状态。

    [root@z1 ~]# pcs status --full
    Cluster name: my_cluster
    [...]
    
    Full list of resources:
    
     smoke-apc      (stonith:fence_apc):    Started z1.example.com
     Clone Set: locking-clone [locking]
         Resource Group: locking:0
             dlm    (ocf::pacemaker:controld):      Started z2.example.com
             lvmlockd       (ocf::heartbeat:lvmlockd):      Started z2.example.com
         Resource Group: locking:1
             dlm    (ocf::pacemaker:controld):      Started z1.example.com
             lvmlockd       (ocf::heartbeat:lvmlockd):      Started z1.example.com
         Started: [ z1.example.com z2.example.com ]
     Clone Set: shared_vg1-clone [shared_vg1]
         Resource Group: shared_vg1:0
             sharedlv1      (ocf::heartbeat:LVM-activate):  Started z2.example.com
             sharedlv2      (ocf::heartbeat:LVM-activate):  Started z2.example.com
             sharedfs1      (ocf::heartbeat:Filesystem):    Started z2.example.com
             sharedfs2      (ocf::heartbeat:Filesystem):    Started z2.example.com
         Resource Group: shared_vg1:1
             sharedlv1      (ocf::heartbeat:LVM-activate):  Started z1.example.com
             sharedlv2      (ocf::heartbeat:LVM-activate):  Started z1.example.com
             sharedfs1      (ocf::heartbeat:Filesystem):    Started z1.example.com
             sharedfs2      (ocf::heartbeat:Filesystem):    Started z1.example.com
         Started: [ z1.example.com z2.example.com ]
     Clone Set: shared_vg2-clone [shared_vg2]
         Resource Group: shared_vg2:0
             sharedlv3      (ocf::heartbeat:LVM-activate):  Started z2.example.com
             sharedfs3      (ocf::heartbeat:Filesystem):    Started z2.example.com
         Resource Group: shared_vg2:1
             sharedlv3      (ocf::heartbeat:LVM-activate):  Started z1.example.com
             sharedfs3      (ocf::heartbeat:Filesystem):    Started z1.example.com
         Started: [ z1.example.com z2.example.com ]
    
    ...

8.2. 在集群中配置加密的 GFS2 文件系统

您可以按照以下流程创建一个包含 LUKS 加密的 GFS2 文件系统的 Pacemaker 集群。在这个示例中,您可以在逻辑卷上创建一个 GFS2 文件系统,并加密文件系统。使用 crypt 资源代理支持加密 GFS2 文件系统,该代理支持 LUKS 加密。

此流程有三个部分:

  • 在 Pacemaker 集群中配置共享逻辑卷
  • 加密逻辑卷并创建一个 crypt 资源
  • 使用 GFS2 文件系统格式化加密的逻辑卷并为集群创建文件系统资源

8.2.1. 在 Pacemaker 集群中配置共享逻辑卷

先决条件

  • 在两个集群节点上安装并启动集群软件,并创建一个基本的双节点集群。
  • 为集群配置隔离。

有关创建 Pacemaker 集群并为集群配置隔离的详情,请参考 使用 Pacemaker 创建红帽高可用性集群

步骤

  1. 在集群中的两个节点上,启用与您的系统架构对应的弹性存储存储库。例如,要为 x86_64 系统启用 Resilient Storage 仓库,您可以输入以下 subscription-manager 命令:

    # subscription-manager repos --enable=rhel-9-for-x86_64-resilientstorage-rpms

    请注意,弹性存储存储库是高可用性存储库的超集。如果启用弹性存储存储库,则不需要启用高可用性存储库。

  2. 在集群的两个节点上安装 lvm2-lockdgfs2-utilsdlm 软件包。要支持这些软件包,您必须订阅 AppStream 频道和 Resilient Storage 频道。

    # dnf install lvm2-lockd gfs2-utils dlm
  3. 在集群的两个节点上,将 /etc/lvm/lvm.conf 文件中的 use_lvmlockd 配置选项设置为 use_lvmlockd=1

    ...
    use_lvmlockd = 1
    ...
  4. 将全局 Pacemaker 参数 no-quorum-policy 设置为 freeze

    注意

    默认情况下,no-quorum-policy 的值设置为 stop,表示仲裁丢失时,剩余分区上的所有资源将立即停止。通常,这个默认行为是最安全、最优的选项,但与大多数资源不同,GFS2 要求使用 quorum 才可以正常工作。当使用 GFS2 挂载的应用程序和 GFS2 挂载都丢失时,就无法正确停止 GFS2 挂载。任何在没有 quorum 的情况下停止这些资源的尝试都会失败,并最终会在每次 quorum 都丢失时保护整个集群。

    要解决这个问题,请在使用 GFS2 时将 no-quorum-policy 设置为 freeze。这意味着,当 quorum 丢失时,剩余的分区将不会进行任何操作,直到 quorum 功能被恢复。

    [root@z1 ~]# pcs property set no-quorum-policy=freeze
  5. 设置 dlm 资源。这是在集群中配置 GFS2 文件系统所需的依赖软件包。这个示例创建 dlm 资源作为名为 locking 的资源组的一部分。

    [root@z1 ~]# pcs resource create dlm --group locking ocf:pacemaker:controld op monitor interval=30s on-fail=fence
  6. 克隆 locking 资源组,以便资源组可以在集群的两个节点上都活跃。

    [root@z1 ~]# pcs resource clone locking interleave=true
  7. 设置 lvmlockd 资源作为组 locking 的一部分。

    [root@z1 ~]# pcs resource create lvmlockd --group locking ocf:heartbeat:lvmlockd op monitor interval=30s on-fail=fence
  8. 检查集群的状态,以确保在集群的两个节点上启动了 locking 资源组。

    [root@z1 ~]# pcs status --full
    Cluster name: my_cluster
    [...]
    
    Online: [ z1.example.com (1) z2.example.com (2) ]
    
    Full list of resources:
    
     smoke-apc      (stonith:fence_apc):    Started z1.example.com
     Clone Set: locking-clone [locking]
         Resource Group: locking:0
             dlm    (ocf::pacemaker:controld):      Started z1.example.com
             lvmlockd       (ocf::heartbeat:lvmlockd):      Started z1.example.com
         Resource Group: locking:1
             dlm    (ocf::pacemaker:controld):      Started z2.example.com
             lvmlockd       (ocf::heartbeat:lvmlockd):      Started z2.example.com
         Started: [ z1.example.com z2.example.com ]
  9. 在集群的一个节点中创建一个共享卷组。

    注意

    如果您的 LVM 卷组包含一个或多个位于远程块存储上的物理卷,如 iSCSI 目标,红帽建议您确保服务在 Pacemaker 启动前启动。有关为 Pacemaker 集群使用的远程物理卷配置启动顺序的详情,请参考 为不由 Pacemaker 管理的资源依赖项配置启动顺序

    以下命令在 /dev/sda1 上创建共享卷组 shared_vg1

    [root@z1 ~]# vgcreate --shared shared_vg1 /dev/sda1
      Physical volume "/dev/sda1" successfully created.
      Volume group "shared_vg1" successfully created
      VG shared_vg1 starting dlm lockspace
      Starting locking.  Waiting until locks are ready...
  10. 在集群的第二个节点上:

    1. 如果设备文件的使用是通过 lvm.conf 文件中的 use_devicesfile = 1 参数启用的,请将共享设备添加到集群中第二个节点上的设备文件中。此功能默认为启用。

      [root@z2 ~]# lvmdevices --adddev /dev/sda1
    2. 启动共享卷组的锁定管理器。

      [root@z2 ~]# vgchange --lockstart shared_vg1
        VG shared_vg1 starting dlm lockspace
        Starting locking.  Waiting until locks are ready...
  11. 在集群的一个节点中创建共享逻辑卷。

    [root@z1 ~]# lvcreate --activate sy -L5G -n shared_lv1 shared_vg1
      Logical volume "shared_lv1" created.
  12. 为逻辑卷创建一个 LVM-activate 资源,以便在所有节点中自动激活逻辑卷。

    以下命令为卷组 shared_vg1 中的逻辑卷 shared_lv1 创建名为 sharedlv1LVM-activate 资源。此命令还会创建包含该资源的资源组 shared_vg1。在这个示例中,资源组的名称与包含逻辑卷的共享卷组的名称相同。

    [root@z1 ~]# pcs resource create sharedlv1 --group shared_vg1 ocf:heartbeat:LVM-activate lvname=shared_lv1 vgname=shared_vg1 activation_mode=shared vg_access_mode=lvmlockd
  13. 克隆新资源组。

    [root@z1 ~]# pcs resource clone shared_vg1 interleave=true
  14. 配置排序限制,以确保首先启动包含 dlmlvmlockd 资源的 locking 资源组。

    [root@z1 ~]# pcs constraint order start locking-clone then shared_vg1-clone
    Adding locking-clone shared_vg1-clone (kind: Mandatory) (Options: first-action=start then-action=start)
  15. 配置 colocation 约束,以确保 vg1vg2 资源组在与 locking 资源组相同的节点上启动。

    [root@z1 ~]# pcs constraint colocation add shared_vg1-clone with locking-clone

验证步骤

在集群中的两个节点中,验证逻辑卷是否活跃。这可能会延迟几秒钟。

[root@z1 ~]# lvs
  LV         VG          Attr       LSize
  shared_lv1 shared_vg1  -wi-a----- 5.00g

[root@z2 ~]# lvs
  LV         VG          Attr       LSize
  shared_lv1 shared_vg1  -wi-a----- 5.00g

8.2.2. 加密逻辑卷并创建 crypt 资源

先决条件

  • 您已在 Pacemaker 集群中配置了共享逻辑卷。

步骤

  1. 在集群的一个节点中,创建一个包含 crypt 密钥的新文件,并在文件中设置权限,使其只能被 root 读取。

    [root@z1 ~]# touch /etc/crypt_keyfile
    [root@z1 ~]# chmod 600 /etc/crypt_keyfile
  2. 创建 crypt 密钥。

    [root@z1 ~]# dd if=/dev/urandom bs=4K count=1 of=/etc/crypt_keyfile
    1+0 records in
    1+0 records out
    4096 bytes (4.1 kB, 4.0 KiB) copied, 0.000306202 s, 13.4 MB/s
    [root@z1 ~]# scp /etc/crypt_keyfile root@z2.example.com:/etc/
  3. 使用 -p 参数将 crypt keyfile 分发到集群中的其他节点,以保留您设置的权限。

    [root@z1 ~]# scp -p /etc/crypt_keyfile root@z2.example.com:/etc/
  4. 在要配置加密的 GFS2 文件系统的 LVM 卷中创建加密设备。

    [root@z1 ~]# cryptsetup luksFormat /dev/shared_vg1/shared_lv1 --type luks2 --key-file=/etc/crypt_keyfile
    WARNING!
    ========
    This will overwrite data on /dev/shared_vg1/shared_lv1 irrevocably.
    
    Are you sure? (Type 'yes' in capital letters): YES
  5. 创建 crypt 资源,作为 shared_vg1 卷组的一部分。

    [root@z1 ~]# pcs resource create crypt --group shared_vg1 ocf:heartbeat:crypt crypt_dev="luks_lv1" crypt_type=luks2 key_file=/etc/crypt_keyfile encrypted_dev="/dev/shared_vg1/shared_lv1"

验证步骤

确保 crypt 资源已创建了 crypt 设备,本例中为 /dev/mapper/luks_lv1

[root@z1 ~]# ls -l /dev/mapper/
...
lrwxrwxrwx 1 root root 7 Mar 4 09:52 luks_lv1 -> ../dm-3
...

8.2.3. 使用 GFS2 文件系统格式化加密的逻辑卷,并为集群创建一个文件系统资源

先决条件

  • 您已加密逻辑卷并创建 crypt 资源。

步骤

  1. 在集群的一个节点中,使用 GFS2 文件系统格式化卷。每个挂载文件系统的节点都需要一个日志。确保为集群中的每个节点创建足够日志。锁表名称的格式为 ClusterName:FSName,其中 ClusterName 是创建 GFS2 文件系统的集群名称,FSName 是文件系统名称,它必须在集群中所有 lock_dlm 文件系统是唯一的。

    [root@z1 ~]# mkfs.gfs2 -j3 -p lock_dlm -t my_cluster:gfs2-demo1 /dev/mapper/luks_lv1
    /dev/mapper/luks_lv1 is a symbolic link to /dev/dm-3
    This will destroy any data on /dev/dm-3
    Are you sure you want to proceed? [y/n] y
    Discarding device contents (may take a while on large devices): Done
    Adding journals: Done
    Building resource groups: Done
    Creating quota file: Done
    Writing superblock and syncing: Done
    Device:                    /dev/mapper/luks_lv1
    Block size:                4096
    Device size:               4.98 GB (1306624 blocks)
    Filesystem size:           4.98 GB (1306622 blocks)
    Journals:                  3
    Journal size:              16MB
    Resource groups:           23
    Locking protocol:          "lock_dlm"
    Lock table:                "my_cluster:gfs2-demo1"
    UUID:                      de263f7b-0f12-4d02-bbb2-56642fade293
  2. 创建文件系统资源在所有节点中自动挂载 GFS2 文件系统。

    不要将该文件系统添加到 /etc/fstab 文件中,因为它将作为 Pacemaker 集群资源进行管理。可以通过 options=options 将挂载选项指定为资源配置的一部分。运行 pcs resource describe Filesystem 命令以了解完整的配置选项。

    以下命令创建文件系统资源。这个命令在包含该文件系统逻辑卷资源的资源组中添加资源。

    [root@z1 ~]# pcs resource create sharedfs1 --group shared_vg1 ocf:heartbeat:Filesystem device="/dev/mapper/luks_lv1" directory="/mnt/gfs1" fstype="gfs2" options=noatime op monitor interval=10s on-fail=fence

验证步骤

  1. 验证 GFS2 文件系统是否挂载到集群的两个节点上。

    [root@z1 ~]# mount | grep gfs2
    /dev/mapper/luks_lv1 on /mnt/gfs1 type gfs2 (rw,noatime,seclabel)
    
    [root@z2 ~]# mount | grep gfs2
    /dev/mapper/luks_lv1 on /mnt/gfs1 type gfs2 (rw,noatime,seclabel)
  2. 检查集群的状态。

    [root@z1 ~]# pcs status --full
    Cluster name: my_cluster
    [...]
    
    Full list of resources:
    
      smoke-apc      (stonith:fence_apc):    Started z1.example.com
      Clone Set: locking-clone [locking]
          Resource Group: locking:0
              dlm    (ocf::pacemaker:controld):      Started z2.example.com
              lvmlockd       (ocf::heartbeat:lvmlockd):      Started z2.example.com
          Resource Group: locking:1
              dlm    (ocf::pacemaker:controld):      Started z1.example.com
              lvmlockd       (ocf::heartbeat:lvmlockd):      Started z1.example.com
         Started: [ z1.example.com z2.example.com ]
      Clone Set: shared_vg1-clone [shared_vg1]
         Resource Group: shared_vg1:0
                 sharedlv1      (ocf::heartbeat:LVM-activate):  Started z2.example.com
                 crypt       (ocf::heartbeat:crypt) Started z2.example.com
                 sharedfs1      (ocf::heartbeat:Filesystem):    Started z2.example.com
        Resource Group: shared_vg1:1
                 sharedlv1      (ocf::heartbeat:LVM-activate):  Started z1.example.com
                 crypt      (ocf::heartbeat:crypt)  Started z1.example.com
                 sharedfs1      (ocf::heartbeat:Filesystem):    Started z1.example.com
              Started:  [z1.example.com z2.example.com ]
    ...

第 9 章 GFS2 追踪点和 glock debugfs 接口

本文档介绍了 GFS2 追踪点和 glock debugfs 接口的文档,适用于熟悉文件系统内部的高级用户,以及想要了解更多有关 GFS2 设计以及如何调试 GFS2 具体问题的信息。

以下小节描述了 GFS2 追踪点和 GFS2 glocks 文件。

9.1. GFS2 追踪点(tracepoint)类型

目前有三种类型的 GFS2 追踪点:glock (发音为 "gee-lock")追踪点、bmap 追踪点和 log 追踪点。它们可以用来监控正在运行的 GFS2 文件系统。当问题(如挂起或性能问题)可以重复出现时,追踪点就会非常有用,因此可以在有问题的操作过程中获得追踪点的输出。在 GFS2 中,glocks 是主要缓存控制机制,它们是了解 GFS2 内核性能的关键。bmap(块映射)追踪点可用于监控块分配和块映射(查找磁盘元数据树中已分配的块)以及检查与本地访问相关的任何问题。日志追踪点跟踪从日志中写入和释放的数据,并提供了有关 GFS2 部分的有用信息。

追踪点的设计原则是尽可能通用。这意味着,在 Red Hat Enterprise Linux 9 过程中不需要更改 API。另外,这个接口的用户应该注意,这是一个调试接口,而不是正常的 Red Hat Enterprise Linux 9 API 集合的一部分,因此红帽不保证 GFS2 追踪点接口中的更改不会发生。

追踪点是 Red Hat Enterprise Linux 的一般功能,其范围超出了 GFS2。特别是用于实施 blktrace 基础架构,并且可将 blktrace 追踪点与 GFS2 结合使用,以获得系统性能的完整信息。取决于追踪点操作的级别,它们可能会在短时间内产生大量数据。虽然追踪点被设计为在启用时有最小的系统负载,但它们无可避免地会产生一些影响。通过不同方法过滤事件可帮助减少数据的数量,并帮助只获得有助于了解特定情形的信息。

9.2. 追踪点(Tracepoints)

追踪点可以在 /sys/kernel/debug/ 目录下找到,假设 debugfs 挂载于 /sys/kernel/debug 目录中的标准位置。events 子目录包含所有可以被指定的追踪事件,如果提供了载入的 gfs2 模块,则在每个 GFS2 事件中都有一个 gfs2 子目录。/sys/kernel/debug/tracing/events/gfs2 目录的内容类似如下:

[root@chywoon gfs2]# ls
enable            gfs2_bmap       gfs2_glock_queue         gfs2_log_flush
filter            gfs2_demote_rq  gfs2_glock_state_change  gfs2_pin
gfs2_block_alloc  gfs2_glock_put  gfs2_log_blocks          gfs2_promote

要启用所有 GFS2 追踪点,请输入以下命令:

[root@chywoon gfs2]# echo -n 1 >/sys/kernel/debug/tracing/events/gfs2/enable

要启用特定的追踪点,在每个事件子目录中有一个 enable 文件。filter 文件也是如此,可用于为每个事件或一组事件设置事件过滤器。下面详细解释了各个事件的含义。

追踪点的输出以 ASCII 或二进制格式提供。本附录目前不包含二进制接口。ASCII 接口有两种方式。要列出环缓冲(ring buffer)的当前内容,您可以输入以下命令:

[root@chywoon gfs2]# cat /sys/kernel/debug/tracing/trace

当您在一定时间段内使用长时间运行的过程时,且希望在这些事件进行之后重新查看缓冲区中最新捕获的信息时,这个接口很有用。需要所有输出时,也可以使用另一种接口 /sys/kernel/debug/tracing/trace_pipe。事件发生时会从这个文件中进行读取,这个接口不提供历史数据。两个接口的输出格式是相同,在本附录后续部分对每个 GFS2 事件都有说明。

可以使用名为 trace-cmd 的实用程序来读取追踪点数据。有关这个工具的详情,请参考 http://lwn.net/Articles/341902/trace-cmd 实用程序可用方式与 strace 实用程序类似,例如在从不同源收集追踪数据时运行命令。

9.3. Glocks

对于 GFS2,最重要的一个独特的概念就是 glocks。就源代码而言,glock 是一个数据结构,它将合并 DLM 并缓存到单个状态机器。每个 glock 与一个 DLM 锁定有一个 1:1 的关系,为该锁定状态提供缓存,以便从文件系统中单一节点执行的重复操作不必重复调用 DLM,这有助于避免不必要的网络流量。有两大类 glock,一类是有元数据缓存的 glock,另外是没有元数据缓存的 glock。内节点 glock 和资源组 glock 都有元数据缓存,其他类型的 glock 不缓存元数据。内节点 glock 除元数据外还会缓存数据,并且具有所有 glocks 中最复杂的逻辑。

表 9.1. Glock 模式和 DLM 锁定模式

Glock 模式DLM 锁定模式备注

UN

IV/NL

未锁定(没有与 glock 相关的 DLM 锁定,或 NL 锁定取决于 I 标记)

SH

PR

共享(读保护)锁定

EX

EX

专用锁定

DF

CW

用于直接 I/O 和文件系统停止的延迟(并性写)

Glocks 会一直保留在内存中,直到其被解锁(根据另一个节点的请求,或虚拟机的请求)或不再有本地用户。此时它们会从 glock 哈希表中移除并释放。当 glock 创建时,DLM 锁定不会立即与 glock 关联。当对 DLM 第一次请求时,DLM 锁定与 glock 关联,如果这个请求成功,那么会在 glock 中设定 'I'(初始)标记。glock debugfs 接口 中的 "Glock Flags" 表显示不同 glock 标记的含义。当 DLM 与 glock 关联后,DLM 锁定将始终保持至少为 NL(Null)锁定模式,直到 glock 被释放。当 DLM 锁从 NL 变为解锁状态始终是 glock 生命周期中的最后一个操作。

每个 glock 都有多个与它关联的"拥有者(holder)",每个都代表来自更高层的一个锁定请求。与来自 glock 队列的 GFS2 queue 和 dequeue holder 相关的系统调用,用来保护代码的关键部分。

glock 状态机器基于一个工作队列。出于性能的原因,可能会首选 tasklets;但是,在当前的实施中,我们需要从那些禁止他们使用的情况下提交 I/O。

注意

Workqueue 有自己的追踪点,它们可与 GFS2 追踪点结合使用。

下表显示了每个 glock 模式下可能会缓存哪些状态,以及缓存的状态是否为脏数据。这适用于内节点和资源组锁定,尽管资源组锁中没有数据组件,只有元数据。

表 9.2. Glock 模式和数据类型

Glock 模式缓存数据缓存元数据脏数据脏元数据

UN

SH

DF

EX

9.4. glock debugfs 接口

glock debugfs 接口允许视觉化 glocks 的内部状态和拥有者,并包括了在一些情况下被锁定的对象的一些概述详情。文件的每一行都以 G: 开头,没有缩进(代表 glock 本身),或者以不同的字母开始,使用单个空格缩进,代表在文件中立即与 glock 关联的结构(H: 是拥有者、I: 是一个内节点、R: 资源组)。下面是一个示例:

G:  s:SH n:5/75320 f:I t:SH d:EX/0 a:0 r:3
 H: s:SH f:EH e:0 p:4466 [postmark] gfs2_inode_lookup+0x14e/0x260 [gfs2]
G:  s:EX n:3/258028 f:yI t:EX d:EX/0 a:3 r:4
 H: s:EX f:tH e:0 p:4466 [postmark] gfs2_inplace_reserve_i+0x177/0x780 [gfs2]
 R: n:258028 f:05 b:22256/22256 i:16800
G:  s:EX n:2/219916 f:yfI t:EX d:EX/0 a:0 r:3
 I: n:75661/219916 t:8 f:0x10 d:0x00000000 s:7522/7522
G:  s:SH n:5/127205 f:I t:SH d:EX/0 a:0 r:3
 H: s:SH f:EH e:0 p:4466 [postmark] gfs2_inode_lookup+0x14e/0x260 [gfs2]
G:  s:EX n:2/50382 f:yfI t:EX d:EX/0 a:0 r:2
G:  s:SH n:5/302519 f:I t:SH d:EX/0 a:0 r:3
 H: s:SH f:EH e:0 p:4466 [postmark] gfs2_inode_lookup+0x14e/0x260 [gfs2]
G:  s:SH n:5/313874 f:I t:SH d:EX/0 a:0 r:3
 H: s:SH f:EH e:0 p:4466 [postmark] gfs2_inode_lookup+0x14e/0x260 [gfs2]
G:  s:SH n:5/271916 f:I t:SH d:EX/0 a:0 r:3
 H: s:SH f:EH e:0 p:4466 [postmark] gfs2_inode_lookup+0x14e/0x260 [gfs2]
G:  s:SH n:5/312732 f:I t:SH d:EX/0 a:0 r:3
 H: s:SH f:EH e:0 p:4466 [postmark] gfs2_inode_lookup+0x14e/0x260 [gfs2]

上面的例子是一系列摘录(来自由命令 cat /sys/kernel/debug/gfs2/unity:myfs/glocks >my.locks >my.locks >my.lock 在单一节点 GFS2 文件系统运行基准的大约 18MB 文件)图中的 glocks 已选择,以便显示一些更值得关注的 glock 转储特性。

glock 状态是 EX(专用)、DF(推迟)、SH(共享)或 UN(未锁定)。这些状态与 DLM 锁定模式直接对应,但 UN 可能代表 DLM null 锁定状态,或者 GFS2 没有包含 DLM 锁定(取决于上面解释的 I 标记)。glock 的 s: 字段显示锁定的当前状态,拥有者中的同一字段指示请求的模式。如果准许了锁定,则拥有者将在标记(f: field)中带有 H 位。否则,它将设置 W wait 位。

n: 字段(数字)表示与每个项目关联的数字。对于 glocks,这是类型号后接 glock 号,在上例中第一个 glock 是 n:5/75320;,它代表了一个 iopen glock,它与内节点 75320 相关。在内节点和 iopen glocks 中,glock 号始终与内节点的磁盘块号相同。

注意

debugfs glocks 文件中的 glock 号(n: field)以十六进制表示,而追踪点输出以十进制表示。这是因为历史原因造成的;glock 数字使用十六进制,但追踪点使用十进制数字以便可轻松地与其他追踪点输出(例如 blktrace)和来自 stat(1 的输出进行比较。

holder 和 glock 标记的完整列表包括在以下的 "Glock Flags" 表中,以及 Glock holders 的 "Glock Holder Flags" 表中。目前无法通过 glock debugfs 接口获取锁定值块的内容。

下表显示了不同 glock 类型的含义。

表 9.3. Glock 类型

类型号锁定类型使用

1

trans

事务锁定

2

inode

内节点元数据和数据

3

rgrp

源组群元数据

4

meta

超级块

5

iopen

内节点最近探测

6

flock

flock(2)syscall

8

quota

配额操作

9

journal

Journal mutex

更重要的 glock 标记之一就是 l (locked) 标记。这是执行状态更改时用于识别对 glock 状态的访问的位锁定。当状态机器要通过 DLM 发送远程锁定请求时设置它,只有在执行完操作时才会清除它。有时这意味着已发送了多个锁定请求,不同时间发生各种无效请求。

下表显示了不同 glock 标记的含义。

表 9.4. Glock 标记

标记名称含义

d

Pending demote

推迟(远程)降级请求

D

Demote

降级请求(本地或者远程)

f

Log flush

释放这个 glock 前需要提交该日志

F

Frozen

回复忽略的远程节点 -- 恢复正在进行。

i

Invalidate in progress

这个 glock 下无效页面的进程中

I

Initial

设定何时将 DLM 锁定与这个 glock 关联

l

Locked

这个 glock 处于更改状态中

L

LRU

设置什么时候 glock 出现在 LRU 列表中

o

Object

设置 glock 何时与对象关联(即类型为 2 glocks 的内节点,以及类型为 3 的 glock 的资源组)

p

Demote in progress

glock 正在响应降级请求

q

Queued

设定当拥有者排队到 glock 时,并在 glock 保留时清除,但没有剩余所有者。作为算法的一部分使用,计算 glock 的最小保留时间。

r

Reply pending

从远程节点接收的回复正在等待过程中

y

Dirty

释放这个 glock 前需要冲刷到磁盘中的数据

当从节点收到远程回调时,希望获得锁定时,与本地节点上保留的冲突,然后设置两个标志 D(降级)或 d(降级待处理)冲突。为了防止在特定锁定竞争时出现不足的情况,可以为每个锁定分配一个最少的时间。在时间间隔到期前,允许最小保留锁定的节点保留这个锁定。

如果时间间隔已过期,那么将设置 D(demote)标志,并记录所需状态。在这种情况下,在拥有者队列中没有允许的锁定,锁定将被降级。如果时间间隔没有过期,则将设置 d(降级待处理)标记。这也会调度状态机器清除 d(降级待处理)并在最小的静默时间已过期时设置 D(降级)。

当为 glock 分配 DLM 锁定时,会设定 I(初始)标记。当 glock 首次被使用,而且 I 标签将会一直被设置,直到 glock 最终被释放(DLM 锁定被解锁)。

9.5. Glock 拥有者(holder)

下表显示了不同 glock 拥有者标记的含义。

表 9.5. Glock Holder Flags

标记名称含义

a

Async

不要等待 glock 结果(以后轮询结果)

A

Any

接受任意兼容锁定模式

c

No cache

取消锁定时,立即降级 DLM 锁定

e

No expire

忽略随后的锁定取消请求

E

Exact

必须有准确的锁定模式

F

First

设定赋予这个锁定的第一个拥有者

H

Holder

表示赋予请求的锁定

p

Priority

在队列头启用 ENQUEUE 拥有者

t

Try

"try" 锁定

T

Try 1CB

发送回调的 "try" 锁定

W

Wait

等待请求完成的设置

如前面提到的,最重要的拥有者标志是 H(拥有者)和 W(等待),因为它们分别被设置在赋予的锁定请求和锁定请求中。在队列中的拥有者的顺序非常重要。如果有被允许的所有者,则他们将总位于队列的前头,后接其他进入队列的所有者。

如果没有被允许的所有者,列表中的第一个拥有者就是触发下一个状态更改的拥有者。因为降级请求总是被认为比文件系统的请求具有更高的优先级,所以可能并不总是直接导致请求的状态改变。

glock 子系统支持两种类型的 "try" 锁定。这两类都比较有用,因为它们允许把锁定移出正常的顺序(使用适当的 back-off 和 retry),且它们可以被用来帮助避免资源被其他节点使用。正常的 t(try) 锁定如其名字所示,它是一个 "try"锁定,不会做任何特殊操作。相反,T(try 1CB)锁定和 t 锁基本一样,唯一的不同是 DLM 会向当前不兼容的锁定拥有者发送一个回调。T(try 1CB)锁定的一个用法是带有 iopen 锁定,它用于在内节点的 i_nlink 计数为零时,在节点间进行判断,并确定哪些节点将负责取消内节点的事务。iopen glock 通常处于共享状态,但如果 i_nlink 计数为零,并调用了 →evict_inode(),它将请求一个带有 T(try 1CB)设置的专用锁定。如果允许了锁定,它将继续取消内节点的配置。如果没有允许的锁定,则会导致阻止锁定的节点使用 D(demote)标记标记它们的 glock,该标记会在 →drop_inode() 时检查以确保取消分配不会被忘记。

这意味着,具有零个链接计数但仍打开的内节点,将在最终 close() 发生时被节点取消分配。另外,当内节点的链接计数降为 0 时,内节点被标记为处于具有零链路计数的特殊状态,但仍在资源组位映射中使用。这和 ext3 文件系统的孤儿列表类似,它可让位图的任意后续读者知道有可能会回收的空间,并尝试重新声明它。

9.6. Glock 追踪点

追踪点也被设计为能够通过将缓存控制与 blktrace 输出合并,并了解磁盘布局来确认缓存控制的正确性。然后可以检查是否在正确锁定下发布并完成任意给定的 I/O,并且没有竞争。

gfs2_glock_state_change 追踪点是要理解的最重要的一点。它跟踪 glock 每次从初始创建到最终降级的状态更改,该演示以 gfs2_glock_put 结束,最终 NL 被解锁转换。l (locked) glock 标志总是在状态更改发生前设置,且只有在完成更改后才会清除。在状态更改过程中,不会有未允许的拥有者(H glock 拥有者标志)。如果有排队的拥有者,他们将总是处于 W(等待)状态。当完成了状态更改后,允许拥有者可能是清除 l glock 标签前的最后操作。

gfs2_demote_rq 追踪点会跟踪降级请求,包括本地和远程的降级请求。假设节点上有足够的内存,本地降级请求将很少出现,最常见的是由 umount 创建,或者偶尔内存被重新声明。远程降级请求数量是节点针对特定内节点或资源组间争用的指标。

gfs2_glock_lock_time 追踪点提供有关对 DLM 请求所需时间的信息。阻塞(b)标志被加入到 glock 中,专门用于与这个追踪点结合使用。

当为拥有者授予锁定时,会调用 gfs2_promote,这是作为状态更改的最后阶段,或者请求锁定时,可能会因为 glock 状态已缓存合适的模式而立即授予该拥有者。如果拥有者是授予这个 glock 的第一个拥有者,那么就会在该拥有者中设定 f(第一个)标记。目前,这只由资源组使用。

9.7. Bmap 追踪点

块映射对任何文件系统都是一个核心任务。GFS2 使用传统的基于位图的系统,每个块有两个位。这个子系统中的追踪点的主要目的是,允许监控分配和映射块的时间。

每个 bmap 操作都会调用 gfs2_bmap 追踪点:一次在开始显示 bmap 请求,一次在结尾以显示结果。这样可轻松地将请求和结果匹配,并测量在文件系统的不同部分映射块、不同文件偏移甚至不同文件所需时间。也可以查看返回的平均扩展大小与请求的比较。

gfs2_rs 跟踪点跟踪块在块分配器中创建、使用和销毁时的块保留。

要追踪分配的块,gfs2_block_alloc 不仅在分配时被调用,在释放块时也会被调用。由于分配都是根据块所针对的内节点引用的所有,因此可用来跟踪哪些物理块属于 live 文件系统中的文件。这在与 blktrace 合并时特别有用,这会显示有问题的 I/O 模式,然后使用追踪点提供的映射将其返回到相关的内节点。

直接 I/O(iomap)是一个替代缓存策略,它允许在磁盘和用户缓冲区之间直接进行文件数据传输。当缓存的匹配率低时,这将非常有用。gfs2_iomap_startgfs2_iomap_end 追踪点可跟踪这些操作,并可用于跟踪使用 Direct I/O 的文件系统的映射,即直接 I/O 文件系统中的位置,以及操作类型。

9.8. 日志追踪点

该子系统中的追踪点跟踪添加到日志或从日志中删除的块(gfs2_pin),以及将事务提交至日志所需的时间(gfs2_log_flush)。这在调试日志性能问题时非常有用。

gfs2_log_blocks 追踪点会跟踪日志中保留的块,这可以帮助显示日志是否太小的工作负载,例如:

gfs2_ail_flush 追踪点与 gfs2_log_flush 追踪点(跟踪 AIL 列表的开始和结束)相似。AIL 列表包含已通过日志的缓冲区,但尚未写回。这应该定期清除,以释放文件系统使用的更多日志文件,或者一个进程请求 syncfsync 时进行。

9.9. Glock 统计

GFS2 维护可帮助您跟踪文件系统中正在运行的统计信息。这可让您发现性能问题。

GFS2 维护两个计数器:

  • dcount 统计请求的 DLM 操作数量。这显示了数据量的 mean/variance 值。
  • qcount 统计请求的 syscall 级别操作数量。通常 qcount 等于或大于 dcount

另外,GFS2 维护三个平均/变量对。平均/变量对是平滑度估算,使用的算法是用于计算网络代码中往返时间的算法。

GFS2 中维护的 mean 和 variance 值没有经过 scale 处理,而是以整数纳秒为单位。

  • srtt/srttvar:非阻塞操作的平稳往返时间
  • srttb/srttvarb:阻塞操作的平稳往返时间
  • irtt/irttvar:在请求的间时间(例如,DLM 请求之间的时间)

非阻塞请求是一个马上完成的请求,无论有疑问的 DLM 锁定状态如何。这当前意味着,请求的条件为 (a) 当前的锁定状态为专用( exclusive);(b) 请求的状态为 null 或者非锁定(unlocked);或 (c) 设定了"try lock"标记。其他锁定请求都为阻塞请求。

对于 IRTTs 来说,较大的时间比较好;对于 RTTs 来说,比较小的时间更好。

统计数据保存在两个 sysfs 文件中:

  • glstats 文件。这个文件与 glocks 文件类似,但它包含统计信息,每个 glock 一行。数据从那个 glock 类型的"每个 cpu"数据初始化,数据会被创建 glock(来自计数器,零)。这个文件可能非常大。
  • lkstats 文件。它为每个 glock 类型包含 "per cpu" 统计信息。它每行包含一个统计数据,每列都是一个 cpu 内核。每个 glock 类型有 8 行,一个类型跟随另一个类型。

9.10. 参考信息

有关追踪点和 GFS2 glocks 文件的详情,请查看以下资源:

第 10 章 使用 Performance Co-Pilot(PCP)监控和分析 GFS2 文件系统

Performance Co-Pilot(PCP)有助于监控和分析 GFS2 文件系统。监控 PCP 中的 GFS2 文件系统是由 Red Hat Enterprise Linux 中的 GFS2 PMDA 模块提供的,该模块可通过 pcp-pmda-gfs2 软件包获得。

GFS2 PMDA 提供很多由 debugfs 子系统提供的 GFS2 统计给出的指标。安装后,PMDA 会公开 glocks, glstats, 和 sbstats 文件中给出的值。报告每个挂载的 GFS2 文件系统的统计组。PMDA 还使用由 Kernel Function Tracer(ftrace)公开的 GFS2 内核追踪点。

10.1. 安装 GFS2 PMDA

为了正确运行,GFS2 PMDA 要求挂载 debugfs 文件系统。如果没有挂载 debugfs 文件系统,请在安装 GFS2 PMDA 前运行以下命令:

# mkdir /sys/kernel/debug
# mount -t debugfs none /sys/kernel/debug

在默认安装中不启用 GFS2 PMDA。要通过 PCP 使用 GFS2 指标监控,您必须在安装后启用它。

运行以下命令来安装 PCP 并启用 GFS2 PMDA。请注意,PMDA 安装脚本必须以 root 用户身份运行。

# dnf install pcp pcp-pmda-gfs2
# cd /var/lib/pcp/pmdas/gfs2
# ./Install
Updating the Performance Metrics Name Space (PMNS) ...
Terminate PMDA if already installed ...
Updating the PMCD control file, and notifying PMCD ...
Check gfs2 metrics have appeared ... 346 metrics and 255 values

10.2. 使用 pminfo 工具显示可用性能指标的信息

pminfo 工具显示有关可用性能指标的信息。以下示例显示了您可以使用这个工具显示的不同 GFS2 指标。

10.2.1. 检查每个文件系统目前存在的 glock 结构数

GFS2 glock 指标可让您了解当前挂载的 GFS2 文件系统的 glock 结构数及其锁定状态。在 GFS2 中,glock 是一个数据结构,它将合并 DLM 并缓存到单个状态机器。每个 glock 都有一个与单个 DLM 锁定的 1:1 映射,为锁定状态提供缓存,使得在单个节点中进行的重复操作不必重复调用 DLM,从而减少不必要的网络流量。

以下 pminfo 命令按其锁定模式显示每个挂载的 GFS2 文件系统的 glocks 数列表。

# pminfo -f gfs2.glocks

gfs2.glocks.total
    inst [0 or "afc_cluster:data"] value 43680
    inst [1 or "afc_cluster:bin"] value 2091

gfs2.glocks.shared
    inst [0 or "afc_cluster:data"] value 25
    inst [1 or "afc_cluster:bin"] value 25

gfs2.glocks.unlocked
    inst [0 or "afc_cluster:data"] value 43652
    inst [1 or "afc_cluster:bin"] value 2063

gfs2.glocks.deferred
    inst [0 or "afc_cluster:data"] value 0
    inst [1 or "afc_cluster:bin"] value 0

gfs2.glocks.exclusive
    inst [0 or "afc_cluster:data"] value 3
    inst [1 or "afc_cluster:bin"] value 3

10.2.2. 根据类型检查每个文件系统目前存在的 glock 结构数

GFS2 glstats 指标给出了每种 glock 类型的计数,这些 glock 每个 ystem 文件都存在,它们通常属于内节点(inode 和 metadata)或者资源组(资源组元数据)类型。

以下 pminfo 命令显示每个挂载的 GFS2 文件系统中的每种 Glock 类型的数目。

# pminfo -f gfs2.glstats

gfs2.glstats.total
    inst [0 or "afc_cluster:data"] value 43680
    inst [1 or "afc_cluster:bin"] value 2091

gfs2.glstats.trans
    inst [0 or "afc_cluster:data"] value 3
    inst [1 or "afc_cluster:bin"] value 3

gfs2.glstats.inode
    inst [0 or "afc_cluster:data"] value 17
    inst [1 or "afc_cluster:bin"] value 17

gfs2.glstats.rgrp
    inst [0 or "afc_cluster:data"] value 43642
    inst [1 or "afc_cluster:bin"] value 2053

gfs2.glstats.meta
    inst [0 or "afc_cluster:data"] value 1
    inst [1 or "afc_cluster:bin"] value 1

gfs2.glstats.iopen
    inst [0 or "afc_cluster:data"] value 16
    inst [1 or "afc_cluster:bin"] value 16

gfs2.glstats.flock
    inst [0 or "afc_cluster:data"] value 0
    inst [1 or "afc_cluster:bin"] value 0

gfs2.glstats.quota
    inst [0 or "afc_cluster:data"] value 0
    inst [1 or "afc_cluster:bin"] value 0

gfs2.glstats.journal
    inst [0 or "afc_cluster:data"] value 1
    inst [1 or "afc_cluster:bin"] value 1

10.2.3. 检查处于等待状态的 glock 结构数量

最重要的拥有者标志是 H(holder:表示赋予请求的锁定)和 W(wait:等待请求完成时设置)。这些标记分别在赋予锁定请求和锁定请求队列中设置。

以下 pminfo 命令显示每个挂载的 GFS2 文件系统的 Wait(W)拥有者标签的 glocks 数。

# pminfo -f gfs2.holders.flags.wait

gfs2.holders.flags.wait
    inst [0 or "afc_cluster:data"] value 0
    inst [1 or "afc_cluster:bin"] value 0

如果您看到在资源组锁定中排队了大量等待的请求,,那么可能有很多原因。一个原因可能是,在文件系统中,相对于资源组有大量的节点。另一个可能的原因是,文件系统可能接近完全被使用(平均来讲,需要较长的搜索时间)可以通过添加更多存储并使用 gfs2_grow 命令来扩展文件系统来提高这种情况。

10.2.4. 使用基于内核追踪点的指标检查文件系统操作延迟

GFS2 PMDA 支持从 GFS2 内核追踪点收集指标数据。默认情况下,禁用了对这些指标的读取。当收集指标时,激活这些指标会打开 GFS2 内核跟踪点来填充指标值。当启用了这些内核追踪点指标数据时,这可能会对性能吞吐量产生小的影响。

PCP 提供了 pmstore 工具,它允许您根据指标值修改 PMDA 设置。gfs2.control.* 指标允许切换 GFS2 内核追踪点。以下示例使用 pmstore 命令启用所有 GFS2 内核追踪点。

# pmstore gfs2.control.tracepoints.all 1
gfs2.control.tracepoints.all old value=0 new value=1

当运行这个命令时,PMDA 会切换 debugfs 文件系统中的所有 GFS2 追踪点。PCP 中 GFS2 可用指标的完整列表中的"完整指标列表"表说明了每个控制追踪点及其用法,也可以通过 pminfo 中的 帮助切换了解每个控制追踪点及其可用选项的影响。

GFS2 提升指标计算文件系统中提升请求的数量。这些请求由首次尝试和"其他"在初始提升请求后授予的请求数量分隔。第一次提升的时间减少"其他人"的提升可指示文件争用问题。

GFS2 降级请求指标(如提升请求指标)统计文件系统中的降级请求数。但是,这些也被分隔为来自当前节点的请求和来自系统中其他节点的请求。来自远程节点的大量降级请求可能会表示给定资源组在两个节点间出现竞争。

pminfo 工具显示有关可用性能指标的信息。这个过程显示每个挂载的 GFS2 文件系统的 Wait(W)拥有者标签的 glocks 数。以下 pminfo 命令显示每个挂载的 GFS2 文件系统的 Wait(W)拥有者标签的 glocks 数。

# pminfo -f gfs2.latency.grant.all gfs2.latency.demote.all

gfs2.latency.grant.all
    inst [0 or "afc_cluster:data"] value 0
    inst [1 or "afc_cluster:bin"] value 0

gfs2.latency.demote.all
    inst [0 or "afc_cluster:data"] value 0
    inst [1 or "afc_cluster:bin"] value 0

做好的做法是,在工作负载运行时没有问题的情况下观察一般的值,因此当这些值不在正常的范围内时,可以注意到性能的变化。

例如,您可能会看到等待完成的提升请求数量的变化,而不是在第一次请求时就可以完成。您可以从以下命令的输出结果中看到相关的信息。

# pminfo -f gfs2.latency.grant.all gfs2.latency.demote.all

gfs2.tracepoints.promote.other.null_lock
     inst [0 or "afc_cluster:data"] value 0
     inst [1 or "afc_cluster:bin"] value 0

gfs2.tracepoints.promote.other.concurrent_read
     inst [0 or "afc_cluster:data"] value 0
     inst [1 or "afc_cluster:bin"] value 0

gfs2.tracepoints.promote.other.concurrent_write
     inst [0 or "afc_cluster:data"] value 0
     inst [1 or "afc_cluster:bin"] value 0

gfs2.tracepoints.promote.other.protected_read
     inst [0 or "afc_cluster:data"] value 0
     inst [1 or "afc_cluster:bin"] value 0

gfs2.tracepoints.promote.other.protected_write
     inst [0 or "afc_cluster:data"] value 0
     inst [1 or "afc_cluster:bin"] value 0

gfs2.tracepoints.promote.other.exclusive
     inst [0 or "afc_cluster:data"] value 0
     inst [1 or "afc_cluster:bin"] value 0

以下命令的输出允许您确定远程降级请求的大幅增加(特别是如果来自其他集群节点)。

# pminfo -f gfs2.tracepoints.demote_rq.requested

gfs2.tracepoints.demote_rq.requested.remote
     inst [0 or "afc_cluster:data"] value 0
     inst [1 or "afc_cluster:bin"] value 0

gfs2.tracepoints.demote_rq.requested.local
     inst [0 or "afc_cluster:data"] value 0
     inst [1 or "afc_cluster:bin"] value 0

以下命令的输出可能会显示,出现无法解释的日志清除数量的增加。

# pminfo -f gfs2.tracepoints.log_flush.total]

gfs2.tracepoints.log_flush.total
     inst [0 or "afc_cluster:data"] value 0
     inst [1 or "afc_cluster:bin"] value 0

10.3. PCP 中 GFS2 可用指标的完整列表

下表描述了 GFS2 文件系统的 pcp-pmda-gfs2 软件包给出的性能指标的完整列表。

表 10.1. 完整指标数据列表

指标名称描述

gfs2.glocks.*

有关从 glock 统计文件(glocks)收集的信息的指标,该指标计算目前存在于系统中每个 GFS2 文件系统的 glock 数量。

gfs2.glocks.flags.*

计算给定 glocks 标签已存在的 glock 数量的指标范围

gfs2.holders.*

有关从 glock 统计文件(glocks)收集的信息的指标,该指标计算目前挂载于系统中的每个 GFS2 文件系统中存在的带有锁定状态 holder 的 glocks 数。

gfs2.holders.flags.*

带有给定拥有者标记的 glocks 数量的指标范围

gfs2.sbstats.*

有关从超级块统计文件(sbstats)收集到当前挂载到系统中的每个 GFS2 文件系统的信息相关的时间指标。

gfs2.glstats.*

有关从 glock 统计文件(glstats)收集到的信息的指标,该指标计算目前存在于系统中每个 GFS2 文件系统的 glock 数量。

gfs2.latency.grant.*

一个派生的指标,利用 gfs2_glock_queuegfs2_glock_state_change 追踪点中的数据来计算针对每个挂载的文件系统完成 glock 授权请求的平均延迟。这个指标可用于发现,当授权延迟增加时降低文件系统性能的问题。

gfs2.latency.demote.*

一个派生的指标,利用来自 gfs2_glock_state_state_changegfs2_demote_rq 追踪点的数据来计算针对每个挂载的文件系统完成 glock 降级请求的平均延迟。这个指标可用于发现,当降级延迟增加时降低文件系统性能的问题。

gfs2.latency.queue.*

一个派生的指标,利用 gfs2_glock_queue 追踪点中的数据来计算针对每个挂载的文件系统完成的 glock 队列请求的平均延迟。

gfs2.worst_glock.*

一个派生的指标,利用来自 gfs2_glock_lock_time 追踪点的数据来为每个挂载的文件系统计算被识别的 "current worst glock"。如果多次建议同一锁定,这个指标可用于发现潜在的锁定争用和文件系统减慢。

gfs2.tracepoints.*

有关 GFS2 debugfs 追踪点中当前挂载的每个文件系统的输出结果的指标。这些指标的每个子类型(每个 GFS2 追踪点中的一个)都可以被控制,无论是启用或关闭控制指标。

gfs2.control.*

配置用于在 PMDA 中打开或关闭指标记录的指标数据。通过 pmstore 工具切换指标。

10.4. 执行最小 PCP 设置来收集文件系统数据

此流程概述了如何安装最小 PCP 设置来收集 Red Hat Enterprise Linux 上的统计信息。这个设置涉及在产品系统中添加收集数据以便进一步分析所需的最小软件包数量。

可以使用其他 PCP 工具分析 pmlogger 输出生成的 tar.gz 存档,并可与其他性能信息来源进行比较。

步骤

  1. 安装所需的 PCP 软件包。

    # dnf install pcp pcp-pmda-gfs2
  2. 为 PCP 激活 GFS2 模块。

    # cd /var/lib/pcp/pmdas/gfs2
    # ./Install
  3. 启动 pmcdpmlogger 服务。

    # systemctl start pmcd.service
    # systemctl start pmlogger.service
  4. 在 GFS2 文件系统中执行操作。
  5. 停止 pmcdpmlogger 服务。

    # systemctl stop pmcd.service
    # systemctl stop pmlogger.service
  6. 收集输出并将其保存到基于主机名和当前日期和时间的 tar.gz 文件中。

    # cd /var/log/pcp/pmlogger
    # tar -czf $(hostname).$(date+%F-%Hh%M).pcp.tar.gz $(hostname)

10.5. 其他资源

法律通告

Copyright © 2024 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.