Ceph分布式存儲-常見OSD故障處理
1. 常見 OSD 故障處理
進行 OSD 排障前,先檢查一下 monitors 和網(wǎng)絡。如果 ceph health 或 ceph -s 返回的是健康狀態(tài),這意味著 monitors 形成了法定人數(shù)。如果 monitor 還沒達到法定人數(shù)、或者 monitor 狀態(tài)錯誤,要先解決 monitor 的問題。核實下你的網(wǎng)絡,確保它在正常運行,因為網(wǎng)絡對 OSD 的運行和性能有顯著影響。
1.1 收集 OSD 數(shù)據(jù)
開始 OSD 排障要先收集信息,另外還有監(jiān)控 OSD 時收集的,如 ceph osd tree 。
Ceph 日志
如果你沒改默認路徑,可以在 /var/log/ceph 下找到 Ceph 的日志:
- ls /var/log/ceph
如果看到的日志還不夠詳細,可以增大日志級別。請參考[1.12 日志和調試],查閱如何保證看到大量日志又不影響集群運行。
管理套接字
用管理套接字工具檢索運行時信息。列出節(jié)點上所有 Ceph 套接字:
- ls /var/run/ceph
然后,執(zhí)行下例命令顯示可用選項,把 {daemon-name} 換成實際的守護進程(如 osd.0 ):
- ceph daemon osd.0 help
或者,你也可以指定一個 {socket-file} (如 /var/run/ceph 下的文件):
- ceph daemon {socket-file} help
和其它手段相比,管理套接字允許你:
- 在運行時列出配置
- 列出歷史操作
- 列出操作的優(yōu)先隊列狀態(tài)
- 列出在進行的操作
- 列出性能計數(shù)器
顯示可用空間
可能會引起文件系統(tǒng)問題。用 df 命令顯示文件系統(tǒng)的可用空間。
- df -h
其它用法見 df --help 。
I/O 統(tǒng)計信息
用 iostat 工具定位 I/O 相關問題。
- iostat -x
診斷信息
要查看診斷信息,配合 less 、 more 、 grep 或 tail 使用 dmesg ,例如:
- dmesg | grep scsi
1.2 停止數(shù)據(jù)向外重平衡
你得周期性地對集群的子集進行維護,或解決某個故障域的問題(如某個機架)。如果你不想在停機維護 OSD 時讓 CRUSH 自動重均衡,首先設置集群的 noout 標志:
- ceph osd set noout
設置了 noout 后,你就可以停機維護失敗域內的 OSD 了。
- stop ceph-osd id={num}
注意:在定位某故障域內的問題時,停機的 OSD 內的 PG 狀態(tài)會變?yōu)?degraded 。
維護結束后,重啟 OSD 。
- start ceph-osd id={num}
解除 noout 標志。
- ceph osd unset noout
1.3 OSD 沒運行
通常情況下,簡單地重啟 ceph-osd 進程就可以讓它重回集群并恢復。
OSD 起不來
如果你重啟了集群,但其中一個 OSD 起不來,依次檢查:
- 配置文件: 如果你新裝的 OSD 不能啟動,檢查下配置文件,確保它符合規(guī)定(比如 host 而非 hostname ,等等)。
- 檢查路徑: 檢查配置文件的路徑,以及 OSD 的數(shù)據(jù)和日志分區(qū)路徑。如果你分離了 OSD 的數(shù)據(jù)和日志分區(qū)、而配置文件和實際掛載點存在出入,啟動 OSD 時就可能失敗。如果你想把日志存儲于一個塊設備,應該為日志硬盤分區(qū)并為各 OSD 分別指定一個分區(qū)。
- 檢查線程數(shù): 如果你的節(jié)點有很多 OSD ,也許就會觸碰到默認的線程數(shù)限制(如通常是 32k 個),尤其是在恢復期間。你可以用 sysctl 增大線程數(shù),把線程數(shù)更改為支持的上線(即 4194303 ),看看是否有用。例如:
- sysctl -w kernel.pid_max=4194303
如果增大線程數(shù)解決了這個問題,你可以把此配置 kernel.pid_max 寫入配置文件 /etc/sysctl.conf,使之生效,例如:
- kernel.pid_max = 4194303
- 內核版本: 確認你使用的內核版本和發(fā)布版本。 Ceph 默認依賴一些第三方工具,這些工具可能有缺陷或者與特定發(fā)布版和/或內核版本沖突(如 Google perftools )。檢查下操作系統(tǒng)推薦表,確保你已經(jīng)解決了內核相關的問題。
- 段錯誤: 如果有了段錯誤,提高日志級別(如果還沒提高),再試試。如果重現(xiàn)了,聯(lián)系 ceph-devel 郵件列表并提供你的配置文件、monitor 輸出和日志文件內容。
OSD 失敗
當 ceph-osd 掛掉時,monitor 可通過活著的 ceph-osd 了解到此情況,并通過 ceph health 命令報告:
- ceph health
- HEALTH_WARN 1/3 in osds are down
特別地,有 ceph-osd 進程標記為 in 且 down 的時候,你也會得到警告。你可以用下面的命令得知哪個 ceph-osd 進程掛了:
- ceph health detail
- HEALTH_WARN 1/3 in osds are down
- osd.0 is down since epoch 23, last address 192.168.106.220:6800/11080
如果有硬盤失敗或其它錯誤使 ceph-osd 不能正常運行或重啟,將會在日志文件 /var/log/ceph/ 里輸出一條錯誤信息。
如果守護進程因心跳失敗、或者底層核心文件系統(tǒng)無響應而停止,查看 dmesg 獲取硬盤或者內核錯誤。
如果是軟件錯誤(失敗的斷言或其它意外錯誤),應該向 ceph-devel 郵件列表報告。
硬盤沒剩余空間
Ceph 不允許你向滿的 OSD 寫入數(shù)據(jù),以免丟失數(shù)據(jù)。在運行著的集群中,你應該能收到集群空間將滿的警告。 mon osd full ratio 默認為 0.95 ,或達到 95% 的空間使用率時它將阻止客戶端寫入數(shù)據(jù)。 mon osd nearfull ratio 默認為 0.85 ,也就是說達到容量的 85% 時它會產(chǎn)生健康警告。
滿載集群問題一般產(chǎn)生于測試小型 Ceph 集群上如何處理 OSD 失敗時。當某一節(jié)點使用率較高時,集群能夠很快掩蓋將滿和占滿率。如果你在測試小型集群上的 Ceph 如何應對 OSD 失敗,應該保留足夠的可用磁盤空間,然后試著臨時降低 mon osd full ratio 和 mon osd nearfull ratio 值。
ceph health 會報告將滿的 ceph-osds :
- ceph health
- HEALTH_WARN 1 nearfull osds
- osd.2 is near full at 85%
或者:
- ceph health
- HEALTH_ERR 1 nearfull osds, 1 full osds
- osd.2 is near full at 85%
- osd.3 is full at 97%
處理這種情況的方法就是在出現(xiàn) near full 告警時盡快增加新的 ceph-osd ,這允許集群把數(shù)據(jù)重分布到新 OSD 里。
如果因滿載而導致 OSD 不能啟動,你可以試著刪除那個 OSD 上的一些數(shù)據(jù)。但是這時有個問題,當一個 OSD 使用比例達到 95% 時,集群將不接受任何 Ceph Client 端的讀寫數(shù)據(jù)的請求。這時 rbd rm 刪除命令將不會得到響應。
讓集群能夠讀寫是首先要做的事情。最容易想到的就是調高 mon osd full ratio 和 mon osd nearfull ratio 值,但是對于生產(chǎn)環(huán)境,一旦調整這個全局比例,可能會導致整個集群的數(shù)據(jù)都會動起來,引發(fā)更多的數(shù)據(jù)遷移。因此另一種折衷方法就是單獨調整已滿 OSD 的 near full 和 full 比例;也可以使用調低 OSD 的 crush weight 的方法,使已滿 OSD 上的數(shù)據(jù)遷移一部分出去。
- # 調整單個 osd 的比例
- ceph tell osd.id injectargs '--mon-osd-full-ratio .98'
- ceph tell osd.id injectargs '--mon-osd-full-ratio 0.98'
- # 調整 osd 的 crush weight 值
- ceph osd crush reweight osd.id {a-little-lower-weight-value}
1.4 OSD 龜速或無響應
一個反復出現(xiàn)的問題是 OSD 龜速或無響應。在深入性能問題前,你應該先確保不是其他故障。例如,確保你的網(wǎng)絡運行正常、且 OSD 在運行,還要檢查 OSD 是否被恢復流量拖住了。
Tip: 較新版本的 Ceph 能更好地處理恢復,可防止恢復進程耗盡系統(tǒng)資源而導致 up 且 in 的 OSD 不可用或響應慢。
網(wǎng)絡問題
Ceph 是一個分布式存儲系統(tǒng),所以它依賴于網(wǎng)絡來互聯(lián) OSD 們、復制對象、從錯誤中恢復和檢查心跳。網(wǎng)絡問題會導致 OSD 延時和震蕩(反復經(jīng)歷 up and down,詳情可參考下文中的相關小節(jié)) 。
確保 Ceph 進程和 Ceph 依賴的進程已建立連接和/或在監(jiān)聽。
- netstat -a | grep ceph
- netstat -l | grep ceph
- sudo netstat -p | grep ceph
檢查網(wǎng)絡統(tǒng)計信息。
- netstat -s
驅動器配置
一個存儲驅動器應該只用于一個 OSD 。如果有其它進程共享驅動器,順序讀寫吞吐量會成為瓶頸,包括日志、操作系統(tǒng)、monitor 、其它 OSD 和非 Ceph 進程。
Ceph 在日志記錄完成之后才會確認寫操作,所以使用 ext4 或 XFS 文件系統(tǒng)時高速的 SSD 對降低響應延時很有吸引力。與之相比, btrfs 文件系統(tǒng)可以同時讀寫日志和數(shù)據(jù)分區(qū)。
注意: 給驅動器分區(qū)并不能改變總吞吐量或順序讀寫限制。把日志分離到單獨的分區(qū)可能有幫助,但可以放在另外一塊硬盤的分區(qū)。
扇區(qū)損壞 / 碎片化硬盤
檢修下硬盤是否有壞扇區(qū)和碎片。這會導致總吞吐量急劇下降。
MON 和 OSD 共存
Monitor 通常是輕量級進程,但它們會頻繁調用 fsync() ,這會妨礙其它工作負載,特別是 Mon 和 OSD 共享驅動器時。另外,如果你在 OSD 主機上同時運行 Mon,遭遇的性能問題可能和這些相關:
- 運行較老的內核(低于 3.0 )
- Argonaut 版運行在老的 glibc 之上
- 運行的內核不支持 syncfs(2) 系統(tǒng)調用
在這些情況下,同一主機上的多個 OSD 會相互拖垮對方。它們經(jīng)常導致爆炸式寫入。
進程共存
共用同一套硬件、并向 Ceph 寫入數(shù)據(jù)的進程(像基于云的解決方案、虛擬機和其他應用程序)會導致 OSD 延時大增。一般來說,我們建議用單獨的主機跑 Ceph 、其它主機跑其它進程。實踐證明把 Ceph 和其他應用程序分開可提高性能、并簡化故障排除和維護。
日志記錄級別
如果你為追蹤某問題提高過日志級別,結束后又忘了調回去,這個 OSD 將向硬盤寫入大量日志。如果你想始終保持高日志級別,可以考慮給默認日志路徑(即 /var/log/ceph/$cluster-$name.log )掛載一個單獨的硬盤。
恢復限流
根據(jù)你的配置, Ceph 可以降低恢復速度來維持性能,否則它會加快恢復速度而影響 OSD 的性能。檢查下 OSD 是否正在恢復。
內核版本
檢查下你在用的內核版本。較老的內核也許沒有反合能提高 Ceph 性能的代碼。
內核與 SYNCFS 問題
試試在一個主機上只運行一個 OSD ,看看能否提升性能。老內核未必支持有 syncfs(2) 系統(tǒng)調用的 glibc 。
文件系統(tǒng)問題
當前,我們推薦基于 xfs 部署集群。 btrfs 有很多誘人的功能,但文件系統(tǒng)內的缺陷可能會導致性能問題。我們不推薦使用 ext4 ,因為 xattr 大小的限制破壞了對長對象名的支持( RGW 需要)。
內存不足
我們建議為每 OSD 進程規(guī)劃 1GB 內存。你也許注意到了,通常情況下 OSD 僅會使用一小部分(如 100 - 200MB )。你也許想用這些空閑內存跑一些其他應用,如虛擬機等等。然而當 OSD 進入恢復狀態(tài)時,其內存利用率將激增。如果沒有足夠的可用內存,此 OSD 的性能將會明顯下降。
OLD REQUESTS 或 SLOW REQUESTS
如果某 ceph-osd 守護進程對一請求響應很慢,它會生成日志消息來抱怨請求耗費的時間過長。默認警告閥值是 30 秒,可以通過 osd op complaint time 選項來配置。這種情況發(fā)生時,集群日志會收到這些消息。
很老的版本抱怨 “old requests” :
- osd.0 192.168.106.220:6800/18813 312 : [WRN] old request osd_op(client.5099.0:790 fatty_26485_object789 [write 0~4096] 2.5e54f643) v4 received at 2012-03-06 15:42:56.054801 currently waiting for sub ops
較新版本的 Ceph 抱怨 “slow requests” :
- {date} {osd.num} [WRN] 1 slow requests, 1 included below; oldest blocked for > 30.005692 secs
- {date} {osd.num} [WRN] slow request 30.005692 seconds old, received at {date-time}: osd_op(client.4240.0:8 benchmark_data_ceph-1_39426_object7 [write 0~4194304] 0.69848840) v4 currently waiting for subops from [610]
可能的原因有:
- 壞驅動器(查看 dmesg 輸出)
- 內核文件系統(tǒng)缺陷(查看 dmesg 輸出)
- 集群過載(檢查系統(tǒng)負載、 iostat 等等)
- ceph-osd 守護進程的 bug
可能的解決方法:
- 從 Ceph 主機分離 VM 云解決方案
- 升級內核
- 升級 Ceph
- 重啟 OSD
1.5 震蕩的 OSD
我們建議同時部署 public(前端)網(wǎng)絡和 cluster(后端)網(wǎng)絡,這樣能更好地滿足對象復制的網(wǎng)絡性能需求。另一個優(yōu)點是你可以運營一個不連接互聯(lián)網(wǎng)的集群,以此避免某些拒絕服務威脅。 OSD 們互聯(lián)和檢查心跳時會優(yōu)選 cluster(后端)網(wǎng)絡。
然而,如果 cluster(后端)網(wǎng)絡失敗、或出現(xiàn)了明顯的延時,同時 public(前端)網(wǎng)絡卻運行良好, OSD 目前不能很好地處理這種情況。這時 OSD 們會向 monitor 報告鄰居 down 了、同時報告自己是 up 的,我們把這種情形稱為震蕩( flapping )。
如果有原因導致 OSD 震蕩(反復地被標記為 down ,然后又 up ),你可以強制 monitor 停止這種震蕩狀態(tài):
- ceph osd set noup # prevent OSDs from getting marked up
- ceph osd set nodown # prevent OSDs from getting marked down
這些標記記錄在 osdmap 數(shù)據(jù)結構里:
- ceph osd dump | grep flags
- flags no-up,no-down
可用下列命令清除標記:
- ceph osd unset noup
- ceph osd unset nodown
Ceph 還支持另外兩個標記 noin 和 noout ,它們可防止正在啟動的 OSD 被標記為 in (可以分配數(shù)據(jù)),或被誤標記為 out (不管 mon osd down out interval 的值是多少)。