在测试ceph故障时,发现如果osd节点故障,那么 rados ls
命令将长时间hang住,一直不返回。
测试是这样进行的,
tp, size=3
,rados -p tp ls
,会发现命令一直不返回。从ceph的bug库里面看到一个类似的记录: http://tracker.ceph.com/issues/14992 。这个bug得到的解释认为这是正常的,pool里面rbd_directory
映射到的3个OSD都down掉了,所以rados ls命令不返回。然而有几点疑惑的是,1) pool里面并没有创建过rbd_directory
对象 2) 测试中并没有把3个OSD都关掉,仍然有1个OSD是活动的。
对测试过程进行进一步分析,发现:
rbd_directory
映射到的OSD是这样的:# ceph osd map tp rbd_directory
osdmap e107 pool 'tp' (3) object 'rbd_directory' -> pg 3.30a98c1c (3.4) -> up ([3,2,1], p3) acting ([3,2,1], p3)
rbd_directory
映射到的OSD是这样的:# ceph osd map tp rbd_directory
osdmap e121 pool 'tp' (3) object 'rbd_directory' -> pg 3.30a98c1c (3.4) -> up ([2,1], p2) acting ([2,1], p2)
此时运行rados -p tp ls
仍然能得到返回值。
rbd_directory
映射到的OSD是这样的:# ceph osd map tp rbd_directory
osdmap e123 pool 'tp' (3) object 'rbd_directory' -> pg 3.30a98c1c (3.4) -> up ([1], p1) acting ([1], p1)
然而rados -p tp ls
就Hang住不返回任何响应了。上面官方bug网站的解释显然不能完全解释我现在遇到的情况,这里显然还有一个acting osd。
打开client端的log(在/etc/ceph/ceph.conf里面增加debug objecter = 20/20
打开Log), 对Log进行分析,发现了hang住前进行了的操作和hang住的位置如下:
client.154225.objecter list_nobjects pool_id 3 pool_snap_seq -2 max_entries 1024 list_context 0x55aa8af8f1d0 onfinish 0x55aa8aeefed0 current_pg 0 pos MIN
client.154225.objecter _calc_target raw pgid 3.0 -> actual 3.0 acting [1] primary 1
client.154225.objecter _get_session s=0x55aa8af90f90 osd=1 3
client.154225.objecter response.entries.size 0, response.entries , handle 3:20000000::::head, tentative new pos 3:20000000::::head
client.154225.objecter list_nobjects pool_id 3 pool_snap_seq -2 max_entries 1024 list_context 0x55aa8af8f1d0 onfinish 0x55aa8aeefed0 current_pg 0 pos 3:20000000::::head
client.154225.objecter _calc_target raw pgid 3.4 -> actual 3.4 acting [1] primary 1
client.154225.objecter _get_session s=0x55aa8af90f90 osd=1 4
client.154225.objecter response.entries.size 0, response.entries , handle 3:40000000::::head, tentative new pos 3:40000000::::head
client.154225.objecter list_nobjects pool_id 3 pool_snap_seq -2 max_entries 1024 list_context 0x55aa8af8f1d0 onfinish 0x55aa8aeefed0 current_pg 4 pos 3:40000000::::head
client.154225.objecter _calc_target raw pgid 3.2 -> actual 3.2 acting [1] primary 1
client.154225.objecter _get_session s=0x55aa8af90f90 osd=1 4
client.154225.objecter response.entries.size 1, response.entries objA, handle 3:60000000::::head, tentative new pos 3:60000000::::head
client.154225.objecter list_nobjects pool_id 3 pool_snap_seq -2 max_entries 1024 list_context 0x55aa8af8f1d0 onfinish 0x55aa8aeefed0 current_pg 2 pos 3:60000000::::head
client.154225.objecter _calc_target raw pgid 3.6 -> actual 3.6 acting [] primary -1
client.154225.objecter _get_session osd=-1 returning homeless
client.154225.objecter _maybe_request_map subscribing (onetime) to next osd map
从日志看其实已经成功list了好几个pg, 只是当操作到pg 3.6时进行不下去。从最后的日志看,
_calc_target raw pgid 3.6 -> actual 3.6 acting [] primary -1
_get_session osd=-1 returning homeless
无法找到pg 3.6的acting set, 因此后面的get_session也无法获得一个连接以进行操作。
进一步追踪,发现问题出在_pg_to_raw_osds
函数的返回结果。对于pg 3.6, 这个函数返回的raw osd
列表只有{2}, 不像其他的几个pg,raw osd列表里面都有{1, 2}。因为目前2是down的状态,所以pg 3.6就没有acting osd了。接下来继续看为什么会这样。
ceph -s
看集群状态,发现一个奇怪的现象,osd 2处于down/in的状态。这就解释了为什么osd 2能被选中到raw osd列表。
只是为什么osd 2一直长期处于down/in的状态,还不清楚。