Ceph 存储集群7-故障排除
Ceph 仍在積極開發中,所以你可能碰到一些問題,需要評估 Ceph 配置文件、并修改日志和調試選項來糾正它。
?
?
一、日志記錄和調試
般來說,你應該在運行時增加調試選項來調試問題;也可以把調試選項添加到 Ceph 配置文件里來調試啟動問題,然后查看 /var/log/ceph (默認位置)下的日志文件。
注意:調試輸出會拖慢系統,這種延時有可能掩蓋競爭條件
?
日志記錄是資源密集任務。如果你碰到的問題在集群的某個特定區域,只啟用那個區域對應的日志功能即可。例如,你的 OSD 運行良好、元數據服務器卻不行,這時應該先打開那個可疑元數據服務器例程的調試日志;如果不行再打開各子系統的日志。
?
?
注意:詳盡的日志每小時可能超過 1GB ,如果你的系統盤滿了,這個節點就會停止工作。
?
如果你要打開或增加 Ceph 日志級別,確保系統盤空間足夠。滾動日志文件的方法見加快日志更迭。集群穩定運行后,可以關閉不必要的調試選項以更好地運行。在運營中記錄調試輸出會拖慢系統、且浪費資源。
?
運行時
?
如果你想查看一進程的運行時配置,必須先登錄對應主機,然后執行命令:
ceph daemon {daemon-name} config show | less例如:
ceph daemon osd.0 config show | less?
要在運行時激活 Ceph 的調試輸出(即 dout() ),用 ceph tell 命令把參數注入運行時配置:
?
ceph tell {daemon-type}.{daemon id or *} injectargs --{name} {value} [--{name} {value}]?
用 osd 、 mon 或 mds 替代 {daemon-type} 。你可以用星號( * )把配置應用到同類型的所有守護進程,或者指定具體守護進程的 ID 。例如,要給名為 ods.0 的 ceph-osd 守護進程提高調試級別,用下列命令:
ceph tell osd.0 injectargs --debug-osd 0/5?
ceph tell 命令會貫穿所有監視器。如果你不能綁定監視器,還可以登錄你要改的那臺主機用 ceph daemon 來更改。例如:
sudo ceph daemon osd.0 config set debug_osd 0/5?
?
啟動時
?
要在啟動時激活調試輸出(即 dout() ),你得把選項加入配置文件。各進程共有配置可寫在配置文件的 [global] 下,某類進程的配置可寫在守護進程段下(如 [mon] 、 [osd] 、 [mds] )。例如:
?
[global]debug ms = 1/5[mon]debug mon = 20debug paxos = 1/5debug auth = 2[osd]debug osd = 1/5debug filestore = 1/5debug journal = 1debug monc = 5/20[mds]debug mds = 1debug mds balancer = 1debug mds log = 1debug mds migrator = 1?
?
加快日志更迭
?
如果你的系統盤比較滿,可以修改 /etc/logrotate.d/ceph 內的日志滾動配置以加快滾動。在滾動頻率后增加一個尺寸選項(達到此尺寸就滾動)來加快滾動(通過 cronjob )。例如默認配置大致如此:
rotate 7 weekly compress sharedscripts?
增加一個 size 選項。
rotate 7 weekly size 500M compress sharedscripts?
然后,打開 crontab 編輯器。
crontab -e?
最后,增加一條用以檢查 /etc/logrorate.d/ceph 文件。
?
30 * * * * /usr/sbin/logrotate /etc/logrotate.d/ceph >/dev/null 2>&1?
本例中每 30 分鐘檢查一次 /etc/logrorate.d/ceph 文件。
?
Valgrind
你也許還得追蹤內存和線程問題,可以在 Valgrind 中運行一個守護進程、一類進程、或整個集群。 Valgrind 是計算密集型程序,應該只用于開發或調試,否則會拖慢系統。其消息記錄到 stderr 。
?
子系統、日志和調試選項
?
大多數情況下你可以通過子系統打開調試。
?
Ceph 子系統概覽
各子系統都有日志級別用于分別控制其輸出日志、和暫存日志,你可以分別為這些子系統設置不同的記錄級別。 Ceph 的日志級別從 1 到 20 , 1 是簡潔、 20 是詳盡。通常,內存駐留日志不會發送到輸出日志,除非:
?
致命信號冒出來了,或者 源碼中的 assert 被觸發,或者 明確要求發送。?
調試選項允許用單個數字同時設置日志級別和內存級別,會設置為一樣。比如,如果你指定 debug ms = 5 , Ceph 會把日志級別和內存級別都設置為 5 。也可以分別設置,第一個選項是日志級別、后一個是內存級別,二者必須用斜線( / )分隔。假如你想把 ms 子系統的調試日志級別設為 1 、內存級別設為 5 ,可以寫為 debug ms = 1/5 ,如下:
debug {subsystem} = {log-level}/{memory-level} #for example debug mds log = 1/20下表列出了 Ceph 子系統及其默認日志和內存級別。一旦你完成調試,應該恢復默認值、或一個適合平常運營的級別。
子系統 日志級別 內存日志級別 default 0 5 lockdep 0 5 context 0 5 crush 1 5 mds 1 5 mds balancer 1 5 mds locker 1 5 mds log 1 5 mds log expire 1 5 mds migrator 1 5 buffer 0 0 timer 0 5 filer 0 5 objecter 0 0 rados 0 5 rbd 0 5 journaler 0 5 objectcacher 0 5 client 0 5 osd 0 5 optracker 0 5 objclass 0 5 filestore 1 5 journal 1 5 ms 0 5 mon 1 5 monc 0 5 paxos 0 5 tp 0 5 auth 1 5 finisher 1 5 heartbeatmap 1 5 perfcounter 1 5 rgw 1 5 javaclient 1 5 asok 1 5 throttle 1 5?
?
日志記錄選項
?
日志和調試選項不是必需配置,但你可以按需覆蓋默認值。 Ceph 支持如下配置:
?
log file 描述: 集群日志文件的位置。 類型: String 是否必需: No 默認值: /var/log/ceph/$cluster-$name.loglog max new 描述: 新日志文件的最大數量。 類型: Integer 是否必需: No 默認值: 1000log max recent 描述: 一個日志文件包含的最新事件的最大數量。 類型: Integer 是否必需: No 默認值: 1000000log to stderr 描述: 設置日志消息是否輸出到標準錯誤( stderr )。 類型: Boolean 是否必需: No 默認值: trueerr to stderr 描述: 設置錯誤消息是否輸出到標準錯誤( stderr )。 類型: Boolean 是否必需: No 默認值: truelog to syslog 描述: 設置日志消息是否輸出到 syslog 。 類型: Boolean 是否必需: No 默認值: falseerr to syslog 描述: 設置錯誤消息是否輸出到 syslog 。 類型: Boolean 是否必需: No 默認值: falselog flush on exit 描述: 設置 Ceph 退出后是否回寫日志文件。 類型: Boolean 是否必需: No 默認值: trueclog to monitors 描述: 設置是否把 clog 消息發送給監視器。 類型: Boolean 是否必需: No 默認值: trueclog to syslog 描述: 設置是否把 clog 輸出到 syslog 。 類型: Boolean 是否必需: No 默認值: falsemon cluster log to syslog 描述: 設置集群日志是否輸出到 syslog 。 類型: Boolean 是否必需: No 默認值: falsemon cluster log file 描述: 集群日志位置。 類型: String 是否必需: No 默認值: /var/log/ceph/$cluster.log?
?
?
OSD
?
osd debug drop ping probability 描述: ? 類型: Double 是否必需: No 默認值: 0osd debug drop ping duration 描述: 類型: Integer 是否必需: No 默認值: 0osd debug drop pg create probability 描述: 類型: Integer 是否必需: No 默認值: 0osd debug drop pg create duration 描述: ? 類型: Double 是否必需: No 默認值: 1osd preserve trimmed log 描述: 裁減后保留剩余日志。 類型: Boolean 是否必需: No 默認值: falseosd tmapput sets uses tmap 描述: 使用 tmap ,僅用于調試。 類型: Boolean 是否必需: No 默認值: falseosd min pg log entries 描述: 歸置組日志最小條數。 類型: 32-bit Unsigned Integer 是否必需: No 默認值: 1000osd op log threshold 描述: 一次發送多少操作日志消息。 類型: Integer 是否必需: No 默認值: 5 Filestorefilestore debug omap check 描述: 調試同步檢查,這是昂貴的操作。 類型: Boolean 是否必需: No 默認值: 0?
?
MDS
?
mds debug scatterstat 描述: Ceph 將把各種回歸狀態常量設置為真(謹為開發者)。 類型: Boolean 是否必需: No 默認值: falsemds debug frag 描述: Ceph 將在方便時校驗目錄碎片(謹為開發者)。 類型: Boolean 是否必需: No 默認值: falsemds debug auth pins 描述: debug auth pin 開關(謹為開發者)。 類型: Boolean 是否必需: No 默認值: falsemds debug subtrees 描述: debug subtree 開關(謹為開發者)。 類型: Boolean 是否必需: No 默認值: false?
?
RADOS 網關
?
rgw log nonexistent bucket 描述: 記錄不存在的桶? 類型: Boolean 是否必需: No 默認值: falsergw log object name 描述: 是否記錄對象名稱。注:關于格式參考 man date ,子集也支持。 類型: String 是否必需: No 默認值: %Y-%m-%d-%H-%i-%nrgw log object name utc 描述: 對象日志名稱包含 UTC ? 類型: Boolean 是否必需: No 默認值: falsergw enable ops log 描述: 允許記錄 RGW 的每一個操作。 類型: Boolean 是否必需: No 默認值: truergw enable usage log 描述: 允許記錄 RGW 的帶寬使用。 類型: Boolean 是否必需: No 默認值: truergw usage log flush threshold 描述: 回寫未決的日志數據閥值。 類型: Integer 是否必需: No 默認值: 1024rgw usage log tick interval 描述: 每隔 s 回寫一次未決日志。 類型: Integer 是否必需: No 默認值: 30rgw intent log object name 描述: 類型: String 是否必需: No 默認值: %Y-%m-%d-%i-%nrgw intent log object name utc 描述: 日志對象名字里包含 UTC 時間戳。 類型: Boolean 是否必需: No 默認值: false?
二、監視器故障排除
?
當集群遇到與監視器相關的問題時, 會有恐慌的傾向, 有時還有很好的理由。你應該記住, 失去一個顯示器, 或一堆, 并不一定意味著你的集群是下降, 只要大多數是, 運行和形成的法定人數。
?
開始排障
?
監視器在運行嗎?
首先, 我們需要確保監視器正在運行。你會驚訝于人們經常忘記運行監視器, 或者在升級后重新啟動它們。這并不可恥, 但是讓我們試著不要失去幾個小時去追逐一個不存在的問題。
?
ceph -s 是否能運行并收到集群回復?
如果答案是肯定的,那么你的集群已啟動并運行著。你可以想當然地認為如果已經形成法定人數,監視器們就只會響應 status 請求。
?
但是, 如果 ceph 被阻止, 而沒有從群集得到答復或顯示大量的錯誤消息, 那么很可能您的監視器要么完全關閉, 要么只是部分上升--這部分不足以形成仲裁 (請記住, 如果 f由大多數顯示器 ormed)。?
?
使用監視器的管理套接字
通過管理套接字,你可以用 Unix 套接字文件直接與指定守護進程交互。這個文件位于你監視器的 run 目錄下,默認配置時它位于 /var/run/ceph/ceph-mon.ID.asok ,但你要是改過就不一定在那里了。如果你在那里沒找到它,請看看 ceph.conf 里是否配置了其它路徑、或者用下面的命令獲取:
ceph-conf --name mon.ID --show-config-value admin_socket?
請牢記,只有在監視器運行時管理套接字才可用。監視器正常關閉時,管理套接字會被刪除;如果監視器不運行了、但管理套接字還存在,就說明監視器不是正常關閉的。不管怎樣,監視器沒在運行,你就不能使用管理套接字, ceph 命令會返回類似 Error 111: Connection Refused 的錯誤消息。
訪問管理套接字很簡單,就是讓 ceph 工具使用 asok 文件。對于 Dumpling 之前的版本,命令是這樣的:
?
ceph --admin-daemon /var/run/ceph/ceph-mon.<id>.asok <command>?
對于 Dumpling 及后續版本,你可以用另一個(推薦的)命令:
?
ceph daemon mon.<id> <command>?
ceph 工具的 help 命令會顯示管理套接字支持的其它命令。請仔細了解一下 config get 、 config show 、 mon_status 和 quorum_status 命令,在排除監視器故障時它們能給你些啟發。
?
?
理解 mon_status
?
mon_status 可以通過 ceph 工具獲得, 當您有一個形成的法定人數, 或通過管理插座, 如果你不。此命令將輸出有關監視器的大量信息, 包括與 quorum_status 相同的輸出。
?
以下 mon_status 為例:
?
?
{ "name": "c","rank": 2,"state": "peon","election_epoch": 38,"quorum": [1,2],"outside_quorum": [],"extra_probe_peers": [],"sync_provider": [],"monmap": { "epoch": 3,"fsid": "5c4e9d53-e2e1-478a-8061-f543f8be4cf8","modified": "2013-10-30 04:12:01.945629","created": "2013-10-29 14:14:41.914786","mons": [{ "rank": 0,"name": "a","addr": "127.0.0.1:6789\/0"},{ "rank": 1,"name": "b","addr": "127.0.0.1:6790\/0"},{ "rank": 2,"name": "c","addr": "127.0.0.1:6795\/0"}]}}?
?
最常見的監視器問題
?
有仲裁, 但至少有一個顯示器關閉
當這一切發生的時候,取決于運行的ceph版本。你應該看到類似的東西
$ ceph health detail [snip] mon.a (rank 0) addr 127.0.0.1:6789/0 is down (out of quorum)?
?
?
三、OSD 故障排除
進行 OSD 排障前,先檢查一下監視器集群和網絡。如果 ceph health 或 ceph -s 返回的是健康狀態,這意味著監視器們形成了法定人數。如果你還沒監視器法定人數、或者監視器狀態錯誤,要先解決監視器問題。核實下你的網絡,確保它在正常運行,因為網絡對 OSD 的運行和性能有顯著影響。
?
收集 OSD 數據
?
開始 OSD 排障的第一步最好先收集信息,另外還有監控 OSD 時收集的,如 ceph? osd tree 。
?
Ceph 日志
?
如果你沒改默認路徑,可以在 /var/log/ceph 下找到日志:
?
ls /var/log/ceph如果看到的日志還不夠詳細,可以增大日志級別。請參考日志記錄和調試,看看如何保證看到大量日志時又不影響集群運行。
?
管理套接字
用管理套接字檢索運行時信息。所有 Ceph 套接字列表:
ls /var/run/ceph?
然后,執行下例命令顯示可用選項,把 {daemon-name} 換成實際的守護進程(如 osd.0 ):
ceph daemon osd.0 help?
另外,你也可以指定一個 {socket-file} (如 /var/run/ceph 下的文件):
?
ceph daemon {socket-file} help?
和其它手段相比,管理接口允許你:
?
在運行時列出配置列出歷史操作列出操作的優先隊列狀態列出在進行的操作列出性能計數器?
顯示剩余空間
?
可能是文件系統問題,用 df 顯示文件系統剩余空間。
?
df -h?
?
I/O 統計信息
?
用 iostat 定位 I/O 相關問題。
?
iostat -x?
診斷消息
要查看診斷信息,配合 less 、 more 、 grep 或 tail 使用 dmesg ,例如:
dmesg | grep scsi?
停止自動重均衡
你得周期性地維護集群的子系統、或解決某個失敗域的問題(如一機架)。如果你不想在停機維護 OSD 時讓 CRUSH 自動重均衡,提前設置 noout :
?
ceph osd set noout?
在集群上設置 noout 后,你就可以停機維護失敗域內的 OSD 了。
stop ceph-osd id={num}?
注意:在定位同一故障域內的問題時,停機 OSD 內的歸置組狀態會變為 degraded 。
維護結束后,重啟OSD。
?
start ceph-osd id={num}?
最后,解除 noout 標志。
ceph osd unset noout?
OSD 沒運行
?
通常情況下,簡單地重啟 ceph-osd 進程就可以重回集群并恢復。
?
OSD 起不來
?
如果你重啟了集群,但其中一個 OSD 起不來,依次檢查:
?
配置文件: 如果你新裝的 OSD 不能啟動,檢查下配置文件,確保它合爻性(比如 host 而非 hostname ,等等);檢查路徑: 檢查你配置的路徑,以及它們自己的數據和日志路徑。如果你分離了 OSD 數據和日志、而配置文件和實際掛載點存在出入,啟動 OSD 時就可能遇挫。如果你想把日志存儲于一個塊設備,應該為日志硬盤分區并為各 OSD 分別分配一分區。檢查最大線程數: 如果你的節點有很多 OSD ,也許就會觸碰到默認的最大線程數限制(如通常是 32k 個),尤其是在恢復期間。你可以用 sysctl 增大線程數,把最大線程數更改為支持的最大值(即 4194303 ),看看是否有用。例如: sysctl -w kernel.pid_max=4194303如果增大最大線程數解決了這個問題,你可以把此配置 kernel.pid_max 寫入配置文件 /etc/sysctl.conf,使之永久生效,例如:
kernel.pid_max = 4194303 內核版本: 確認你在用的內核版本以及所用的發布版。 Ceph 默認依賴一些第三方工具,這些工具可能有缺陷或者與特定發布版和/或內核版本沖突(如 Google perftool )。檢查下操作系統推薦確保你已經解決了內核相關的問題。
段錯誤: 如果有了段錯誤,提高日志級別(如果還沒提高),再試試。如果重現了,聯系 ceph-devel 并提供你的配置文件、顯示器輸出和日志文件內容。
?
如果問題仍未解決,電子郵件也無用,你可以聯系 Inktank 尋求幫助
?
OSD 失敗
?
ceph-osd 掛掉時,監視器可通過活著的 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/ 里。
如果守護進程因心跳失敗、或者底層文件系統無響應而停止,查看 dmesg 獲取硬盤或者內核錯誤。
如果是軟件錯誤(失敗的插入或其它意外錯誤),就應該回饋到 ceph-devel 郵件列表。
?
?
硬盤沒剩余空間
?
Ceph 不允許你向滿的 OSD 寫入數據,以免丟失數據。在運營著的集群中,你應該能收到集群空間將滿的警告。 mon osd full ratio 默認為 0.95 、或達到 95% 時它將阻止客戶端寫入數據。 mon osd nearfull ratio 默認為 0.85 、也就是說達到容量的 85% 時它會產生健康警告。
滿載集群問題一般產生于測試 Ceph 在小型集群上如何處理 OSD 失敗時。當某一節點利用率較高時,集群能夠很快掩蓋將滿和占滿率。如果你在測試小型集群上的 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%?
處理這種情況的最好方法就是增加新的 ceph-osd ,這允許集群把數據重分布到新 OSD 里。
如果因滿載而導致 OSD 不能啟動,你可以試著刪除那個 OSD 上的一些歸置組數據目錄。
?
注意:如果你準備從填滿的 OSD 中刪除某個歸置組,注意不要刪除另一個OSD 上的同名歸置組,否則你會丟數據。必須在多個 OSD 上保留至少一份數據副本。
?
OSD 龜速或無響應
?
一個反復出現的問題是龜速或無響應。在深入性能問題前,你應該先確保不是其他故障。例如,確保你的網絡運行正常、且 OSD 在運行,還要檢查 OSD 是否被恢復流量拖住了。
?
注意:較新版本的 Ceph 能更好地處理恢復,可防止恢復進程耗盡系統資源而導致 up 且 in 的 OSD 不可用或響應慢。
?
網絡問題
?
Ceph 是一個分布式存儲系統,所以它依賴于網絡來互聯 OSD 們、復制對象、恢復錯誤、和檢查心跳。網絡問題會導致 OSD 延時和打擺子,詳情參見打擺子的 OSD 。
確保 Ceph 進程和 Ceph 依賴的進程連接了、和/或在監聽。
?
netstat -a | grep ceph netstat -l | grep ceph sudo netstat -p | grep ceph?
檢查網絡統計信息。
?
netstat -s?
?
驅動器配置
一個存儲驅動器應該只用于一個 OSD 。如果有其它進程共享驅動器,順序讀和順序寫吞吐量會成為瓶頸,包括日志記錄、操作系統、監視器、其它 OSD 和非 Ceph 進程。
Ceph 在日志記錄完成之后才會確認寫操作,所以使用 ext4 或 XFS 文件系統時高速的 SSD 對降低響應延時很有吸引力。相反, btrfs 文件系統可以同時讀寫。
注意:給驅動器分區并不能改變總吞吐量或順序讀寫限制。把日志分離到單獨的分區可能有幫助,但最好是另外一塊硬盤的分區。
?
壞扇區和碎片化硬盤
檢修下硬盤是否有壞扇區和碎片。這會導致總吞吐量急劇下降。
?
監視器和 OSD 蝸居
監視器是普通的輕量級進程,但它們會頻繁調用 fsync() ,這會妨礙其它工作量,特別是監視器和 OSD 共享驅動器時。另外,如果你在 OSD 主機上同時運行監視器,遭遇的性能問題可能和這些相關:
運行較老的內核(低于3.0)v0.48 版運行在老的 glibc 之上運行的內核不支持 syncfs(2) 系統調用?
在這些情況下,同一主機上的多個 OSD 會相互拖垮對方。它們經常導致爆炸式寫入。
?
?
?
進程蝸居
共存于同一套硬件、并向 Ceph 寫入數據的進程(像基于云的解決方案、虛擬機和其他應用程序)會導致 OSD 延時大增。一般來說,我們建議用一主機跑 Ceph 、其它主機跑其它進程,實踐證明把 Ceph 和其他應用程序分開可提高性能、并簡化故障排除和維護。
日志記錄級別
如果你為追蹤某問題提高過日志級別、但結束后忘了調回去,這個 OSD 將向硬盤寫入大量日志。如果你想始終保持高日志級別,可以考慮給默認日志路徑掛載個硬盤,即 /var/log/ceph/$cluster-$name.log 。
恢復節流
根據你的配置, Ceph 可以降低恢復速度來維持性能,否則它會不顧 OSD 性能而加快恢復速度。檢查下 OSD 是否正在恢復。
內核版本
檢查下你在用的內核版本。較老的內核也許沒有移植能提高 Ceph 性能的功能。
內核與 SyncFS 問題
試試在一主機上只運行一個 OSD ,看看能否提升性能。老內核未必支持有 syncfs(2) 系統調用的 glibc 。
文件系統問題
當前,我們推薦基于 xfs 或 ext4 部署集群。 btrfs 有很多誘人的功能,但文件系統內的缺陷可能導致性能問題。
內存不足
我們建議為每 OSD 進程規劃 1GB 內存。你也許注意到了,通常情況下 OSD 僅會用一小部分(如 100-200MB )。你也許想用這些空閑內存跑一些其他應用,如虛擬機等等,然而當 OSD 進入恢復狀態時,其內存利用率激增,如果沒有可用內存,此 OSD 的性能將差的多。
old requests 或 slow requests
如果某 ceph-osd 守護進程對一請求響應很慢,它會生成日志消息來抱怨請求耗費的時間過長。默認警告閥值是 30 秒,用 osd op complaint time 選項來配置。這種情況發生時,集群日志系統會收到這些消息。
很老的版本抱怨 “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 輸出);內核文件系統缺陷(查看 dmesg 輸出);集群過載(檢查系統負載、 iostat 等等);ceph-osd 守護進程缺陷。?
可能的解決方法:
從 Ceph 主機去除 VM 云解決方案;升級內核;升級 Ceph ;重啟 OSD 。?
打擺子的 OSD
?
我們建議同時部署公網(前端)和集群網(后端),這樣能更好地滿足對象復制的容量需求。另一個優點是你可以運營一個不連接互聯網的集群,以此避免拒絕估計。 OSD 們互聯和檢查心跳時會優選集群網(后端),詳情見監視器與 OSD 的交互。
然而,如果集群網(后端)失敗、或出現了明顯的延時,同時公網(前端)卻運行良好, OSD 現在不能很好地處理這種情況。這時 OSD 們會向監視器報告鄰居 down 了、同時報告自己是 up 的,我們把這種情形稱為打擺子( flapping )。
如果有東西導致 OSD 打擺子(反復地被標記為 down ,然后又 up ),你可以強制監視器停止:
ceph osd set noup # prevent OSDs from getting marked up ceph osd set nodown # prevent OSDs from getting marked down?
這些標記記錄在 osdmap 數據結構里:
ceph osd dump | grep flags flags no-up,no-down?
下列命令可清除標記:
ceph osd unset noup ceph osd unset nodown?
mon osd down out interval is). 還支持其它兩個標記 noin 和 noout ,它們分別可防止正在啟動的 OSD 被標記為 in 、或被誤標記為 out (不管 `` mon osd down out interval`` 的值是什么)。
?
注意:noup 、 noout 和 nodown 從某種意義上說是臨時的,一旦標記清除了,它們被阻塞的動作短時間內就會發生;相反, noin 標記阻止 OSD 啟動后進入集群,但其它守護進程都維持原樣。
?
四、歸置組排障
?
歸置組總不整潔
?
當您創建群集并且您的群集處于active, active+remapped or active+degraded狀態并且從未達到active+clean狀態時, 您的配置可能會有問題
?
一個節點群集
Ceph 不再提供在單個節點上操作的文檔, 因為您永遠不會在單個節點上部署專為分布式計算設計的系統。
此外, 在包含 Ceph 守護進程的單個節點上安裝客戶端內核模塊可能會由于 Linux 內核本身的問題而導致死鎖 (除非您為客戶端使用 vm)。
?
您可以在1節點的配置中進行 Ceph 實驗,
?
如果您試圖在單個節點上創建群集, 則必須在創建監視器和osd之前,在 Ceph 配置文件中選擇 "從 1 (意味著主機或節點) 到 0 (意味著 osd)" 中的 "從您的默認值" 中選取 "葉類型" 設置。
?
如果使用單個磁盤創建 OSD, 則必須首先手動創建數據目錄。例如: mkdir /var/local/osd0 /var/local/osd1 ceph-deploy osd prepare {localhost-name}:/var/local/osd0 {localhost-name}:/var/local/osd1 ceph-deploy osd activate {localhost-name}:/var/local/osd0 {localhost-name}:/var/local/osd1?
比復制副本更少的 OSD
?
如果您已經將兩個 osd 設置為 in 和 up, 但仍未看到 active + clean放置組, 則可能是 osd 池的默認大小設置為大于2。
有幾種方法可以解決這種情況。如果要在具有兩個副本的active + degraded狀態下操作群集, 可以將 osd pool default min size設置為 2, 以便可以在active + degraded狀態下編寫對象。
?
您也可以將 osd pool default size 設置為 2, 以便您只有兩個存儲的副本 (原件和一個副本), 在這種情況下, 群集應該實現一個active + clean的狀態
?
注意:您可以在運行時進行更改。如果您在 Ceph 配置文件中進行了更改, 則可能需要重新啟動群集。
?
Pool Size = 1
?
如果將 osd pool default size設置為 1, 則只會有一個該對象的副本。osd 依賴于其他 osd 來告訴他們應該擁有哪些對象。
如果第一個 osd 有一個對象的副本, 并且沒有第二個拷貝, 那么沒有第二個 osd 可以告訴第一個 osd 它應該有該副本。
對于映射到第一個 osd 的每個放置組 (請參見 ceph pg 轉儲), 您可以強制第一個 osd 通過運行來注意它需要的放置組:
?
ceph pg force_create_pg <pgid>?
CRUSH 圖錯誤
另一個候選的安置組仍然不潔涉及在你的CRUSH map的錯誤。
?
卡住的歸置組
有失敗時歸置組會進入“degraded”(降級)或“peering”(連接建立中)狀態,這事時有發生,通常這些狀態意味著正常的失敗恢復正在進行。然而,如果一個歸置組長時間處于某個這些狀態就意味著有更大的問題,因此監視器在歸置組卡 (stuck) 在非最優狀態時會警告。我們具體檢查:
inactive (不活躍)——歸置組長時間無活躍(即它不能提供讀寫服務了);unclean (不干凈)——歸置組長時間不干凈(例如它未能從前面的失敗完全恢復);stale (不新鮮)——歸置組狀態沒有被 ceph-osd 更新,表明存儲這個歸置組的所有節點可能都掛了。?
你可以擺出卡住的歸置組:
?
?
ceph pg dump_stuck stale ceph pg dump_stuck inactive ceph pg dump_stuck unclean?
卡在 stale 狀態的歸置組通過修復 ceph-osd 進程通常可以修復;卡在 inactive 狀態的歸置組通常是互聯問題(參見 歸置組掛了——互聯失敗 );卡在 unclean 狀態的歸置組通常是由于某些原因阻止了恢復的完成,像未找到的對象(參見 未找到的對象 )。
?
歸置組掛了——互聯失敗
在某些情況下, ceph-osd 連接建立進程會遇到問題,使 PG 不能活躍、可用,例如 ceph health 也許顯示:
?
ceph health detail HEALTH_ERR 7 pgs degraded; 12 pgs down; 12 pgs peering; 1 pgs recovering; 6 pgs stuck unclean; 114/3300 degraded (3.455%); 1/3 in osds are down ... pg 0.5 is down+peering pg 1.4 is down+peering ... osd.1 is down since epoch 69, last address 192.168.106.220:6801/8651?
可以查詢到 PG 為何被標記為 down :
?
ceph pg 0.5 query { "state": "down+peering",..."recovery_state": [{ "name": "Started\/Primary\/Peering\/GetInfo","enter_time": "2012-03-06 14:40:16.169679","requested_info_from": []},{ "name": "Started\/Primary\/Peering","enter_time": "2012-03-06 14:40:16.169659","probing_osds": [0,1],"blocked": "peering is blocked due to down osds","down_osds_we_would_probe": [1],"peering_blocked_by": [{ "osd": 1,"current_lost_at": 0,"comment": "starting or marking this osd lost may let us proceed"}]},{ "name": "Started","enter_time": "2012-03-06 14:40:16.169513"}] }?
recovery_state 段告訴我們連接建立因 ceph-osd 進程掛了而被阻塞,本例是 osd.1 掛了,啟動這個進程應該就可以恢復。
另外,如果 osd.1 是災難性的失敗(如硬盤損壞),我們可以告訴集群它丟失( lost )了,讓集群盡力完成副本拷貝。
?
注意:集群不能保證其它數據副本是一致且最新就危險了!
?
讓 Ceph 無論如何都繼續:
ceph osd lost 1恢復將繼續
?
未找到的對象
?
某幾種失敗相組合可能導致 Ceph 抱怨有找不到( unfound )的對象:
?
ceph health detail HEALTH_WARN 1 pgs degraded; 78/3778 unfound (2.065%) pg 2.4 is active+degraded, 78 unfound?
這意味著存儲集群知道一些對象(或者存在對象的較新副本)存在,卻沒有找到它們的副本。下例展示了這種情況是如何發生的,一個 PG 的數據存儲在 ceph-osd 1 和 2 上:
?
1 掛了;2 獨自處理一些寫動作;1 起來了;1 和 2 重新互聯, 1 上面丟失的對象加入隊列準備恢復;新對象還未拷貝完, 2 掛了。?
?
這時, 1 知道這些對象存在,但是活著的 ceph-osd 都沒有副本,這種情況下,讀寫這些對象的 IO 就會被阻塞,集群只能指望節點早點恢復。這時我們假設用戶希望先得到一個 IO 錯誤。
首先,你應該確認哪些對象找不到了:
ceph pg 2.4 list_missing [starting offset, in json] { "offset": { "oid": "", "key": "", "snapid": 0, "hash": 0, "max": 0}, "num_missing": 0, "num_unfound": 0, "objects": [ { "oid": "object 1", "key": "", "hash": 0, "max": 0 }, ... ], "more": 0}?
如果在一次查詢里列出的對象太多, more 這個字段將為 true ,因此你可以查詢更多。(命令行工具可能隱藏了,但這里沒有)
其次,你可以找出哪些 OSD 上探測到、或可能包含數據:
?
ceph pg 2.4 query "recovery_state": [{ "name": "Started\/Primary\/Active", "enter_time": "2012-03-06 15:15:46.713212", "might_have_unfound": [ { "osd": 1, "status": "osd is down"}]},?
?
本例中,集群知道 osd.1 可能有數據,但它掛了( down )。所有可能的狀態有:
?
已經探測到了在查詢OSD 掛了尚未查詢?
有時候集群要花一些時間來查詢可能的位置。
還有一種可能性,對象存在于其它位置卻未被列出,例如,集群里的一個 ceph-osd 停止且被剔出,然后完全恢復了;后來的失敗、恢復后仍有未找到的對象,它也不會覺得早已死亡的 ceph-osd 上仍可能包含這些對象。(這種情況幾乎不太可能發生)。
如果所有位置都查詢過了仍有對象丟失,那就得放棄丟失的對象了。這仍可能是罕見的失敗組合導致的,集群在寫入完成前,未能得知寫入是否已執行。以下命令把未找到的( unfound )對象標記為丟失( lost )。
?
?
ceph pg 2.5 mark_unfound_lost revert|delete?
上述最后一個參數告訴集群應如何處理丟失的對象。
delete 選項將導致完全刪除它們。
revert 選項(糾刪碼存儲池不可用)會回滾到前一個版本或者(如果它是新對象的話)刪除它。要慎用,它可能迷惑那些期望對象存在的應用程序。
?
?
無根歸置組
擁有歸置組拷貝的 OSD 都可以失敗,在這種情況下,那一部分的對象存儲不可用,監視器就不會收到那些歸置組的狀態更新了。為檢測這種情況,監視器把任何主 OSD 失敗的歸置組標記為 stale (不新鮮),例如:
?
ceph health HEALTH_WARN 24 pgs stale; 3/300 in osds are down?
你能找出哪些歸置組 stale 、和存儲這些歸置組的最新 OSD ,命令如下:
?
ceph health detail HEALTH_WARN 24 pgs stale; 3/300 in osds are down ... pg 2.5 is stuck stale+active+remapped, last acting [2,0] ... osd.10 is down since epoch 23, last address 192.168.106.220:6800/11080 osd.11 is down since epoch 13, last address 192.168.106.220:6803/11539 osd.12 is down since epoch 24, last address 192.168.106.220:6806/11861?
如果想使歸置組 2.5 重新在線,例如,上面的輸出告訴我們它最后由 osd.0 和 osd.2 處理,重啟這些 ceph-osd 將恢復之(還有其它的很多 PG )。
?
只有幾個 OSD 接收數據
如果你的集群有很多節點,但只有其中幾個接收數據,檢查下存儲池里的歸置組數量。因為歸置組是映射到多個 OSD 的,這樣少量的歸置組將不能分布于整個集群。試著創建個新存儲池,其歸置組數量是 OSD 數量的若干倍。詳情見歸置組,存儲池的默認歸置組數量沒多大用,你可以參考這里更改它。
不能寫入數據
如果你的集群已啟動,但一些 OSD 沒起來,導致不能寫入數據,確認下運行的 OSD 數量滿足歸置組要求的最低 OSD 數。如果不能滿足, Ceph 就不會允許你寫入數據,因為 Ceph 不能保證復制能如愿進行。詳情參見存儲池、歸置組和 CRUSH 配置參考里的 osd pool default min size 。
歸置組不一致
如果您收到一個active + clean + inconsistent的狀態, 這可能發生由于在洗滌過程中的錯誤。如果不一致的原因是磁盤錯誤, 請檢查磁盤。
?
您可以通過執行以下操作來修復不一致的放置組:
ceph pg repair {placement-group-ID}?
如果由于時鐘歪斜而周期性地收到active + clean + inconsistent的狀態, 您可以考慮在監視器主機上配置您的 NTP 守護程序,
?
糾刪編碼的歸置組不是 active+clean
CRUSH 找不到足夠多的 OSD 映射到某個 PG 時,它會顯示為 2147483647 ,意思是 ITEM_NONE 或 no OSD found ,例如:
[2,1,6,0,5,8,2147483647,7,4]?
OSD 不夠多
?
如果 Ceph 集群僅有 8 個 OSD ,但是糾刪碼存儲池需要 9 個,就會顯示上面的錯誤。這時候,你仍然可以另外創建需要較少 OSD 的糾刪碼存儲池:
ceph osd erasure-code-profile set myprofile k=5 m=3 ceph osd pool create erasurepool 16 16 erasure myprofile?
或者新增一個 OSD ,這個 PG 會自動用上的。
?
CRUSH 條件不能滿足
即使集群擁有足夠多的 OSD , CRUSH 規則集的強制要求仍有可能無法滿足。假如有 10 個 OSD 分布于兩個主機上,且 CRUSH 規則集要求相同歸置組不得使用位于同一主機的兩個 OSD ,這樣映射就會失敗,因為只能找到兩個 OSD ,你可以從規則集里查看必要條件:
?
$ ceph osd crush rule ls ["replicated_ruleset","erasurepool"] $ ceph osd crush rule dump erasurepool { "rule_id": 1,"rule_name": "erasurepool","ruleset": 1,"type": 3,"min_size": 3,"max_size": 20,"steps": [{ "op": "take","item": -1,"item_name": "default"},{ "op": "chooseleaf_indep","num": 0,"type": "host"},{ "op": "emit"}]}?
可以這樣解決此問題,創建新存儲池,其內的 PG 允許多個 OSD 位于同一主機,命令如下:
?
ceph osd erasure-code-profile set myprofile ruleset-failure-domain=osd ceph osd pool create erasurepool 16 16 erasure myprofile?
CRUSH 過早中止
假設集群擁有的 OSD 足以映射到 PG (比如有 9 個 OSD 和一個糾刪碼存儲池的集群,每個 PG 需要 9 個 OSD ), CRUSH 仍然有可能在找到映射前就中止了。可以這樣解決:
降低糾刪存儲池內 PG 的要求,讓它使用較少的 OSD (需創建另一個存儲池,因為糾刪碼配置不支持動態修改)。向集群添加更多 OSD (無需修改糾刪存儲池,它會自動回到清潔狀態)。通過手工打造的 CRUSH 規則集,讓它多試幾次以找到合適的映射。把 set_choose_tries 設置得高于默認值即可。?
你從集群中提取出 crushmap 之后,應該先用 crushtool 校驗一下是否有問題,這樣你的試驗就無需觸及 Ceph 集群,只要在一個本地文件上測試即可:
?
$ ceph osd crush rule dump erasurepool { "rule_name": "erasurepool","ruleset": 1,"type": 3,"min_size": 3,"max_size": 20,"steps": [{ "op": "take","item": -1,"item_name": "default"},{ "op": "chooseleaf_indep","num": 0,"type": "host"},{ "op": "emit"}]} $ ceph osd getcrushmap > crush.map got crush map from osdmap epoch 13 $ crushtool -i crush.map --test --show-bad-mappings \--rule 1 \--num-rep 9 \--min-x 1 --max-x $((1024 * 1024)) bad mapping rule 8 x 43 num_rep 9 result [3,2,7,1,2147483647,8,5,6,0] bad mapping rule 8 x 79 num_rep 9 result [6,0,2,1,4,7,2147483647,5,8] bad mapping rule 8 x 173 num_rep 9 result [0,4,6,8,2,1,3,7,2147483647]?
?
其中 --num-rep 是糾刪碼 crush 規則集所需的 OSD 數量, --rule 是 ceph osd crush rule dump 命令結果中 ruleset 字段的值。此測試會嘗試映射一百萬個值(即 [--min-x,--max-x] 所指定的范圍),且必須至少顯示一個壞映射;如果它沒有任何輸出,說明所有映射都成功了,你可以就此打住:問題的根源不在這里。
反編譯 crush 圖后,你可以手動編輯其規則集:
?
$ crushtool --decompile crush.map > crush.txt?
?
并把下面這行加進規則集:
step set_choose_tries 100?
然后 crush.txt 文件內的這部分大致如此:
rule erasurepool {ruleset 1type erasuremin_size 3max_size 20step set_chooseleaf_tries 5step set_choose_tries 100step take defaultstep chooseleaf indep 0 type hoststep emit }?
然后編譯、并再次測試:
$ crushtool --compile crush.txt -o better-crush.map?
所有映射都成功時,用 crushtool 的 --show-choose-tries 選項能看到成功映射的嘗試次數直方圖:
$ crushtool -i better-crush.map --test --show-bad-mappings \--show-choose-tries \--rule 1 \--num-rep 9 \--min-x 1 --max-x $((1024 * 1024)) ... 11: 42 12: 44 13: 54 14: 45 15: 35 16: 34 17: 30 18: 25 19: 19 20: 22 21: 20 22: 17 23: 13 24: 16 25: 13 26: 11 27: 11 28: 13 29: 11 30: 10 31: 6 32: 5 33: 10 34: 3 35: 7 36: 5 37: 2 38: 5 39: 5 40: 2 41: 5 42: 4 43: 1 44: 2 45: 2 46: 3 47: 1 48: 0 ... 102: 0 103: 1 104: 0 ...?
有 42 個歸置組需 11 次重試、 44 個歸置組需 12 次重試,以此類推。這樣,重試的最高次數就是防止壞映射的最低值,也就是 set_choose_tries 的取值(即上面輸出中的 103 ,因為任意歸置組成功映射的重試次數都沒有超過 103 )。
?
轉載于:https://www.cnblogs.com/zhongguiyao/p/7966287.html
總結
以上是生活随笔為你收集整理的Ceph 存储集群7-故障排除的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Delphi东京版FireDAC连接MS
- 下一篇: tensorflow基础-placeho