sleep期间读取所有_ceph部分数据所有副本先后故障的抢救
網易游戲高級運維工程師,主要負責云存儲的運維;一個既希望跟業務聊又喜歡能夠默默在后面忙活的普通運維人。
背景故障現場故障恢復故障恢復分析第一種方式:物理磁盤對拷第二種方式:服務啟動時跳過故障扇區來避免異常退出解決方案恢復流程找到故障扇區處的文件移走故障扇區的文件總結
背景
對于 ceph 運維而言,硬件故障導致的 ceph 存儲故障是占比最高的一個故障源,小到單個磁盤故障大到機器故障,每天都在上演,ceph 的多副本、故障域等機制已經能夠保證絕大部分的硬件故障不影響整個 ceph 集群的可用性,比如:
- 多副本能夠確保只要還有一個副本在,數據就不會丟失,業務依然可用
- 故障域的劃分能夠確保一個故障域內的機器或者機柜故障時,數據不會丟失,業務依然可用
- 有需要時還可以將故障服務踢出集群,觸發數據遷移到故障域內其他硬盤,縮短副本數不達標的時間,降低二次故障的影響
但是在日常實際場景中,概率低不代表不會發生,我們必須對這種雖然概率低但是影響可能很大的故障做好預案,確保一旦發生故障能夠快速恢復服務。
故障現場
這里先簡單介紹一下整個故障現場:
- ceph 的版本是Hammer 0.94.5
- 故障域是 host,副本數是 2(即同一個業務的數據會寫兩份,落在不同 host 的各一個硬盤上)
- 一臺服務器的一塊硬盤故障
- 更換磁盤,同步數據
- 另一臺服務器上又有一塊硬盤故障
- 數據兩個副本存放在這兩塊硬盤上的所有業務請求被 block 住
- 集群狀態關鍵信息如下:
2 pgs down; 2 pgs peering;
57 requests are blocked > 32 sec;
recovery 4292086/381750087 objects degraded (1.124%);
recovery 7/137511185 unfound (0.000%);
21/967 in osds are down;- down 表示有部分數據的兩個副本都不在線
- 有 57 個客戶端的請求被 block 超過 32 秒
- 注意這里是 7 個對象的狀態是 unfound
故障恢復
故障恢復分析
目前數據層的影響面及恢復分析如下:
- 毫無疑問,第一要務是先拉回所有存儲服務
- 服務都在線后才能明確兩塊硬盤先后故障是否有數據丟失
- 根據數據實際情況再決定后續恢復操作
目前是因為磁盤有壞道,讀取壞道數據出錯導致服務無法啟動。
第一種方式:物理磁盤對拷
最先想到也是操作最簡單的一種方法就是將故障盤數據全量拷貝到一塊新的硬盤上,忽略其中的故障扇區讀取錯誤,方法如下:
- 在同機房找到一臺空閑服務器,插上新硬盤,格式化分區
- 通過 dd+nc 的方式將故障盤數據 dd 到準備的新盤
# 備用機器,新硬盤
nc -lp {port} | dd of=/dev/sde1
# 故障機器
dd if=/dev/sdX conv=noerror | nc -q 10 {backup ip} {nc port} - 拷貝完成后將新盤替換掉故障盤啟動服務即可
- 這種方法是可行的,尤其是對于較大范圍的磁盤硬件故障這是一個相對穩妥且節省人力的方法
- 但是由于故障 SAS 盤讀寫速度也就 200MB/s 的峰值,即使保持這個速度,1.2TB 的盤同步完成也需要接近兩小時,線上業務坐等兩小時是無計可施的保底方法。
第二種方式:服務啟動時跳過故障扇區來避免異常退出
解決方案
回過頭仔細分析本次故障的信息及規避方法匯總如下:
- 磁盤故障范圍小,雖然 dmesg 很多報錯信息,但是都集中在同一個扇區
Sep 26 16:09:33 cld-XXXX-XX kernel: [51720946.582063] end_request: critical medium error, dev sdd, sector 49382788
...
Sep 26 16:23:02 cld-XXXX-XX kernel: [51721756.747154] end_request: critical medium error, dev sdd, sector 49382788 - 存儲服務啟動時的報錯信息是讀寫錯誤,嘗試啟動一次上面的 dmesg 信息就會再刷一些通用的日志:
FAILED assert(0 == "Input/output error") - 找到故障扇區所在的文件,移走該文件,移走文件并不會變更該扇區所在的文件,以確保故障扇區依然被占用而不會分配給其他文件使用
- osd 啟動時就不會讀取故障扇區所在文件,就不會拋異常退出
恢復流程
經過上述分析后,恢復流程就比較清晰而且簡單了:
找到故障扇區處的文件
- 在配置文件中調大 osd 服務的 debug_filestore 日志級別到 20/20
- 啟動故障盤的存儲服務,從日志中可以看到故障扇區的文件,如下
7f08ae8ee700 10 filestore(/home/ceph/var/lib/osd/ceph-387) FileStore::read(28.7cb_head/b7e767cb/rb.0.8e1ad1d.238e1f29.00000000a418/head//28) pread error: (5) Input/output error - 得到關鍵信息:PG 是 28.7cb ,目錄結構是b7e767cb,故障扇區所在文件是 rb.0.8e1ad1d.238e1f29.00000000a418
- 根據 filestore 的存儲規則定位到該對象在磁盤上的絕對路徑如下:
/home/ceph/var/lib/osd/ceph-387/current/28.7cb_head/DIR_B/DIR_C/DIR_7/DIR_6/rb.0.8e1ad1d.238e1f29.00000000a418__head_B7E767CB__1c
移走故障扇區的文件
這時候通過 cat 嘗試查看這個文件可以看到中途會卡住,dmesg 也會繼續刷上面的扇區錯誤,進一步實錘了磁盤壞道所在文件即為rb.0.8e1ad1d.238e1f29.00000000a418__head_B7E767CB__1c :
- 移動故障對象
mv /home/ceph/var/lib/osd/ceph-387/current/28.7cb_head/DIR_B/DIR_C/DIR_7/DIR_6/rb.0.8e1ad1d.238e1f29.00000000a418__head_B7E767CB__1c /home/ceph/var/lib/osd/ceph-387 - 拉起服務,成功運行,一段時間后集群狀態如下這個 object 狀態仍然是 unfound:
1 requests are blocked > 32 sec;
recovery 1/137522689 unfound (0.000%); - 注意這里的recovery 1/137524092 unfound (0.000%),前面服務沒有拉起來時 ceph 提示有 7 個對象處于 unfound,現在只剩下一個了,這個對象的 osd 的日志提示如下:
# 從名字上看也恰好是故障扇區的那個文件
28.7cb missing primary copy of b7e767cb/rb.0.8e1ad1d.238e1f29.00000000a418/head//28, unfound
- 這時候只能用以下命令通過 ceph 將這個 pg 下的 object 回滾到另一個副本上的版本了
ceph pg 28.7cb mark_unfound_lost revert
至此,集群完全恢復,后續的步驟就是根據這個故障對象名找到 rbd,繼而找到所屬的虛擬機,請求業務確認影響面并檢查虛擬機。
總結
以上就是我們針對雙副本對象的兩個副本因為故障先后離線這種極端情況下進行數據搶救的過程。針對故障、搶救過程以及后續優化總結如下:
- 單個磁盤故障可能會導致整個機器的 raid 卡控制器 reset
- 在一個副本故障期間,又有新的磁盤硬件故障,就導致了本問描述的嚴重故障,三副本能大大減少本次故障概率
- 如果硬盤故障,在完全恢復前不要刪除數據或者格式化硬盤,以免碰到另一個副本也故障時,連回滾來版本的機會也沒有了
- 搶救的根本方法是找到問題癥結,如本次故障中采用移走故障文件的方式就可以解決無法啟動問題
- ceph 故障都會有比較詳細的日志提示,根據提示結合 ceph 的結構特點做針對性的處理即可
- 雙副本發生二次故障的概率更高,尤其是使用年限較高深圳過保的老集群
- 對于關掉了 deep-scrub 的集群,需要手動不定期去觸發 deep-scrub,防止一些可能隱藏的磁盤故障。
往期精彩
﹀
﹀
﹀
那些年,CDN踩過的坑
智能監控中的時間序列預測
使用 d3.js 繪制資源拓撲圖
運維里的人工智能
CI構建環境下的docker build最佳實踐
總結
以上是生活随笔為你收集整理的sleep期间读取所有_ceph部分数据所有副本先后故障的抢救的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python文本去重函数_python3
- 下一篇: 已经定了,民间借贷最高利率大降,利率高过