某次机房断电后,再启动ceph后,出现如下错误:
[root@k8s-node2 ~]# ceph health detail
HEALTH_ERR mds rank 0 is damaged; mds cluster is degraded
mds.0 is damaged
mds cluster is degraded
提示 mds.0
不可用。 在部署ceph时,安装了3个mds, 分别运行在3台服务器上。并且参考官方的配置,使其中一个作为 master
对外提供服务,另外两个作为 standby
。来预防单点故障。(max_mds 设置为 2)
http://docs.ceph.com/docs/jewel/cephfs/standby/#examples
该错误发生后,3 个mds,均为 standby
状态。按照官网的描述来看,当所有 mds 均处于 standby
状态时,其中一个 mds 会选举称为 master
.
于是挨个停止mds, 随后又逐个启动并查看/var/log/ceph/ceph-mds.xx.log。发现 mds 在称为 master 时,出现了如下错误:
...
2017-09-26 11:30:48.976326 7f9ee3941700 0 mds.0.journaler(ro) _finish_read got less than expected (4194304)
2017-09-26 11:30:48.976354 7f9ee1734700 0 mds.0.log _replay journaler got error -22, aborting
2017-09-26 11:30:49.071230 7f9ee3941700 0 mds.0.journaler(ro) _finish_read got less than expected (4194304)
2017-09-26 11:30:49.071472 7f9ee1734700 -1 log_channel(cluster) log [ERR] : Error loading MDS rank 0: (22) Invalid argument
2017-09-26 11:30:49.076129 7f9ee1734700 1 mds.k8s-node1 respawn
...
2017-09-26 11:30:49.099291 7f99e58be180 0 pidfile_write: ignore empty --pid-file
2017-09-26 11:30:49.571643 7f99dfacf700 1 mds.k8s-node1 handle_mds_map standby
提示在读取 journal 的时候出现差错,因此可以确定问题出在 mds journal
上。
通过 google 也查到过一些类似的 issue, 大致解决办法是执行:
$ ceph mds repaire 0
并重启各个 mds daemon, 但该方式并不适用此问题。最终参考官方的故障恢复部分章节得以解决:
http://docs.ceph.com/docs/jewel/cephfs/disaster-recovery/
步骤如下(译自上述文档):
在执行有风险的操作之前,先将 journal 备份:
$ ceph-journal-tool journal export backup.bin
Note : 这个文件大小和ceph集群存储数据量成正比,会很大
当 mds 因为 journal 损坏或者其他原因无法读取,为了恢复文件元数据可以执行:
$ ceph-journal-tool event recover_dentries summary
默认会从 mds.0
中恢复, 使用 --rank=
来指定其他mds
这条指令会将 journal 中所有可回收的 inodes/dentries 写到后端存储,前提是要写入的 innodes/dentries 版本比后端存储里面的要高。 如果某个区块的 journal 丢失或者损坏,那么就不会被写到后端存储中。
Note : 除了将inodes/dentries 写入之外, 这条命令还会更新每个 MDS 的 InoTables, 标明被写入的 inodes 号在使用中,在一般情况下,会让后端存储恢复正常状态。
Warning : 此操作不能保证后端存储的状态达到前后一致,而且在此之后有必要执行 MDS 在线 scrub。此命令不会更改日志内容,恢复了能恢复的部分后应该把journal截短。
Note : 然而在执行这个命令之后,集群并未恢复正常,因此还需要往下看
$ cephfs-journal-tool journal reset
Warning : 重置journal 将会造成metadata丢失,除非你提前通过诸如
recover_dentries
的方式将metadata保存。该操作可能会在数据池里面产生一些孤儿对象。这会造成已写入的inodes再次被重新分配, 权限规则可能因此被违反。Note : 有个类似的 issue中也提到了上述步骤(link),但执行到这一步后,就没往下走了。
And mds rejoined again and everything seems to work fine now.
这点我没验证过,担心会有隐患。于是按照文档步骤继续执行了。
在 journal 被 reset 之后, 它可能不再符合MDS表的内容(包括:InoTable, SessionMap, SnapServer
). 重置 SessionMap
(即擦除所有Session) , 通过命令:
$ cephfs-table-tool all reset session
这条命令会在所有mds中生效, 可以将 all 替换为指定 mds 标号。
一旦文件系统底层的 RADOS 状态(即元数据存储池的内容)有所恢复,有必要更新 MDS 图以反映元数据存储池的内容。可以用下面的命令把 MDS MAP 重置到单个 MDS :
$ ceph fs reset --yes-i-really-mean-it
运行此命令之后, MDS rank 保存在 RADOS 上的任何不为 0 的状态都会被忽略:因此这有可能导致数据丢失。
也许有人想知道 fs reset
和 fs remove; fs new
的不同。主要区别在于,执行删除、新建操作会使 rank 0
处于 creating
状态,那样会覆盖所有根索引节点、并使所有文件变成孤儿;相反, reset
命令会使 rank 0
处于 active
状态,这样下一个要认领此 rank
的 MDS
守护进程会继续、并使用已存在于 RADOS
中的数据。
Note :
fs name
可通过ceph fs ls
查看
# Session table
cephfs-table-tool 0 reset session
# SnapServer
cephfs-table-tool 0 reset snap
# InoTable
cephfs-table-tool 0 reset inode
# Journal
cephfs-journal-tool --rank=0 journal reset
# Root inodes ("/" and MDS directory)
cephfs-data-scan init
最后,会基于数据池中丢失的文件和目录来重新创建 METADATA OBJECT。分为2步。
扫描所有对象并计算出inodes
的大小和 mtime metadata
$ cephfs-data-scan scan_extents
扫描每个文件中的第一个对象来收集METADATA,随后注入到 metadata pool
$ cephfs-data-scan scan_inodes
Note : 这两个步骤太耗时了,应该考虑起多个workers来同步处理。
data pool
可通过ceph fs ls
查看
# Worker 0
cephfs-data-scan scan_extents <data pool> 0 1
# Worker 1
cephfs-data-scan scan_extents <data pool> 1 1
# Worker 0
cephfs-data-scan scan_inodes <data pool> 0 1
# Worker 1
cephfs-data-scan scan_inodes <data pool> 1 1
==Note : 一定要确保在所有 workers
完成 scan_extents
之后再进行scan_inodes
操作。==
待所有操作执行完毕之后:
[root@k8s-master ~]# ceph -s
cluster e61d687d-f43d-4f50-af66-da96e5856be9
health HEALTH_OK
monmap e5: 3 mons at {k8s-master=172.16.18.30:6789/0,k8s-node1=172.16.18.6:6789/0,k8s-node2=172.16.18.7:6789/0}
election epoch 676, quorum 0,1,2 k8s-node1,k8s-node2,k8s-master
fsmap e4970: 1/1/1 up {0=k8s-node1=up:active}, 2 up:standby
osdmap e2914: 6 osds: 6 up, 6 in
flags sortbitwise,require_jewel_osds
pgmap v10110565: 256 pgs, 4 pools, 25575 MB data, 372 kobjects
58730 MB used, 11115 GB / 11172 GB avail
256 active+clean
集群恢复正常!