飞行的蜗牛

一个正在觉醒的无名氏修行者,略懂编程,略懂音乐。

Ceph-04 Ceph 存储池

存储池介绍

Ceph 对集群中所有存储资源进行池化管理,pool 是一个逻辑上的概念,其表达的是一组数据存储和查找的约束条件。

Ceph 集群刚刚搭建成功之后会有系统内会默认创建一个 RBD 存储池(然而本人测试的 Luminous 版本却发现并没有默认的 RBD)。

Ceph 提供两种类型的存储池,多副本存储池(Replicated Pool) 和 **纠删码存储池(Erasure Code Pool)**。

存储池提供以下功能:

  • 自恢复力: 你可以设置在不丢数据的前提下允许多少 OSD 失效,对多副本存储池来说,此值是一对象应达到的副本数。
    典型配置存储一个对象和它的一个副本(即 size = 2 ), 但你可以更改副本数;
    对纠删编码的存储池来说,此值是编码块数(即纠删码配置里的 m=2 )。
  • 归置组: 你可以设置一个存储池的归置组数量。典型配置给每个 OSD 分配大约 100 个归置组,
    这样,不用过多计算资源就能得到较优的均衡。配置了多个存储池时,要考虑到这些存储池和整个集群的归置组数量要合理。
  • CRUSH 规则: 当你在存储池里存数据的时候,与此存储池相关联的 CRUSH 规则集可控制 CRUSH 算法,
    并以此操纵集群内对象及其副本的复制(或纠删码编码的存储池里的数据块)。你可以自定义存储池的 CRUSH 规则。
  • 快照: 用 ceph osd pool mksnap 创建快照的时候,实际上创建了某一特定存储池的快照。
  • 设置所有者: 你可以设置一个用户 ID 为一个存储池的所有者。

要把数据组织到存储池里,你可以列出、创建、删除存储池,也可以查看每个存储池的利用率。

环境说明

  • 操作系统: Ubuntu 18.04 LTS
  • Ceph 版本: 12.2.12 Luminous (stable)
  • 节点架构: 1 mon, 1 mgr, 3 osd

多副本存储池

所谓多副本存储池,就是把所有的对象都存多个副本,Ceph 默认的副本配置是 size = 3, 也就是说数据存三份,2 个副本。但是一般典型的配置
都会把 size 重置为 2,节省空间。

查看存储池列表

1
2
3
4
5
6
7
root@ceph1:~# ceph osd lspools
1 rbd,2 cephfs_data,3 cephfs_metadata,

root@ceph1:~# rados lspools
rbd
cephfs_data
cephfs_metadata

查看详细的存储池信息:

1
ceph osd pool ls detail 

在新安装好的集群上,只有一个 rbd 存储池。

创建存储池

创建存储池前先看看 存储池、归置组和 CRUSH 配置参考
你最好在配置文件里重置默认归置组数量,因为默认值并不理想。关于归置组数量请参考
设置归置组数量

修改默认归置组数量,只需要在 ceph.conf 文件的 [osd] 配置段修改就好了。

例如:

1
2
osd pool default pg num = 100
osd pool default pgp num = 100

命令形式:

ceph osd pool create {pool_name} {pg_num} [{pgp_num}] [replicated]
[crush_ruleset_name] [expected_num_objects]

参数说明:

名称 类型 是否必需 参数说明
pool_name string Yes 存储池名称,必须唯一
pg_num int Yes 存储池的归置组总数,默认值为 8
pgp_num int No 用于归置的归置组总数。此值应该等于归置组总数
replicated string No replicated 表示创建的为多副本存储池
crush_ruleset_name string No 此存储池所用的 CRUSH 规则集名字。指定的规则集必须存在。
expected_num_objects int No 为这个存储池预估的对象数。
设置此值(要同时把 filestore merge threshold 设置为负数)后,
在创建存储池时就会拆分 PG 文件夹,
以免运行时拆分文件夹导致延时增大。

例如:

1
ceph osd pool create mytestpool 256 256 

设置存储池配额

存储池配额可设置最大字节数、以及每个存储池最大对象数。

命令形式:

ceph osd pool set-quota {pool_name} [max_objects {obj_count}] [max_bytes {bytes}]

例如:

1
ceph osd pool set-quota mytestpool max_objects 10000

查看存储池配额

1
2
3
4
5
root@ceph1:~#  ceph osd pool get-quota mytestpool
quotas for pool 'rbd':
max objects: 10000
max bytes : N/A

获取/设置 pool 副本数

获取存储池副本:

ceph osd pool get {pool_name} size

例如:

1
ceph osd pool get mytestpool size

设置存储池副本:

ceph osd pool set {pool_name} size {size}

例如:

1
ceph osd pool set mytestpool size 2

调整存储池选项值

命令形式:

ceph osd pool set {pool_name} {key} {value}

例如:

1
2
3
4
5
6
# 获取 pg_num / pgp_num
ceph osd pool get mytestpool pg_num
ceph osd pool get mytestpool pgp_num
# 设置 pg_num
ceph osd pool set mytestpool pg_num 512
ceph osd pool set mytestpool pgp_num 512

具体有哪些属性可以调整,以及有效范围说明,请参考 调整存储池选项值

::: warning 警告
Pool 的 pg_num 只能增大,不能减小。并且如果修改了 pg_num 最好同时修改 pgp_num,保持 pg_num = pgp_num。
:::

减少 pg_num 会报错,例如:

1
2
3
4
root@ceph1:~# ceph osd pool get rbd pg_num
pg_num: 64
root@ceph1:~# ceph osd pool set rbd pg_num 60
Error EEXIST: specified pg_num 60 <= current 64

删除存储池

删除存储是非常危险测操作,会销毁存储池中的全部数据,所以如果要删除存储池,你首先要在配置文档 ceph.conf 加入一条配置,
设置允许删除存储池,然后重启 MON 服务生效。

1
mon_allow_pool_delete = true

其次为了防止删错,你需要连续输入两次 {pool_name}, 并且命令后面跟上 --yes-i-really-really-mean-it 参数。

命令形式:

ceph osd pool rm {pool_name} [{pool_name} –yes-i-really-really-mean-it]

例如:

1
2
root@ceph1:~# ceph osd pool rm mytestpool mytestpool --yes-i-really-really-mean-it
pool 'mytestpool' removed

::: tip 提示:
如果你给自建的存储池创建了定制的规则集,你不需要存储池时最好删除它。
如果你曾严格地创建了用户及其权限给一个存储池,但存储池已不存在,最好也删除那些用户。
:::

重命名存储池

ceph osd pool rename {current_pool_name} {new_pool_name}

例如:

1
2
root@ceph1:~# ceph osd pool rename mytestpool new-pool-name
pool 'mytestpool' renamed to 'new-pool-name'

查看存储池统计信息

1
2
3
4
5
6
7
8
9
10
11
root@ceph1:~# rados df
POOL_NAME USED OBJECTS CLONES COPIES MISSING_ON_PRIMARY UNFOUND DEGRADED RD_OPS RD WR_OPS WR
cephfs_data 1.00GiB 258 0 516 0 0 0 2 2KiB 290 1.00GiB
cephfs_metadata 214KiB 22 0 44 0 0 0 75 479KiB 213 338KiB
new-pool-name 0B 0 0 0 0 0 0 0 0B 0 0B
rbd 1.07GiB 294 5 588 0 0 0 1943 14.6MiB 709 1.07GiB

total_objects 574
total_used 11.2GiB
total_avail 24.1GiB
total_space 35.3GiB

创建/删除存储池快照

创建存储池快照

1
ceph osd pool mksnap {pool_name} {snap_name}

删除存储池快照

1
ceph osd pool rmsnap {pool_name} {snap_name}

纠删码存储池

Ceph 在没有特别指定参数的情况下,默认创建的是多副本存储池。纠删码存储池可以在提供与副本相同的冗余水平的同时节省空间。

最简单的纠删码存储池等效于RAID5,它相当于 size = 2 的副本池,却能节省 25% 的磁盘空间。

创建存储池

命令形式:

ceph osd pool create {pool_name} {pg_num} {pgp_num} erasure [erasure_code_profile] [crush_ruleset_name] [expected_num_objects]

下面命令创建一个最简单的纠删码存储池:

1
2
3
4
5
root@ceph1:~# ceph osd pool create ecpool 12 12 erasure
pool 'ecpool' created
root@ceph1:~# echo ABCDEFGHI | rados --pool ecpool put NYAN -
root@ceph1:~# rados --pool ecpool get NYAN -
ABCDEFGHI

纠删码配置

默认的纠删码配置只能允许损坏一个 OSD。它等效于 size=2 的 多副本存储池,但是需要 1.5TB 而不是 2TB 的数据来存储 1TB 的数据。

一个默认的纠删码配置是这样的:

1
2
3
4
5
root@ceph1:~# ceph osd erasure-code-profile get default
k=2
m=1
plugin=jerasure
technique=reed_sol_van

在此配置中 k=2 和 m=1 ,其含义为数据分布于 3 个 OSD ( k+m==3 )且允许一个失效。

::: warning 注意:
选择正确的配置文件很重要,因为在创建池之后无法对其进行修改:需要创建一个具有不同配置文件的新池,并将先前池中的所有对象移至新池。
:::

为了在不增加原始存储空间需求的前提下提升冗余性,你可以新建配置。
例如,一个 k=10 且 m=4 的配置可容忍 4 个 OSD 失效,它会把一对象分布到 14 个( k+m=14 ) OSD 上。
此对象先被分割为 10 块(若对象为 10MB ,那每块就是 1MB )、并计算出 4 个用于恢复的编码块(各编码块尺寸等于数据块,即 1MB );
这样,原始空间仅多占用 10% 就可容忍 4 个 OSD 同时失效、且不丢失数据。

可以通过下面命令创建纠删码配置:

1
2
3
root@ceph1:~# ceph osd erasure-code-profile set myprofile k=10 m=4 ruleset-failure-domain=rack
root@ceph1:~# ceph osd pool create ecpool 12 12 erasure myprofile
pool 'ecpool' created

纠删码存储池与缓存分级

纠删码存储池比复制池需要更多的资源,并且缺少某些功能,例如部分写入。为了弥补这些缺陷,建议在纠删码存储池前面设置一个缓存层。

比如,如果 hot-storage 是由快速存储组成,我们可以使用下面的方式设置缓存层:

1
2
3
ceph osd tier add ecpool hot-storage
ceph osd tier cache-mode hot-storage writeback
ceph osd tier set-overlay ecpool hot-storage

此时会将 hot-storage 池作为 ecpool 池的回写模式,这样一来 ecpool 的每次写入和读取实际上都在使用 hot-storage 缓存池,并从其灵活性和速度中受益。

::: warning 注意:
此外由于它需要部分写入,因此无法在纠删码池上创建 RBD 镜像。但是,当复制池层设置了缓存层时,可以在擦除编码池上创建RBD映像,
但是,当复制池层设置了缓存层时,可以在纠删码池上创建 RBD 镜像。
:::

1
rbd create --size 10G ecpool/myvolume

参考文献