天天看點

ceph分布式存儲-管理crushmap1. 介紹2. 編輯 CRUSH Map3. CRUSH Map 參數5. 增加/移動 OSD6. 調整 OSD 的 CRUSH 權重7. 删除 OSD8. 增加桶9. 移動桶10. 删除桶11. 可調選項

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;
  2. 反編譯 CRUSH 圖;
  3. 至少編輯一個裝置、桶、規則;
  4. 重編譯 CRUSH Map;
  5. 注入 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 都應該有一個裝置。
  2. 桶類型: 定義了 CRUSH 分級結構裡要用的桶類型(

    types

    ),桶由逐級彙聚的存儲位置(如行、機櫃、機箱、主機等等)及其權重組成。
  3. 桶執行個體: 定義了桶類型後,還必須聲明主機的桶類型、以及規劃的其它故障域。
  4. 規則: 由選擇桶的方法組成。

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
    }           

複制

調整桶的權重

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

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

3.4 CRUSH Map 之規則

CRUSH Map 支援“ CRUSH 規則”的概念,用以确定一個存儲池裡資料的分布。CRUSH 規則定義了歸置和複制政策、或分布政策,用它可以規定 CRUSH 如何放置對象副本。對大型叢集來說,你可能建立很多存儲池,且每個存儲池都有它自己的 CRUSH 規則集和規則。預設的 CRUSH Map 裡,每個存儲池有一條規則、一個規則集被配置設定到每個預設存儲池。

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

規則格式如下:

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

,其中

意為此 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           

複制

5.7 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 ,普通硬碟作副本。