CephFS 內(nèi)部實現(xiàn)(四):MDS是如何啟動的?

MDS啟動時要經(jīng)歷一系列狀態(tài)裝換,但mds的各個狀態(tài)是如何產(chǎn)生、確定的?這些狀態(tài)究竟在處理什么?本篇嘗試以正常啟動mds為背景解釋這兩個問題。

MDS和Monitor的交互

為提供FS服務,首先要ceph fs new命令創(chuàng)建filesystem,然后再啟動mds進程。
其中ceph fs new命令由MDSMonitor組件處理,將一個文件系統(tǒng)信息(底層pool是哪些,一些feature等)寫入monitor store,此時文件系統(tǒng)是沒有關(guān)聯(lián)mds的,所以是不可用的。
mds進程啟動后,通過向MDSMonitor發(fā)送Beacon消息,并接收從MDSMonitor返回的MDSMap消息逐步啟動自己。Beacon除了用于告知monitor關(guān)于mds的健康狀態(tài),還有want_state這一信息。want_state的值是在mds啟動或者收到MDSMap后由mds自己決定的(如向resolve、reconnect、rejoin等轉(zhuǎn)換)。
MDSMonitor接收mds發(fā)來的Beacon消息,更新pending_fsmap,寫入store。MDSMonitor::tick()在每次寫完store后被調(diào)用,對pending_fsmap進行遍歷,嘗試給fsmap關(guān)聯(lián)mds,然后更新pending_fsmap,再次寫入store,完成后向mds發(fā)送MDSMap。關(guān)聯(lián)到fsmap的mds分兩類:一類是具有rank的,最終mds daemon會進入到STATE_ACTIVE狀態(tài),其中rank值由MDSMonitor分配;另一類是STATE_STANDBY_REPLAY,每個fsmap最多有一個,沒有rank值。關(guān)聯(lián)動作是通過遍歷已創(chuàng)建fs map(如果創(chuàng)建了多個filesystem,那么此處就會有多個fs map),尋找可用的處于STATE_STANDBY狀態(tài)的mds實現(xiàn)的,具體在MDSMonitor::maybe_expand_cluster()
在眾多mds狀態(tài)中,由MDSMonitor路徑負責的狀態(tài)轉(zhuǎn)換只有一部分,所以在MDSMonitor的代碼里不會看到全部mds狀態(tài)。其他狀態(tài)轉(zhuǎn)換是在mds端做的決策,此時monitor只是作為一個記錄者,負責將狀態(tài)寫入store中。

mds_start.png

MDS 狀態(tài)

Monitor關(guān)于mds狀態(tài)的處理

MDSMonitor每次寫完store后都會由MDSMonitor::tick()做三件事:

  • 查看是否有filesystem需要關(guān)聯(lián)mds
  • 查看是否有非健康的mds
  • 查看是否需要將mds從STATE_STANDBY變成STATE_STANDBY_REPALY
    后兩個相對簡單些,這里就不再詳述。對于第一個給filesystem關(guān)聯(lián)mds,是由MDSMonitor::maybe_expand_cluster()完成。
    MDSMonitor計算mds狀態(tài)

在正常啟動階段,MDSMonitor代碼,已經(jīng)MDSMonitor調(diào)用的FSMap::promote中主要使用了以下狀態(tài):

  • STATE_STANDBY :收到BOOT beacon時直接設置mds為此狀態(tài),表明空閑可用
  • STATE_STANDBY_REPLAY
  • STATE_CREATING:全新的rank,表明mds需要準備journal對象等元數(shù)據(jù),由于沒有歷史包袱,所以這里不需要load元數(shù)據(jù)或者replay日志之類的操作
  • STATE_STARING:停止的rank,不需要創(chuàng)建journal等元數(shù)據(jù),但需要load元數(shù)據(jù)
  • STATE_REPLAY

對于resolve等狀態(tài)MDSMonitor是不涉及的,這些是在MDS端處理。

mds側(cè)關(guān)于mds狀態(tài)的處理

MDS在啟動時設置自己狀態(tài)為STATE_BOOT,并通過beacon發(fā)送給MDSMonitor。后續(xù)將通過接收到的MDSMap來進一步?jīng)Q定自己的狀態(tài)。

mds狀態(tài)變化

MDS_BOOT_xxx對應MDSRank::boot_start()中的步驟,每個步驟作用:

  • MDS_BOOT_INITIAL:從rados中讀取并初始化inodetable,sessionmap,log等信息。

  • MDS_BOOT_OPEN_ROOT:初始化目錄樹的根目錄(包括mdsdir和rootdir)

  • MDS_BOOT_PREPARE_LOG:設置log的參數(shù),如果mds處于replay,則會在此進行l(wèi)og-replay

  • MDS_BOOT_REPLAY_DONE:log replay已完成,進行一些清理工作,準備進入下一個階段(對于standby_replay不會再改變狀態(tài))

  • STATE_RESOLVE:處理slave updates和subtree auth。
    slave update是在多active MDS下,且op需要跨越兩個或以上mds時才會產(chǎn)生。如對一個普通文件創(chuàng)建硬鏈接,目標和源在不同dir下,且兩個dir被pin在不同mds時,就會產(chǎn)生slave op。
    這一階段要做的另外一件事是處理migrator進行到一半的import/export,進行到一半的import/export dir auth是無法確定的,需要在resolve階段進行確定。slave op處理完后mds會互發(fā)subtree信息,這一步中存活的mds會根據(jù)從resolve狀態(tài)的mds接收到的對subtree的聲明來進行import_reverseimport_finish最終將subtree的auth確定下來。

  • STATE_RECONNECT:遍歷sessionmap中的clients,等待client重新建立連接,超時后自動進入下一狀態(tài)。這一步client可能會將自己對inode已擁有的cap進行聲明,如果這些cap有誤,可能是inode auth已經(jīng)改變或者cache中沒有inode,對于前者當前mds將inode記錄到MDCache::cap_exports,表明會在下一階段export到auth mds,對于第二種情況,則將inode記錄到MDCache::cap_imports表明會在下一階段對inode進行查找。

  • STATE_REJOIN
    這一階段要處理的事情有:

    • rejoin mds通過MDCache::process_imported_caps查找導入的cap對應的inode。首先遍歷mds,如果沒有找到則從rados讀取
    • rejoin mds對需要export的inode進行處理
    • 處理元數(shù)據(jù)。對于rejoin mds,replay并不能重建全部元數(shù)據(jù)信息,且由于subtree map只存在于每個LogSegment開頭,所以replay后產(chǎn)生的subtree 信息也可能是過時的,這時如果其他節(jié)點有相應的元數(shù)據(jù),則需要在rejoin階段進行處理。rejoin mds需要確保其他 mds宣稱自己應該擁有的auth元數(shù)據(jù)已經(jīng)正確初始化,對于自己擁有的非auth元數(shù)據(jù),要和其他mds保持一致。這些一致主要體現(xiàn)在鎖和目錄樹結(jié)構(gòu)上。rejoin mds缺少的auth元數(shù)據(jù)最后需要從rados讀取。
  • STATE_CLIENT_REPLAY mds啟動階段block的op在此階段繼續(xù)處理

  • STATE_ACTIVE mds啟動成功

其他狀態(tài)

除了以上狀態(tài)外,還有stop、dne等狀態(tài),本文沒有涉及。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容