标签:
本系列文章会深入研究 Ceph 以及 Ceph 和 OpenStack 的集成:
(1)安装和部署
(3)Ceph 物理和逻辑结构
(4)Ceph 的基础数据结构
(6)QEMU-KVM 和 Ceph RBD 的 缓存机制总结
(8)基本的性能测试工具和方法
(9) pool 的size 和 min_size,choose 和 chooseleaf,pg scrubbing 和 repair 等概念
注意:
- 1:
64 active+clean
osdmap e277 pool ‘pool1‘ (9) object ‘Evernote_5.8.6.7519.exe‘ -> pg 9.6094a41e (9.1e) -> up ([5,3,0], p5) acting ([5,3,0], p5)
一开始,PG 和 Ceph 集群都是 active + clean 的。pool1 的 size 和 min_size 都是 3,它的一个 pg 9.1e 分布在 OSD [5,0,3] 上。
0:
杀掉 osd.5
+ 1:
osdmap e277 pool ‘pool1‘ (9) object ‘Evernote_5.8.6.7519.exe‘ -> pg 9.6094a41e (9.1e) -> up ([5,3,0], p5) acting ([5,3,0], p5)
杀掉之后 osdmap 并不会立刻更新。
+ 20:
14:28:57.634378 mon.0 [INF] pgmap v5610: 64 pgs: 64 active+clean; 97071 kB data, 2379 MB used, 18056 MB / 20435 MB avail
14:49:18.850232 mon.0 [INF] osd.5 192.168.56.103:6800/11598 failed (3 reports from 3 peers after 20.000173 >= grace 20.000000)
经过 20 秒以后,mon 将 osd.5 设置为 down 状态。该时长是由配置项 osd heartbeat interval 和 osd heartbeat grace 共同决定的。见下文解释。
14:49:18.933796 mon.0 [INF] osdmap e290: 4 osds: 3 up, 4 in
up 状态的 osd 少了一个,因为 osd.5 down 了。
14:49:18.944307 mon.0 [INF] pgmap v5611: 64 pgs: 16 stale+active+clean, 48 active+clean; 97071 kB data, 2379 MB used, 18056 MB / 20435 MB avail
注意此时只有16个PG有呈现stale 状态,这 16 个 PG 的主OSD 都是 osd.5, 因为它没法上报 PG 状态给 mon 了,所有mon 将这些PG 设为 stale 状态。
HEALTH_WARN 16 pgs stale; too few pgs per osd (16 < min 20); 1/4 in osds are down
pg 9.1e is stale+active+clean, acting [5,3,0]
osd.5 is down since epoch 290, last address 192.168.56.103:6800/11598
2016-06-06:14:49:19.379867646
其中,PG 9.1e 的 acting set 保持不变,但是因为主 OSD down 了,因此 MON 将它标记为 stale 状态。
14:49:19.953801 mon.0 [INF] osdmap e291: 4 osds: 3 up, 4 in
14:49:19.966491 mon.0 [INF] pgmap v5612: 64 pgs: 16 stale+active+clean, 48 active+clean; 97071 kB data, 2379 MB used, 18056 MB / 20435 MB avail
HEALTH_WARN 52 pgs incomplete; 52 pgs stuck inactive; 52 pgs stuck unclean; too few pgs per osd (16 < min 20); 1/4 in osds are down
pg 9.1e is stuck inactive for 3135.552554, current state incomplete, last acting [3,0]
pg 9.1e is incomplete, acting [3,0] (reducing pool pool1 min_size from 3 may help; search ceph.com/docs for ‘incomplete‘)
osd.5 is down since epoch 290, last address 192.168.56.103:6800/11598
14:49:25.487264438
6 秒钟后,PG 的 acting 由 ([5,3,0], p5) 变为 ([3,0], p3), 该 PG 的状态变为 incomplete,因为它只存在于 2 个OSD 上,这个数目小于规定的副本数3。下面是 pg 9.1e 的状态:
root@ceph1:~# ceph pg 9.1e query
{ "state": "incomplete",
"snap_trimq": "[]",
"epoch": 315,
"up": [5,3],
"acting": [5,3] }
为什么 6 秒之后才发生,需要进一步研究。
+ 302:
14:54:20.348720 mon.0 [INF] osd.5 out (down for 301.434591)
301 秒之后,MON 将 osd.5 标记为 out,该时长是由配置项 mon osd down out interval 决定的。见下文分析。
14:54:20.484881 mon.0 [INF] osdmap e292: 4 osds: 3 up, 3 in
in 状态的 osd 数目从 4 变为 3,因为 osd.5 out 了。
14:54:20.493183 mon.0 [INF] pgmap v5617: 64 pgs: 12 active+clean, 52 incomplete; 97071 kB data, 2247 MB used, 13079 MB / 15326 MB avail
14:54:21.588324 mon.0 [INF] osdmap e293: 4 osds: 3 up, 3 in
14:54:21.602137 mon.0 [INF] pgmap v5618: 64 pgs: 12 active+clean, 52 incomplete; 97071 kB data, 2247 MB used, 13079 MB / 15326 MB avail
14:54:26.190982 mon.0 [INF] pgmap v5619: 64 pgs: 50 active+clean, 14 incomplete; 97071 kB data, 2376 MB used, 12950 MB / 15326 MB avail
这个时候应该有 osd.2 加入了 acting set,然后有部分对象呈现 degraded 状态,因为此时 osd.2 上还没有副本,因此开始恢复过程。
{ "state": "active+recovering",
"snap_trimq": "[]",
"epoch": 317,
"up": [5,3,2],
"acting": [5,3,2],
"actingbackfill": ["2","3","5"],}
14:54:27.401982 mon.0 [INF] pgmap v5620: 64 pgs: 1 active, 63 active+clean; 97071 kB data, 2377 MB used, 12949 MB / 15326 MB avail; 2/3 objects degraded (66.667%)
7 秒之后,数据恢复进行中,此时查看 pg 的话,其状态是 “active+recovering”。
HEALTH_WARN 1 pgs stuck unclean; recovery 2/3 objects degraded (66.667%)
pg 9.1e is stuck unclean for 3437.937873, current state active, last acting [3,0,2]
recovery 2/3 objects degraded (66.667%)
2016-06-06:14:54:27.824171144
14:54:30.871475369 HEALTH_OK
14:54:31.115118 mon.0 [INF] pgmap v5621: 64 pgs: 64 active+clean; 97071 kB data, 2377 MB used, 12949 MB / 15326 MB avail; 19173 kB/s, 0 objects/s recovering
3秒之后,恢复完成,之前的数据恢复速度为 19MB/s。
+60
14:55:10.491940 mon.0 [INF] osd.5 192.168.56.103:6800/11868 boot
osd.5 启动回来。
14:55:10.492120 mon.0 [INF] osdmap e294: 4 osds: 4 up, 4 in
osd map 立刻被更新。为什么启动 osd 会立刻导致 osdmap 被更新,需要研究。
14:55:10.499961 mon.0 [INF] pgmap v5622: 64 pgs: 64 active+clean; 97071 kB data, 2377 MB used, 12949 MB / 15326 MB avail
14:55:10.555947545 osdmap e293 pool ‘pool1‘ (9) object ‘Evernote_5.8.6.7519.exe‘ -> pg 9.6094a41e (9.1e) -> up ([3,0,2], p3) acting ([3,0,2], p3)
14:55:11.075660083 osdmap e294 pool ‘pool1‘ (9) object ‘Evernote_5.8.6.7519.exe‘ -> pg 9.6094a41e (9.1e) -> up ([5,3,0], p5) acting ([5,3,0], p5)
PG 的主 osd 由 osd.3 切换至 osd.5,同时将之前新加入的 osd.2 踢出去了。为什么 osd.5 回来之后立刻恢复其之前的主OSD位子,需要研究,有可能是因为CRUSH 想保持对同样的 osdmap 所选择的 PG acting set 不变,要维持这个连续性就需要做一些牺牲,包括可能出现的 recovery 或者 backfill。
PG 几种状态的说明:
几个关键步骤:
(1)MON 将 osd.5 设置为 down 状态:从上面能看出来 MON 从 osd.5 的 3 个peers 上收到了 3 个 reports,持续了 25 秒。一个 osd 可以有多个 peers,因为它可能会出现多个 pg 的 acting set 中。
文章 CONFIGURING MONITOR/OSD INTERACTION 解释了OSD心跳检测原理。同一个 PG 内的 osd 互相通过心跳机制检测对方的状态,检测间隔是 6s,由配置项 osd heartbeat interval 确定。如果在由 osd heartbeat grace 规定的时间内(20s)某个 OSD 都没有回复心跳,做检测的 osd 将判断这个osd为 down 并向 MON 报告,然后 MON 会更新 osd map 将其设置为 down。
(2)MON 将 osd.5 设置为 out 状态:MON 在由配置项 mon osd down out interval (默认 300s)确定的时间区间内如果发现 osd 没有回复 up 状态,则将其状态从 in 改为 out。这会导致有新的 osd 被加入 PG,并开始数据恢复过程。恢复过程结束后,集群回到 active+clean 状态。
(3)在 osd.5 重启后,osd map 立刻被更新,其状态变为 up,然后 PG 的主 OSD 立刻有之前的 osd.3 变为 osd.5,并将之前加入的 osd.2 踢出去了。因为该过程中没有数据变化,osd.5 上的数据不需要被更新,因此并没有发生数据移动。
pool 的 size 设置的是一个对象包括它自身在内的目标副本数,默认为 3,表示一个对象有另外两个副本;min_size 设置的是处于 degraded 模式下的对象还能接受IO时的最小副本数。当实际副本数低于 min_size 时,该对象将是只读的。
pool size | pool min_size | 对象实际副本数 | PG/对象 状态 |
3 | N/A | 3 | PG:active + clean |
3 | 3 | 2 | 对象不能接受 IO |
3 | 2 | 2 | PG:active + degraded |
3 | 2 | 1 | 对象不能接受 IO |
3 | 2 | 0 | PG:stale |
0:
集群有4个 osd (0,2,5,3),pool 的 size 和 min_size 都是3,pg 9.1e 的 acting set 为 [5,3,0]
1:
将 osd.0 停掉。
经过上面第二部分描述的过程,在几分钟后,系统恢复 OK 状态,pg 9.1e 的 acting set 变为 [5,3,2]
2:
将 osd.5 停掉。
在其变为 out 状态后,pg 9.1e 保持在 incomplete 状态。
运行 rados ls -p pool1 命令,此时已经无法返回了,也就是说此时整个存储池都不接受 IO 了
结论:对于一个 PG 来说,其状态(可以是多个状态的组合)必须包括 active + clean 时它才能接受 IO。
3:
将 pool 的 min_size 从 3 修改为 2。
此时 pg 状态为 active+degraded, 有对象总数 1/3 的部分对象处于降级状态( 1/3 objects degraded (33.333%))。
此时 IO 可以正常进行。
结论:PG 处于 degraded 状态不影响其 IO 能力,因此,min_size 是一个 PG 能接受IO的最小副本数。
Scrubbing 是 Ceph 保持数据完整性的一个机制,类似于文件系统中的 fsck,它会发现存在的数据不一致。scrubbing 会影响集群性能。它分为两类:
下面是默认的 osd scrub 的配置项:
root@ceph2:~# ceph --admin-daemon /var/run/ceph/ceph-osd.5.asok config show | grep scrub "osd_scrub_thread_timeout": "60", "osd_scrub_thread_suicide_timeout": "60", "osd_scrub_finalize_thread_timeout": "600", "osd_scrub_finalize_thread_suicide_timeout": "6000", "osd_scrub_invalid_stats": "true", "osd_max_scrubs": "1", "osd_scrub_load_threshold": "0.5", "osd_scrub_min_interval": "86400", "osd_scrub_max_interval": "604800", "osd_scrub_chunk_min": "5", "osd_scrub_chunk_max": "25", "osd_scrub_sleep": "0", "osd_deep_scrub_interval": "604800", "osd_deep_scrub_stride": "524288",
实验过程:
0:找到对象的 PG acting set
osdmap e334 pool ‘pool1‘ (9) object ‘Evernote_5.8.6.7519.exe‘ -> pg 9.6094a41e (9.1e) -> up ([5,3,0], p5) acting ([5,3,0], p5)
1:删除对象的文件
根据 pg id,osd id 以及 object name,找到 osd.5 上文件路径为 /var/lib/ceph/osd/ceph-5/current/9.1e_head/Evernote\u5.8.6.7519.exe__head_6094A41E__9,将它删除
2:设置 light scrub 周期
为了不等一天,将osd_scrub_min_interval 和 osd_scrub_max_interval 都设为4分钟:
root@ceph2:/var/run/ceph# ceph --admin-daemon ceph-osd.5.asok config set osd_scrub_max_interval 240
{ "success": "osd_scrub_max_interval = ‘240‘ "}
root@ceph2:/var/run/ceph# ceph --admin-daemon ceph-osd.5.asok config get osd_scrub_max_interval
{ "osd_scrub_max_interval": "240"}
root@ceph2:/var/run/ceph# ceph --admin-daemon ceph-osd.5.asok config set osd_scrub_min_interval 240
{ "success": "osd_scrub_min_interval = ‘240‘ "}
root@ceph2:/var/run/ceph# ceph --admin-daemon ceph-osd.5.asok config get osd_scrub_min_interval
{ "osd_scrub_min_interval": "240"}
3:尝试 light scrub,发现问题
能看到 light scrub 按计划进行了,而且发现了 pg 9.1e 的问题,即有文件丢失了:
2016-06-06 18:15:49.798236 osd.5 [INF] 9.1d scrub ok 2016-06-06 18:15:50.799835 osd.5 [ERR] 9.1e shard 5 missing 6094a41e/Evernote_5.8.6.7519.exe/head//9 2016-06-06 18:15:50.799863 osd.5 [ERR] 9.1e scrub 1 missing, 0 inconsistent objects 2016-06-06 18:15:50.799866 osd.5 [ERR] 9.1e scrub 1 errors 2016-06-06 18:15:52.804444 osd.5 [INF] 9.20 scrub ok
pgmap 呈现 inconsistent 状态:
2016-06-06 18:15:58.439927 mon.0 [INF] pgmap v5752: 64 pgs: 63 active+clean, 1 active+clean+inconsistent; 97071 kB data, 2268 MB used, 18167 MB / 20435 MB avail
此时集群状态是 ERROR 状态:
health HEALTH_ERR 1 pgs inconsistent; 1 scrub errors;
除了定时的清理外,管理员也可以通过命令启动清理过程:
root@ceph1:~# ceph pg scrub 9.1e instructing pg 9.1e on osd.5 to scrub
从输出能看出来,scrubbing 是由 PG 的主 OSD 发起的。
4:尝试 deep scrub,结果相同。
手工运行命令 ceph pg deep-scrub 9.1e,它会启动深度清理,结果相同。
5:尝试 pg repair,成功
运行 ceph pg repair 9.1e,启动 PG 修复过程,结果修复成功(1 errors, 1 fixed),被删除的文件回来了,集群重新回到 OK 状态。
结论:
注意:PG repair 目前还有不少问题,根据这篇文章,它会将 primary osd 上的数据复制到其它osd上,这可能会导致正确的数据被错误的数据覆盖,因此使用需要谨慎。下面的实验将验证这个问题。
0:创建一个对象,其内容是一个含有字符串 1111 的文本文件,其PG分布在 [2,0,3] 上。
1:修改 osd.2 上文件内容为 1122
2:启动 light scrub,9.2e scrub ok,无法发现问题。这不是蛮奇怪的么??light scrub 应该会检查文件属性和大小,属性应该包括修改时间吧,应该能检查出来啊。。
3. 启动 deep scrub,9.2e deep-scrub ok,无法发现问题。这不是蛮奇怪的么??deep scrub 应该会检查对象数据的啊,数据变了,应该能检查出来啊。。。
4. 启动 pg repair,内容不变。对不在 inconsistent 状态的 PG 看来做repair 不会做什么。
5. 继续修改 osd.2 上的文件,增加内容,致其 size 改变。
6. 启动 light scrub,终于发现 shard 2: soid b2e6cb6e/text/head//9 size 931 != known size 5, 1 inconsistent objects,集群状态也变为 HEALTH_ERR。
7. 启动 deep scrub,它也同样地终于发现了问题。
8. 运行 rados get 命令,能正确获取原始文件。这说明即使集群处于HEALTH_ERR 状态,处于 active+clean+inconsistent 状态的 PG 的 IO 能正常进行。
9. 启动 pg repari,osd.2 上的文件被覆盖,回到原始内容。这说明 pg repair 也不是从主osd 向别的 osd 拷贝嘛。。
结论:
CRUSH MAP 规则中,有一条是定义选择 bucket 的方式,有 choose 和 chooseleaf 两个动作,其语法为 “step [choose|chooseleaf] [firstn|indep] <N> <bucket-type>”,比较让人费解。
step choose firstn {num} type {bucket-type}
说明:选择一定数量的指定类型的 bucket。num 通常是 pool 的 size。
step chooseleaf firstn {num} type {bucket-type}
说明:首先选择类型为 {bucket-type}的一个 bucket 集合,再从每个 bucket 的子树中选择一个叶子节点。num 通常是 pool size。
两者可以单独使用,也可结合起来使用,比较令人费解。下面通过一系列实验来说明。
choose n 和 m | 规则 | 结果 | 说明 |
n = 0,m = 2 | step choose firstn 0 type host step choose firstn 2 type osd |
CRUSH rule 4 x 1022 [5,9,7] CRUSH rule 4 x 1023 [0,2,3] rule 4 (replicated_ruleset_choose2) num_rep 3 result size == 3: 1024/1024 |
CRUSH 选择了 3 个host(比如 1,2,3),从第一个 host 上就选了 2 个 osd,从第二host 上再选 1 个,因此 PG 的 3 个osd,头两个在一个 host 上,第三个在另一个host上。 |
n = 0,m = 0 | step choose firstn 0 type host step choose firstn 0 type osd |
CRUSH rule 5 x 1021 [7,6,2] CRUSH rule 5 x 1022 [5,9,3] CRUSH rule 5 x 1023 [0,2,7] rule 5 (replicated_ruleset_choose0) num_rep 3 result size == 3: 1024/1024 |
CRUSH 选择了 3 个host(比如 1,2,3),从第一个 host 上就选了 3 个 osd,因此所有 PG 的 osd 全部在一个 host 上。这不符合冗余性要求。 |
n = 0,m = 1 | step choose firstn 0 type host step choose firstn 1 type osd |
CRUSH rule 7 x 1022 [5,7] CRUSH rule 7 x 1023 [0,3] rule 7 (replicated_ruleset_choose1) num_rep 3 result size == 2: 1024/1024 |
CRUSH 选择了 3 个host(比如 1,2,3),但是只成功地从第 1 和 2 个host 上分别选了1个 osd (host3 上没有 osd,因此选择失败),结果 PG 只分布在 2 个 OSD 上。 |
n = 0,m = -1 | step choose firstn 0 type host step choose firstn -1 type osd |
CRUSH rule 6 x 1022 [5,9,7] CRUSH rule 6 x 1023 [0,2,3] rule 6 (replicated_ruleset_choose-1) num_rep 3 result size == 3: 1024/1024 |
同 n=0,m=2 |
结论:效果其实同 4.3.
num | 规则 | 结果 | 说明 |
2 | step chooseleaf firstn 2 type osd |
CRUSH rule 8 x 1022 [5,9] |
选择 2 个osd,任意分布在 2 个 host 上,可能在同一个 host 上,也可能分别在两个host 上 |
0 | step chooseleaf firstn 0 type osd |
CRUSH rule 9 x 1022 [5,9,3] |
选择 3 个osd,任意分布在 2 个 host 上,可能在同一个 host 上,也可能分别在两个host 上 |
1 | step chooseleaf firstn 1 type osd |
CRUSH rule 10 x 1022 [5] |
选择 1 个osd。 |
-1 | step chooseleaf firstn -1 type osd |
CRUSH rule 11 x 1022 [5,9] |
选择 2 个osd,任意分布在 2 个host 上,可能在同一个 host 上,也可能分别在两个host 上 |
结论:根据 {num}的情形选择若干个 osd。对于 num < 0 的情形,准确地讲,应该是选择 pool-size + num 个。
num | 规则 | 结果 | 说明 |
2 |
step choose firstn 0 type host step chooseleaf firstn 2 type osd |
CRUSH rule 14 x 1022 [5,9,7] |
选择 3 个osd,前两个在一个host,另一个在另一个host 上 |
0 |
step choose firstn 0 type host step chooseleaf firstn 0 type osd |
CRUSH rule 12 x 1022 [5,9,3] |
选择 3 个osd,都在一个 host 上 |
1 |
step choose firstn 0 type host step chooseleaf firstn 1 type osd |
CRUSH rule 13 x 1022 [5,7] |
选择 2 个osd,分布在 2 个host上,这应该是因为第三个 host 没有osd可供选择 |
-1 |
step choose firstn 0 type host step chooseleaf firstn -1 type osd |
CRUSH rule 15 x 1022 [5,9,7] |
选择 3 个osd,前两个在一个host,另一个在另一个host 上 |
结论:因为 choose 语句的 num ==0,因此首选选择 3 个 host,然后从第一个 host 开始从其子树中,按照 chooseleaf 语句中 {num}的情况选择若干个 osd,直到遍历完所有的 host 或者达到 pool size。
理解 OpenStack + Ceph (9): Ceph 的size/min_size/choose/chooseleaf/scrubbing/repair 等概念
标签:
原文地址:http://www.cnblogs.com/sammyliu/p/5568989.html