Ceph 文件系统客户端的驱逐
当某个文件系统客户端不响应或者有其它异常行为时,有必要强制切断它到文件系统的访问,这个过程就叫做驱逐。
这个过程有点过头,它是为了防止异常客户端导致数据不一致。
OSD 黑名单机制
首先,把此客户端加入黑名单以防止此它在 RADOS 级再操作任何数据。你可能熟悉这个概念,它在其它存储系统里叫做隔离栏( fencing )。
找出要从 MDS 会话列表中驱逐的客户端:
- # ceph daemon mds.a session ls
- [
- { "id": 4117,
- "num_leases": 0,
- "num_caps": 1,
- "state": "open",
- "replay_requests": 0,
- "reconnecting": false,
- "inst": "client.4117 172.16.79.251:0\/3271",
- "client_metadata": { "entity_id": "admin",
- "hostname": "fedoravm.localdomain",
- "mount_point": "\/home\/user\/mnt"}}]
本例中, ‘fedoravm’ 客户端的地址是 172.16.79.251:0/3271 ,所以这样加黑名单:
- # ceph osd blacklist add 172.16.79.251:0/3271
- 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 元图:
- # ceph osd dump
- epoch 12
- fsid fd61ca96-53ff-4311-826c-f36b176d69ea
- created 2014-12-09 12:03:38.595844
- modified 2014-12-09 12:09:56.619957
- ...
本例中它是 12 ,让 MDS 屏蔽此元图:
- # ceph daemon mds.a osdmap barrier 12
MDS 会话驱逐
最后就可以安全地驱逐此客户端的 MDS 会话了,这样它持有的所有能力就可以发行给其它客户端了。这里的 ID 是 sessionls 输出里的 id 属性:
- # ceph daemon mds.a session evict 4117
好了!这个客户端现在已经被驱逐了,而且它持有的资源也可以重分配给其它客户端了。
背景: OSD 元图屏蔽
此屏蔽的目的是为了确保当我们分配出这些能力后,别的客户端就有可能触碰同样的 RADOS 对象,接受分配能力的客户端们必须有足够新的 OSD 图,这样它们才不会与取消的操作(来自 ENOSPC )或进了黑名单的客户端(来自驱逐过程)竞争。
更具体些,我们设置元图屏蔽的情形有:
- 客户端驱逐(此客户端被加入黑名单了、且其它客户端必须等到有加黑之后的元图出现才能触碰同一批对象);
- 客户端正在处理 OSD 图的完整标识(此客户端可能会在快完整的元图中取消一些 OSD 操作,这样其它客户端都必须等着,直到元图完整或周期达到才能触碰同样的对象);
- MDS 启动,因为我们不会永久存储屏蔽图元,所以必须假设重启后总是需要最新的 OSD 图。
注意,为保持简洁性这是个全局值,其实我们可以做到按每索引节点维护此值,但我们没有这么做,因为:
- 它会复杂得多;
- 每索引节点需额外多占 4 字节的内存;
- 无论如何它都不会比大家一直都拥有最新的 OSD 图更有效,多数情况下,大家都能轻松地越过这个屏障而不是等着它。
- 我们仅在极少数情形下使用这种屏蔽,所以每索引节点这样细粒度的实现带来的好处也很少见。
元图屏蔽随其它能力消息一起传递,并且可指示消息接收器在看到这个 OSD 元图前、别再向那些 OSD 发送 RADOS 操作。主要是面向客户端(它们直接向文件写入数据)的,也适用于 MDS ,因为像文件尺寸探测和文件删除这样的操作都是直接在 MDS 上进行的。