首頁 >頭條 >ceph物件存放一定要在上線前摸清楚

ceph物件存放一定要在上線前摸清楚

-
-原創
2018-03-12 09:14:143868瀏覽

Ceph作為一款開源的分散式儲存軟體,可以利用X86伺服器本身的本機儲存資源,創建一個或多個儲存資源池,並基於資源池對使用者提供統一儲存服務,包括區塊儲存、物件存儲、文件存儲,滿足企業對儲存高可靠性、高效能、高可擴充性方面的需求,並越來越受到企業的青睞。經過大量的生產實踐證明,Ceph的設計理念先進,功能全面,使用靈活,富有彈性。不過,Ceph的這些優點對企業來說也是一把雙面刃,駕馭的好可以很好地服務於企業,倘若功力不夠,沒有摸清Ceph的脾性,有時也會製造不小的麻煩,下面我要給大家分享的正是這樣的一個案例。

ceph物件存放一定要在上線前摸清楚

A公司透過部署Ceph物件儲存集群,對外提供雲端儲存服務,提供SDK幫助客戶快速實現對圖片、視訊、apk安裝包等非結構化資料的雲端化管理。在業務正式上線前,曾經對Ceph做過充分的功能測試、異常測試和效能測試。

叢集規模不是很大,使用的是社區0.80版本,總共有30台伺服器,每台伺服器配置32GB內存,10塊4T的SATA盤和1塊160G的Intel S3700 SSD盤。 300塊SATA盤組成一個資料資源池(缺省配置情況下就是名稱為.rgw.buckets的pool),存放物件資料;30塊SSD盤組成一個元資料資源池(缺省配置情況下就是名稱為. rgw.buckets.index的pool),存放物件元資料。有過Ceph物件儲存運作經驗的朋友都知道,這樣的配置也算是國際慣例,因為Ceph物件儲存支援多租戶,多個使用者在往同一個bucket(使用者的一個邏輯空間)中PUT物件的時候,會向bucket索引對像中寫入對象的元數據,由於是共享同一個bucket索引對象,訪問時需要對這個索引對象加鎖,將bucket索引對象存放到高性能盤SSD組成的資源池中,減少每一次索引物件存取的時間,提升IO效能,提高物件儲存的整體並發量。

系統上線後,客戶資料開始源源不斷地存入到Ceph物件儲存集群,在前面的三個月中,一切運作正常。期間也出現SATA磁碟故障,依靠Ceph自身的故障偵測、修復機制輕鬆搞定,維運的兄弟感覺很輕鬆。進入到5月份,維運兄弟偶爾抱怨說SSD盤對應的OSD有時會變的很慢,導致業務卡頓,遇到這種情況他們簡單有效的辦法就是重新啟動這個OSD,又能恢復正常。大概這種現象零星發生過幾次,維運兄弟詢問是不是我們在SSD的使用上有什麼不對。我們分析後覺得SSD碟的應用沒有什麼特別的地方,除了將磁碟調度演算法修改成deadline,這個已經修改過了,也就沒有太在意這個事情。

5月28日晚上21:30,在運維兄弟手機上接到系統告警,少部分文件寫入失敗,馬上登陸系統檢查,發現是因為一台伺服器上的SSD盤對應的OSD讀寫緩慢引起的。依照先前的經驗,此類情況重新啟動OSD進程後就能恢復正常,毫不猶豫地重新啟動該OSD進程,等待系統恢復正常。但這一次,SSD的OSD進程啟動過程非常緩慢,並引發同台伺服器上的SATA盤OSD進程卡頓,心跳丟失,一段時間後,又發現其它伺服器上開始出現SSD盤OSD進程卡頓緩慢。繼續重啟其它伺服器上SSD盤對應的OSD進程,出現了類似情況,這樣反覆多次重啟SSD盤OSD進程後,起不來的SSD盤OSD進程越來越多。運維兄弟立即將此情況回饋給技術研發部門,要求火速前往支援。

到辦公室後,根據維運兄弟的回饋,我們登上伺服器,試著啟動幾個SSD盤對應的OSD進程,反覆觀察比對進程的啟動過程:

#1 、 用top指令發現這個OSD進程啟動後就開始瘋狂分配內存,高達20GB甚至有時達到30GB;有時因係統內存耗盡,開始使用swap交換分區;有時即使最後進程被成功拉起,但OSD任然佔用高達10GB的記憶體。

2、 查看OSD的日誌,發現進入FileJournal::_open階段後就停止了日誌輸出。經過很久(30分鐘以上)後才輸出進入load_pg階段;進入load_pg階段後,再次經歷漫長的等待,雖然load_pg完成,但進程仍然自殺退出。

3、 在上述漫長啟動過程中,用pstack查看程序調用棧信息,FileJournal::_open階段看到的調用棧是在做OSD日誌回放,事務處理中是執行levelDB的記錄刪除;在load_pg階段看到的呼叫堆疊資訊是利用levelDB的日誌來修復levelDB檔案。

4、 有時候一個SSD盤OSD進程啟動成功,運行一段時間後會導致另外的SSD盤OSD進程異常死掉。

從這些現象來看,都是跟levelDB有關係,記憶體大量分配是不是跟這個有關係呢?進一步查看levelDB相關的程式碼後發現,在一個事務處理中使用levelDB迭代器,迭代器存取記錄過程中會不斷分配內存,直到迭代器使用完才會釋放全部記憶體。從這一點上看,如果迭代器存取的記錄數非常大,就會在迭代過程中分配大量的記憶體。根據這一點,我們查看bucket中的物件數,發現有幾個bucket中的物件數量達到了2000萬、3000萬、5000萬,而且這幾個大的bucket索引物件儲存位置剛好就是出現問題的那幾個SSD盤OSD。內存大量消耗的原因應該是找到了,這是一個重大突破,此時已是30日21:00,這兩天已經有用戶開始電話投訴,兄弟們都倍感“鴨梨山大”。已經持續奮戰近48小時,兄弟們眼睛都紅腫了,必須停下來休息,否則會有兄弟倒在黎明前。

31日8:30,兄弟們再次投入戰鬥。

還有一個問題,就是有些OSD在經歷漫長啟動過程,最後在load_pg完成後仍自殺退出。透過走讀ceph程式碼,確認是有些線程因長時間沒有被調度(可能是因levelDB的線程長時間佔用了CPU導致)而超時自殺所致。在ceph的配置中有一個filestore_op_thread_suicide_timeout參數,透過測試驗證,將這個參數設定成一個很大的值,可以避免這種自殺。又看到了一點曙光,時鐘指向12:30。

有些進程起來後,仍然會佔用高達10GB的內存,這個問題不解決,即使SSD盤OSD拉起來了,同台伺服器上的其它SATA盤OSD運行因內存不足都要受到影響。兄弟們再接再厲啊,這是黎明前的黑暗,一定要撐過去。有人查資料,有人看程式碼,終於在14:30從ceph資料文檔查到一個強制釋放內存的命令:ceph tell osd.* heap release,可以在進程啟動後執行此命令釋放OSD進程佔用的過多內存。大家都格外興奮,立即測試驗證,果然有效。

一個SSD盤OSD起來後運行一會導致其它SSD盤OSD進程退出,綜合上面的分析定位,這主要是因為發生數據遷移,有數據遷出的OSD,在數據遷出後會刪除相關記錄訊息,觸發levelDB刪除對像元資料記錄,一旦遇到一個超大的bucket索引對象,levelDB使用迭代器遍歷對象的元資料記錄,就會導致過度記憶體消耗,從而導致伺服器上的OSD進程異常。

根據上述分析,經過近2個小時的反覆討論論證,我們制定瞭如下應急措施:

1、 給集群設置noout標誌,不允許做PG遷移,因為一旦出現PG遷移,有PG遷出的OSD,就會在PG遷出後刪除PG中的物件數據,觸發levelDB刪除物件元資料記錄,遇到PG中有一個超大的bucket索引物件就會因迭代器遍歷元數據記錄而消耗大量記憶體。

2、 為了能救活SSD對應的OSD,盡快恢復系統,在啟動SSD對應的OSD進程時,附加啟動參數filestore_op_thread_suicide_timeout,設定一個很大的值。由於故障OSD拉起時,LevelDB的一系列處理會搶佔CPU,導致執行緒調度阻塞,在Ceph中有執行緒死鎖偵測機制,超過這個參數配置的時間執行緒仍然沒有被調度,就判定為執行緒死鎖。為了避免因線程死鎖導致將進程自殺,需要設定這個參數。

3、 在目前記憶體有限的情況下,異常的OSD啟動會使用swap交換分區,為了加快OSD進程啟動,將swap分區調整到SSD盤上。

4、 啟動一個定時任務,定時執行指令ceph tell osd.* heap release,強制釋放OSD所佔用的記憶體。

5、 SSD對應的OSD出現問題的時候,如下步驟處理:

a) 先將該伺服器上的所有OSD進程都停掉,以騰出全部記憶體。

b) 然後啟動OSD進程,並攜帶filestore_op_thread_suicide_timeout參數,給予一個很大的值,例如72000。

c) 觀察OSD的啟動過程,一旦load_pgs執行完畢,可以立即手動執行ceph tell osd.N heap release指令,將其佔用的記憶體強制釋放。

d) 觀察叢集狀態,當所有PG的狀態都恢復正常時,再將其他SATA磁碟對應的OSD進程啟動起來。

依照上述步驟,我們從17:30開始逐一恢復OSD進程,在恢復過程中,那幾個超大bucket索引物件在做backfilling的時候需要較長時間,在此期間訪問這個bucket的請求都被阻塞,導致應用程式業務請求出現逾時,這也是單一bucket儲存大量物件帶來的負面影響。

5月31日23:00,終於恢復了全部OSD進程,從故障到系統全部成功恢復,我們驚心動魄奮戰了72小時,大家相視而笑,興奮過度,再接再厲,一起討論制定徹底解決此問題的方案:

1、 擴大伺服器記憶體到64GB。

2、對新建bucket,限制儲存物件的最大數量。

3、 Ceph 0.94版本經過充分測試後,升級到0.94版本,解決單一bucket索引物件過大問題。

4、優化Ceph對levelDB迭代器的使用,在一個大的事務中,透過分段迭代,一個迭代器在完成一定數量的記錄遍歷後,記錄其當前迭代位置,將其釋放,再重新建立一個新的迭代器,從上次迭代的位置開始繼續遍歷,如此可以控制迭代器的記憶體使用量。

前事不忘後事之師,汲取經驗教訓,我們總結如下幾點:

#1、 系統上線前必須經過充分的測試

A公司的系統上線前,雖然對ceph做了充分的功能、性能、異常測試,但卻沒有大量數據的壓力測試,如果之前單bucket灌入了幾千萬對象測試,也許就能提前發現這個隱患。

2、 運維過程中的每一個異常都要及時引起重視

此案例中,在問題爆發前一段時間,維運部門已經有反饋SSD異常的問題,可惜沒有引起我們重視,倘若當時就深入分析,或許可以找到問題根由,事先制定規避措施。

3、 摸清ceph的脾性

任何軟體產品都有相應的規格限制,ceph也不例外。如果能事先深入了解ceph架構及其實現原理,了解單bucket過度存放大量物件所帶來的負面影響,提前規劃,也不會出現本案例中遇到的問題。 RGW對配額的支援非常全面,包括使用者等級的、bucket等級的,都可以配置單一bucket允許存放的最大物件數量。

4、時刻追蹤社群最新進展

在Ceph的0.94版本中,已經支援了bucket索引物件的shard功能,一個bucket索引物件可以分成多個shard物件存儲,可有效緩解單bucket索引物件過大問題。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn