ceph分布式存储-常见 PG 故障处理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ceph分布式存储-常见 PG 故障处理相关的知识,希望对你有一定的参考价值。

参考技术A

创建一个新集群后,PG 的状态一直处于 active , active + remapped 或 active + degraded 状态, 而无法达到 active + clean 状态 ,那很可能是你的配置有问题。

你可能需要检查下集群中有关 Pool 、 PG 和 CRUSH 的配置项,做以适当的调整。

一般来说,你的集群中需要多于 1 个 OSD,并且存储池的 size 要大于 1 副本。

有时候,我们需要搭建一个单节点的 Ceph 实验环境。此时,在开始创建 monitor 和 OSD 之前,你需要把 Ceph 配置文件中的 osd crush chooseleaf type 选项从默认值 1 (表示 host 或 node )修改为 0 (表示 osd )。这样做是告诉 Ceph 允许把数据的不同副本分布到同一 host 的 OSDs 上。

如果你已经启动了 2 个 OSD,它们都处于 up 和 in 的状态,但 PG 仍未达到 active + clean 状态,那可能是给 osd pool default size 设置了一个大于 2 的值。

如果你想要在 active + degraded 状态( 2 副本)操作你的集群,可以设置 osd pool default min size 为 2 ,这样你就可以对处于 active + degraded 的对象写入数据。然后你还可以把 osd pool default size 的值改为 2 ,这样集群就可以达到 active + clean 状态了。

另外,修改参数 osd pool default size/min_size 后,只会对后面新建的 pool 起作用。如果想修改已存在的 pool 的 size/min_size ,可用下面的命令:

注意: 你可以在运行时修改参数值。如果是在 Ceph 配置文件中进行的修改,你可能需要重启集群。

如果你设置了 osd pool default size 的值为 1 ,那你就仅有对象的单份拷贝。OSD 依赖于其他 OSD 告诉自己应该保存哪些对象。如果第一个 OSD 持有对象的拷贝,并且没有第二份拷贝,那么也就没有第二个 OSD 去告诉第一个 OSD 它应该保管那份拷贝。对于每一个映射到第一个 OSD 上的 PG (参考 ceph pg dump 的输出),你可以强制第一个 OSD 关注它应该保存的 PGs :

PG 达不到 clean 状态的另一个可能的原因就是集群的 CRUSH Map 有错误,导致 PG 不能映射到正确的地方。

有失败发生后,PG 会进入“degraded”(降级)或“peering”(连接建立中)状态,这种情况时有发生。通常这些状态意味着正常的失败恢复正在进行。然而,如果一个 PG 长时间处于这些状态中的某个,就意味着有更大的问题。因此 monitor 在 PG 卡 ( stuck ) 在非最优状态时会告警。我们具体检查:

你可以用下列命令显式地列出卡住的 PGs:

卡在 stale 状态的 PG 通过重启 ceph-osd 进程通常可以修复;卡在 inactive 状态的 PG 通常是互联问题(参见 PG 挂了 —— 互联失败 );卡在 unclean 状态的 PG 通常是由于某些原因阻止了恢复的完成,像未找到的对象(参见 未找到的对象 )。

在某些情况下, ceph-osd 互联 进程会遇到问题,阻值 PG 达到活跃、可用的状态。例如, ceph health 也许显示:

可以查询到 PG 为何被标记为 down :

recovery_state 段告诉我们互联过程因 ceph-osd 进程挂了而被阻塞,本例是 osd.1 挂了,启动这个进程应该就可以恢复。

或者,如果 osd.1 发生了灾难性的失败(如硬盘损坏),我们可以告诉集群它丢失( lost )了,让集群尽力完成副本拷贝。

重要: 集群不能保证其它数据副本是一致且最新的,就会很危险!

让 Ceph 无论如何都继续:

恢复将继续进行。

某几种失败相组合,可能导致 Ceph 抱怨有找不到( unfound )的对象:

这意味着存储集群知道一些对象(或者存在对象的较新副本)存在,却没有找到它们的副本。下例展示了这种情况是如何发生的,一个 PG 的数据存储在 ceph-osd 1 和 2 上:

这时, 1 知道这些对象存在,但是活着的 ceph-osd 都没有这些副本。这种情况下,读写这些对象的 IO 就会被阻塞,集群只能指望 down 掉的节点尽早恢复。这样处理是假设比直接给用户返回一个 IO 错误要好一些。

首先,你应该确认哪些对象找不到了:

如果在一次查询里列出的对象太多, more 这个字段将为 true ,你就可以查询更多。

其次,你可以找出哪些 OSD 上探测到、或可能包含数据:

本例中,集群知道 osd.1 可能有数据,但它挂了( down )。所有可能的状态有:

有时候集群要花一些时间来查询可能的位置。

还有一种可能性,对象存在于其它位置却未被列出。例如,集群里的一个 ceph-osd 停止且被剔出集群,然后集群完全恢复了;后来一系列的失败导致了未找到的对象,它也不会觉得早已死亡的 ceph-osd 上仍可能包含这些对象。(这种情况几乎不太可能发生)。

如果所有可能的位置都查询过了但仍有对象丢失,那就得放弃丢失的对象了。这仍可能是罕见的失败组合导致的,集群在写操作恢复后,未能得知写入是否已执行。以下命令把未找到的( unfound )对象标记为丢失( lost )。

上述最后一个参数告诉集群应如何处理丢失的对象。

拥有 PG 拷贝的 OSD 可能会全部失败,这种情况下,那一部分的对象存储不可用, monitor 也就不会收到那些 PG 的状态更新了。为检测这种情况,monitor 会把任何主 OSD 失败的 PG 标记为 stale (不新鲜),例如:

可以找出哪些 PG 是 stale 状态,和存储这些归置组的最新 OSD ,命令如下:

如果想使 PG 2.5 重新上线,例如,上面的输出告诉我们它最后由 osd.0 和 osd.2 管理,重启这些 ceph-osd 将恢复之(可以假定还有其它的很多 PG 也会进行恢复 )。

如果你的集群有很多节点,但只有其中几个接收数据, 检查 下存储池里的 PG 数量。因为 PG 是映射到多个 OSD 的,较少的 PG 将不能均衡地分布于整个集群。试着创建个新存储池,设置 PG 数量是 OSD 数量的若干倍。更详细的信息可以参考 Ceph 官方文档 —— Placement Groups 。

如果你的集群已启动,但一些 OSD 没起来,导致不能写入数据,确认下运行的 OSD 数量满足 PG 要求的最低 OSD 数。如果不能满足, Ceph 就不会允许你写入数据,因为 Ceph 不能保证复制能如愿进行。这个最低 OSD 个数是由参数 osd pool default min size 限定的。

如果收到 active + clean + inconsistent 这样的状态,很可能是由于在对 PG 做擦洗( scrubbing )时发生了错误。如果是由于磁盘错误导致的不一致,请检查磁盘,如果磁盘有损坏,可能需要将这个磁盘对应的 OSD 踢出集群,然后进行更换。生产环境中遇到过不一致的问题,就是由于磁盘坏道导致的。

当集群中出现 PG 不一致的问题时,执行 ceph -s 命令会出现下面的信息:

1、查找处于 inconsistent 状态的问题 PG :

这个有问题的 PG 分布在 osd.1 、 osd.2 和 osd.0 上,其中 osd.1 是主 OSD。

2、去主 OSD( osd.1 )的日志中查找不一致的具体对象 。

从日志中可以知道,是 rbd_data.1349f035c101d9.0000000000000001 这个对象的属性 _ 丢失了,所以在 scrub 的过程中产生了 error 。

3、执行 ceph pg repair 命令修复问题 PG 。

4、检查 Ceph 集群是否恢复到 HEALTH_OK 状态。

osd.1 的日志里也提示修复成功:

如果经过前面的步骤,Ceph 仍没有达到 HEALTH_OK 状态,可以尝试用下面这种方式进行修复。

1、停掉不一致的 object 所属的 osd 。

2、刷新该 osd 的日志。

3、将不一致的 object 移除。

4、重新启动该 osd 。

5、重新执行修复命令。

6、检查 Ceph 集群是否恢复到 HEALTH_OK 状态。

有时候,我们在 ceph -s 的输出中可以看到如下的告警信息:

这是因为集群 OSD 数量较少,测试过程中建立了多个存储池,每个存储池都要建立一些 PGs 。而目前 Ceph 配置的默认值是每 OSD 上最多有 300 个 PGs 。在测试环境中,为了快速解决这个问题,可以调大集群的关于此选项的告警阀值。方法如下:

在 monitor 节点的 ceph.conf 配置文件中添加:

然后重启 monitor 进程。

或者直接用 tell 命令在运行时更改参数的值而不用重启服务:

而另一种情况, too few PGs per OSD (16 < min 20) 这样的告警信息则往往出现在集群刚刚建立起来,除了默认的 rbd 存储池,还没建立自己的存储池,再加上 OSD 个数较多,就会出现这个提示信息。这通常不是什么问题,也无需修改配置项,在建立了自己的存储池后,这个告警信息就会消失。

Ceph —— 均衡PG

Ceph —— 均衡PG

日常工作中,我们常常会发现PG不均衡,而集群中只要有一个OSD先达到full的状态,则整个集群都无法写入数据,所以为了尽可能的提高集群存储空间的利用率,我们都希望PG尽可能的均匀分布在OSD上。

出现PG不均衡最常见的背景情况:

  • 刚刚安装部署Ceph集群完毕

  • 集群扩容或是其他情况,进行了加盘的操作,OSD数量发生变化

为了节省日常工作的时间,针对PG均衡问题,写了个python脚本:

version : ceph_luminous (12.2.2)

 1 #!/usr/bin/python
 2 
 3 import os
 4 
 5 
 6 def Ceph_balance():
 7     # Gets the PG number for each OSD
 8     PGS = os.popen(""" ceph osd df | awk ‘{print $10}‘ | egrep -v "^$|PGS" """).readlines()
 9     # Get the max difference of PG number
10     MAX_DIFFERENT_PG = max(map(eval, PGS)) - min(map(eval, PGS))
11     # Get pool list
12     lspools = os.popen(ceph osd lspools).read().split(,)[:-1]
13     POOL_LIST = map(lambda x: x[2:], lspools)
14     # To allow use of the feature, you must tell the cluster that it only needs to support luminous (and newer) clients with: 
15     os.system(ceph osd set-require-min-compat-client luminous)
16     if MAX_DIFFERENT_PG >= 1:
17         # Grab the latest copy of your osdmap
18         os.system(ceph osd getmap -o /tmp/osd.map)
19         for i in POOL_LIST:
20             # Run the optimizer
21             os.system(osdmaptool /tmp/osd.map --upmap /tmp/%sout.txt --upmap-pool %s % (i, i))
22         for i in POOL_LIST:
23             # Apply the changes to the cluster
24             os.system(source /tmp/%sout.txt % i)
25     # clean up txt file
26     for i in POOL_LIST:
27         os.system(rm -f /tmp/%sout.txt % i)
28     os.system(rm -f /tmp/osd.map)
29     print("Ceph balance has been successful !")
30 
31 
32 if __name__ == __main__:
33     Ceph_balance()

 


此脚本只适用于luminous及以上的版本

ps:因本人awk比较菜,所以这个脚本获取PGS部分无法达到准确应用。大家可以根据自己的情况酌情修改脚本。适合自己的才是最好的。


有何意见建议,可以留言,欢迎指正。

觉得写的不错,用着还可以的,可以点个推荐关注啥的。

以上是关于ceph分布式存储-常见 PG 故障处理的主要内容,如果未能解决你的问题,请参考以下文章

架构设计:系统存储(29)——分布式文件系统Ceph(管理)

ceph之PG逻辑概念

ceph 之 crush存储规则理解

Ceph分布式存储实践应用之集群测试验证(Rados运用)

5种最常见的CEPH失败方案

Ceph-相关概念