1. PG 介绍
继上次分享的《Ceph介绍及原理架构分享》,这次主要来分享 Ceph 中的 PG 各种状态详解,PG 是最复杂和难于理解的概念之一,PG 的复杂如下:
在架构层次上,PG 位于 RADOS 层的中间。
a. 往上负责接收和处理来自客户端的请求。
b. 往下负责将这些数据请求翻译为能够被本地对象存储所能理解的事务。
是组成存储池的基本单位,存储池中的很多特性,都是直接依托于 PG 实现的。
面向容灾域的备份策略使得一般而言的 PG 需要执行跨节点的分布式写,因此数据在不同节点之间的同步、恢复时的数据修复也都是依赖 PG 完成。
2. PG 状态表
正常的 PG 状态是 100%的 active + clean, 这表示所有的 PG 是可访问的,所有副本都对全部 PG 都可用。
如果 Ceph 也报告 PG 的其他的警告或者错误状态。PG 状态表:
3. 状态详解及故障模拟复现
3.1 Degraded
3.1.1 说明
降级:由上文可以得知,每个 PG 有三个副本,分别保存在不同的 OSD 中,在非故障情况下,这个 PG 是 active+clean 状态,那么,如果 PG 的 副本 osd.4 挂掉了,这个 PG 是降级状态。
3.1.2 故障模拟
a. 停止 osd.1
b. 查看 PG 状态
c. 查看集群监控状态
d. 客户端 IO 操作
故障总结:
为了模拟故障,(size = 3, min_size = 2) 我们手动停止了 osd.1,然后查看 PG 状态,可见,它此刻的状态是 active+undersized+degraded,当一个 PG 所在的 OSD 挂掉之后,这个 PG 就会进入 undersized+degraded 状态,而后面的[0,2]的意义就是还有两个副本存活在 osd.0 和 osd.2 上, 并且这个时候客户端可以正常读写 IO。
3.1.3 总结
降级就是在发生了一些故障比如 OSD 挂掉之后,Ceph 将这个 OSD 上的所有 PG 标记为 Degraded。
降级的集群可以正常读写数据,降级的 PG 只是相当于小毛病而已,并不是严重的问题。
Undersized 的意思就是当前存活的 PG 副本数为 2,小于副本数 3,将其做此标记,表明存货副本数不足,也不是严重的问题。
3.2 Peered
3.2.1 说明
Peering 已经完成,但是 PG 当前 Acting Set 规模小于存储池规定的最小副本数(min_size)。
3.2.2 故障模拟
a. 停掉两个副本 osd.1,osd.0
b. 查看集群健康状态
c. 客户端 IO 操作(夯住)
故障总结:
现在 pg 只剩下 osd.2 上存活,并且 pg 还多了一个状态:peered,英文的意思是仔细看,这里我们可以理解成协商、搜索。
这时候读取文件,会发现指令会卡在那个地方一直不动,为什么就不能读取内容了,因为我们设置的 min_size=2 ,如果存活数少于 2,比如这里的 1 ,那么就不会响应外部的 IO 请求。
d. 调整 min_size=1 可以解决 IO 夯住问题
e. 查看集群监控状态
f. 客户端 IO 操作
故障总结:
可以看到,PG 状态 Peered 没有了,并且客户端文件 IO 可以正常读写了。
当 min_size=1 时,只要集群里面有一份副本活着,那就可以响应外部的 IO 请求。
3.2.3 总结
Peered 状态我们这里可以将它理解成它在等待其他副本上线。
当 min_size = 2 时,也就是必须保证有两个副本存活的时候就可以去除 Peered 这个状态。
处于 Peered 状态的 PG 是不能响应外部的请求的并且 IO 被挂起。
3.3 Remapped
3.3.1 说明
Peering 完成,PG 当前 Acting Set 与 Up Set 不一致就会出现 Remapped 状态。
3.3.2 故障模拟
a. 停止 osd.x
b. 间隔 5 分钟,启动 osd.x
c. 查看 PG 状态
d. 客户端 IO 操作
3.3.3 总结
在 OSD 挂掉或者在扩容的时候 PG 上的 OSD 会按照 Crush 算法重新分配 PG 所属的 osd 编号。并且会把 PG Remap 到别的 OSD 上去。
Remapped 状态时,PG 当前 Acting Set 与 Up Set 不一致。
客户端 IO 可以正常读写。
3.4 Recovery
3.4.1 说明
指 PG 通过 PGLog 日志针对数据不一致的对象进行同步和修复的过程。
3.4.2 故障模拟
a. 停止 osd.x
b. 间隔 1 分钟启动 osd.x
c. 查看集群监控状态
3.4.3 总结
Recovery 是通过记录的 PGLog 进行恢复数据的。
记录的 PGLog 在 osd_max_pg_log_entries=10000 条以内,这个时候通过 PGLog 就能增量恢复数据。
3.5 Backfill
3.5.1 说明
当 PG 的副本无非通过 PGLog 来恢复数据,这个时候就需要进行全量同步,通过完全拷贝当前 Primary 所有对象的方式进行全量同步。
3.5.2 故障模拟
a. 停止 osd.x
b. 间隔 10 分钟启动 osd.x
c. 查看集群健康状态
3.5.3 总结
无法根据记录的 PGLog 进行恢复数据时,就需要执行 Backfill 过程全量恢复数据。
如果超过 osd_max_pg_log_entries=10000 条, 这个时候需要全量恢复数据。
3.6 Stale
3.6.1 说明
mon 检测到当前 PG 的 Primary 所在的 osd 宕机。
Primary 超时未向 mon 上报 pg 相关的信息(例如网络阻塞)。
PG 内三个副本都挂掉的情况。
3.6.2 故障模拟
a. 分别停止 PG 中的三个副本 osd, 首先停止 osd.23
b. 然后停止 osd.24
c. 查看停止两个副本 PG 1.45 的状态(undersized+degraded+peered)
d. 在停止 PG 1.45 中第三个副本 osd.10
e. 查看停止三个副本 PG 1.45 的状态(stale+undersized+degraded+peered)
f. 客户端 IO 操作
故障总结:
先停止同一个 PG 内两个副本,状态是 undersized+degraded+peered。
然后停止同一个 PG 内三个副本,状态是 stale+undersized+degraded+peered。
3.6.3 总结
当出现一个 PG 内三个副本都挂掉的情况,就会出现 stale 状态。
此时该 PG 不能提供客户端读写,IO 挂起夯住。
Primary 超时未向 mon 上报 pg 相关的信息(例如网络阻塞),也会出现 stale 状态。
3.7 Inconsistent
3.7.1 说明
PG 通过 Scrub 检测到某个或者某些对象在 PG 实例间出现了不一致
3.7.2 故障模拟
a. 删除 PG 3.0 中副本 osd.34 头文件
b. 手动执行 PG 3.0 进行数据清洗
c. 检查集群监控状态
d. 修复 PG 3.0
故障总结:
当 PG 内部三个副本有数据不一致的情况,想要修复不一致的数据文件,只需要执行 ceph pg repair 修复指令,ceph 就会从其他的副本中将丢失的文件拷贝过来就行修复数据。
3.7.3 故障模拟
当 osd 短暂挂掉的时候,因为集群内还存在着两个副本,是可以正常写入的,但是 osd.34 内的数据并没有得到更新,过了一会 osd.34 上线了,这个时候 osd.34 的数据是陈旧的,就通过其他的 OSD 向 osd.34 进行数据的恢复,使其数据为最新的,而这个恢复的过程中,PG 的状态会从 inconsistent ->recover -> clean,最终恢复正常。
这是集群故障自愈一种场景。
3.8 Down
3.8.1 说明
Peering 过程中,PG 检测到某个不能被跳过的 Interval 中(例如该 Interval 期间,PG 完成了 Peering,并且成功切换至 Active 状态,从而有可能正常处理了来自客户端的读写请求),当前剩余在线的 OSD 不足以完成数据修复.
3.8.2 故障模拟
a. 查看 PG 3.7f 内副本数
b. 停止 PG 3.7f 副本 osd.21
c. 查看 PG 3.7f 状态
d. 客户端写入数据,一定要确保数据写入到 PG 3.7f 的副本中[5,29]
e. 停止 PG 3.7f 中副本 osd.29,并且查看 PG 3.7f 状态(undersized+degraded+peered)
f. 停止 PG 3.7f 中副本 osd.5,并且查看 PG 3.7f 状态(undersized+degraded+peered)
g. 拉起 PG 3.7f 中副本 osd.21(此时的 osd.21 数据比较陈旧), 查看 PG 状态(down)
h. 客户端 IO 操作
故障总结:
首先有一个 PG 3.7f 有三个副本[5,21,29], 当停掉一个 osd.21 之后, 写入数据到 osd.5, osd.29。 这个时候停掉 osd.29, osd.5 ,最后拉起 osd.21。 这个时候 osd.21 的数据比较旧,就会出现 PG 为 down 的情况,这个时候客户端 IO 会夯住,只能拉起挂掉的 osd 才能修复问题。
3.8.3 结论
典型的场景:A(主)、B、C
a. 首先 kill B
b. 新写入数据到 A、C
c. kill A 和 C
d. 拉起 B
出现 PG 为 Down 的场景是由于 osd 节点数据太旧,并且其他在线的 osd 不足以完成数据修复。
这个时候该 PG 不能提供客户端 IO 读写, IO 会挂起夯住。
作者信息
作者简介:李航,多年的底层开发经验,在高性能 nginx 开发和分布式缓存 redis cluster 有着丰富的经验,目前从事 Ceph 工作两年左右。
先后在 58 同城、汽车之家、优酷土豆集团工作。
目前供职于滴滴基础平台运维部-技术专家岗位 负责分布式 Ceph 集群开发及运维等工作。
个人主要关注的技术领域:高性能 Nginx 开发、分布式缓存、分布式存储。
评论