前言
这里通过实验操作,说明下集群出现pg inconsistent状态的原因和处理办法。
实验操作
1、准备测试集群
下面是我准备的3节点测试集群
[root@ceph01 23.1_head]# ceph -s
cluster 29978a95-87f1-4a0c-96fa-2369e985bfbe
health HEALTH_OK
monmap e1: 1 mons at {ceph01=192.168.10.20:6789/0}
election epoch 13, quorum 0 ceph01
fsmap e44: 1/1/1 up {0=ceph01=up:active}
osdmap e462: 7 osds: 7 up, 7 in
flags sortbitwise,require_jewel_osds
pgmap v142266: 464 pgs, 15 pools, 156 MB data, 272 objects
1153 MB used, 103 GB / 104 GB avail
464 active+clean
[root@ceph01 23.1_head]# ceph osd tree
ID WEIGHT TYPE NAME UP/DOWN REWEIGHT PRIMARY-AFFINITY
-1 0.08752 root default
-2 0.02917 host ceph01
0 0.01459 osd.0 up 1.00000 1.00000
1 0.01459 osd.1 up 1.00000 1.00000
-3 0.02917 host ceph02
2 0.01459 osd.2 up 1.00000 1.00000
3 0.01459 osd.3 up 1.00000 1.00000
-4 0.02917 host ceph03
4 0.01459 osd.4 up 1.00000 1.00000
5 0.01459 osd.5 up 1.00000 1.00000
6 0 osd.6 up 1.00000 1.00000
2、模拟pg inconsistent状态
随便选择一个pg,我这里选择的是23.1这个pg,该pg分布在osd.2和osd.2上面:
[root@ceph01 23.1_head]# ceph pg map 23.1
osdmap e462 pg 23.1 (23.1) -> up [0,2] acting [0,2]
在主本osd.0所在节点上进入pg 23.1的目录,并选择一个对象获取其所有的xattrs:
[root@ceph01 23.1_head]# pwd
/var/lib/ceph/osd/ceph-0/current/23.1_head
[root@ceph02 23.1_head]# getfattr -m ".*" 475caa43-5052-4d27-8ffb-897db2b8a2ec.84114.2\\u222__head_81BA0161__17
# file: 475caa43-5052-4d27-8ffb-897db2b8a2ec.84114.2\134u222__head_81BA0161__17
user.ceph._
user.ceph._@1
user.ceph._user.rgw.acl
user.ceph._user.rgw.etag
user.ceph._user.rgw.idtag
user.ceph._user.rgw.manifest
user.ceph._user.rgw.manifest@1
user.ceph._user.rgw.manifest@2
user.ceph._user.rgw.pg_ver
user.ceph._user.rgw.source_zone
user.ceph._user.rgw.unix-key1
user.ceph._user.rgw.unix1
user.ceph.snapset
user.cephos.spill_out
user.foo
然后获取其中一个xattr:
[root@ceph01 23.1_head]# getfattr -n user.ceph._user.rgw.idtag 475caa43-5052-4d27-8ffb-897db2b8a2ec.84114.2\\u222__head_81BA0161__17
# file: 475caa43-5052-4d27-8ffb-897db2b8a2ec.84114.2\134u222__head_81BA0161__17
user.ceph._user.rgw.idtag="_oamSgdWXhjtMSTEP3OI9g1dL42ZQNx11"
到pg 23.1的副本osd上,同样获取下这个对象的xattr:
[root@ceph02 23.1_head]# getfattr -n user.ceph._user.rgw.idtag 475caa43-5052-4d27-8ffb-897db2b8a2ec.84114.2\\u222__head_81BA0161__17
# file: 475caa43-5052-4d27-8ffb-897db2b8a2ec.84114.2\134u222__head_81BA0161__17
user.ceph._user.rgw.idtag="_oamSgdWXhjtMSTEP3OI9g1dL42ZQNx11"
可以看到对象的user.ceph._user.rgw.idtag扩展属性在主副本上是一样的,这就是正常情况。下面我们手动把主本的扩展属性改下:
[root@ceph01 23.1_head]# setfattr -n user.ceph._user.rgw.idtag -v "_oamSgdWXhjtMSTEP3OI9g1dL42ZQNx12" 475caa43-5052-4d27-8ffb-897db2b8a2ec.84114.2\\u222__head_81BA0161__17
然后手动触发scrub:
[root@ceph01 23.1_head]# ceph pg scrub 23.1
instructing pg 23.1 on osd.0 to scrub
然后再看集群状态变成了ERR:
[root@ceph01 23.1_head]# ceph -s
cluster 29978a95-87f1-4a0c-96fa-2369e985bfbe
health HEALTH_ERR
1 pgs inconsistent
1 scrub errors
monmap e1: 1 mons at {ceph01=192.168.10.20:6789/0}
election epoch 13, quorum 0 ceph01
fsmap e44: 1/1/1 up {0=ceph01=up:active}
osdmap e462: 7 osds: 7 up, 7 in
flags sortbitwise,require_jewel_osds
pgmap v142290: 464 pgs, 15 pools, 156 MB data, 272 objects
1153 MB used, 103 GB / 104 GB avail
463 active+clean
1 active+clean+inconsistent
此时在osd.0的日志里面可以看到scrub的信息:
2019-02-26 17:33:49.841272 7f4976219700 0 log_channel(cluster) log [INF] : 23.1 scrub starts
2019-02-26 17:33:49.842529 7f4976219700 -1 log_channel(cluster) log [ERR] : 23.1 : soid 23:86805d81:::475caa43-5052-4d27-8ffb-897db2b8a2ec.84114.2_222:head attr value mismatch '_user.rgw.idtag'
2019-02-26 17:33:49.842613 7f4976219700 -1 log_channel(cluster) log [ERR] : 23.1 scrub 0 missing, 1 inconsistent objects
2019-02-26 17:33:49.842619 7f4976219700 -1 log_channel(cluster) log [ERR] : 23.1 scrub 1 errors
上面的信息告诉我们23.1这个pg里面的475caa43-5052-4d27-8ffb-897db2b8a2ec.84114.2_222这个对象的_user.rgw.idtag属性在主副本之间不一致。
这里可以知道pg出现inconsistent状态时,是由于pg里面的对象的主副本之间出现数据或元数据不一致导致的(我们上面是修改了其中一个副本的xattr,也可以直接删掉某一个xattr)。
下面看下如何处理这种情况。
3、如何解决
3.1、方式一
上面我们通过osd日志知道哪个pg出现了问题(也可以直接通过ceph health detail命令查看),然后对这个pg执行repair操作即可:
[root@ceph01 23.1_head]# ceph pg repair 23.1
instructing pg 23.1 on osd.0 to repair
一般情况下,等待一小会儿,集群就可以恢复正常了。
这里要注意:repair会去选择权威的副本,然后把选择出来的权威副本上属性同步到其他副本上去。
那我们如何知道权威副本是哪个呢?可以把debug_osd开到10,然后执行完ceph pg scrub {pgid},然后在pg的主osd日志里面可以看到如下信息:
[root@ceph01 ~]# cat /var/log/ceph/ceph-osd.0.log|grep auth
2019-02-26 18:22:33.849430 7f4976219700 10 osd.0 pg_epoch: 462 pg[23.1( v 367'28 (0'0,367'28] local-les=460 n=1 ec=181 les/c/f 460/462/0 459/459/383) [0,2] r=0 lpr=459 crt=367'28 lcod 0'0 mlcod 0'0 active+clean+scrubbing] be_select_auth_object: **selecting osd 0** for obj 23:86805d81:::475caa43-5052-4d27-8ffb-897db2b8a2ec.84114.2_222:head with oi 23:86805d81:::475caa43-5052-4d27-8ffb-897db2b8a2ec.84114.2_222:head(367'25 client.84123.0:989 dirty|data_digest|omap_digest s 0 uv 25 dd ffffffff od ffffffff alloc_hint [0 0])
2019-02-26 18:22:33.849718 7f4976219700 10 osd.0 pg_epoch: 462 pg[23.1( v 367'28 (0'0,367'28] local-les=460 n=1 ec=181 les/c/f 460/462/0 459/459/383) [0,2] r=0 lpr=459 crt=367'28 lcod 0'0 mlcod 0'0 active+clean+scrubbing] scrub_process_inconsistent: checking authoritative
从上面的日志中可以看出osd.0被选成了权威副本。
3.2、方式二
1.查看pg的详细错误信息
[root@ceph01 0.14_head]# rados list-inconsistent-obj 0.14 --format=json-pretty
2.通过rados get/put的方式修复
先把该对象获取出来
[root@ceph01 0.14_head]# rados -p rbd get rbd_data.d37a6b8b4567.0000000000000017 /tmp/rbd_data.d37a6b8b4567.0000000000000017
然后再put进去
[root@ceph01 0.14_head]# rados -p rbd put rbd_data.d37a6b8b4567.0000000000000017 /tmp/rbd_data.d37a6b8b4567.0000000000000017
3.3、方式三
如果经过上面的操作,集群仍没有达到OK状态,可以尝试用下面这种方式进行修复。(参考:https://lihaijing.gitbooks.io/ceph-handbook/content/Troubleshooting/troubleshooting_pg.html)
1、停掉数据不一致且非权威副本所属的 osd (如何知道哪个是权威副本,请参考我上面的说明)。
$ systemctl stop ceph-osd@{osdid}
2、刷新该 osd 的日志。
$ ceph-osd -i {osdid} --flush-journal
3、将不一致的 object 移除。
$ mv /var/lib/ceph/osd/ceph-{osdid}/current/{pgid}_head/ {object-name} /home
4、重新启动该 osd 。
$ systemctl start ceph-osd@{osdid}
5、重新执行修复命令。
$ ceph pg repair {pgid}
总结
上面是两种修复的方法,基本的思想是一样的,就是先找出不一致(inconsistent)的对象,然后对比这个对象的主副本数据哪个更新,然后使用正确的副本对象去修复其他有问题的副本对象。