注意
本文档适用于 Ceph 开发版本。
故障排除 PGs
排置组从未变得干净
剩留在active
状态、active+remapped
状态或active+degraded
状态且从未达到active+clean
状态的处置组可能表示 Ceph 集群的配置存在问题。
在这种情况下,请检查池、PG 和 CRUSH 配置参考中的设置,并进行适当的调整。
作为一般规则,请使用多个 OSD 和大于两个对象副本的池大小运行您的集群。
单节点集群
Ceph 不再提供有关在单个节点上操作的文档。为分布式计算而设计的系统按定义不会在单个节点上运行。在包含 Ceph 守护进程的单个节点上挂载客户端内核模块可能会导致由于 Linux 内核本身的问题而出现死锁(除非使用虚拟机作为客户端)。尽管有本节所述的限制,但您可以尝试在一节点配置中实验 Ceph。
要在单个节点上创建集群,您必须在创建监视器和 OSD 之前,在您的 Ceph 配置文件中将osd_crush_chooseleaf_type
设置从默认的1
(意味着host
或node
)更改为0
(意味着osd
)。osd_crush_chooseleaf_type
is greater than 0
,
Ceph will attempt to place the PGs of one OSD with the PGs of another OSD on
another node, chassis, rack, row, or datacenter depending on the setting.
提示
请勿将内核客户端直接挂载到您的 Ceph 存储集群所在的同一节点上。可能会出现内核冲突。但是,您可以在单个节点上的虚拟机(VM)中挂载内核客户端。
如果您使用单个磁盘创建 OSD,则必须首先手动创建数据目录。
OSD 少于副本
如果两个 OSD 处于up
和in
状态,但处置组未处于active + clean
状态,则您可能设置了大于osd_pool_default_size
。有几种方法可以解决这个问题。如果您希望以具有两个副本的2
.
的active + degraded
状态运行您的集群,可以将osd_pool_default_min_size
to2
设置为允许您以active + degraded
状态写入对象。您还可以将osd_pool_default_size
设置为2
,以便您只有两个存储副本(原始副本和一个副本)。在这种情况下,集群应该达到active + clean
状态。
Note
您可以在集群运行时进行更改。如果您在 Ceph 配置文件中进行更改,则可能需要重新启动您的集群。
池大小 = 1
如果您有osd_pool_default_size
设置为1
,则您将只有一个对象副本。OSD 依赖于其他 OSD 来告诉它们应该拥有哪些对象。如果一个 OSD 拥有某个对象的副本,而没有任何第二个副本,那么就没有第二个 OSD 告诉第一个 OSD 它应该拥有该副本。对于映射到第一个 OSD 的每个处置组(参见ceph pg dump
),您可以通过运行以下形式的命令强制第一个 OSD 注意它需要的处置组:
ceph osd force-create-pg <pgid>
CRUSH 映射错误
如果您的集群中的任何处置组不干净,则您的 CRUSH 映射中可能存在错误。
卡住的处置组
处置组在组件故障后进入“降级”或“对等”状态是正常的。通常,这些状态反映了通过故障恢复过程的预期进展。但是,长时间处于这些状态之一的处置组可能是更大问题的迹象。因此,当处置组“卡住”在非最佳状态时,Ceph 监视器会发出警告。具体来说,我们检查以下内容:
inactive
- 处置组已经active
太久了(即它无法服务读写请求)。unclean
- 处置组已经clean
太久了(即它尚未完全恢复之前的故障)。stale
- 处置组状态尚未由ceph-osd
更新。这表明存储此处置组的所有节点可能都down
.
通过运行以下命令之一列出卡住的处置组:
ceph pg dump_stuck stale
ceph pg dump_stuck inactive
ceph pg dump_stuck unclean
卡住的
stale
处置组通常表示关键ceph-osd
守护进程未运行。卡住的
inactive
处置组通常表示对等问题(参见处置组下 - 对等失败).卡住的
unclean
处置组通常表示有某些东西阻止恢复完成,可能是找不到的对象(参见找不到的对象);
处置组下 - 对等失败
在某些情况下,ceph-osd
对等过程可能会遇到问题,这会阻止处置组变得活动并可用。在这种情况下,运行命令ceph health detail
将报告类似以下内容:
ceph health detail
HEALTH_ERR 7 pgs degraded; 12 pgs down; 12 pgs peering; 1 pgs recovering; 6 pgs stuck unclean; 114/3300 degraded (3.455%); 1/3 in osds are down
...
pg 0.5 is down+peering
pg 1.4 is down+peering
...
osd.1 is down since epoch 69, last address 192.168.106.220:6801/8651
查询集群以确定为什么处置组被标记为down
中的套接字连接到守护进程,运行以下格式的命令:
ceph pg 0.5 query
{ "state": "down+peering",
...
"recovery_state": [
{ "name": "Started\/Primary\/Peering\/GetInfo",
"enter_time": "2012-03-06 14:40:16.169679",
"requested_info_from": []},
{ "name": "Started\/Primary\/Peering",
"enter_time": "2012-03-06 14:40:16.169659",
"probing_osds": [
0,
1],
"blocked": "peering is blocked due to down osds",
"down_osds_we_would_probe": [
1],
"peering_blocked_by": [
{ "osd": 1,
"current_lost_at": 0,
"comment": "starting or marking this osd lost may let us proceed"}]},
{ "name": "Started",
"enter_time": "2012-03-06 14:40:16.169513"}
]
}
The recovery_state
部分告诉我们,由于ceph-osd
守护进程下线,对等被阻塞,具体来说,osd.1
。在这种情况下,我们可以启动该特定ceph-osd
并恢复。
或者,如果osd.1
发生灾难性故障(例如,如果发生磁盘故障),集群可以被告知 OSD 已lost
,集群可以指示它必须尽力应对。
重要
告知集群 OSD 已丢失是危险的,因为集群无法保证其他数据副本的一致性和最新性。
要报告 OSDlost
并指示 Ceph 继续尝试恢复,请运行以下形式的命令:
ceph osd lost 1
恢复将进行。
找不到的对象
在某些故障组合下,Ceph 可能会抱怨unfound
对象,如下面的示例所示:
ceph health detail
HEALTH_WARN 1 pgs degraded; 78/3778 unfound (2.065%)
pg 2.4 is active+degraded, 78 unfound
这意味着存储集群知道某些对象(或现有对象的更新副本)存在,但它没有找到它们的副本。以下是 PG 数据位于两个 OSD 上(我们称之为“1”和“2”)的示例,这种情况可能发生:
1 停机
2 单独处理一些写入
1 恢复
1 和 2 重新对等,1 上丢失的对象排队进行恢复。
在新对象复制之前,2 停机。
在这一点上,1 知道这些对象存在,但没有活动的ceph-osd
拥有对象的副本。在这种情况下,对该对象的 IO 将被阻塞,集群将希望故障节点尽快恢复。这被认为比向用户返回 IO 错误更好。
Note
上述情况是设置size=2
在复制池上和m=1
在纠删码池上的一个原因,这可能导致数据丢失。
通过运行以下形式的命令识别哪些对象是找不到的:
ceph pg 2.4 list_unfound [starting offset, in json]
{
"num_missing": 1,
"num_unfound": 1,
"objects": [
{
"oid": {
"oid": "object",
"key": "",
"snapid": -2,
"hash": 2249616407,
"max": 0,
"pool": 2,
"namespace": ""
},
"need": "43'251",
"have": "0'0",
"flags": "none",
"clean_regions": "clean_offsets: [], clean_omap: 0, new_object: 1",
"locations": [
"0(3)",
"4(2)"
]
}
],
"state": "NotRecovering",
"available_might_have_unfound": true,
"might_have_unfound": [
{
"osd": "2(4)",
"status": "osd is down"
}
],
"more": false
}
如果在单个结果中列出的对象太多,则more
字段将为 true,您可以查询更多。 (最终命令行工具将隐藏此内容,但目前还没有。)
现在您可以识别哪些 OSD 已被探测或可能包含数据。
在列表末尾(在more: false
),might_have_unfound
提供available_might_have_unfound
为 true 时),这相当于ceph pg #.# query
的输出。 这消除了直接使用query
的需要。 给出的might_have_unfound
信息行为与query
相同,如下所述。 唯一的区别是,状态为already probed
的 OSD 被忽略。
使用query
:
ceph pg 2.4 query
"recovery_state": [
{ "name": "Started\/Primary\/Active",
"enter_time": "2012-03-06 15:15:46.713212",
"might_have_unfound": [
{ "osd": 1,
"status": "osd is down"}]},
在这种情况下,集群知道osd.1
可能拥有数据,但它处于down
状态。以下是所有可能的状态的完整范围:
已探测
查询中
OSD 停机
尚未查询(尚未)
有时集群查询可能的地点只需要一些时间。
可能存在其他地点,对象可能存在,但未列出。 例如:如果 OSD 停止并从集群中移除,然后集群完全恢复,然后通过后续的一系列故障,集群最终得到一个找不到的对象,集群将忽略已移除的 OSD。(然而,这种情况不太可能。)
如果所有可能的地点都已查询,对象仍然丢失,您可能不得不放弃丢失的对象。这只有在发生不寻常的故障组合,允许集群在写入本身恢复之前了解写入的情况下才可能。要标记“找不到”的对象为“丢失”,请运行以下形式的命令:
ceph pg 2.5 mark_unfound_lost revert|delete
在这里,最后一个参数 (revert|delete
) 指定集群应如何处理丢失的对象。
The delete
选项将导致集群完全忘记它们。
The revert
选项(纠删码池上不可用)将要么回滚到对象的先前版本,要么(如果是新对象)完全忘记该对象。使用revert
要小心,因为它可能会让期望对象存在的应用程序感到困惑。
无家可归的处置组
可能是存储给定处置组副本的每个 OSD 都发生故障。如果发生这种情况,则包含这些处置组的对象存储子集将变得不可用,监视器将不会收到这些处置组的任何状态更新。监视器将任何主要 OSD 已故障的处置组标记为stale
。 例如:
ceph health
HEALTH_WARN 24 pgs stale; 3/300 in osds are down
通过运行以下命令识别哪些处置组是stale
以及哪些是最后存储stale
处置组的 OSD:
ceph health detail
HEALTH_WARN 24 pgs stale; 3/300 in osds are down
...
pg 2.5 is stuck stale+active+remapped, last acting [2,0]
...
osd.10 is down since epoch 23, last address 192.168.106.220:6800/11080
osd.11 is down since epoch 13, last address 192.168.106.220:6803/11539
osd.12 is down since epoch 24, last address 192.168.106.220:6806/11861
此输出表示处置组 2.5 (pg 2.5
) 最后由osd.0
和osd.2
管理。重新启动这些 OSD 以允许集群恢复该处置组。
只有少数 OSD 接收数据
如果集群中的只有少数节点接收数据,请按照放置组文档中的说明检查池中的处置组数量。由于处置组映射到 OSD 的操作涉及将集群中的处置组数量除以集群中的 OSD 数量,因此有时会有少量处置组(此操作的余数)未分布在集群中。在这种情况下,请创建一个处置组计数是 OSD 数量的倍数的池。有关详细信息,请参阅放置组。有关如何更改用于确定每个池分配多少处置组的默认值的说明,请参阅池、PG 和 CRUSH 配置参考。
无法写入数据
如果集群已启动,但一些 OSD 已停机且您无法写入数据,请确保池中运行了最小数量的 OSD。如果您在池中运行的 OSD 数量不足最小数量,Ceph 将不允许您向其写入数据,因为 Ceph 无法保证可以复制您的数据。请参阅osd_pool_default_min_size
。Cephadm 还支持使用池、PG 和 CRUSH for details.
PGs 不一致
如果命令ceph health detail
返回active + clean +
inconsistent
状态,这可能表示擦除过程中的错误。通过运行以下命令识别不一致的处置组或处置组:
ceph health detail
HEALTH_ERR 1 pgs inconsistent; 2 scrub errors
pg 0.6 is active+clean+inconsistent, acting [0,1,2]
2 scrub errors
或者,如果您更喜欢以编程方式检查输出,请运行此命令:
rados list-inconsistent-pg rbd
["0.6"]
只有一个一致状态,但在最坏的情况下,我们可能在多个对象中找到多个视角的不同不一致。如果 PGfoo
被截断,命令0.6
中的对象rados list-inconsistent-pg rbd
的输出将类似于以下内容:
rados list-inconsistent-obj 0.6 --format=json-pretty
{
"epoch": 14,
"inconsistents": [
{
"object": {
"name": "foo",
"nspace": "",
"locator": "",
"snap": "head",
"version": 1
},
"errors": [
"data_digest_mismatch",
"size_mismatch"
],
"union_shard_errors": [
"data_digest_mismatch_info",
"size_mismatch_info"
],
"selected_object_info": "0:602f83fe:::foo:head(16'1 client.4110.0:1 dirty|data_digest|omap_digest s 968 uv 1 dd e978e67f od ffffffff alloc_hint [0 0 0])",
"shards": [
{
"osd": 0,
"errors": [],
"size": 968,
"omap_digest": "0xffffffff",
"data_digest": "0xe978e67f"
},
{
"osd": 1,
"errors": [],
"size": 968,
"omap_digest": "0xffffffff",
"data_digest": "0xe978e67f"
},
{
"osd": 2,
"errors": [
"data_digest_mismatch_info",
"size_mismatch_info"
],
"size": 0,
"omap_digest": "0xffffffff",
"data_digest": "0xffffffff"
}
]
}
]
}
在这种情况下,输出表示以下内容:
唯一的不一致对象是名为
foo
的对象,其头部存在不一致。不一致分为两类:
errors
: 这些错误表示片段之间不一致,但没有指示哪些片段是坏的。检查errors
。Cephadm 还支持使用shards
数组,如果可用,以确定问题。data_digest_mismatch
: 从OSD.2
读取的副本的摘要与从OSD.0
和OSD.1
size_mismatch
: 从OSD.2
是0
读取的副本的大小与OSD.0
和OSD.1
是968
.
union_shard_errors
: 所有片段特定errors
。Cephadm 还支持使用shards
数组的并集。 对于有问题的片段,errors
被设置。 这些错误包括read_error
和其他类似错误。 以errors
结尾的oi
表示与selected_object_info
的比较。 检查shards
数组以确定哪个片段有哪个错误或错误。data_digest_mismatch_info
: 存储在object-info
中的摘要与从0xffffffff
不同。 : 存储在OSD.2
size_mismatch_info
读取的片段计算出的object-info
中的大小与从OSD.2
读取的大小不同。 后者是由0
.
警告
如果read_error
列出的,该值存储在片段的errors
属性中,不一致可能是由于物理存储错误。在这种情况下,请检查该 OSD 使用的存储。 在尝试驱动修复之前,请检查
Examine the output of dmesg
和smartctl
的输出。
要修复不一致的处置组,请运行以下形式的命令:
ceph pg repair {placement-group-ID}
例如:
ceph pg repair 1.4
Note
PG ID 的形式为N.xxxxx
,其中N
是包含 PG 的池的编号。命令ceph osd listpools
和命令ceph osd dump | grep pool
返回池编号的列表。
如果您由于时钟偏移而定期收到active + clean + inconsistent
状态,请考虑配置监视器主机上的NTP守护进程以作为对等。请参阅网络时间协议和 Ceph时钟设置 for more information.
更多关于 PG 修复的信息
Ceph 存储并更新集群中存储的对象的校验和。当对 PG 执行擦除时,主 OSD 尝试从其副本中选择一个权威副本。在可能的案例中只有一个是一致的。在执行深度擦除后,Ceph 计算从磁盘读取的每个对象的校验和,并将其与之前记录的校验和进行比较。如果当前校验和与之前记录的校验和不匹配,则该不匹配被视为不一致。在复制池的情况下,任何副本的校验和与权威副本的校验和之间的任何不匹配都意味着存在不一致。发现这些不一致会导致 PG 的状态设置为inconsistent
.
The pg repair
命令尝试修复各种类型的不一致。当pg repair
发现不一致的 PG 时,它尝试用权威副本的摘要覆盖不一致副本的摘要。当pg
repair
在复制池中发现不一致副本时,它会将不一致副本标记为丢失。在复制池的情况下,恢复超出了pg repair
.
的范围。 在纠删码和 BlueStore 池的情况下,如果osd_scrub_auto_repair
(默认false
)设置为true
且找到的错误不超过osd_scrub_auto_repair_num_errors
(默认5
)错误,Ceph 将自动执行修复。
The pg repair
命令不会解决所有问题。当发现 PG 包含不一致时,Ceph 不会自动修复 PGs。
RADOS 对象或 omap 的校验和并不总是可用的。校验和是增量计算的。如果复制对象非顺序更新,则更新中涉及的写入操作会更改对象并使其校验和失效。在重新计算校验和时,不会读取整个对象。命令能够即使校验和不可用也能进行修复,就像 Filestore 的情况一样。与复制 Filestore 池工作的用户可能更喜欢手动修复而不是pg repair
command is able to make repairs even when
checksums are not available to it, as in the case of Filestore. Users working
with replicated Filestore pools might prefer manual repair to ceph pg
repair
.
这部分内容与 Filestore 相关,但与 BlueStore 不同,BlueStore有自己的内部校验和。匹配记录校验和与计算校验和不能证明任何特定副本实际上是权威的。如果没有校验和可用,pg repair
倾向于主上的数据,但这可能不是未损坏的副本。由于这种不确定性,当发现不一致时,需要人工干预。这种干预有时涉及使用ceph-objectstore-tool
.
PG 修复演练
https://ceph.io/geen-categorie/ceph-manually-repair-object/- 此页面包含 PG 修复的演练。如果您想修复 PG 但从未这样做过,建议阅读。
纠删码 PGs 没有处于活动+干净状态
如果 CRUSH 无法找到足够的 OSD 映射到 PG,它将显示为2147483647
,这意味着ITEM_NONE
或no OSD found
从仓库中删除它。例如:
[2,1,6,0,5,8,2147483647,7,4]
OSD 数量不足
如果 Ceph 集群只有八个 OSD,而纠删码池需要九个 OSD,集群将显示“OSD 数量不足”。在这种情况下,您可以通过运行以下形式的命令创建另一个需要较少 OSD 的纠删码池:
ceph osd erasure-code-profile set myprofile k=5 m=3
ceph osd pool create erasurepool erasure myprofile
或添加新的 OSD,PG 将自动使用它们。
CRUSH 约束无法满足
如果集群有足够的 OSD,那么 CRUSH 规则可能强加了无法满足的约束。如果有两个主机上有十个 OSD,而 CRUSH 规则要求来自同一主机的两个 OSD 不能在同一个 PG 中使用,则映射可能会因为只能找到两个 OSD 而失败。通过显示(“转储”)规则来检查约束,如下所示:
ceph osd crush rule ls
[
"replicated_rule",
"erasurepool"]
$ ceph osd crush rule dump erasurepool
{ "rule_id": 1,
"rule_name": "erasurepool",
"type": 3,
"steps": [
{ "op": "take",
"item": -1,
"item_name": "default"},
{ "op": "chooseleaf_indep",
"num": 0,
"type": "host"},
{ "op": "emit"}]}
通过创建一个新的池来解决此问题,其中允许 PG 拥有驻留在同一主机上的 OSD,通过运行以下命令:
ceph osd erasure-code-profile set myprofile crush-failure-domain=osd
ceph osd pool create erasurepool erasure myprofile
CRUSH 太早放弃
如果 Ceph 集群刚好有足够的 OSD 来映射 PG(例如,一个总共九个 OSD 的集群和一个每个 PG 需要九个 OSD 的纠删码池),CRUSH 可能会在找到映射之前放弃。这个问题可以通过以下方式解决:
降低纠删码池要求以使用每个 PG 更少的 OSD(这需要创建另一个池,因为纠删码配置文件不能动态修改)。
向集群添加更多 OSD(这不需要修改纠删码池,因为它将自动变得干净)
使用手工制作的 CRUSH 规则尝试更多次找到好的映射。这可以通过设置
set_choose_tries
为大于默认值来修改现有的 CRUSH 规则。
首先,使用crushtool
在从集群中提取 crushmap 后验证问题。这确保了您的实验不会修改 Ceph 集群,并且它们仅在对本地文件操作:
ceph osd crush rule dump erasurepool
{ "rule_id": 1,
"rule_name": "erasurepool",
"type": 3,
"steps": [
{ "op": "take",
"item": -1,
"item_name": "default"},
{ "op": "chooseleaf_indep",
"num": 0,
"type": "host"},
{ "op": "emit"}]}
$ ceph osd getcrushmap > crush.map
got crush map from osdmap epoch 13
$ crushtool -i crush.map --test --show-bad-mappings \
--rule 1 \
--num-rep 9 \
--min-x 1 --max-x $((1024 * 1024))
bad mapping rule 8 x 43 num_rep 9 result [3,2,7,1,2147483647,8,5,6,0]
bad mapping rule 8 x 79 num_rep 9 result [6,0,2,1,4,7,2147483647,5,8]
bad mapping rule 8 x 173 num_rep 9 result [0,4,6,8,2,1,3,7,2147483647]
这里,--num-rep
是纠删码 CRUSH 规则需要的 OSD 数,--rule
是rule_id
字段值。此测试将尝试映射一百万个值(在本例中,由ceph osd crush rule dump
显示的[--min-x,--max-x]
定义的范围),并且必须显示至少一个坏映射。如果此测试输出为空,则所有映射都成功,您可以确信您集群中的问题不是由坏映射引起的。
更改 set_choose_tries 的值
通过运行以下命令解编译 CRUSH 映射以编辑 CRUSH 规则:
crushtool --decompile crush.map > crush.txt
添加以下行到规则中:
step set_choose_tries 100
相关的
crush.txt
文件部分将类似于以下内容:rule erasurepool { id 1 type erasure step set_chooseleaf_tries 5 step set_choose_tries 100 step take default step chooseleaf indep 0 type host step emit }
重新编译并重新测试 CRUSH 规则:
crushtool --compile crush.txt -o better-crush.map
当所有映射成功时,使用
--show-choose-tries
选项的替代方案crushtool
命令显示所需映射的尝试次数直方图,如下面的示例所示:crushtool -i better-crush.map --test --show-bad-mappings \ --show-choose-tries \ --rule 1 \ --num-rep 9 \ --min-x 1 --max-x $((1024 * 1024)) ... 11: 42 12: 44 13: 54 14: 45 15: 35 16: 34 17: 30 18: 25 19: 19 20: 22 21: 20 22: 17 23: 13 24: 16 25: 13 26: 11 27: 11 28: 13 29: 11 30: 10 31: 6 32: 5 33: 10 34: 3 35: 7 36: 5 37: 2 38: 5 39: 5 40: 2 41: 5 42: 4 43: 1 44: 2 45: 2 46: 3 47: 1 48: 0 ... 102: 0 103: 1 104: 0 ...
此输出表示映射四十两个 PG 需要十一次尝试,映射四十四个 PG 需要十二次尝试等。最高尝试次数是防止坏映射的最小
set_choose_tries
值(例如,在上述输出中,因为任何 PG 映射都没有超过 103 次尝试)。103
in the above output, because it did not take more than 103 tries for any PG to be mapped).
由 Ceph 基金会带给您
Ceph 文档是一个社区资源,由非盈利的 Ceph 基金会资助和托管Ceph Foundation. 如果您想支持这一点和我们的其他工作,请考虑加入现在加入.