通过示例理解Ceph

Ceph发展至今,参与者众,资料已多。本文从实际操作角度写下个人对Ceph架构、原理和实现的理解,不当不全之处,请大家指出。

本文应贵神邀而作,将持续更新。转载请注明作者(@xanpeng)和出处。

Ceph的使用场景

Ceph提供了3种使用场景:

1、分布式文件系统CephFS。

多个客户端mount CephFS到本地,CephFS遵循POSIX接口,使用体验类似于ext4等本地文件系统。

类似于其他分布式文件系统,各个CephFS客户端共享同一命名空间。

2、RadosGW(rgw)对象存储。

rgw使用场景类似于Amazon S3,据个人理解也类似于七牛云存储。

3、块设备rbd(Rados Block Device)。

Ceph提供虚拟的rbd块设备,用户像使用SATA盘那样的物理块设备一样使用rbd。

rbd的使用是排他的,每个rbd块设备是用户私有的,相对的,CephFS的使用方式是共享的。

虚拟化和云计算的发展正当盛年,IaaS结合rbd块设备这一使用方式有如干柴遇烈火,因此rbd是Ceph社区开发的重心之一。本文也主要从rbd的视角来了解Ceph。

这3种使用场景是从用户视角来看。从实现角度,它们都基于同一核心RADOS(Reliable, Autonomic Distributed Object Store)存储层,参见官方示意图:

部署环境

准备设备

设想我们要研究或使用Ceph,我们已采购一批设备,准备部署一套Ceph分布式存储系统。

没有一套物理设备也没关系,本文用一套虚拟环境来模拟。

据已有理解,以及据前文所说本文只从rbd使用场景出发,Ceph环境分成两部分:monitor集群和OSD节点集。

monitor是Ceph的心脏,一般采用1、3、5、7等奇数个节点组成集群,节点越多集群越稳定。我们是实验环境,且也不是要专门分析monitor集群,因此使用一个monitor节点。

Ceph默认将数据存储为两份(暂不考虑Erasure Code),我们准备两个节点作为存储节点,这样一个数据存2个备份,如果每个备份放在不同的物理节点上,自然会更可靠——我们如此理解和猜测,实际如何还待实验。

基于这些分析,实验环境准备如下:

  1. 1 mon:用一个VM做Monitor。
  2. 2 storage hosts:用2个VM做存储节点。
  3. 2 * 3 osd:每个存储节点挂载3块硬盘,专门用于存储数据。

# virsh list

Id    Name                           State

----------------------------------------------------

4     ceph-mon0                      running

5     ceph-osd0                      running

6     ceph-osd1                      running

[email protected]:~# lsblk

NAME   MAJ:MIN RM SIZE RO TYPE MOUNTPOINT

vda    253:0    0  40G  0 disk

├─vda1 253:1    0  36G  0 part /

├─vda2 253:2    0   1K  0 part

└─vda5 253:5    0   4G  0 part [SWAP]

vdb    253:16   0  10G  0 disk

└─vdb1 253:17   0  10G  0 part /var/lib/ceph/osd/ceph-1 (已经安装并运行Ceph)

vdc    253:32   0  10G  0 disk

└─vdc1 253:33   0  10G  0 part /var/lib/ceph/osd/ceph-2

vdd    253:48   0  10G  0 disk

└─vdd1 253:49   0  10G  0 part /var/lib/ceph/osd/ceph-3

[email protected]:~# lsblk

NAME   MAJ:MIN RM SIZE RO TYPE MOUNTPOINT

vda    253:0    0  40G  0 disk

├─vda1 253:1    0  36G  0 part /

├─vda2 253:2    0   1K  0 part

└─vda5 253:5    0   4G  0 part [SWAP]

vdb    253:16   0  10G  0 disk

└─vdb1 253:17   0  10G  0 part /var/lib/ceph/osd/ceph-7

vdc    253:32   0  10G  0 disk

└─vdc1 253:33   0  10G  0 part /var/lib/ceph/osd/ceph-5

vdd    253:48   0  10G  0 disk

└─vdd1 253:49   0  10G  0 part /var/lib/ceph/osd/ceph-6

说明:虚拟机和硬盘均用virt-manager创建。

安装和部署Ceph

官方文档有详细说明,这里不再赘述。仅强调几点:

  • mkcephfs是以前的部署方式,尽量不去使用。而是用ceph-deploy。
  • ceph-deploy根据OS不同,从不同的地方下载和安装Ceph。如图方便,用Ubuntu 14.04是很好的选择。
  • 如果想使用自己修改和编译的Ceph,也可以结合ceph-deploy使用,跳过"ceph-deploy install"即可。

在我们的“1mon + 2*3osd”环境中,部署Ceph集群如下:

[email protected]:~# ceph -s

cluster dee2e486-6942-4469-abd4-d25388fcdadb

health HEALTH_OK

monmap e1: 1 mons at {mon0=192.168.122.58:6789/0}, election epoch 1, quorum 0 mon0

osdmap e67: 6 osds: 6 up, 6 in

pgmap v895: 128 pgs, 1 pools, 62039 kB data, 3 objects

328 MB used, 61045 MB / 61373 MB avail

128 active+clean

[email protected]:~# ceph osd tree

# id    weight  type name       up/down reweight

-1      0.05997 root default

-2      0.02998         host osd0

1       0.009995                        osd.1   up      1

2       0.009995                        osd.2   up      1

3       0.009995                        osd.3   up      1

-3      0.02998         host osd1

5       0.009995                        osd.5   up      1

6       0.009995                        osd.6   up      1

7       0.009995                        osd.7   up      1

存储节点

在进一步之前,先考虑这点:Ceph是分布式存储系统,不管其“分布式逻辑”的细节,数据最终是要存储到设备上。

此时有两种选择:直接操作设备,或者由本地文件系统代理。前者表示直接面对硬盘,怎么在硬盘上组织数据都是自己做。后者表示不直接面对硬盘,而是使用已有的文件系统。Ceph使用第二种方式,可选的本地文件系统有ext4、btrfs和xfs等,我们使用ext4.

crush算法

设想你是用户,你有一部动作片要存放到Ceph集群中。你拿着你的笔记本来到机房,你所看到的Ceph集群是数个机架的服务器。你在想,我的动作片最终是存储在哪里?

你考虑的实际是数据定位的问题。

常见有两种数据定位方法:

  1. 记录。将“数据A:位置location(A)”这样的信息记录下来,访问数据时查询记录,获取位置,再进行读取。
  2. 计算。存放和数据A时,其存储位置location(A)是即时计算得到的。能感觉到这种方式更为便利。

常见的计算方式是一致性哈希(consistent hashing),GlusterFS使用的是这种方式,基本思路是,面对数据A,以数据A的文件名等类似信息为key,通过一致性哈希计算consist_hash(keyA) = location(A)得到存储位置。

ceph使用的是crush算法:Controlled, Scalable, Decentralized Placement of Replicated Data。crush是ceph核心之一,本文也将重点描述。

简单来说crush也利用哈希来计算位置,只不过它更多地利用了集群的结构信息。下面通过实例来尝试理解。

前文提到rbd、cephfs和rgw这三种使用场景,它们都基于RADOS层。RADOS层对外提供有librados接口,据此可以实现自己的工具。ceph默认提供一个程序rados,通过rados可以直接上传一个object到ceph集群。

mon0# rados put bigfile bigfile.data -p rbd // 将数据bigfile.data上传为object bigfile

mon0# rados ls -p rbd

bigfile

bigfile的存储位置是通过CRUSH计算得来,ceph提供命令可查询一个object的位置。

mon0# ceph osd map rbd bigfile

osdmap e67 pool ‘rbd‘ (1) object ‘bigfile‘ -> pg 1.a342bdeb (1.6b) -> up ([6,3], p6) acting ([6,3], p6)

[6,3]表示bigfile这个object存储在osd.6和osd.3上(ceph集群部署参考前文),并且放置在pg 1.6b下,也即放在目录1.6b下。

验证这一点:

osd0# ls /var/lib/ceph/osd/ceph-6/current/1.6b_head/ -lh

total 61M

-rw-r--r-- 1 root root 61M 10月 29 08:12 bigfile__head_A342BDEB__1 // 感受下object的命名方式

pg (placement group)

上例中提到pg,这是ceph crush数据映射的一个中间层。

讨论pg需要提及pool,pool是ceph的一个逻辑概念,用户可在ceph集群上创建数个pool,设置不同的属性,然后根据需求,将不同的数据放在不同的pool中。比如我有两种数据,一种只需要存储2个备份,另一种更重要,我需要存储3个备份,从而可以创建两个pool,设置size=2和size=3。

我的实验环境中只有一个pool,命名为rbd(这个命名是随意的,不要和rbd块设备使用场景混淆),其备份数目是2份:

mon0# ceph osd dump | grep pool

pool 1 ‘rbd‘ replicated size 2 min_size 2 crush_ruleset 0 object_hash rjenkins pg_num 128 pgp_num 128 last_change 48 flags hashpspool stripe_width 0

ceph在pool的概念下提供placement group的概念,并通过参数pg_num指定placement group的数目。从上面的输出可知我的rbd pool下有128个pg。

pg实际对应目录,rbd pool下有128个pg,意即rbd pool设置为有128个目录来存放数据。之所以增加pg层来管理数据,是为了数据管理的便利,也减少了元数据信息量。

rbd pool128个pg,每个pg放置在哪些osd上,这也是计算确定的,计算过程是crush算法的一部分。128个pg整体分散存储在所有osd上,因此在某个osd上,我们不会看到所有128个目录。

1.11_head  1.1f_head  1.27_head  1.33_head  1.39_head  1.42_head  1.4c_head  1.54_head  1.60_head  1.66_head  1.74_head  1.79_head  1.7e_head  1.8_head  1.b_head  1.f_head       nosnap

1.15_head  1.21_head  1.2e_head  1.36_head  1.3_head   1.44_head  1.4f_head  1.56_head  1.61_head  1.6a_head  1.75_head  1.7b_head  1.7f_head  1.9_head  1.d_head  commit_op_seq  omap

1.1b_head  1.26_head  1.2f_head  1.37_head  1.41_head  1.45_head  1.50_head  1.5a_head  1.63_head  1.73_head  1.78_head  1.7c_head  1.7_head   1.a_head  1.e_head  meta

说明:pg的命名方式是${pool_id}.${pg.id}_${snap},pgid是16进制值,如1.a_head表示128个pg中的第10个pg。

因此crush数据定位算法的大致逻辑是:

  • step 1: 输入object id,计算得到它应该被放置在哪个pg下,得到pgid。
  • step 2: 输入pgid,计算pg位于哪些osd上。
  • step 3: 访问object.

crush计算示例

我们想在这个理解基础上,来了解更多代码细节,考虑到ceph貌似没有提供访问crush算法的接口,我们在ceph0.86的代码上做些修改,让librados提供ceph集群的layout信息,同时将crush代码拎出来做成libcrush,然后利用修改过的librados和libcrush写程序验证crush算法的步骤。

crush-tester.cc main()展示了数据定位的步骤,其逻辑等同于"ceph osd map"的逻辑。需注意:代码是强依赖于我们前文部署的ceph环境的。

int main(int argc, char **argv) {
  assert(argc == 2);
  string objname = argv[argc-1];

// 假设objname=bigfile,这一步是通过objname计算得到一个数值,和pg其实没有关系,但官方代码就是这么命名的,我们这里也做类似命名
// bigfile->some_value,这里利用的算法是ceph_str_hash_rjenkins,算法这里不细究,其实也无必要细究。
// 其作用是将不同的objname映射层不同的数值,相信其特点是得到的数值冲突率很低。
  pg_t pg = object_to_pg(object_t(objname), object_locator_t(g_pool_id));
  printf("objectr_to_pg: %s -> %x\n", objname.c_str(), pg.seed);

// bigfile得到的值是a342bdeb,作为这一步的输入。
// 这一步的作用是将这个数值,也即将object bigfile映射到具体的pg。
// 用到的方法其实是取模,根据pg_num做取模计算,对应函数是crush_stable_mod(a342bdeb, 128, 127)=6b。
  pg_t mpg = raw_pg_to_pg(pg);
  printf("raw_pg_to_pg: %x\n", mpg.seed);

// 这一步是crush算法的核心步骤,
// 输入是pgid=6b,以及ceph集群的layout,也就是crushmap,
// 输出是6b的存储位置是哪两个osd(因为备份数设置size=2),
// crush算法的过程在libcrush中,注意这样链接本程序"-lcrush -lrados",从而使用libcrush而不是librados中的crush代码,这样我们通过介入libcrush去理解crush算法。
// crush算法计算6b的位置的过程见下文。
  printf("pg_to_osds:\n");
  vector<int> up;
  pg_to_up_acting_osds(mpg, &up);
}

# g++ crush_tester.cc -o test_crush -lcrush -lrados --std=c++11 -g -O0

# ./test_crush bigfile

objectr_to_pg: bigfile -> a342bdeb

raw_pg_to_pg: 6b

pg_to_osds:

osd_weight: 0,65536,65536,65536,0,65536,65536,65536,  // 这一输出我觉得奇怪,感觉是错误的,但偏偏最后crush映射的结果是正确的

ruleno: 0

placement_ps: 1739805228

// 这是crush算法计算6b位置的输出,注意计算依据之一是我们实验环境的crushmap,

// 有数种方法可以从一个live ceph cluster中得到当前的crushmap,我们环境的crushmap见:https://gist.github.com/xanpeng/a41a25b5810cb2c8852c#file-ceph-env-txt

// 通过crushmap可以知道,从crush算法的视角,我们的环境是这样分层的:

// 第一层:root

// id=-1,alg=straw,hash=rjenkins1,包含两个item [osd0, osd1]

// 第二层:host

// host osd0: id=-2, alg=straw, hash=rjenkins1,包含三个item [osd.1, osd.2, osd.3]

// host osd1: id=-3, alg=straw, hash=rjenkins1,包含三个item [osd.5, osd.6, osd.7],之所以不是4,5,6,表示我操作过程中出过点点纰漏,但无碍。

// 第三层:osd

// 共6个osd,id是[1,2,3,5,6,7],每个osd有个权重,通过设置osd的权重,影响数据是否存放在当前osd的偏好。

---start crush_do_rule---

CHOOSE_LEAF bucket -1 x 1739805228 outpos 0 numrep 2 tries 51 recurse_tries 1 local_retries 0 local_fallback_retries 0 parent_r 0

// 算法第一步,从第一层开始,获取第一个数据备份的存放位置,判断我该进入第二层的哪个host。

// 由于第一层设置的alg=straw,表示用straw算法去选取第二层的host,straw算法又利用到rjenkins1哈希算法

// 得到第一个备份存放位置是item -3上,即osd1上

crush_bucket_choose -1 x=1739805228 r=0

item -3 type 1

// 算法第二步,在osd1下的第三层中选一个osd,

// 使用的算法是osd1这个bucket设置的straw+rjenkins1,

// 这是crush算法过程中的第二次哈希。我们的实验环境简单,layout只有三层,在层次更多的环境中,crush需要做更多次数的哈希。

// 得到第一个备份存放位置是osd1上的osd.6

CHOOSE bucket -3 x 1739805228 outpos 0 numrep 1 tries 1 recurse_tries 0 local_retries 0 local_fallback_retries 0 parent_r 0

crush_bucket_choose -3 x=1739805228 r=0

item 6 type 0

CHOOSE got 6

CHOOSE returns 1

CHOOSE got -3

// 算法第三步,计算第二个数据备份的位置,求得位于osd0

crush_bucket_choose -1 x=1739805228 r=1

item -2 type 1

// 算法第四步,同理进而求得第二个备份的位置:osd0上的osd.3

CHOOSE bucket -2 x 1739805228 outpos 1 numrep 2 tries 1 recurse_tries 0 local_retries 0 local_fallback_retries 0 parent_r 0

crush_bucket_choose -2 x=1739805228 r=1

item 3 type 0

CHOOSE got 3

CHOOSE returns 2

CHOOSE got -2

CHOOSE returns 2

---finish crush_do_rule---

numrep: 2, raw_osds: [6,3,]

对比执行多次crush-tester和"ceph osd map",证实上述理解应为正确。见:https://gist.github.com/xanpeng/a41a25b5810cb2c8852c#file-ceph-tester-result-txt

  

时间: 2024-10-13 08:11:53

通过示例理解Ceph的相关文章

正则表达式分组捕获非捕获的示例理解

举几个例子 一.使用捕获型() 比如0.23 1.(^\d+)(\.)(\d{0,2}) 正则表达式有3个()使用match就会产生3个分组 2.^\d+\.\d{0,2} 没有(),不产生分组 二.非捕获型(?:) (?:^\d+)(\.)(\d{0,2}) 第一个分组不再捕获 原文地址:https://www.cnblogs.com/zhaogaojian/p/12207959.html

架构设计:系统存储(27)——分布式文件系统Ceph(安装)

1. 概述 从本篇文章开始介绍一款现在非常火的分布式文件系统Ceph,包括这款文件系统的安装.基本使用场景.常用管理命令和重要工作原理.特别是讨论了PaxOS算法的基本理后,就更容易理解Ceph分布式文件系统中各种角色的工作原理. 2. Ceph的安装部署 本文将介绍Ceph分布式文件系统如何在CentOS 7.X版本上一步一步完成安装,使读者在阅读过程中了解Ceph有哪些重要的子系统/工作模块,以及它们是如何关联工作的.请注意Ceph在Ubuntu等Linux操作系统上的安装过程和注意点大致相

Ceph Monitor基础架构与模块详解

转自:https://www.ustack.com/blog/ceph-monitor/ Ceph rados cluster离不开Monitor,如果没有Monitor,则Ceph将无法执行一条简单的命令.Monitor由于其特殊性,了解它,对于我们深入理解Ceph,保证Ceph的稳定性,有很大帮助. Monitor 基本架构介绍 Monitor的基本架构图: Monitor的主要任务就是维护集群视图的一致性,在维护一致性的时候使用了Paxos协议,并将其实例化到数据库中,方便后续的访问.所以

解析Ceph和9000分布式存储

 Ceph是呼声很高的开源分布式的SDS产品存储系统.同时提供对象存储.块存储和文件系统存储三种功能,满足不同应用需求.Ceph使用C++语言开发,遵循LGPL协议开源.Sage Weil(Ceph论文发表者)于2011年创立了以Inktank公司主导Ceph的开发和社区维护.2014年Redhat收购 inktank公司,并发布Inktank Ceph企业版,业务场景聚焦云.备份和归档,支持对象和块存储应用.从此出现Ceph开源社区版本和Redhat企业版. OceanStor 9000是

ceph结构和工作原理

Ceph是统一分布式存储系统,具有优异的性能.可靠性.可扩展性.Ceph的底层是RADOS(可靠.自动.分布式对象存储),可以通过 LIBRADOS直接访问到RADOS的对象存储系统.RBD(块设备接口).RADOS Gateway(对象存储接口).Ceph File System(POSIX接口)都是基于RADOS的. Ceph存储系统的逻辑层次结构如下图所示: 自下向上,可以将Ceph系统分为四个层次: (1)基础存储系统RADOS(Reliable, Autonomic,Distribut

使用委托中介租房理解委托与事件

委托和事件,.Net Framework中的应用非常广泛,然而,较好的理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像一道门槛儿,跨过去的,觉得太容易了,而没有过去的人每次见到委托事件就觉得心慌慌,浑身不自在. 我个人还是比较喜欢用面向对象的编程思想去理解逻辑程序,理解编程.下面就用委托中介公司租房子的示例理解使用委托流程: 1.定义委托和委托对象——租房人想要租房,但是没有房源,于是委托中介找房子:2.编写要委托的方法——租房中介有房源,可以找到房子:3.将要委托的方法传递给委托

【Ceph浅析笔记】Ceph是什么.md

Ceph是什么 什么是Ceph?首先我们应该明确,Ceph是一种分布式存储系统,所谓分布式,指的是Ceph可以部署在多台服务器上,通过多台服务器并行处理来对外提供高性能的读写块. 同时Ceph除了能提供块存储,还可以提供文件存储.对象存储. Ceph的优势 实际上Ceph不是一个才出现的开源项目,而是走过了 7年的路程,那么Ceph有什么样的优势呢? Ceph的优势在于它的设计思想:无需查表,算算就好.也就是说它可以充分利用服务器的计算能力,消除了对单一中心节点的依赖,可以实现真正的无中心结构

Generator函数的理解和使用

原文:https://blog.csdn.net/ganyingxie123456/article/details/78152770 Generator函数的理解和使用 Generator 函数是 ES6 提供的一种异步编程解决方案. 一.异步编程 1.所谓"异步",简单说就是一个任务分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段. 2.异步编程方式: (1)回调函数 (2)事件监听 (3)发布/订阅者 (4)Promise对象 3.所谓回调函数,就是把

“网红架构师”解决你的Ceph 运维难题

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由Tstack发表于云+社区专栏 本文为长篇连续剧,将分多个篇幅发表,主要介绍了从动手部署环境到后期运营故障处理过程中常见的问题,内容由浅入深,是居家旅行运维Ceph的必备良药. Q1. 环境预准备 绝大多数MON创建的失败都是由于防火墙没有关导致的,亦或是SeLinux没关闭导致的.一定一定一定要关闭每个每个每个节点的防火墙(执行一次就好,没安装报错就忽视): CentOS sed -i 's/SELINUX=.*/SELINUX