Ceph 文件系统客户端的驱逐

当某个文件系统客户端不响应或者有其它异常行为时,有必要强制切断它到文件系统的访问,这个过程就叫做驱逐

这个过程有点过头,它是为了防止异常客户端导致数据不一致。

OSD 黑名单机制

首先,把此客户端加入黑名单以防止此它在 RADOS 级再操作任何数据。你可能熟悉这个概念,它在其它存储系统里叫做隔离栏( fencing )

找出要从 MDS 会话列表中驱逐的客户端:

  1. # ceph daemon mds.a session ls
  2. [
  3. { "id": 4117,
  4. "num_leases": 0,
  5. "num_caps": 1,
  6. "state": "open",
  7. "replay_requests": 0,
  8. "reconnecting": false,
  9. "inst": "client.4117 172.16.79.251:0\/3271",
  10. "client_metadata": { "entity_id": "admin",
  11. "hostname": "fedoravm.localdomain",
  12. "mount_point": "\/home\/user\/mnt"}}]

本例中, ‘fedoravm’ 客户端的地址是 172.16.79.251:0/3271 ,所以这样加黑名单:

  1. # ceph osd blacklist add 172.16.79.251:0/3271
  2. blacklisting 172.16.79.251:0/3271 until 2014-12-09 13:09:56.569368 (3600 sec)

OSD 元图屏蔽

被驱逐的客户端已在 OSD 图的中央( mon )副本中标记为进黑名单了,现在有必要确认一下本次 OSD 图更新已经传递给了后续文件系统 I/O 会涉及的所有守护进程。可以用 osdmapbarrier 这个 MDS 管理套接字命令。

首先读出最新的 OSD 元图:

  1. # ceph osd dump
  2. epoch 12
  3. fsid fd61ca96-53ff-4311-826c-f36b176d69ea
  4. created 2014-12-09 12:03:38.595844
  5. modified 2014-12-09 12:09:56.619957
  6. ...

本例中它是 12 ,让 MDS 屏蔽此元图:

  1. # ceph daemon mds.a osdmap barrier 12

MDS 会话驱逐

最后就可以安全地驱逐此客户端的 MDS 会话了,这样它持有的所有能力就可以发行给其它客户端了。这里的 ID 是 sessionls 输出里的 id 属性:

  1. # ceph daemon mds.a session evict 4117

好了!这个客户端现在已经被驱逐了,而且它持有的资源也可以重分配给其它客户端了。

背景: OSD 元图屏蔽

此屏蔽的目的是为了确保当我们分配出这些能力后,别的客户端就有可能触碰同样的 RADOS 对象,接受分配能力的客户端们必须有足够新的 OSD 图,这样它们才不会与取消的操作(来自 ENOSPC )或进了黑名单的客户端(来自驱逐过程)竞争。

更具体些,我们设置元图屏蔽的情形有:

  • 客户端驱逐(此客户端被加入黑名单了、且其它客户端必须等到有加黑之后的元图出现才能触碰同一批对象);
  • 客户端正在处理 OSD 图的完整标识(此客户端可能会在快完整的元图中取消一些 OSD 操作,这样其它客户端都必须等着,直到元图完整或周期达到才能触碰同样的对象);
  • MDS 启动,因为我们不会永久存储屏蔽图元,所以必须假设重启后总是需要最新的 OSD 图。

注意,为保持简洁性这是个全局值,其实我们可以做到按每索引节点维护此值,但我们没有这么做,因为:

  • 它会复杂得多;
  • 每索引节点需额外多占 4 字节的内存;
  • 无论如何它都不会比大家一直都拥有最新的 OSD 图更有效,多数情况下,大家都能轻松地越过这个屏障而不是等着它。
  • 我们仅在极少数情形下使用这种屏蔽,所以每索引节点这样细粒度的实现带来的好处也很少见。

元图屏蔽随其它能力消息一起传递,并且可指示消息接收器在看到这个 OSD 元图前、别再向那些 OSD 发送 RADOS 操作。主要是面向客户端(它们直接向文件写入数据)的,也适用于 MDS ,因为像文件尺寸探测和文件删除这样的操作都是直接在 MDS 上进行的。