本系列文章會深刻研究 Ceph 以及 Ceph 和 OpenStack 的集成:html
(1)安裝和部署緩存
(2)Ceph RBD 接口和工具數據結構
(3)Ceph 物理和邏輯結構app
(4)Ceph 的基礎數據結構ide
(6)QEMU-KVM 和 Ceph RBD 的 緩存機制總結性能
(7)Ceph 的基本操做和常見故障排除方法測試
(8)基本的性能測試工具和方法ui
(9) pool 的size 和 min_size,choose 和 chooseleaf,pg scrubbing 和 repair 等概念spa
注意:
- 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。