在測試ceph故障時,發現如果osd節點故障,那麼
rados ls
指令将長時間hang住,一直不傳回。
測試是這樣進行的,
- 搭建一個由1個monitor, 3個OSD組成的叢集。
- 建立一個pool
,tp, size=3
- 關閉osd2, osd3
- 運作指令
,會發現指令一直不傳回。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是活動的。
對測試過程進行進一步分析,發現:
- 當3個OSD狀态都OK時,
映射到的OSD是這樣的:rbd_directory
# 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)
- 關閉OSD3後,
映射到的OSD是這樣的:rbd_directory
# 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
仍然能得到傳回值。
- 繼續關閉OSD2後,
映射到的OSD是這樣的:rbd_directory
# 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的狀态,還不清楚。