admin 发表于 2025-3-28 10:00:00

ceph分布式存储的正确玩法之Ceph纠删码实践

一、纠删码原理
纠删码(Erasure Coding,EC)是一种编码容错技术,最早是在通信行业解决部分数据在传输中的损耗问题。其基本原理就是把传输的信号分段,加入一定的校验再让各段间发生相互关联,即使在传输过程中丢失部分信号,接收端仍然能通过算法将完整的信息计算出来。在数据存储中,纠删码将数据分割成片段,把冗余数据块扩展和编码,并将其存储在不同的位置,比如磁盘、存储节点或者其他地理位置。如果需要严格区分,实际上按照误码控制的不同功能,可分为检错、纠错和纠删3种类型。
·检错码仅具备识别错码功能而无纠正错码功能。
·纠错码不仅具备识别错码功能,同时具备纠正错码功能。
·纠删码则不仅具备识别错码和纠正错码的功能,而且当错码超过纠正范围时,还可把无法纠错的信息删除。
从纠删码基本的形态看,它是k个数据块+m个校验块的结构,其中k和m值可以按照一定的规则设定,可以用公式:n=k+m来表示。变量k代表原始数据或符号的值。变量m代表故障后添加的提供保护的额外或冗余符号的值。变量n代表纠删码过程后创建的符号的总值。当小于m个存储块(数据块或校验块)损坏的情况下,整体数据块可以通过计算剩余存储块上的数据得到,整体数据不会丢失。
下面以k=2,m=1为例,介绍一下如何以纠删码的形式将一个名称为cat.jpg的对象存放在Ceph中,假定该对象的内容为ABCDEFGH。客户端在将cat.jpg上传到Ceph以后,会在主OSD中调用相应的纠删码算法对数据进行编码计算:将原来的ABCDEFGH拆分成两个分片,对应图11-2中的条带分片1(内容为ABCD)和条带分片2(内容为EFGH),之后再计算出另外一个校验条带分片3(内容为WXYZ)。按照crushmap所指定的规则,将这3个分片随机分布在3个不同的OSD上面,完成对这个对象的存储操作。如图所示。
下面再看一下如何使用纠删码读取数据,同样还是以cat.jpg为例。客户端在发起读取cat.jpg请求以后,这个对象所在PG的主OSD会向其他关联的OSD发起读取请求,比如主OSD是图中的OSD1,当请求发送到了OSD2和OSD3,此时刚好OSD2出现故障无法回应请求,导致最终只能获取到OSD1(内容为ABCD)和OSD3(WXYZ)的条带分片,此时OSD1作为主OSD会对OSD1和OSD3的数据分片做纠删码解码操作,计算出OSD2上面的分片内容(即EFGH),之后重新组合出新的cat.jpg内容(ABCDEFGH),最终将该结果返回给客户端。整个过程如图所示。
虽然纠删码能够提供和副本相近的数据可靠性,并降低冗余数据的开销,整体上能提高存储设备的可用空间。但是,纠删码所带来的额外开销主要是大量计算和网络高负载,优点同时伴随缺点。特别是在一个硬盘出现故障的情况下,重建数据非常耗费CPU资源,而且计算一个数据块时需要读出大量数据并通过网络传输。相比副本数据恢复,纠删码数据恢复时给网络带来巨大的负担。因此,使用纠删码对硬件的设备性能是一个较大的考验,这点需要注意。另外,需要注意的是,使用纠删码所建立的存储资源池无法新建RBD块设备。
Ceph安装后默认有Default Rule,这个Rule默认是在Host层级进行三副本读写。副本技术带来的优点是高可靠性、优异的读写性能和快速的副本恢复。然而,副本技术带来的成本压力是较高的,特别是三副本数据情景下,每TB数据的成本是硬盘裸容量3倍以上(包括节点CPU和内存均摊开销)。纠删码具备与副本相近的高可用特性,而且降低了冗余数据的开销,同时带来了大量计算和网络高负载。


二、纠删码实践
纠删码是通过创建erasure类型的Ceph池实现的。这些池是基于一个纠删码配置文件进行创建的,在这个配置文件中定义了纠删码的特征值。现在我们将创建一个纠删码配置文件,并根据这个配置文件创建纠删码池。下面的命令将创建一个名为Ecprofile的纠删码配置文件,它定义的特征值是:k=3和m=2,两者分别表示数据块和校验块的数量。所以,每一个存储在纠删码池中的对象都将分为3(即k)个数据块,和2(即m)个额外添加的校验块,一共有5个块(k+m)。最后,这5(即k+m)个块将分布在不同故障区域中的OSD上。
1、创建纠删码配置文件:
# ceph osd erasure-code-profile set Ecprofilecrush-failure-domain=osd k=3 m=2
2、查看配置文件
# ceph osd erasure-code-profile ls
Ecprofile
default
# ceph osd erasure-code-profile get Ecprofile
crush-device-class=
crush-failure-domain=osd
crush-root=default
jerasure-per-chunk-alignment=false
k=3
m=2
plugin=jerasure
technique=reed_sol_van
w=8
我们顺便也看Ceph默认的配置文件
# ceph osd erasure-code-profile get default
k=2
m=1
plugin=jerasure
technique=reed_sol_van
3、基于上一步生成的纠删码配置文件新建一个erasure类型的Ceph池:
# ceph osd pool create testcpool 16 16 erasureEcprofile
pool 'testcpool' created
4、检查新创建的池的状态,你会发现池的大小是5(k+m),也就是说,erasure大小是5。因此,数据将被写入五个不同的OSD中:
# ceph osd dump | grep testcpool
pool 8 'testcpool' erasure size 5 min_size 4crush_rule 3 object_hash rjenkins pg_num 16 pgp_num 16 last_change 231 flagshashpspool stripe_width 12288
5、现在我们创建个文件放到纠删码池中。
# echo test > test
# ceph osd pool ls
testcpool
# rados put -p testcpool object1 test
# rados -p testcpool ls
object1
6、检查testcpool池中和object1的OSDmap。命令的输出将清晰地显示对象的每个块所在的OSDID。正如步骤1)中说明的那样,object1被分为3(m)个数据块和2(k)个额外的校验块,因此,5个块分别存储在Ceph集群完全不同的OSD上。在这个演示中,object1一直存储在这5个OSD中,它们是osd.5、osd.1、osd.3、osd.2、osd.4。
# ceph osd map testcpool object1
osdmap e233 pool 'testcpool' (8) object'object1' -> pg 8.bac5debc (8.c) -> up (, p5) acting(, p5)

三、纠删码测试
1、我们先来关闭一个osd
# systemctl stop ceph-osd@3
停止osd.3,检查testcpool池和object1的OSDmap。你应该注意,这里的osd.3变成NONE了,这意味着osd.3在这个池是不可用的:
# ceph osd map testcpool object1
osdmap e235 pool 'testcpool' (8) object'object1' -> pg 8.bac5debc (8.c) -> up (, p5) acting (,p5)
2、我们再来关闭一个osd
# systemctl stop ceph-osd@5
停止osd.5,检查testcpool池和object1的OSDmap。你应该注意,这里的osd.5变成NONE了,这意味着osd.5在这个池是不可用的:
# ceph osd map testcpool object1
osdmap e237 pool 'testcpool' (8) object'object1' -> pg 8.bac5debc (8.c) -> up (, p1) acting(, p1)
3、我们从纠删码池中下载文件
## rados get -p testcpool object1 /tmp/devops



admin 发表于 2025-3-28 10:00:01

19 纠删码存储池


Ceph 提供了一种在存储池中正常复制数据的替代方案,称为纠删存储池或纠删码存储池。纠删码存储池不能提供副本存储池的所有功能(例如,它们无法存储 RBD 存储池的元数据),但其所需的原始存储空间更少。一个能够存储 1 TB 数据的默认纠删码存储池需要 1.5 TB 的原始存储空间,以应对发生单个磁盘故障的情况。从这方面而言,纠删码存储池优于副本存储池,因为后者需要 2 TB 的原始存储空间才能实现相同目的。

有关纠删码的背景信息,请参见 https://en.wikipedia.org/wiki/Erasure_code。

有关 EC 存储池相关的存储池值列表,请参考纠删码存储池值。
19.1 纠删码存储池的先决条件


要使用纠删码,您需要:

    在 CRUSH 索引中定义纠删码规则。

    定义指定要使用的编码算法的纠删码配置。

    创建使用上述规则和配置的存储池。

请记住,一旦创建好存储池且存储池中包含数据,便无法更改配置和配置中的详细信息。

确保纠删码存储池的 CRUSH 规则对 step 使用 indep。有关详细信息,请参见第 17.3.2 节 “firstn 和 indep”。
19.2 创建示例纠删码存储池


最简单的纠删码存储池相当于 RAID5,至少需要三个主机。以下过程介绍如何创建用于测试的存储池。

    命令 ceph osd pool create 用于创建类型为纠删的存储池。12 表示归置组的数量。使用默认参数时,该存储池能够处理一个 OSD 的故障。

    cephuser@adm > ceph osd pool create ecpool 12 12 erasure
    pool 'ecpool' created

字符串 ABCDEFGHI 将写入名为 NYAN 的对象。

cephuser@adm > echo ABCDEFGHI | rados --pool ecpool put NYAN -

为了进行测试,现在可以禁用 OSD,例如,断开其网络连接。

要测试该存储池是否可以处理多台设备发生故障的情况,可以使用 rados 命令来访问文件的内容。

cephuser@adm > rados --pool ecpool get NYAN -
ABCDEFGHI

19.3 纠删码配置


调用 ceph osd pool create 命令来创建纠删码存储池时,除非指定了其他配置,否则会使用默认的配置。配置定义数据冗余。要进行这种定义,可以设置随意命名为 k 和 m 的两个参数。k 和 m 定义要将数据片段拆分成多少个块,以及要创建多少个编码块。然后,冗余块将存储在不同的 OSD 上。

纠删池配置所需的定义:

chunk

    如果调用该编码函数,它会返回相同大小的块:可串联起来以重构造原始对象的数据块,以及可用于重构建丢失的块的编码块。
k

    数据块的数量,即要将原始对象分割成的块数量。例如,如果 k = 2,则会将一个 10 kB 对象分割成各为 5 kB 的 k 个对象。纠删码存储池的默认 min_size 为 k + 1。不过,我们建议将 min_size 设置为 k + 2 或更大的值,以防丢失写入和数据。
m

    编码块的数量,即编码函数计算的额外块的数量。如果有 2 个编码块,则表示可以移出 2 个 OSD,而不会丢失数据。
crush-failure-domain

    定义要将块分布到的设备。其值需要设置为某个存储桶类型。有关所有的存储桶类型,请参见第 17.2 节 “存储桶”。如果故障域为机柜,则会将块存储在不同的机柜上,以提高机柜发生故障时的恢复能力。请记住,这需要 k+m 个机柜。

使用第 19.2 节 “创建示例纠删码存储池”中所用的默认纠删码配置时,如果单个 OSD 或主机发生故障,将不会丢失集群数据。因此,要存储 1 TB 数据,需要额外提供 0.5 TB 原始存储空间。也就是说,需要 1.5 TB 原始存储空间才能存储 1 TB 的数据(因为 k=2、m=1)。这相当于常见的 RAID 5 配置。作为对比,副本存储池需要 2 TB 原始存储空间才能存储 1 TB 数据。

可使用以下命令显示默认配置的设置:

cephuser@adm > ceph osd erasure-code-profile get default
directory=.libs
k=2
m=1
plugin=jerasure
crush-failure-domain=host
technique=reed_sol_van

选择适当的配置非常重要,因为在创建存储池后便无法修改配置。需要创建使用不同配置的新存储池,并将之前的存储池中的所有对象移到新存储池(请参见第 18.6 节 “存储池迁移”)。

最重要的几个配置参数是 k、m 和 crush-failure-domain,因为它们定义存储开销和数据持久性。例如,如果在两个机柜发生故障并且存储开销达到 66% 的情况下,必须能够维系所需的体系结构,可定义以下配置。请注意,这仅适用于拥有“rack”类型的存储桶的 CRUSH 索引:

cephuser@adm > ceph osd erasure-code-profile set myprofile \
   k=3 \
   m=2 \
   crush-failure-domain=rack

对于此新配置,可以重复第 19.2 节 “创建示例纠删码存储池”中的示例:

cephuser@adm > ceph osd pool create ecpool 12 12 erasure myprofile
cephuser@adm > echo ABCDEFGHI | rados --pool ecpool put NYAN -
cephuser@adm > rados --pool ecpool get NYAN -
ABCDEFGHI

NYAN 对象将分割成三个 (k=3),并将创建两个额外的块 (m=2)。m 值定义可以同时丢失多少个 OSD 而不会丢失任何数据。crush-failure-domain=rack 将创建一个 CRUSH 规则组,用于确保不会将两个块存储在同一个机柜中。
#1: 纠删码配置
19.3.1 创建新纠删码配置


以下命令可创建新纠删码配置:

root # ceph osd erasure-code-profile set NAME \
directory=DIRECTORY \
plugin=PLUGIN \
stripe_unit=STRIPE_UNIT \
KEY=VALUE ... \
--force

DIRECTORY

    可选。设置从中加载纠删码插件的目录名称。默认为 /usr/lib/ceph/erasure-code。
PLUGIN

    可选。使用纠删码插件可计算编码块和恢复缺失的块。可用的插件有“jerasure”、“isa”、“lrc”和“shes”。默认为“jerasure”。
STRIPE_UNIT

    可选。数据块中每个条带的数据量。例如,如果配置拥有 2 个数据块且 stripe_unit 等于 4K,则会将范围 0-4K 的数据置于块 0 中,将 4K-8K 置于块 1 中,然后再将 8K-12K 置于块 0 中。需要有多个 4K 才能实现最佳性能。默认值取自创建存储池时的 Monitor 配置选项 osd_pool_erasure_code_stripe_unit。使用此配置的存储池的“stripe_width”等于数据块的数量乘以此“stripe_unit”。
KEY=VALUE

    专用于选定纠删码插件的选项键/值对。
--force

    可选。覆盖名称相同的现有配置,并允许设置不按 4K 对齐的 stripe_unit。

19.3.2 删除纠删码配置


以下命令可按 NAME 所标识的纠删码配置删除相应配置:

root # ceph osd erasure-code-profile rm NAME

重要重要

如果某个存储池引用了该配置,则删除将会失败。
19.3.3 显示纠删码配置的详细信息


以下命令可按 NAME 所标识的纠删码配置显示其详细信息:

root # ceph osd erasure-code-profile get NAME

19.3.4 列出纠删码配置


以下命令可列出所有纠删码配置的名称:

root # ceph osd erasure-code-profile ls

19.4 标记含 RADOS 块设备的纠删码存储池


要将 EC 池标记为 RBD 池,请对其进行相应标记:

cephuser@adm > ceph osd pool application enable rbd ec_pool_name

RBD 可在 EC 池中存储映像数据。但是,映像报头和元数据仍需要存储在副本存储池中。为此,假设您的存储池命名为“rbd”:

cephuser@adm > rbd create rbd/image_name --size 1T --data-pool ec_pool_name

您可以像使用任何其他映像一样正常使用该映像,只不过所有数据都将存储在 ec_pool_name 池而非“rbd”池中。

admin 发表于 2025-3-28 10:00:02

在 OpenStack 中使用 Ceph 纠删码(Erasure Coding, EC)池,通常涉及到以下几个步骤:
1. 配置 Ceph 集群以支持纠删码

首先,确保你的 Ceph 集群已经配置并支持纠删码。这通常涉及到以下几个步骤:
a. 创建纠删码池

在 Ceph 中,你可以创建一个使用纠删码的池。例如,使用 jerasure 和 reed_sol_van 算法创建一个纠删码池:

ceph osd pool create ec_pool 64 64 erasure code_profile ec_profile
ceph osd erasure-code-profile set ec_profile jerasure yel error_domain=1 k=8 m=2 ruleset-failure-domain=host crush-root=default

这里,k=8 表示数据块数量,m=2 表示校验块数量,error_domain=1 表示每个主机最多有一个故障域。
b. 验证池配置

确认池已正确配置为纠删码:

ceph osd pool get ec_pool erasure_code_profile

2. 在 OpenStack 中配置 Ceph 和使用纠删码池

在 OpenStack 中使用 Ceph 纠删码池,你需要在 Cinder 和 Nova 中配置 Ceph 以使用这个新的池。
a. 修改 Cinder 配置文件

编辑 Cinder 的配置文件(通常是 /etc/cinder/cinder.conf),并添加或修改以下设置:


volume_driver = cinder.volume.drivers.rbd.RBDDriver
rbd_pool = ec_pool
rbd_user = cinder-user
rbd_secret_uuid = <secret-uuid>

确保 rbd_secret_uuid 是你的 Ceph 认证密钥的 UUID。你可以使用以下命令生成 UUID:

uuidgen

b. 配置 Ceph 认证密钥

生成 Ceph 认证密钥并将其添加到 Cinder 和 Nova 的配置中:

ceph auth get-key client.cinder-user | base64

将输出添加到 Cinder 和 Nova 的配置文件中:


rbd_secret_uuid = <secret-uuid> from uuidgen
rbd_user = cinder-user
rbd_ceph_conf = /etc/ceph/ceph.conf

c. 重启 Cinder 服务以应用更改

systemctl restart openstack-cinder-api openstack-cinder-volume openstack-cinder-scheduler

3. 验证配置

确认 Cinder 可以正常使用纠删码池:

openstack volume create --image <image-id> --size 10 <volume-name>

检查卷是否正确创建在 EC 池中:

rbd ls -p ec_pool --id cinder-user --keyfile=/etc/ceph/ceph.client.cinder-user.keyring | grep <volume-name>

4. 在 Nova 中使用 Ceph 块存储(可选)

如果需要在 Nova 中使用 Ceph 块存储,确保 Nova 的配置也指向正确的 Ceph 用户和密钥。这通常涉及到编辑 /etc/nova/nova.conf 并添加类似的 RBD 设置。
5. 重启相关服务(如果需要)

根据需要重启 Nova 服务:

systemctl restart openstack-nova-compute openstack-nova-api openstack-nova-scheduler openstack-nova-conductor

通过以上步骤,你应该能够在 OpenStack 中成功配置和使用 Ceph 的纠删码池
页: [1]
查看完整版本: ceph分布式存储的正确玩法之Ceph纠删码实践