Ceph 的 RADOS中,引入了 PG 的概念用以更好地管理数据。PG 的引入降低对数量巨大的对象的管理难度。
1、对象数量时刻处于变化中。而PG的数量经过人工规划因而严格可控。
2、PG数量远小于对象,且生命周期稳定。因此以PG为单位进行数据同步或者迁移,相比较对象难度更小。
PG 最引人注目之处在于其可以在OSD之间(根据CRUSH的实时计算结果)自由迁移,这是ceph赖以实现自动数据恢复、自动数据平衡等高级特性的基础。
RADOS 提供的是基于 Object 的存储功能,每个 Object 会先通过简单的 Hash 算法归到一个 PG 中,PGID 再作为入参通过 CRUSH 计算置入到多个 OSD 中(这里 Object 可以看作是文件,PG 即是一个目录,OSD 是一个数据根目录下仅有一级子目录的简易文件系统)。
链接:https://www.zhihu.com/question/51573421/answer/623415214
假设系统采用了三副本机制。现在有一个osd X发生长期故障了,需要把它所承载的各个object的副本,重新分布到其他节点上去,继续保持三副本。我们怎么做?
首先,得知道osd X到底承载了哪些object,再根据修改过的osd map,计算出这些object需要分布到哪些可用的osd上。
问题是: 怎么知道osd X上面有哪些object? 如果没有PG,可能有两种方法:
1)遍历每个object,用crush计算一遍目标osd,看看其中哪些有副本位于osd X上。
缺点: object潜在的名字空间巨大,没法列举出所有可能的object的id。
2)记录每个osd承载了哪些object
缺点: Object数量可能巨大,且不断产生和删除,记录开销大。失去了CRUSH的本意。
有了PG又怎么搞? 由于PG和OSD的数量都比较有限,记录每个OSD承载了哪些PG可行,而且变化不频繁,开销小。 在OSD X故障后,很容易获得OSD X承载的PG列表,并计算出各个PG的另外两个副本在哪个OSD。而每个PG下面的对象,都按照PG做了聚集(称为collection,每个PG对应一个目录或者共用k/v存储的prefix),很容易获得对象列表。有了这些信息,才具备了故障处理的可行性。
PG是一种间址,PG的数量有限,记录PG跟OSD间的映射关系可行,而记录object到OSD之间的映射因为数量巨大而实际不可行或效率太低。从用途来说,搞个映射本身不是目的,让故障或者负载均衡变得可操作是目的。
链接:https://www.zhihu.com/question/51573421/answer/166030088
官网:
PG = “置放群组”。在集群中放置数据时,对象被映射到 PG,而那些 PG 被映射到 OSD。我们使用间接性,以便我们可以对对象进行分组,这减少了我们需要跟踪的每个对象元数据的数量以及我们需要运行的进程(跟踪例如基于每个对象的放置历史会非常昂贵) )。增加 PG 的数量可以减少集群中每个 OSD 负载的差异,但是每个 PG 在存储它的 OSD 上需要更多的 CPU 和内存。我们尝试以 100 PGs/OSD 的速度进行控制,尽管根据您的集群,它可以有很大的不同而不会产生不良影响。您在我们如何根据集群描述计算初始 PG 数时遇到了错误。
PG 有几种不同的类别;存在的 6 个(在原始电子邮件发送者的 ceph -s 输出中)是与特定 OSD 相关联的“本地”PG。然而,这些实际上并没有用于标准的 Ceph 配置中。
PGS 实践注意
Understanding Ceph Placement Groups (TOO_MANY_PGS) | TheMeanTime
PG是什么
PG就是目录。ls /var/lib/ceph/osd/ceph-0/current/
Object是文件,PG就是目录。管理、转移、备份的时候以目录为单位方便多了。
我事先搭建了一个
3个host, 每个host有3个OSD
的集群,集群使用3副本,min_size
为2。
集群状态如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [root@ceph-1 ~]# ceph osd tree ID WEIGHT TYPE NAME UP/DOWN REWEIGHT PRIMARY-AFFINITY -1 17.90991 root default -2 5.96997 host ceph-1 0 1.98999 osd.0 up 1.00000 1.00000 1 1.98999 osd.1 up 1.00000 1.00000 2 1.98999 osd.2 up 1.00000 1.00000 -4 5.96997 host ceph-2 3 1.98999 osd.3 up 1.00000 1.00000 4 1.98999 osd.4 up 1.00000 1.00000 5 1.98999 osd.5 up 1.00000 1.00000 -3 5.96997 host ceph-3 6 1.98999 osd.6 up 1.00000 1.00000 7 1.98999 osd.7 up 1.00000 1.00000 8 1.98999 osd.8 up 1.00000 1.00000 |
每一个pool都有一个id,系统默认生成的rbd
池的id号为0
,那么rbd池内的所有PG都会以0.
开头,让我们看一下osd.0
下面的current
目录的内容:
1 2 3 4 | [root@ceph-1 ~]# ls /var/lib/ceph/osd/ceph-0/current/ 0.0_head 0.1d_head 0.34_head 0.45_head 0.4e_head ....省略部分内容 0.af_head 0.bc_head 0.d0_head 0.e2_head 0.f4_head |
每个OSD的current
目录下都保存了部分的PG,而rbd池的PG以0.xxx_head
的目录形式存在!
现在我们通过rados
向集群写入一个文件(char.txt
),在集群内保存名为char
,通过下面的指令查看该文件实际保存的位置:
1 2 | [root@ceph-1 ~]# ceph osd map rbd char osdmap e109 pool 'rbd' (0) object 'char' -> pg 0.98165844 (0.44) -> up ([0,7,4], p0) acting ([0,7,4], p0) |
可见,文件会保存在PG 0.44
中,而这个PG位于osd.0
,osd.7
,osd.4
中,之所以有这里有三个OSD,是因为集群副本数为3,可以在0/7/4这三个OSD的current下找到0.44_head
目录。而同一份文件(比如这里的char.txt)的三个副本会分别保存在这三个同名的PG中。
执行指令,将char.txt
文件存入集群,并查看各个OSD的PG目录内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 | [root@ceph-1 cluster]# rados -p rbd put char char.txt [root@ceph-1 0.44_head]# pwd && ll /var/lib/ceph/osd/ceph-0/current/0.44_head -rw-r--r--. 1 root root 8 8月 25 01:38 char__head_98165844__0 -rw-r--r--. 1 root root 0 8月 24 23:40 __head_00000044__0 [root@ceph-2 0.44_head]# pwd && ll /var/lib/ceph/osd/ceph-4/current/0.44_head -rw-r--r-- 1 root root 8 8月 25 13:38 char__head_98165844__0 -rw-r--r-- 1 root root 0 8月 25 11:40 __head_00000044__0 [root@ceph-3 0.44_head]# pwd && ll /var/lib/ceph/osd/ceph-7/current/0.44_head -rw-r--r-- 1 root root 8 8月 25 13:38 char__head_98165844__0 -rw-r--r-- 1 root root 0 8月 25 11:40 __head_00000044__0 |
可见,这三个OSD保存了这个文件的三分副本,这就是ceph的多副本的基础,将一份数据保存成多个副本,按照一定规则分布在各个OSD中,而多副本的数据的一个特点就是,他们都保存在同名的PG下面,也就是同名的目录下。这样,我们就对PG有了一个直接的理解。
扩展阅读
active+clean
想说爱你不容易
active + clean
是PG的健康状态,然而PG也会生病
,有的是小感冒,有的则可能是一级伤残,下面就是集群进入恢复状态时的一个截图,这里面聚集了各种老弱病残,现在就来分析下每种病症的原因:
这里再次回忆下集群的配置:size = 3, min_size = 2
Degraded
降级:由上文可以得知,每个PG有三个副本,分别保存在不同的OSD中,在非故障情况下,这个PG是a+c
状态,那么,如果保存0.44
这个PG的osd.4挂掉了,这个PG是什么状态呢,操作如下:
1 2 3 4 5 | [root@ceph-2 ~]# service ceph stop osd.4 === osd.4 === Stopping Ceph osd.4 on ceph-2...kill 6475...kill 6475...done [root@ceph-2 ~]# ceph pg dump_stuck |egrep ^0.44 0.44 active+undersized+degraded [0,7] 0 [0,7] 0 |
这里我们前往ceph-2节点,手动停止了osd.4,然后查看此时pg 0.44的状态,可见,它此刻的状态是active+undersized+degraded
,当一个PG所在的OSD挂掉之后,这个PG就会进入undersized+degraded
状态,而后面的[0,7]
的意义就是还有两个0.44的副本存活在osd.0和osd.7上。那么现在可以读取刚刚写入的那个文件吗?是可以正常读取的!
1 2 3 | [root@ceph-1 0.44_head]# rados -p rbd get char char.txt [root@ceph-1 0.44_head]# cat char.txt abcdefg |
降级就是在发生了一些故障比如OSD挂掉之后,ceph将这个OSD上的所有PG标记为degraded
,但是此时的集群还是可以正常读写数据的,降级的PG只是相当于小感冒而已,并不是严重的问题,而另一个词undersized
,我的理解就是当前存活的PG 0.44数为2,小于副本数3,将其做此标记,也不是严重的问题。
Peered
那么,什么才是PG的大病呢,peered
算是一个,刚刚我们关闭了osd.4,集群里还活着两个PG 0.44,现在我们关闭osd.7,查看下0.44的状态:
1 2 3 4 5 | [root@ceph-3 0.44_head]# service ceph stop osd.7 === osd.7 === Stopping Ceph osd.7 on ceph-3...kill 5986...kill 5986...done [root@ceph-2 ~]# ceph pg dump_stuck |egrep ^0.44 0.44 undersized+degraded+peered [0] 0 [0] 0 |
可见,现在只剩下独苗苗活在osd.0上了,并且0.44还多了一个状态:peered
,英文的意思是仔细看,这里我们可以理解成协商、搜索
,这时候读取char.txt
文件,会发现指令会卡在那个地方一直不动,如此来解释min_size
的作用,在ceph中,它的全名叫做osd_pool_default_min_size
,这里大家就会问了,不是还活着一个呢吗,为什么就不能读取内容了,因为我们设置的min_size=2
,在ceph中的意义就是,如果存活数少于2了,比如这里的1 ,那么ceph就不会响应外部的IO请求。
在这里如果执行指令,将min_size设置为1:
1 2 3 | [root@ceph-2 ~]# ceph osd pool set rbd min_size 1 [root@ceph-2 ~]# ceph pg dump_stuck |egrep ^0.44 0.44 active+undersized+degraded [0] 0 [0] 0 |
可以看到,0.44没有了peered
状态,并且文件可以正常读写了,因为min_size=1
时,只要集群里面有一份副本活着,那就可以响应外部的IO请求。
peered,我们这里可以将它理解成它在等待其他兄弟姐妹上线,这里也就是osd.4和osd.7的任意一个上线就可以去除这个状态了,处于peered状态的PG是不能响应外部的请求的,外部就会觉得卡卡的。
Remapped
ceph强大的自我恢复能力,是我们选择它的一个重要原因,在上面的试验中,我们关闭了两个OSD,但是至少还有一个PG 0.44存活在osd.0上,如果那两个盘真的坏了,ceph还是可以将这份仅存的数据恢复到别的OSD上的。
在OSD挂掉5min(default 300s)之后,这个OSD会被标记为out状态,可以理解为ceph认为这个OSD已经不属于集群了,然后就会把PG 0.44 map到别的OSD上去,这个map也是按照一定的规则的,重映射之后呢,就会在另外两个OSD上找到0.44这个PG,而这只是创建了这个目录而已,丢失的数据是要从仅存的OSD上回填到新的OSD上的,处于回填状态的PG就会被标记为backfilling
。
所以当一个PG处于remapped+backfilling
状态时,可以认为其处于自我克隆复制的自愈过程。
Recover
这里我们先来做一个实验,首先开启所有OSD使得集群处于健康状态,然后前往osd.4的PG 0.44下面删除char__head_98165844__0
这个文件,再通知ceph扫描(scrub
)这个PG:
1 2 3 4 5 | [root@ceph-2 0.44_head]# pwd && rm -f char__head_98165844__0 /var/lib/ceph/osd/ceph-4/current/0.44_head [root@ceph-2 0.44_head]# ceph pg scrub 0.44 [root@ceph-2 0.44_head]# ceph pg dump |egrep ^0.44 active+clean+inconsistent [0,7,4] 0 [0,7,4] 0 |
可见,0.44多了个inconsistent
状态,顾名思义,ceph发现了这个PG的不一致状态,这样就可以理解这个状态的意义了。
想要修复丢失的文件呢,只需要执行ceph pg repair 0.44
,ceph就会从别的副本中将丢失的文件拷贝过来,这也是ceph自愈的一个情形。
现在再假设一个情形,在osd.4挂掉的过程中呢,我们对char
文件进行了写操作,因为集群内还存在着两个副本,是可以正常写入的,但是osd.4内的数据并没有得到更新,过了一会,osd.4上线了,ceph就发现,osd.4的char
文件是陈旧的,就通过别的OSD向osd.4进行数据的恢复,使其数据为最新的,而这个恢复的过程中,PG就会被标记为recover
。
总结
至此,我们对PG在磁盘的具体意义进行了分析,相信大家也对PG有了更深入的理解,同时,对常见的PG状态进行了剖析,今后看到了长长的病例单也不会有所畏惧了。
最后,本文对PG状态的解释都基于作者对ceph浅显的理解,如果有错误的地