一.背景
今天收到告警短信发现某个业务系统几台服务器的日志收集服务filebeat均已下线,把Filebeat都重启之后,准备到Kibana查阅业务系统的日志,检索异常条目,发现从凌晨开始的日志条目都没有,今天的索引也没有建成,查看集群监控,发现Elasticsearch集群状态为red,也无法继续使用和写入数据,于是开始着手排查故障。
二.系统环境:
所使用集群架构组件及版本信息如下:
操作系统OS版本:CentOS release 7.9.2009 (Core)
名称 | 版本号 |
---|---|
filebeat | 7.10.0 |
kafka | 2.4.1 |
zookeeper | 3.5.7 |
logstash | 7.5.2 |
elasticsearch | 7.5.2 |
kibana | 7.5.2 |
三.故障处理流程
1.首先在Kibana的控制台Dev Tools上使用
GET _cat/shards?v&s=state,prirep
查看索引的分片shard状态
发现主(state中标记为p,primary缩写)副分片(state中标记为r,replica缩写)都处于UNASSIGNED未分配的状态,所以Kibana上无法读取对应名为idr-attendance_2021.11.17以及.monitor-es-7-2021.11.16的索引上的数据
2.继续使用explain接口查看具体原因
GET /_cluster/allocation/explain
{
"index": "idr-attendance_2021.11.17",
"shard": 0,
"primary": true
}
把步骤1中提到的当天出现分片分配异常索引idr-attendance_2021.11.17,和具体的分片编号0,填入到上面的参数中,由于主分片和副本都有异常,首先把primary置为true,用来查询主分片异常原因,之后置为false,用来查询副本分片异常原因,调接口查询结果如下图所示
上图提示在Elasticsearch集群节点Elasticsearch02出现了分片分配异常的情况,节点Elasticsearch02是由于translog损坏corrupt导致的无法恢复(上图异常信息没截全),损坏原因怀疑是Filebeat服务的不正常停止导致数据流传输过程中异常中断。导致该0号分片无法分配UNASSIGNED。并且此时调用以下接口查看集群状态:
GET _cat/health?v
发现集群状态为red,无法正常使用
3.由于分片的事务日志translog出现了failed to recover from translog的问题,表示分片的事务日志已经遭到损坏,无法继续写入分片,所以需要清理已损坏的事务日志。针对三个Elasticsearch节点的集群,由于整个Elasticsearch集群已无法写入且运行清理工具需要暂停,同时避免出现脑裂等数据异常问题,所以首先停止Elasticsearch集群的所有节点
systemctl stop elasticsearch
没有部署成系统服务也可以通过kill进程的方式停止Elasticsearch服务
4.接着查询该问题索引的索引ID,即uuid,以此定位到问题节点Elasticsearch02的事务日志所在目录
GET _cat/indices/idr-attendance_2021.11.17?v
如上图查询结果所示,查询到的idr-attendance_2021.11.17的uuid为B7svQGUgQSm0hyVWUnGAdg
5.登录到节点Elasticsearch02所在服务器,切换成启动Elasticsearch服务用户的身份,去执行清除事务日志translog的操作,否则之后重新生成的文件会出现权限不匹配导致无法写入的问题,操作步骤如下图所示
su - elk
cd /data/ELK/elasticsearch_data/data/nodes/0/indices/B7svQGUgQSm0hyVWUnGAdg/0/translog/
/data/elasticsearch/bin/elasticsearch-shard remove-corrupted-data --index idr-attendance_2021.11.17 --shard-id 0
回车后会对输入的索引和分片的事务日志tranlogs进行检索,并找出已损坏的事务日志,且由于事务日志已损坏,只能放弃部分未写入的数据换取Elasticsearch集群的正常启动,所以输入"y"确认执行清除损坏事务日志的操作,如下图
执行结果如下图所示
6.重启Elasticsearch集群或已暂停的节点,回到kibana的Dev Tools开发者工具页面上,更改出现异常的索引idr-attendance_2021.11.17的参数"accept_data_loss"为"true",重新启用该索引,此次操作由POST请求实现
POST /_cluster/reroute
{
"commands" : [
{
"allocate_stale_primary" : {
"index" :"idr-attendance_2021.11.17",
"shard" : 0,
"node" : "rhjG2W_pStq_8zzbcwZvdA",
"accept_data_loss" : true
}
}
]
}
返回acknowledged:true表示索引参数调整成功,如下图
可以看到该索引分片的主分片(primary为true的一栏,表示为主分片身份)处于初始化"INITIALIZING"状态中,如下图
而副分片(primary为false的一栏,表示为主分片身份)需等待主分片初始化完毕后,才能开始初始化,所以状态state表示为"UNASSIGNED",如下图
之后等待索引各分片恢复为"STARTED"即可,如下图
7.最后查询Elasticsearch集群健康状态,恢复正常green,如下图
GET _cat/health?v
四.后记
1.后续又出现了索引分片未分配UNASSIGNED的错误,老方法,查询并分析后得到如下图的报错
由于Elasticsearch配置文件elasitcsearch.yml中参数cluster.routing.allocation.allow.rebalance的默认值为"indices_all_active",即所有索引都恢复正常使用的状态后才能触发数据平衡,且当前有索引存在未分配UNASSIGNED分片的情况,导致整个Elasticsearch集群无法正常使用
2.网上方案是把出现问题的索引的副本数replica改为0,即针对该问题索引不进行索引数据冗余容灾,则避免出现Elasticsearch集群不停地等待该索引副本数据复制正常后而导致的不可用问题,在线更改索引副本数的命令如下图
curl -H 'Content-Type: application/json' -u elastic:'elastic用户密码' -XPUT http://192.168.193.155:9200/ems-nginx_2021.11.11/_settings -d '{"number_of_replicas": 0 }'
返回的结果为
{"acknowledged": true}
表示成功
之后使用
curl -XGET -u elastic:'elastic用户密码' http://192.168.193.154:9200/ems-nginx_2021.11.11/_settings
查询到该索引分片已调整为1个,符合上述副本分片数置0的调整,如下图
3.本以为把索引分片调整为只保留1个即可恢复的时候,发现Elasticsearch日志又出现了新的报错,如下图
查找资料后发现是当前Elasticsearch集群的索引分片数达到了最大写入上限,需对集群分片上限数进行扩容,使用如下请求
curl -XPUT -H "Content-Type:application/json" -u elastic:'elastic用户密码' -d '{"persistent":{"cluster":{"max_shards_per_node":10000}}}' 'http://192.168.193.154:9200/_cluster/settings'
即可把集群索引分片上限提升到10000,然后分片数据即可正常写入
5.在故障处理过程中,可视化界面Kibana会由于Elasticsearch集群失效而无法访问,这时候在开发工具Dev Tools里执行的操作只能直接通过Elasticsearch的9200接口进行操作,详见上文中curl发起PUT请求过程,接口具体用法此处不再赘述。
6.后续经对Elasticsearch日志进行分析,发现有一处磁盘写满的报错,如下图
于是确认系统磁盘空间,确认Elasticsearch的数据目录/data/ELK,发现当前还有1.5T的空间剩余
于是和系统硬件管理人员确认,发现是磁盘挂载出现了问题,三个服务器节点磁盘总大小是3T,单个节点上限不超过2.5T,意思是此消彼长,并且发现三个节点的磁盘使用量都达到了1.1T,超过了实际磁盘总大小,所以会出现磁盘空间不足的错误信息。之后对磁盘进行扩容之后,重启Elasticsearch集群所有节点,索引分片数据开始正常重建,等待一段处理时间后,恢复正常使用。