1. 程式人生 > >深入理解ceph-disk運行機制

深入理解ceph-disk運行機制

意圖 gui for ons 簡單介紹 water 自動化 深入理解 /var/

谷忠言

一,背景

目前項目所用的ceph集群內部的一個節點, 一般需要管理大約十塊硬盤左右的數據存儲空間,外加一到兩塊ssd組成的journal空間。Ceph要求每個osd對應的數據盤掛載到特定的目錄,對應的ssd的journal分區也不能加載錯,否則osd 無法啟動。

目前對於數據盤的掛載采用的是基於/etc/fstab的方式。

技術分享

上圖是某個節點的/etc/fstab的實例。/dev/slot* 是一個由diskctl_init.sh 腳本產生的從/dev/slot* 到/dev/sdx的映射。如下圖所示。

技術分享

Diskctl_init.sh的原理是生成的slot 與主板物理槽位磁盤接口形成固定映射,這樣當盤符漂移的時候,/dev/slot* 始終對應物理槽位的磁盤。只要磁盤不插拔更換物理槽位,osd 就能加載正確的數據盤。

而對於ssd journal分區,則是直接采用的journalà盤符的裸映射。

存在的問題:

1. Ssd journal分區的盤符裸映射, 有時候會導致機器重啟,ceph服務起不來。測試發現,正是由於盤符漂移,裸映射成為死鏈。

2. Diskctl_init.sh 生成的slot 映射, 據同事反映,也可能有潛在的問題。具體細節不詳。

二,調研ceph-disk

Ceph-disk 是官方發布的一個用於部署osd 數據及journal分區或目錄的工具。基於python.安裝ceph rpm包將默認安裝此工具,安裝目錄是/usr/sbin/ceph-disk。由於此工具涉及數據盤及journal盤的分區。需要root權限。

ceph-disk 是如何工作的?

通過ceph-disk 部署osd, 數據分區和journal 分區將自動掛載到正確的目錄,機器重啟也能保證工作。通過ceph-disk部署osd, 將大大提高ceph部署運維的自動化程度,並降低操作出錯幾率。

以新創建OSD為例,描述ceph-disk的工作機制。

分為兩大步驟:prepare disk 和activate disk

假設/dev/sdg是OSD要使用的數據盤, /dev/sdk 是SSD, OSD要使用的journal分區在這裏創建。則創建OSD 並上線的命令如下:

Ceph-disk prepare /dev/sdg /dev/sdk

Ceph-disk activate /dev/sdg1

下面詳細深入其過程。

1. 準備journal分區。

Prepare_journal_dev()調用分區工具sgdisk從/dev/sdk上劃分一塊journal分區。

有以下註意要點:

a. 在調用sgdisk之前,prepare_journal_dev()會獲取ceph.conf文件中指定的osd_journal_size大小,我們的ceph.conf指定大小如下:

技術分享

b. 實際部署環境中,由於作為journal的ssd分區並不需要很大空間,所以一個ssd很可能被多個osd共享來劃分各自的journal分區,我們的環境是,一個300G的ssd 劃分成5個(甚至更多的)20G的分區,掛載成5個osd的journal.

c. Ceph-disk 在部署journal分區的時候,能自動偵測SSD盤已有分區數,不破壞已有分區,分配不沖突的新分區號來創建分區。

d. 如果不指定創建分區的uuid,ceph-disk會自動為journal分區生成一個,稱之為journal_uuid.

e. 在調用sgdisk的時候,還有一個重要的參數,--typecode. Ceph-disk 使用一個特殊的UUID 作為創建journal的typecode:

技術分享

至於為何用此特殊UUID做typecode, 基本上此UUID可作為辨識分區為ceph journal的憑證,稍後深入解釋。

至此,prepare_journal_dev()已經準備好了sgdisk所需的各個參數,下面給出一個實際發生的參數例子:

/usr/sbin/sgdisk --new=6:0:+20480M--change-name="6:ceph journal" --partition-guid=6:c6422c03-d320-4633-b35d-4f43c6cdd9fa--typecode=6:45b0969e-9b03-4f30-b4c6-b4b80ceff106 --mbrtogpt -- /dev/sdk

2. 在目錄/dev/disk/by-partuuid/下為此journal分區創建link:

技術分享

簡單介紹一下這個link如何產生的。

在調用sgdisk 創建完journal分區後,ceph-disk 調用partx更新分區表,會觸發一個塊設備/分區udev event並通知到內核。Ceph編寫了udev規則文件如下:

技術分享

Udev daemon在收到由partx產生的udev event後,根據以上的ceph規則文件,將調用/usr/sbin/ceph-disk-udev腳本。正是在這個腳本裏,在目錄/dev/disk/by-partuuid/下為此journal分區創建了link。此腳本還有另外一個掃描OSD專屬分區的功能,後文會提及。暫時不表。

這個link有什麽用?

由於這個link是根據partition uuid生成的,可以把它看成是到特定journal分區的固定映射。後文會指出osd的journal將映射到此link:

技術分享

由此圖看出,位於osd 數據分區裏的journal是一個link,指向一個固定的位置:/dev/disk/by-partuuid/c6422c03-d320-4633-b35d-4f43c6cdd9fa, 再由這個link指向真正的journal分區,由此解決的盤符漂移帶來的問題。下文介紹的osd 數據分區的link也是基於此原理。

3. 準備OSD數據分區。

這個過程跟準備journal分區大體一樣。區別在於:

a. 調用sgdisk 使用—largest-new來使用磁盤最大可能空間。所以/dev/sdg會有一個分區sdg1,它使用所有的空間。

b. 格式化/dev/sdg1。這裏對ceph-disk做了小的定制,默認使用了ext4分區格式。

c. 將此分區mount到一個臨時的目錄,然後再其中創建一個名為journal的link,指向/dev/disk/by-partuuid/c6422c03-d320-4633-b35d-4f43c6cdd9fa。至此,OSD的journal分區映射完成。最後umount。

d. 再次調用sgdisk,寫入一個重要的參數,--typecode. Ceph-disk 使用一個特殊的UUID 作為創建OSD的typecode:

技術分享

同JOURNAL_UUID, 為何用此特殊UUID做typecode, 是因為此UUID可作為辨識分區為ceph OSD數據分區的憑證,稍後深入解釋。

4. 在目錄/dev/disk/by-partuuid/下為此OSD 數據分區創建link。

過程同journal的link創建過程。

5. Activate過程。

Activate的命令是 ceph-disk activate /dev/sdg1。

但其實並不需要顯式的調用這個命令。原因是,準備好OSD 數據分區後,udev event 觸發了ceph-disk-udev。而ceph-disk-udev會自動調用ceph-disk activate /dev/sdg1。

下面介紹這個過程是如何自動化的。詳情參見ceph-disk-udev腳本。

新的OSD 數據分區的生成,觸發udev event, 通過ceph udev rule,最終調用ceph-disk-udev,分析該分區的typecode,發現是OSD_UUID,即表明是ceph OSD的數據分區,於是觸發ceph-disk activate /dev/sdg1:

技術分享

Typecode 為JOURNAL_UUID的情況也一樣,只不過是通過ceph-disk activate-journal 來啟動OSD.

在介紹ceph-disk activate /dev/sdg1的具體流程。

a. 將/dev/sdg1 掛載至臨時目錄,一般為var/lib/ceph/tmp/mnt.xxx

b. 分配OSD id,及調用ceph osd create 產生 osd id

c. 初始化OSD, 如ceph-osd –mkfs –osd-data –osd-journal

d. 根據osd id 重新掛載到最終目錄: var/lib/{cluster}/osd/ceph-{osd.id}

e. Service ceph start osd

對於osd id 已經存在,重啟osd的case,也會用到ceph-disk activate,這種情況稍有不同,不需要產生新的osd id,只需要將/dev/sdg1掛載至臨時目錄,獲取osd id後,重新掛載到最終目錄。

Ceph-disk 支持的其他命令如下:

prepare Prepare a directory or disk for aCeph OSD

activate Activate a Ceph OSD

activate-journal Activate an OSD via its journal device

activate-all Activate all tagged OSD partitions

list List disks, partitions, and CephOSDs

suppress-activate Suppress activate on a device (prefix)

unsuppress-activate

Stop suppressingactivate on a device (prefix)

zap Zap/erase/destroy a device‘spartition table (and

contents)

特別強調幾點:

a. Suppress的字面意思就是抑制,用在這裏的意圖主要是,如果只想prepare各個分區,暫時不想activate OSD(創建osd 上線),可以使用此命令,等到所有的分區都prepare好了,unsuppress 一把,再activate-all.

b. Activate-journal 是通過制定journal 分區來啟動osd, 如:ceph-diskactivate-journal /dev/sdk6. Ceph-disk 執行的流程為:

通過 ceph-osd -i 0 --get-journal-uuid --osd-journal /dev/sdk6 返回osd_uuid. 有了osd_uuid,就能找到osd 數據分區了,即定位/dev/disk/by-partuuid/$osd_uuid,這樣就回到了使用osd 數據分區來activate的命令邏輯,即ceph-disk activate /dev/sdg1。

這裏要解釋 為什麽是ceph-osd-i 0?在此條命令中, -i 後面可以跟任何一個整數,在get-journal-uuid中會被忽略。但問題是,不加-i, ceph-osd格式檢查就會報錯。

還有就是—get-journal-uuid,字面意思好像是獲取journal分區的uuid,但實際上返回的一個叫journal.header 結構體裏的fsid. 此fsid的值就是 osd 數據分區的uuid. 所以命令ceph-osd -i 0 --get-journal-uuid --osd-journal /dev/sdk6 返回值是osd_uuid。不得不抱怨一把,這個命令太容易讓人產生混亂。理清邏輯是從源碼中分析得來的。從這個小問題可以看出開源軟件比起商業軟件,細處略顯粗糙,還需精細打磨。

c. 如果prepare不顯式指定 journal, 如 ceph-disk prepare /dev/sdg, 則處理邏輯為:

在sdg上劃出兩個分區,sdg2 為20G的journal分區,sdg1為剩下空間大小的osd 數據分區。

註意事項

Ceph-disk的定制:

1. default fstype ext4

2. keyring的問題,由於目前的ceph部署沒有enablekeyring,所以屏蔽了相關代碼。

ceph-disk –v將打印更詳細的log, 如果想深入理解ceph-disk命令的運行過程,此參數非常有效。

權限問題:

chmod -R 777/home/ceph/software/ceph/var/lib/ceph/osd/ceph-*

刪除OSD產生的死鏈問題。

深入理解ceph-disk運行機制