CrushMap介紹

1. 介紹


CRUSH 算法通過計算數據存儲位置來確定如何存儲和檢索。 CRUSH 授權 Ceph 客戶端直接連接 OSD ,而非通過一箇中央服務器或代理。數據存儲、檢索算法的使用,使 Ceph 避免了單點故障、性能瓶頸、和伸縮的物理限制。

CRUSH 需要一張集羣的 Map,且使用 CRUSH Map 把數據僞隨機地、儘量平均地分佈到整個集羣的 OSD 裏。CRUSH Map 包含 OSD 列表、把設備匯聚爲物理位置的“桶”列表、和指示 CRUSH 如何複製存儲池裏的數據的規則列表。

完全手動管理 CRUSH Map 也是可能的,在配置文件中設定:

osd crush update on start = false

2. 編輯 CRUSH Map

要編輯現有的 CRUSH Map:

  1. 獲取 CRUSH Map;

  1. 反編譯 CRUSH 圖;

  1. 至少編輯一個設備、桶、規則;

  1. 重編譯 CRUSH Map;

  1. 注入 CRUSH Map。

要激活 CRUSH Map 裏某存儲池的規則,找到通用規則集編號,然後把它指定到那個規則集。

2.1 獲取 CRUSH Map

要獲取集羣的 CRUSH Map,執行命令:

ceph osd getcrushmap -o {compiled-crushmap-filename}

Ceph 將把 CRUSH 輸出( -o )到你指定的文件,由於 CRUSH Map 是已編譯的,所以編輯前必須先反編譯。

2.2 反編譯 CRUSH Map

要反編譯 CRUSH Map,執行命令:

crushtool -d {compiled-crushmap-filename} -o {decompiled-crushmap-filename}

Ceph 將反編譯( -d )二進制 CRUSH Map,且輸出( -o )到你指定的文件。

2.3 編譯 CRUSH Map

要編譯 CRUSH Map,執行命令:

crushtool -c {decompiled-crush-map-filename} -o {compiled-crush-map-filename}

Ceph 將把已編譯的 CRUSH Map 保存到你指定的文件。

2.4 注入 CRUSH Map

要把 CRUSH Map 應用到集羣,執行命令:

ceph osd setcrushmap -i  {compiled-crushmap-filename}

Ceph 將把你指定的已編譯 CRUSH Map 注入到集羣。

3. CRUSH Map 參數

CRUSH Map 主要有 4 個段落。

  1. 設備: 由任意對象存儲設備組成,即對應一個 ceph-osd進程的存儲器。 Ceph 配置文件裏的每個 OSD 都應該有一個設備。

  1. 桶類型: 定義了 CRUSH 分級結構裏要用的桶類型( types ),桶由逐級匯聚的存儲位置(如行、機櫃、機箱、主機等等)及其權重組成。

  1. 桶實例: 定義了桶類型後,還必須聲明主機的桶類型、以及規劃的其它故障域。

  1. 規則: 由選擇桶的方法組成。

3.1 CRUSH Map 之設備

爲把 PG 映射到 OSD , CRUSH Map 需要 OSD 列表(即配置文件所定義的 OSD 守護進程名稱),所以它們首先出現在 CRUSH Map 裏。要在 CRUSH Map 裏聲明一個設備,在設備列表後面新建一行,輸入 device 、之後是唯一的數字 ID 、之後是相應的 ceph-osd 守護進程實例名字。

# devices

device {num} {osd.name}

例如:

# devices

device 0 osd.0

device 1 osd.1

device 2 osd.2

device 3 osd.3

3.2 CRUSH Map 之桶類型

CRUSH Map 裏的第二個列表定義了 bucket (桶)類型,桶簡化了節點和葉子層次。節點(或非葉子)桶在分級結構裏一般表示物理位置,節點匯聚了其它節點或葉子,葉桶表示 ceph-osd 守護進程及其對應的存儲媒體。

要往 CRUSH Map 中增加一種 bucket 類型,在現有桶類型列表下方新增一行,輸入 type 、之後是惟一數字 ID 和一個桶名。按慣例,會有一個葉子桶爲 type 0 ,然而你可以指定任何名字(如 osd 、 disk 、 drive 、 storage 等等):

# types

type {num} {bucket-name}

例如:

# types

type 0 osd

type 1 host

type 2 chassis

type 3 rack

type 4 row

type 5 pdu

type 6 pod

type 7 room

type 8 datacenter

type 9 region

type 10 root

3.3 CRUSH Map 之桶層次

CRUSH 算法根據各設備的權重、大致統一的概率把數據對象分佈到存儲設備中。 CRUSH 根據你定義的集羣運行圖分佈對象及其副本, CRUSH Map 表達了可用存儲設備以及包含它們的邏輯單元。

要把 PG 映射到跨故障域的 OSD ,一個 CRUSH Map 需定義一系列分級桶類型(即現有 CRUSH Map 的 # type 下)。創建桶分級結構的目的是按故障域隔離葉子節點,像主機、機箱、機櫃、電力分配單元、機羣、行、房間、和數據中心。除了表示葉子節點的 OSD ,其它分級結構都是任意的,你可以按需定義。

聲明一個桶實例時,你必須指定其類型、惟一名稱(字符串)、惟一負整數 ID (可選)、指定和各條目總容量/能力相關的權重、指定桶算法(通常是 straw )、和哈希(通常爲 0 ,表示哈希算法 rjenkins1 )。一個桶可以包含一到多個條目,這些條目可以由節點桶或葉子組成,它們可以有個權重用來反映條目的相對權重。

你可以按下列語法聲明一個節點桶:

[bucket-type] [bucket-name] {

           id [a unique negative numeric ID]

           weight [the relative capacity/capability of the item(s)]

           alg [the bucket type: uniform | list | tree | straw ]

           hash [the hash type: 0 by default]

           item [item-name] weight [weight]

   }

例如,我們可以定義兩個主機桶和一個機櫃桶,機櫃桶包含兩個主機桶, OSD 被聲明爲主機桶內的條目:

host node1 {

           id -1

           alg straw

           hash 0

           item osd.0 weight 1.00

           item osd.1 weight 1.00

   }


   host node2 {

           id -2

           alg straw

           hash 0

           item osd.2 weight 1.00

           item osd.3 weight 1.00

   }


   rack rack1 {

           id -3

           alg straw

           hash 0

           item node1 weight 2.00

           item node2 weight 2.00

   }

3.4 CRUSHMap 之調整桶的權重

Ceph 用雙精度類型數據表示桶權重。權重和設備容量不同,我們建議用 1.00 作爲 1TB 存儲設備的相對權重,這樣 0.5 的權重大概代表 500GB 、 3.00 大概代表 3TB 。較高級桶的權重是所有葉子桶的權重之和。

一個桶的權重是一維的,你也可以計算條目權重來反映存儲設備性能。例如,如果你有很多 1TB 的硬盤,其中一些數據傳輸速率相對低、其他的數據傳輸率相對高,即使它們容量相同,也應該設置不同的權重(如給吞吐量較低的硬盤設置權重 0.8 ,較高的設置 1.20 )。

3.5 CRUSH Map 之規則

CRUSH Map 支持“ CRUSH 規則”的概念,用以確定一個存儲池裏數據的分佈。CRUSH 規則定義了歸置和複製策略、或分佈策略,用它可以規定 CRUSH 如何放置對象副本。對大型集羣來說,你可能創建很多存儲池,且每個存儲池都有它自己的 CRUSH 規則集和規則。默認的 CRUSH Map 裏,每個存儲池有一條規則、一個規則集被分配到每個默認存儲池。

注意: 大多數情況下,你都不需要修改默認規則。新創建存儲池的默認規則集是 0 。

規則格式如下:

rule <rulename> {


           ruleset <ruleset>

           type [ replicated | erasure ]

           min_size <min-size>

           max_size <max-size>

           step take <bucket-type>

           step [choose|chooseleaf] [firstn|indep] <N> <bucket-type>

           step emit

   }

參數說明:

ruleset:區分一條規則屬於某個規則集的手段。給存儲池設置規則集後激活。

type:規則類型,目前僅支持 replicated 和 erasure ,默認是 replicated 。

min_size:可以選擇此規則的存儲池最小副本數。

max_size:可以選擇此規則的存儲池最大副本數。

step take <bucket-name>:選取起始的桶名,並迭代到樹底。

step choose firstn {num} type {bucket-type}:選取指定類型桶的數量,這個數字通常是存儲池的副本數(即 pool size )。如果 {num} == 0 , 選擇 pool-num-replicas 個桶(所有可用的);如果 {num} > 0 && < pool-num-replicas ,就選擇那麼多的桶;如果 {num} < 0,它意味着選擇 pool-num-replicas - {num} 個桶。

step chooseleaf firstn {num} type {bucket-type}:選擇 {bucket-type} 類型的桶集合,並從各桶的子樹裏選擇一個葉子節點。桶集合的數量通常是存儲池的副本數(即 pool size )。如果 {num} == 0 ,選擇 pool-num-replicas 個桶(所有可用的);如果 {num} > 0 && < pool-num-replicas ,就選擇那麼多的桶;如果 {num} < 0 ,它意味着選擇 pool-num-replicas - {num} 個桶。

step emit:輸出當前值並清空堆棧。通常用於規則末尾,也適用於相同規則應用到不同樹的情況。

4. 主親和性

某個 Ceph 客戶端讀寫數據時,總是連接 acting set 裏的主 OSD (如 [2, 3, 4] 中, osd.2 是主的)。有時候某個 OSD 與其它的相比並不適合做主 OSD (比如其硬盤慢、或控制器慢)。最大化硬件利用率時爲防止性能瓶頸(特別是讀操作),你可以調整 OSD 的主親和性,這樣 CRUSH 就儘量不把它用作 acting set 裏的主 OSD 了。

ceph osd primary-affinity <osd-id> <weight>

主親和性默認爲 1 (就是說此 OSD 可作爲主 OSD )。此值合法範圍爲 0-1 ,其中 0 意爲此 OSD 不能用作主的, 1 意爲 OSD 可用作主的。此權重 < 1 時, CRUSH 選擇主 OSD 時選中它的可能性就較低。

5. 增加/移動 OSD

要增加或移動在線集羣裏 OSD 所對應的 CRUSH Map 條目,執行 ceph osd crush set 命令。

ceph osd crush set {id-or-name} {weight} {bucket-type}={bucket-name} [{bucket-type}={bucket-name} ...]

6. 調整 OSD 的 CRUSH 權重

要調整在線集羣中某個 OSD 的 CRUSH 權重,執行命令:

ceph osd crush reweight {name} {weight}

7. 刪除 OSD

要從在線集羣裏把某個 OSD 徹底踢出 CRUSH Map,或僅踢出某個指定位置的 OSD,執行命令:

ceph osd crush remove {name} {<ancestor>}

8. 增加桶

要在運行集羣的 CRUSH Map 中新建一個桶,用 ceph osd crush add-bucket 命令:

ceph osd crush add-bucket {bucket-name} {bucket-type}

9. 移動桶

要把一個桶移動到 CRUSH Map 裏的不同位置,執行命令:

ceph osd crush move {bucket-name} {bucket-type}={bucket-name} [{bucket-type}={bucket-name} ...]

10. 刪除桶

要把一個桶從 CRUSH Map 的分級結構中刪除,可用此命令:

ceph osd crush remove {bucket-name}

注意:從 CRUSH 分級結構裏刪除時必須是空桶。

11. 可調選項

從 v0.74 起,如果 CRUSH 可調選項不是最優值( v0.73 版裏的默認值) Ceph 就會發出健康告警,有兩種方法可消除這些告警:

1、調整現有集羣上的可調選項。注意,這可能會導致一些數據遷移(可能有 10% 之多)。這是推薦的辦法,但是在生產集羣上要注意此調整對性能帶來的影響。此命令可啓用較優可調選項:

ceph osd crush tunables optimal

如果切換得不太順利(如負載太高)且切換纔不久,或者有客戶端兼容問題(較老的 cephfs 內核驅動或 rbd 客戶端、或早於 bobtail 的 librados 客戶端),你可以這樣切回:

ceph osd crush tunables legacy

2、不對 CRUSH 做任何更改也能消除報警,把下列配置加入 ceph.conf 的 [mon] 段下:

mon warn on legacy crush tunables = false

爲使變更生效需重啓所有監視器,或者執行下列命令:

ceph tell mon.\* injectargs --no-mon-warn-on-legacy-crush-tunables

12.CRUSH Map 實例

假設你想讓大多數存儲池映射到使用大容量硬盤的 OSD 上,但是其中一些存儲池映射到使用高速 SSD 的 OSD 上。在同一個 CRUSH Map 內有多個獨立的 CRUSH 層級結構是可能的,定義兩棵樹、分別有自己的根節點 —— 一個用於機械硬盤(如 root platter )、一個用於 SSD (如 root ssd ),具體的 CRUSH Map 內容如下:

# devices

   device 0 osd.0

   device 1 osd.1

   device 2 osd.2

   device 3 osd.3

   device 4 osd.4

   device 5 osd.5

   device 6 osd.6

   device 7 osd.7


   # types

   type 0 osd

   type 1 host

   type 2 root


   # buckets

   host ceph-osd-ssd-server-1 {

           id -1

           alg straw

           hash 0

           item osd.0 weight 1.00

           item osd.1 weight 1.00

   }

   

   host ceph-osd-ssd-server-2 {

           id -2

           alg straw

           hash 0

           item osd.2 weight 1.00

           item osd.3 weight 1.00

   }


   host ceph-osd-platter-server-1 {

           id -3

           alg straw

           hash 0

           item osd.4 weight 1.00

           item osd.5 weight 1.00

   }


   host ceph-osd-platter-server-2 {

           id -4

           alg straw

           hash 0

           item osd.6 weight 1.00

           item osd.7 weight 1.00

   }


   root platter {

           id -5

           alg straw

           hash 0

           item ceph-osd-platter-server-1 weight 2.00

           item ceph-osd-platter-server-2 weight 2.00

   }


   root ssd {

           id -6

           alg straw

           hash 0

           item ceph-osd-ssd-server-1 weight 2.00

           item ceph-osd-ssd-server-2 weight 2.00

   }


   # rules

   rule replicated_ruleset {

           ruleset 0

           type replicated

           min_size 1

           max_size 10

           step take default

           step chooseleaf firstn 0 type host

           step emit

   }


   rule platter {

           ruleset 1

           type replicated

           min_size 0

           max_size 10

           step take platter

           step chooseleaf firstn 0 type host

           step emit

   }


   rule ssd {

           ruleset 2

           type replicated

           min_size 0

           max_size 4

           step take ssd

           step chooseleaf firstn 0 type host

           step emit

   }


   rule ssd-primary {

           ruleset 3

           type replicated

           min_size 5

           max_size 10

           step take ssd

           step chooseleaf firstn 1 type host

           step emit

           step take platter

           step chooseleaf firstn -1 type host

           step emit

   }

然後你可以設置一個存儲池,讓它使用 SSD 規則:

ceph osd pool set <poolname> crush_ruleset 2

同樣,用 ssd-primary 規則將使存儲池內的各歸置組用 SSD 作主 OSD ,普通硬盤作副本。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章