故障排除对象存储

对于对象存储,所有内容都记录在 /var/log/syslog (或某些发行版上的 messages) 中。 几个设置可以进一步自定义日志记录,例如对象服务器配置文件中的 log_namelog_facilitylog_level

驱动器故障

问题

驱动器故障可能会阻止对象存储执行复制。

解决方案

如果驱动器发生故障,第一步是确保驱动器已卸载。 这将使对象存储更容易绕过故障,直到故障得到解决。 如果驱动器将立即更换,那么最好更换驱动器、格式化驱动器、重新挂载驱动器,然后让复制填充它。

如果您无法立即更换驱动器,那么最好将其卸载,并将其从环中移除。 这将允许所有位于该驱动器上的副本复制到其他位置,直到驱动器更换。 更换驱动器后,可以将其重新添加到环中。

您可以查看 /var/log/kern.log 文件中的错误消息,以获取有关驱动器故障的提示。

服务器故障

问题

服务器可能离线,可能已故障,或者需要重新启动。

解决方案

如果服务器存在硬件问题,确保对象存储服务未运行是一个好主意。 这将允许对象存储在您进行故障排除时绕过故障。

如果服务器只需要重新启动,或者只需要花费几个小时的少量工作,那么最好让对象存储绕过故障,并修复并使机器重新上线。 当机器重新上线时,复制将确保在停机期间丢失的任何内容都会得到更新。

如果服务器存在更严重的问题,那么最好从环中移除服务器的所有设备。 服务器维修并重新上线后,可以将服务器的设备重新添加到环中。 重要的是,在将设备放回环之前对其进行重新格式化,因为它很可能负责与之前不同的分区集。

检测故障驱动器

问题

当驱动器发生故障时,很难检测到驱动器已发生故障以及故障的详细信息。

解决方案

根据我们的经验,当驱动器即将发生故障时,错误消息会出现在 /var/log/kern.log 文件中。 有一个名为 swift-drive-audit 的脚本可以通过 cron 运行来监视不良驱动器。 如果检测到错误,它将卸载不良驱动器,以便对象存储可以绕过它。 该脚本采用具有以下设置的配置文件

drive-audit.conf 中 [drive-audit] 的配置选项说明

配置选项 = 默认值

描述

device_dir = /srv/node

设备挂载的目录

error_limit = 1

在卸载设备之前需要找到的错误数

log_address = /dev/log

syslog 发送日志的位置

log_facility = LOG_LOCAL0

syslog 日志设施

log_file_pattern = /var/log/kern.*[!.][!g][!z]

日志文件的位置,带有用于检查设备错误的 globbing 模式,在日志文件中找到设备块

log_level = INFO

日志级别

log_max_line_length = 0

将日志行长度限制为给定的值;如果设置为 0(默认值),则没有限制。

log_to_console = False

此选项没有帮助文本。

minutes = 60

要在 /var/log/kern.log 中回溯的分钟数

recon_cache_path = /var/cache/swift

存储少量项目统计信息的目录

regex_pattern_1 = \berror\b.*\b(dm-[0-9]{1,2}\d?)\b

此选项没有帮助文本。

unmount_failed_device = True

此选项没有帮助文本。

警告

此脚本仅在 Ubuntu 10.04 上进行了测试;在生产环境中其他操作系统上使用时请谨慎。

环构建器文件紧急恢复

问题

紧急情况可能会阻止成功的备份将集群恢复到运行状态。

解决方案

您应该始终保留 swift 环构建器文件的备份。 但是,如果发生紧急情况,此过程可能有助于将您的集群恢复到运行状态。

使用现有的 swift 工具,无法从 ring.gz 文件中恢复构建器文件。 但是,如果您了解 Python,则可以构建一个与您丢失的文件非常接近的构建器文件。

警告

此过程是紧急情况下的最后手段。 它需要了解 swift python 代码,并且可能无法成功。

  1. 在 Python REPL 中加载环和新的环构建器对象

    >>> from swift.common.ring import RingData, RingBuilder
    >>> ring = RingData.load('/path/to/account.ring.gz')
    
  2. 开始将环中的数据复制到构建器中

    >>> import math
    >>> partitions = len(ring._replica2part2dev_id[0])
    >>> replicas = len(ring._replica2part2dev_id)
    
    >>> builder = RingBuilder(int(math.log(partitions, 2)), replicas, 1)
    >>> builder.devs = ring.devs
    >>> builder._replica2part2dev = ring._replica2part2dev_id
    >>> builder._last_part_moves_epoch = 0
    >>> from array import array
    >>> builder._last_part_moves = array('B', (0 for _ in range(partitions)))
    >>> builder._set_parts_wanted()
    >>> for d in builder._iter_devs():
                d['parts'] = 0
    >>> for p2d in builder._replica2part2dev:
                for dev_id in p2d:
                    builder.devs[dev_id]['parts'] += 1
    
    This is the extent of the recoverable fields.
    
  3. 对于 min_part_hours,您要么必须记住您使用的值,要么只需创建一个新的值

    >>> builder.change_min_part_hours(24) # or whatever you want it to be
    
  4. 验证构建器。 如果这引发异常,请检查您之前的代码

    >>> builder.validate()
    
  5. 验证通过后,保存构建器并创建一个新的 account.builder

    >>> import pickle
    >>> pickle.dump(builder.to_dict(), open('account.builder', 'wb'), protocol=2)
    >>> exit ()
    
  6. 现在应该在当前工作目录中有一个名为 account.builder 的文件。 运行 swift-ring-builder account.builder write_ring 并将新的 account.ring.gz 与您开始的 account.ring.gz 进行比较。 它们可能不会逐字节相同,但如果您在 REPL 中加载它们,并且它们的 _replica2part2dev_iddevs 属性相同(或几乎相同),那么您就万事俱备了。

  7. container.ring.gzobject.ring.gz 重复该过程,您可能会得到可用的构建器文件。