• 4. 监控 PG
    • 4.1 节点互联
    • 4.2 监控 PG 状态
      • PG ID
    • 4.3 找出故障 PG
    • 4.4 定位对象位置
      • 练习:定位一个对象

    4. 监控 PG

    CRUSH 算法把 PG 分配到 OSD 时,它会根据存储池的副本数设置,把 PG 分配到不同的 OSD 上。比如,如果存储池设置为 3 副本, CRUSH 可能把它们分别分配到 osd.1osd.2osd.3 。考虑到 CRUSH Map 中设定的故障域,实际上 CRUSH 找出的是伪随机位置,所以在大型集群中,很少能看到 PG 被分配到了相邻的 OSD 。我们把涉及某个特定 PG 副本的一组 OSD 称为 acting set 。在某些情况下,位于 acting set 中的一个 OSD down 了或者不能为 PG 内的对象提供服务,这些情形发生时无需惊慌,常见原因如下:

    • 你增加或移除了某个 OSD 。然后 CRUSH 算法把 PG 重新分配到了其他 OSD ,因此改变了 Acting Set 的构成,并且引发了 “backfill” 过程来进行数据迁移。
    • 某个 OSD down 了、重启了,而现在正在恢复( recovering )。
    • Acting Set 中的一个 OSD down 了,不能提供服务,另一个 OSD 临时接替其工作。

    Ceph 靠 Up Set 处理客户端请求,它们是实际处理读写请求的 OSD 集合。大多数情况下 Up Set 和 Acting Set 是相同的。如果不同,说明可能 Ceph 正在迁移数据、某 OSD 在恢复、或者有别的问题。这种情况下, Ceph 通常表现为 “HEALTH WARN” 状态,还有 “stuck stale” 消息。

    用下列命令获取 PG 列表:

    1. ceph pg dump

    查看指定 PG 的 Acting Set 或 Up Set 中包含的 OSD,执行:

    1. ceph pg map {pg-num}

    命令的输出会告诉你 osdmap 版本( eNNN )、PG 号( {pg-num} )、Up Set 内的 OSD ( up[] )、和 Acting Set 内的 OSD ( acting[] )。

    1. osdmap e1196 pg 0.2d (0.2d) -> up [13,30] acting [13,30]

    4.1 节点互联

    写入数据前,PG 必须处于 active 、而且应该clean 状态。假设某存储池的 PG 有 3 副本,为让 Ceph 确定 PG 的当前状态,PG 的主 OSD (即 acting set 内的第一个 OSD )会与第二和第三 OSD 建立连接、并就 PG 的当前状态达成一致意见。

    4. 监控 PG - 图1

    OSD 们也向 Mon 报告自己的状态。要排除节点互联的问题,请参考本手册第二部分 3. 常见 PG 故障处理 中的相关部分进行处理。

    4.2 监控 PG 状态

    如果你执行了 ceph healthceph -s 、或 ceph -w 命令,你也许注意到了集群并非总返回 HEALTH_OK 。检查完 OSD 是否在运行后,你还应该检查 PG 的状态。你应该明白,在 PG 建立连接时集群不会返回 HEALTH_OK

    • 刚刚创建了一个存储池,PG 还没达成一致。
    • PG 正在恢复。
    • 刚刚增加或删除了一个 OSD 。
    • 刚刚修改了 CRUSH Map,PG 正在迁移。
    • 某一 PG 的副本间的数据不一致。
    • Ceph 正在洗刷一个 PG 的副本。
    • Ceph 没有足够可用容量来完成回填操作。

    如果是前述原因之一导致了 Ceph 返回 HEALTH_WARN ,无需紧张。很多情况下,集群会自行恢复;有些时候你得采取些措施。归置 PG 的一件重要事情是保证集群启动并运行着,所有 PG 都处于 active 状态、并且最好是 clean 状态。用下列命令查看所有 PG 状态:

    1. ceph pg stat

    其结果会告诉你 PG map 的版本号( vNNNNNN )、PG 总数 x 、有多少 PG 处于某种特定状态,如 active+clean ( y )。

    1. vNNNNNN: x pgs: y active+clean; z MB data, aa MB used, bb MB / cc MB avail

    除了 PG 状态之外, Ceph 也会报告数据占据的空间( aa )、剩余可用空间( bb )和 PG 总容量。这些数字在某些情况下是很重要的:

    • 集群快达到 near full ratiofull ratio 时。
    • 由于 CRUSH 配置错误致使数据没能在集群内正确分布。

    PG ID

    PG IDs 由存储池号(不是存储池名字)、后面跟一个点( . )、再加一个 16 进制数字的 PG ID 。用 ceph osd lspools 可查看存储池号及其名字,例如,默认存储池 rbd 对应的存储池号是 0 。完整的 PG ID 格式如下:

    1. {pool-num}.{pg-id}

    典型例子:

    1. 0.1f

    用下列命令获取 PG 列表:

    1. ceph pg dump

    你也可以让它输出到 JSON 格式,并保存到文件:

    1. ceph pg dump -o {filename} --format=json

    要查询某个 PG,用下列命令:

    1. ceph pg {poolnum}.{pg-id} query

    Ceph 会输出成 JSON 格式。

    1. {
    2. "state": "active+clean",
    3. "snap_trimq": "[]",
    4. "epoch": 26760,
    5. "up": [
    6. 1,
    7. 2
    8. ],
    9. "acting": [
    10. 1,
    11. 2
    12. ],
    13. "actingbackfill": [
    14. "1",
    15. "2"
    16. ],
    17. "info": {
    18. "pgid": "0.2d",
    19. "last_update": "26708'96",
    20. "last_complete": "26708'96",
    21. "log_tail": "0'0",
    22. "last_user_version": 96,
    23. "last_backfill": "MAX",
    24. "purged_snaps": "[1~1]",
    25. "history": {
    26. "epoch_created": 1,
    27. "last_epoch_started": 26760,
    28. "last_epoch_clean": 26760,
    29. ......
    30. "recovery_state": [
    31. {
    32. "name": "Started\/Primary\/Active",
    33. "enter_time": "2016-11-05 11:01:12.719671",
    34. "might_have_unfound": [],
    35. "recovery_progress": {
    36. "backfill_targets": [],
    37. "waiting_on_backfill": [],
    38. "last_backfill_started": "0\/\/0\/\/-1",
    39. "backfill_info": {
    40. "begin": "0\/\/0\/\/-1",
    41. "end": "0\/\/0\/\/-1",
    42. "objects": []
    43. },
    44. "peer_backfill_info": [],
    45. "backfills_in_flight": [],
    46. "recovering": [],
    47. "pg_backend": {
    48. "pull_from_peer": [],
    49. "pushing": []
    50. }
    51. },
    52. "scrub": {
    53. "scrubber.epoch_start": "26752",
    54. "scrubber.active": 0,
    55. "scrubber.waiting_on": 0,
    56. "scrubber.waiting_on_whom": []
    57. }
    58. },
    59. {
    60. "name": "Started",
    61. "enter_time": "2016-11-05 11:01:11.737126"
    62. }
    63. ],
    64. "agent_state": {}
    65. }

    4.3 找出故障 PG

    如前所述,一个 PG 状态不是 active+clean 时未必有问题。一般来说,PG 卡住时 Ceph 的自修复功能可能会不起作用,卡住的状态细分为:

    • Unclean: PG 里有些对象的副本数未达到期望值,它们应该进行恢复。
    • Inactive: PG 不能处理读写请求,因为它们在等着一个持有最新数据的 OSD 回到 up 状态。
    • Stale: PG 处于一种未知状态,因为存储它们的 OSD 有一阵子没向 Mon 报告了(由参数 mon osd report timeout 配置)。

    为找出卡住的归置组,执行:

    1. ceph pg dump_stuck [unclean|inactive|stale|undersized|degraded]

    关于排除卡住的 PG 见请参考本手册第二部分 3. 常见 PG 故障处理 中的相关部分进行处理。

    4.4 定位对象位置

    要把对象数据存入 Ceph 对象存储, Ceph 客户端必须:

    1. 设置对象名
    2. 指定存储池

    Ceph 客户端索取最新集群 map、并用 CRUSH 算法计算对象到 PG 的映射,然后计算如何动态地把 PG 分配到 OSD 。要定位对象位置,只需要知道对象名和存储池名字:

    1. ceph osd map {poolname} {object-name}
    练习:定位一个对象

    我们先创建一个对象。给 rados put 命令指定一对象名、一个包含数据的测试文件路径、和一个存储池名字,例如:

    1. rados put {object-name} {file-path} --pool=data
    2. rados put test-object-1 testfile.txt --pool=data

    用下列命令确认 Ceph 对象存储已经包含此对象:

    1. rados -p data ls

    现在可以定位对象了:

    1. ceph osd map {pool-name} {object-name}
    2. ceph osd map data test-object-1

    Ceph 应该输出对象的位置,例如:

    1. osdmap e537 pool 'data' (0) object 'test-object-1' -> pg 0.d1743484 (0.4) -> up [1,0] acting [1,0]

    要删除测试对象,用 rados rm 即可,如:

    1. rados rm test-object-1 --pool=data