Erasure Coding in Ceph

syndicated

Erasure Coding : All you have to know

如果存在数据,就一定会发生故障,并且也会有像我们这样的管理员来恢复这些数据。Erasure Coding 就是我们的盾牌。

存储系统拥有用于在发生故障时保护和恢复数据的技术。主要有三种数据保护方法:

  1. 复制

  2. RAID

等等,还有第三种传奇(等一下...)方法

  1. Erasure Coding

首先,Erasure Coding 并非现在才出现,它诞生于 RAID 和复制方法之前,但当时并未实际应用。RAID 现在正处于衰落期。RAID 数据保护方法是在几年前,当找到容量为 1 GB 的硬盘驱动器很困难的时候构建的。在过去的 30 年里,驱动器容量增加了 4000 倍。尽管如此,驱动器的一致性和耐用性仍然是一个问题。RAID 本不应该为 exabyte 级别的存储阵列提供数据保护,它根本不是为未来设计的。我们需要一种高度适应性并为未来需求做准备的数据保护方法。回到基础,Erasure Codes 就是答案。

Erasure coding (EC) 是一种数据保护方法,其中数据被分解成片段,编码后以分布式方式存储。Ceph 由于其分布式特性,可以很好地利用 EC。

Erasure coding 使用数学公式来实现数据保护。整个概念围绕以下公式展开。

n = k + m ,其中,

k = 将原始数据分成的数据块的数量。

m = 添加到原始数据块以提供数据保护的额外代码。为了便于理解,您可以将其视为可靠性级别。

n = Erasure coding 过程后创建的总数据块数量。

在 erasure coding 公式的基础上,还有几个术语:

恢复:要执行恢复操作,我们需要从 n 个数据块中获取任何 k 个数据块,从而可以容忍任何 m 个数据块的故障。

可靠性级别:我们可以容忍最多 m 个数据块的故障。

编码率 (r):r = k / n,其中 r < 1
所需存储空间:1 / r

示例 1:(3,5) Erasure Code 对于任何数据文件看起来像

n = 5,k = 3,m = 2 (m = n - k)

Erasure coding 公式 5 = 3 + 2

因此,将 2 个编码块添加到 3 个数据块,形成 5 个总块,这些块将以分布式方式存储在 ceph 集群中。如果发生故障,要构造原始文件,我们需要从这 5 个块中获取任何 3 个块来恢复它。因此,在本例中,我们可以处理任何 2 个块的丢失。

编码率 (r) = 3 / 5 = 0.6 < 1
所需存储空间 = 1 / 0.6 = 原始文件大小的 1.6 倍。

如果原始文件大小为 1GB,那么要在 ceph 集群中存储 erasure coded (3,5) pool 中的此文件,您需要 1.6GB 的存储空间。

示例 2:(10,6) Erasure Code 对于任何数据文件看起来像

n = 16,k = 10,m = 6

编码率 (r) = 10 / 16 = 0.6 < 1

所需存储空间 = 1 / 0.6 = 原始文件大小的 1.6 倍。

此 erasure code 可以承受 16 个块中的任何 6 个块的故障,如果发生故障,为了恢复,我们需要从 16 个块中获取任何 10 个块。

Erasure Codes 逐步操作

步骤 1:了解 EC profile

查看 EC profile 时,您会遇到一些定义该 profile 的 EC 模式的选项。

k ===> 如前所述,它是数据将被分成的数据块的数量,并且每个数据块将存储在单独的 OSD 上。此命令行参数等效于
erasure-code-k=<数据块数量>
默认值 = 2

m ===> 添加到数据块以提供可靠性的额外代码(块)的数量。这也是可以容忍多少个 OSD 发生故障而不会丢失数据的数量。也称为可靠性级别。此命令行参数等效于
erasure-code-m=<编码块数量>
默认值 = 1

plugin ===> 这是促进 Ceph 中 erasure coding 的库。该插件用于计算编码块和恢复丢失的块。当前实现使用 jerasure,但即将发布的版本可能会使用 GF-complete,因为它比 jerasure 快两倍。此命令行参数等效于
erasure-code-plugin=<插件名称>
默认值 = 1

directory ===> 从中加载 EC 插件库的目录名称。在大多数情况下,一旦定义了插件名称,此参数就会自动添加。此命令行参数等效于
erasure-code-directory=<目录路径>
默认值 = /usr/lib64/ceph/erasure-code
ruleset-failure-domain ===> 定义故障域,您应该将其设置为 OSD,以获得数据的更好可靠性。
默认值 = host

步骤 2:生成 EC profile

# ceph osd erasure-code-profile set EC-temp-pool

# ceph osd erasure-code-profile ls
EC-temp-pool
profile1

# ceph osd erasure-code-profile get EC-temp-pool
directory=/usr/lib64/ceph/erasure-code
k=2
m=1
plugin=jerasure
technique=reed_sol_van

步骤 3:自定义您的 EC profile

我们可以使用子命令 set 来更改现有 profile,但是我们可能需要使用 --force 来更改 profile。这可能很危险。

在此示例中,我们将更改 k=4 的值

# ceph osd erasure-code-profile set EC-temp-pool ruleset-failure-domain=osd k=4 m=2
错误 EPERM:将不会覆盖 erasure code profile EC-temp-pool

# ceph osd erasure-code-profile set EC-temp-pool ruleset-failure-domain=osd k=4 m=2 --force

# ceph osd erasure-code-profile get EC-temp-pool
directory=/usr/lib64/ceph/erasure-code
k=4
m=2
plugin=jerasure
ruleset-failure-domain=osd
technique=reed_sol_van

同样,您可以根据需要更改其他参数。

步骤 4:基于您的 profile 创建 EC Ceph Pool

Ceph osd pool create <Pool_name> <pg_num> <pgp_num> erasure <EC_profile_name>

# ceph osd pool create ECtemppool 128 128 erasure EC-temp-pool
创建 pool 'ECtemppool'

# rados lspools
data
metadata
rbd
ECtemppool

# ceph osd dump | grep -i erasure
pool 22 'ECtemppool' erasure size 6 min_size 2 crush_ruleset 1 object_hash rjenkins pg_num 128 pgp_num 128 last_change 2034 owner 0 flags hashpspool stripe_width 4096

步骤 5:写入您的 EC pool

  • 创建一个临时文件

# echo "Erasure Coding is ******* Awesome" > testfile

# cat testfile
Erasure Coding is ******* Awesome

  • 列出您的 pool 中的对象,由于您创建了一个新的 pool,其中将没有对象。将测试文件放入您的 EC pool。

# rados -p ECtemppool ls

# rados -p ECtemppool put object.1 testfile

# rados -p ECtemppool ls
object.1

  • 检查您的 pool 的 PG 映射,您将了解此 object.1 放置在多少个 OSD 上。
  • 仔细分析,您会发现 object.1 放置在 6 个不同的 OSD 上,这是由于我们的 erasure code profile 中指定了 k=4 和 m=2,因此总块数为 6,这些块将放置在所有不同的 OSD 上

# ceph osd map ECtemppool object.1
osdmap e2067 pool 'ECtemppool' (22) object 'object.1' -> pg 22.f560f2ec (22.2ec) -> up ([144,39,55,15,123,65], p144) acting ([144,39,55,15,123,65], p144)

现在您拥有一个可靠的 erasure coded pool,可以同时承受两个 OSD 的故障。

Erasure Codes 是 100% 可靠的:

到目前为止,您拥有一个 erasure coded pool (4,2),这意味着它可以同时承受 2 个 OSD 故障。

从上面的输出中,这些是将文件“testfile”传播到的 6 个 OSD = [144,39,55,15,123,65]

测试 1:故意破坏 OSD 以测试 EC 可靠性

  • 破坏第一个 OSD(osd.65)

# service ceph status osd.65
=== osd.65 ===
osd.65: running {"version":"0.79-125-gcf69bdb"}

# service ceph stop osd.65
=== osd.65 ===
停止 Ceph osd.65 on storage0106-ib...kill 3505...done

# service ceph status osd.65
=== osd.65 ===
osd.65: not running.

  • 由于 osd.65 宕机,它将从以下输出中丢失,而是您会找到一些垃圾条目“2147483647”

# ceph osd map ECtemppool object.1
osdmap e2069 pool 'ECtemppool' (22) object 'object.1' -> pg 22.f560f2ec (22.2ec) -> up ([144,39,55,15,123,2147483647], p144) acting ([144,39,55,15,123,2147483647], p144)

  • 破坏第二个 OSD(osd.123)

# service ceph status osd.123
=== osd.123 ===
osd.123: running {"version":"0.79-125-gcf69bdb"}

# service ceph stop osd.123
=== osd.123 ===
停止 Ceph osd.123 on storage0114-ib...kill 5327...done

# service ceph status osd.123
=== osd.123 ===
osd.123: not running.

  • 现在第二个 osd.123 宕机,它将从以下输出中丢失,就像 osd.65 一样,但这里出现了神奇之处
  • Erasure codings 是智能的,它知道何时丢失数据或文件的编码块。一旦块丢失,它会立即在新的 OSD 上创建完全相同的块。在本例中,您可以看到,OSD.65 和 OSD.123 宕机,因此 ceph 会智能地将失败的块恢复到 OSD.85(这是一个新的 OSD)

# ceph osd map ECtemppool object.1
osdmap e2104 pool 'ECtemppool' (22) object 'object.1' -> pg 22.f560f2ec (22.2ec) -> up ([144,39,55,15,2147483647,85], p144) acting ([144,39,55,15,2147483647,85], p144)

总结:

Erasure coding 是一种美妙的可靠解决方案,并且工作得非常好,它智能地管理失败的块并尝试在无需任何管理干预的情况下恢复它们。这使得 ceph 更加可靠,并且具有惊人的成本效益。Ceph Firefly 0.80 中最近添加了 EC 功能,我们可以期待更稳定和性能更优化的 EC 版本。